diff options
author | ivan <ivan> | 2007-08-01 22:26:52 +0000 |
---|---|---|
committer | ivan <ivan> | 2007-08-01 22:26:52 +0000 |
commit | eb4ff7f73c5d4bdf74a3472448b5a195598ff4cd (patch) | |
tree | bb38241e8c865c3bca861da7749071feeadd2b5b /httemplate/edit | |
parent | 32b5d3a31f112a381f0a15ac5e3a2204242f3405 (diff) |
event refactor, landing on HEAD!
Diffstat (limited to 'httemplate/edit')
-rw-r--r-- | httemplate/edit/access_group.html | 122 | ||||
-rwxr-xr-x | httemplate/edit/agent.cgi | 114 | ||||
-rwxr-xr-x | httemplate/edit/cust_main.cgi | 3 | ||||
-rw-r--r-- | httemplate/edit/elements/edit.html | 630 | ||||
-rw-r--r-- | httemplate/edit/invoice_logo.html | 136 | ||||
-rw-r--r-- | httemplate/edit/invoice_template.html | 80 | ||||
-rwxr-xr-x | httemplate/edit/part_bill_event.cgi | 18 | ||||
-rw-r--r-- | httemplate/edit/part_event.html | 642 | ||||
-rwxr-xr-x | httemplate/edit/part_pkg.cgi | 7 | ||||
-rwxr-xr-x | httemplate/edit/part_referral.html | 9 | ||||
-rw-r--r-- | httemplate/edit/process/access_group.html | 1 | ||||
-rw-r--r-- | httemplate/edit/process/elements/process.html | 312 | ||||
-rw-r--r-- | httemplate/edit/process/invoice_logo.html | 26 | ||||
-rw-r--r-- | httemplate/edit/process/invoice_template.html | 15 | ||||
-rw-r--r-- | httemplate/edit/process/part_event.html | 86 | ||||
-rw-r--r-- | httemplate/edit/process/quick-cust_pkg.cgi | 26 | ||||
-rw-r--r-- | httemplate/edit/reason.html | 4 |
17 files changed, 1820 insertions, 411 deletions
diff --git a/httemplate/edit/access_group.html b/httemplate/edit/access_group.html index d447512..4686a62 100644 --- a/httemplate/edit/access_group.html +++ b/httemplate/edit/access_group.html @@ -1,46 +1,80 @@ <% include( 'elements/edit.html', - 'name' => 'Internal Access Group', - 'table' => 'access_group', - 'labels' => { - 'groupnum' => 'Group number', - 'groupname' => 'Group name', - }, - - 'viewall_dir' => 'browse', - - 'html_bottom' => - sub { - my $access_group = shift; - - "<BR>Group virtualized to customers of agents:<BR>". - ntable("#cccccc",2). - '<TR><TD>'. - include( '/elements/checkboxes-table.html', - 'source_obj' => $access_group, - 'link_table' => 'access_groupagent', - 'target_table' => 'agent', - 'name_col' => 'agent', - 'target_link' => $p.'edit/agent.cgi?', - 'disable-able' => 1, - ). - '</TR></TD></TABLE>'. - - "<BR>Group rights:<BR>". - ntable("#cccccc",2). - '<TR><TD>'. - include( '/elements/checkboxes-table-name.html', - 'source_obj' => $access_group, - 'link_table' => 'access_right', - 'link_static' => { 'righttype' => - 'FS::access_group', - }, - 'num_col' => 'rightobjnum', - 'name_col' => 'rightname', - 'names_list' => [ FS::AccessRight->rights() ], - ). - '</TR></TD></TABLE>' - - ; - }, - ) + 'name' => 'Internal Access Group', + 'table' => 'access_group', + 'labels' => { + 'groupnum' => 'Group number', + 'groupname' => 'Group name', + }, + + 'viewall_dir' => 'browse', + + 'html_bottom' => $html_bottom_sub, + ) %> +<%once> + +tie my %rights, 'Tie::IxHash', FS::AccessRight->rights_info; + +</%once> +<%init> + +my $html_bottom_sub = sub { + my $access_group = shift; + + #some false laziness w/browse/access_group.html + my $columns = 3; + my $count = 0; + + '<BR>'. + '<FONT SIZE="+1">Group limited to these agent(s)</FONT><BR>'. + 'Employees in this group will only see customers of the selected agents in the system and reports.<BR>'. + ntable("#cccccc",2). + '<TR><TD>'. + include( '/elements/checkboxes-table.html', + 'source_obj' => $access_group, + 'link_table' => 'access_groupagent', + 'target_table' => 'agent', + 'name_col' => 'agent', + 'target_link' => $p.'edit/agent.cgi?', + 'disable-able' => 1, + ). + '</TD></TR></TABLE>'. + + '<BR><FONT SIZE="+1">Group access rights</FONT><BR>'. + include('/elements/table-grid.html', bgcolor=>'#cccccc' ). + '<TR>'. join( '', map { + '<TD CLASS="inv" VALIGN="top"><TABLE BGCOLOR="#cccccc" WIDTH=100%>'. + '<TR><TH BGCOLOR="#dcdcdc">'. $_. '</TH></TR>'. + '<TR><TD>'. + include( '/elements/checkboxes-table-name.html', + 'source_obj' => $access_group, + 'link_table' => 'access_right', + 'link_static' => { 'righttype' => + 'FS::access_group', + }, + 'num_col' => 'rightobjnum', + 'name_col' => 'rightname', + 'names_list' => [ map { + my $rn = + ref($_) ? $_->{'rightname'} : $_; + my %hash = (); + $hash{'note'} = ' *' + if ref($_) && $_->{'global'}; + $hash{'desc'} = $_->{'desc'} + if ref($_) && $_->{'desc'}; + [ $rn => \%hash ]; + } + @{ $rights{$_} } + ], + ). + '<BR>'. + '</TD></TR></TABLE></TD>'. + ( ++$count % $columns ? '' : '</TR><TR>') + + } keys %rights ). '</TR></TABLE>'. + + '* Global rights. These rights provide access to global data which is shared among all agents. Their use is not recommended for groups which are limited to a subset of agents.<BR>'; + +}; + +</%init> diff --git a/httemplate/edit/agent.cgi b/httemplate/edit/agent.cgi index 5992bfa..830862f 100755 --- a/httemplate/edit/agent.cgi +++ b/httemplate/edit/agent.cgi @@ -1,25 +1,3 @@ -% -% -%my $agent; -%if ( $cgi->param('error') ) { -% $agent = new FS::agent ( { -% map { $_, scalar($cgi->param($_)) } fields('agent') -% } ); -%} elsif ( $cgi->keywords ) { -% my($query) = $cgi->keywords; -% $query =~ /^(\d+)$/; -% $agent = qsearchs( 'agent', { 'agentnum' => $1 } ); -%} else { #adding -% $agent = new FS::agent {}; -%} -%my $action = $agent->agentnum ? 'Edit' : 'Add'; -%my $hashref = $agent->hashref; -% -%my $conf = new FS::Conf; -% -% - - <% include("/elements/header.html","$action Agent", menubar( 'Main Menu' => $p, 'View all agents' => $p. 'browse/agent.cgi', @@ -31,43 +9,42 @@ <FORM ACTION="<%popurl(1)%>process/agent.cgi" METHOD=POST> -<INPUT TYPE="hidden" NAME="agentnum" VALUE="<% $hashref->{agentnum} %>"> -Agent #<% $hashref->{agentnum} ? $hashref->{agentnum} : "(NEW)" %> +<INPUT TYPE="hidden" NAME="agentnum" VALUE="<% $agent->agentnum %>"> +Agent #<% $agent->agentnum ? $agent->agentnum : "(NEW)" %> <% &ntable("#cccccc", 2, '') %> -<TR> - <TH ALIGN="right">Agent</TH> - <TD><INPUT TYPE="text" NAME="agent" SIZE=32 VALUE="<% $hashref->{agent} %>"></TD> -</TR> + <TR> + <TH ALIGN="right">Agent</TH> + <TD><INPUT TYPE="text" NAME="agent" SIZE=32 VALUE="<% $agent->agent %>"></TD> + </TR> <TR> <TH ALIGN="right">Agent type</TH> - <TD><SELECT NAME="typenum" SIZE=1> -% foreach my $agent_type (qsearch('agent_type',{})) { + <TD> + <SELECT NAME="typenum" SIZE=1> +% foreach my $agent_type (qsearch('agent_type',{})) { - <OPTION VALUE="<% $agent_type->typenum %>"<% ( $hashref->{typenum} && ( $hashref->{typenum} == $agent_type->typenum ) ) ? ' SELECTED' : '' %>> + <OPTION VALUE="<% $agent_type->typenum %>"<% ( $agent->typenum && ( $agent->typenum == $agent_type->typenum ) ) ? ' SELECTED' : '' %>> <% $agent_type->getfield('typenum') %>: <% $agent_type->getfield('atype') %> -% } - +% } - </SELECT></TD> + </SELECT> + </TD> </TR> - + <TR> <TD ALIGN="right">Disable</TD> - <TD><INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<% $hashref->{disabled} eq 'Y' ? ' CHECKED' : '' %>></TD> - </TR> - - <TR> - <TD ALIGN="right"><!--Frequency--></TD> - <TD><INPUT TYPE="hidden" NAME="freq" VALUE="<% $hashref->{freq} %>"></TD> + <TD><INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<% $agent->disabled eq 'Y' ? ' CHECKED' : '' %>></TD> </TR> + + <% include('/elements/tr-select-invoice_template.html', + 'label' => 'Invoice template', + 'field' => 'invoice_template', + 'curr_value' => $agent->invoice_template, + ) + %> - <TR> - <TD ALIGN="right"><!--Program--></TD> - <TD><INPUT TYPE="hidden" NAME="prog" VALUE="<% $hashref->{prog} %>"></TD> - </TR> % if ( $conf->config('ticket_system') ) { % my $default_queueid = $conf->config('ticket_system-default_queueid'); % my $default_queue = FS::TicketSystem->queue($default_queueid); @@ -92,24 +69,33 @@ Agent #<% $hashref->{agentnum} ? $hashref->{agentnum} : "(NEW)" %> </TR> % } - - <TR> - <TD ALIGN="right">(DEPRECATED) Agent interface username</TD> - <TD> - <INPUT TYPE="text" NAME="username" VALUE="<% $hashref->{username} %>"> - </TD> - </TR> - - <TR> - <TD ALIGN="right">(DEPRECATED) Agent interface password</TD> - <TD> - <INPUT TYPE="text" NAME="_password" VALUE="<% $hashref->{_password} %>"> - </TD> - </TR> - </TABLE> -<BR><INPUT TYPE="submit" VALUE="<% $hashref->{agentnum} ? "Apply changes" : "Add agent" %>"> - </FORM> - </BODY> -</HTML> +<BR> +<INPUT TYPE="submit" VALUE="<% $agent->agentnum ? "Apply changes" : "Add agent" %>"> + +</FORM> + +<% include('/elements/footer.html') %> + +<%init> + +my $agent; +if ( $cgi->param('error') ) { + $agent = new FS::agent ( { + map { $_, scalar($cgi->param($_)) } fields('agent') + } ); +} elsif ( $cgi->keywords ) { + my($query) = $cgi->keywords; + $query =~ /^(\d+)$/; + $agent = qsearchs( 'agent', { 'agentnum' => $1 } ); +} else { #adding + $agent = new FS::agent {}; +} +my $action = $agent->agentnum ? 'Edit' : 'Add'; + +my $conf = new FS::Conf; + +</%init> + + diff --git a/httemplate/edit/cust_main.cgi b/httemplate/edit/cust_main.cgi index 0a7a8c0..d13732a 100755 --- a/httemplate/edit/cust_main.cgi +++ b/httemplate/edit/cust_main.cgi @@ -122,7 +122,8 @@ <!-- agent --> -<% include('/elements/tr-select-agent.html', $cust_main->agentnum, +<% include('/elements/tr-select-agent.html', + 'curr_value' => $cust_main->agentnum, 'label' => "<B>${r}Agent</B>", 'empty_label' => 'Select agent', ) diff --git a/httemplate/edit/elements/edit.html b/httemplate/edit/elements/edit.html index 17c5ad3..d7d55a2 100644 --- a/httemplate/edit/elements/edit.html +++ b/httemplate/edit/elements/edit.html @@ -1,214 +1,406 @@ -% -% -% # options example... -% # -% # 'name' => -% # 'table' => -% # #? 'primary_key' => #required when the dbdef doesn't know...??? -% # 'labels' => { -% # 'column' => 'Label', -% # } -% # -% # listref - each item is a literal column name (or method) or hashref -% # or (notyet) coderef -% # if not specified all columns (except for the primary key) will be editable -% # 'fields' => [ -% # 'columname', -% # { 'field' => 'another_columname', -% # 'type' => 'text', #text -% # #checkbox -% # #select -% # #hidden - hidden value from object -% # #fixed - display fixed value from here -% # #fixedhidden - hidden value from here -% # 'value' => 'Y', #for checkbox, fixed, fixedhidden -% # }, -% # ] -% # -% # 'menubar' => '', #menubar arrayref -% # -% # #run when re-displaying with an error -% # 'error_callback' => sub { my( $cgi, $object ) = @_; }, -% # -% # #run when editing -% # 'edit_callback' => sub { my( $cgi, $object ) = @_; }, -% # -% # # returns a hashref for the new object -% # 'new_hashref_callback' -% # -% # #run when adding -% # 'new_callback' => sub { my( $cgi, $object ) = @_; }, -% # -% # #XXX describe -% # 'field_callback' => sub { }, -% # -% # #string or coderef of additional HTML to add before </TABLE> -% # 'html_table_bottom' => '', -% # -% # 'viewall_dir' => '', #'search' or 'browse', defaults to 'search' -% # -% # 'html_bottom' => '', #string -% # 'html_bottom' => sub { -% # my $object = shift; -% # # ... -% # "html_string"; -% # }, -% # -% # # overrides default popurl(1)."process/$table.html" -% # 'post_url' => popurl(1).'process/something', -% -% my(%opt) = @_; -% -% #false laziness w/process.html -% my $table = $opt{'table'}; -% my $class = "FS::$table"; -% my $pkey = dbdef->table($table)->primary_key; #? $opt{'primary_key'} || -% my $fields = $opt{'fields'} -% #|| [ grep { $_ ne $pkey } dbdef->table($table)->columns ]; -% || [ grep { $_ ne $pkey } fields($table) ]; -% #my @actualfields = map { ref($_) ? $_->{'field'} : $_ } @$fields; -% -% my $object; -% if ( $cgi->param('error') ) { -% -% $object = $class->new( { -% map { $_ => scalar($cgi->param($_)) } fields($table) -% }); -% -% &{$opt{'error_callback'}}($cgi, $object) -% if $opt{'error_callback'}; -% -% } elsif ( $cgi->keywords || $cgi->param($pkey) ) { #editing -% -% my $value; -% if ( $cgi->param($pkey) ) { -% $value = $cgi->param($pkey) -% } else { -% my( $query ) = $cgi->keywords; -% $value = $query; -% } -% $value =~ /^(\d+)$/ or die "unparsable $pkey"; -% $object = qsearchs( $table, { $pkey => $1 } ); -% warn "$table $pkey => $1" -% if $opt{'debug'}; -% -% &{$opt{'edit_callback'}}($cgi, $object) -% if $opt{'edit_callback'}; -% -% } else { #adding -% -% my $hashref = $opt{'new_hashref_callback'} -% ? &{$opt{'new_hashref_callback'}} -% : {}; -% -% $object = $class->new( $hashref ); -% -% &{$opt{'new_callback'}}($cgi, $object) -% if $opt{'new_callback'}; -% -% } -% -% my $action = $object->$pkey() ? 'Edit' : 'Add'; -% -% my $title = "$action $opt{'name'}"; -% -% my $viewall_url = $p . ( $opt{'viewall_dir'} || 'search' ) . "/$table.html"; -% $viewall_url = $opt{'viewall_url'} if $opt{'viewall_url'}; -% -% my @menubar = (); -% if ( $opt{'menubar'} ) { -% @menubar = @{ $opt{'menubar'} }; -% } else { -% @menubar = ( -% 'Main menu' => $p, #eventually get rid of this when the ACL/UI update is done -% #eventually use Lingua::bs to pluralize -% "View all $opt{'name'}s" => $viewall_url, -% ); -% } -% -% +<%doc> + +Example: + + include( 'elements/edit.html', + 'name' => + 'table' => + #? 'primary_key' => #required when the dbdef doesn't know...??? + 'labels' => { + 'column' => 'Label', + } + + listref - each item is a literal column name (or method) or hashref + or (notyet) coderef + if not specified all columns (except for the primary key) will be editable + 'fields' => [ + 'columname', + { 'field' => 'another_columname', + 'type' => 'text', #text + #money + #checkbox + #select + #selectlayers + #title + #hidden - hidden value from object + #fixed - display fixed value from here + #fixedhidden - hidden value from here + 'value' => 'Y', #for checkbox, title, fixed, fixedhidden + 'disabled' => 0, + 'onchange' => 'javascript_function', + 'm2name_table' => 'table_name', #only tested w/ + # selectlayers so far + # might work w/select + # dunno others + 'm2name_namecol' => 'name_column', # + 'm2name_label' => 'Label', # + 'm2name_new_default' => \@table_name_objects, #default + #m2name + #objects for + #new records + 'm2name_error_callback' => sub { my($cgi, $object) = @_; }, + 'm2name_remove_warnings' => \%warnings, #hashref of warning + #messages for + #m2name removal + 'm2name_new_js' => 'function_name', #javascript function + #called on spawned rows + #(one arg: new_element) + 'm2name_remove_js' => 'function_name', #js function called + #when a row is + #deleted + #(three args: + # value, text, + # 'no_match') + #layer_fields & layer_values_callback only for selectlayer + 'layer_fields' => [ + 'fieldname' => 'Label', + 'another_field' => { + label=>'Label', + type =>'text', #text, money + }, + ], + 'layer_values_callback' => + sub { + my( $cgi, $object ) = @_; + { 'layer' => { 'fieldname' => 'current_value', + 'fieldname2' => 'field2value', + ... + }, + 'layer2' => { 'l2fieldname' => 'l2value', + ... + }, + ... + }; + }, + }, + ] + + 'menubar' => '', #menubar arrayref + + #agent virtualization + 'agent_virt' => 1, + 'agent_null_right' => 'Access Right Name', + + #run when re-displaying with an error + 'error_callback' => sub { my( $cgi, $object, $fields_listref ) = @_; }, + + #run when editing + 'edit_callback' => sub { my( $cgi, $object, $fields_listref ) = @_; }, + + # returns a hashref for the new object + 'new_hashref_callback' + + #run when adding + 'new_callback' => sub { my( $cgi, $object, $fields_listref ) = @_; }, + + #XXX describe + 'field_callback' => sub { }, + + #string or coderef of additional HTML to add before </TABLE> + 'html_table_bottom' => '', + + 'viewall_dir' => '', #'search' or 'browse', defaults to 'search' + + 'html_bottom' => '', #string + 'html_bottom' => sub { + my $object = shift; + # ... + "html_string"; + }, + + # overrides default popurl(1)."process/$table.html" + 'post_url' => popurl(1).'process/something', + ); + +</%doc> + <% include("/elements/header.html", $title, include( '/elements/menubar.html', @menubar ) ) %> -% if ( $cgi->param('error') ) { +% if ( $cgi->param('error') ) { <FONT SIZE="+1" COLOR="#ff0000">Error: <% $cgi->param('error') %></FONT> <BR><BR> % } % my $url = $opt{'post_url'} || popurl(1)."process/$table.html"; -<FORM ACTION="<% $url %>" METHOD=POST> +<FORM ACTION="<% $url %>" METHOD=POST NAME="edit_topform"> + <INPUT TYPE="hidden" NAME="svcdb" VALUE="<% $table %>"> <INPUT TYPE="hidden" NAME="<% $pkey %>" VALUE="<% $object->$pkey() %>"> + <% ( $opt{labels} && exists $opt{labels}->{$pkey} ) ? $opt{labels}->{$pkey} : $pkey %> #<% $object->$pkey() || "(NEW)" %> -<% ntable("#cccccc",2) %> +%# <% ntable("#cccccc",0) %> +<TABLE ID="OneTrueTable" BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0> + +% my $g_row = 0; % foreach my $f ( map { ref($_) ? $_ : {'field'=>$_} } % @$fields % ) { % -% &{ $opt{'field_callback'} }( $f ) -% if $opt{'field_callback'}; +% &{ $opt{'field_callback'} }( $f ) +% if $opt{'field_callback'}; +% +% my $field = $f->{'field'}; +% my $type = $f->{'type'} ||= 'text'; +% +% my $label = ( $opt{labels} && exists $opt{labels}->{$field} ) +% ? $opt{labels}->{$field} +% : $field; +% +% my $onchange = $f->{'onchange'}; +% +% my $layer_values = {}; +% if ( $f->{'layer_values_callback'} && ! $f->{'m2name_table'} ) { +% $layer_values = &{ $f->{'layer_values_callback'} }( $cgi, $object ); +% } +% warn "layer values: ". Dumper($layer_values) +% if $opt{'debug'}; +% +% my %include_common = ( +% #checkbox, title +% #& deprecated weird value hashref used only by reason.html +% 'value' => $f->{'value'}, +% +% #select(-*) +% 'options' => $f->{'options'}, +% 'labels' => $f->{'labels'}, +% 'multiple' => $f->{'multiple'}, +% 'disable_empty' => $f->{'disable_empty'}, +% #select-reason +% 'reason_class' => $f->{'reason_class'}, % -% my $field = $f->{'field'}; -% my $type = $f->{'type'} ||= 'text'; +% #selectlayers +% 'layer_fields' => $f->{'layer_fields'}, +% 'layer_values' => $layer_values, +% 'html_between' => $f->{'html_between'}, +% ); % +% my $layer_prefix_on = ''; % +% my $include_sub = sub { +% my %opt = @_; +% +% my $fieldnum = delete $opt{'fieldnum'}; +% +% my $include = $type; +% $include = "input-$include" if $include =~ /^(text|money)$/; +% $include = "tr-$include" unless $include eq 'hidden'; +% +% $include_common{'layer_prefix'} = "$field$fieldnum." +% if $layer_prefix_on; +% +% my @include = +% ( "/elements/$include.html", +% 'field' => "$field$fieldnum", +% 'id' => "$field$fieldnum", #separate? +% 'label_id' => $field."_label$fieldnum", #don't want field0_label0... +% %include_common, +% %opt, +% ); +% @include; +% }; +% +% $g_row++; +% $g_row++ if $type eq 'title'; +% +% my $fieldnum = ''; +% my $curr_value = ''; +% if ( $f->{'m2name_table'} ) { #XXX test this for all types of fields +% my $table = $f->{'m2name_table'}; +% my $col = $f->{'m2name_namecol'}; +% $fieldnum = 0; +% $layer_prefix_on = 1; +% #print out the fields for the existing m2names +% my @existing = (); +% if ( $mode eq 'error' ) { +% @existing = &{ $f->{'m2name_error_callback'} }( $cgi, $object ); +% } elsif ( $object->$pkey() ) { # $mode eq 'edit' +% @existing = $object->$table(); +% } elsif ( $f->{'m2name_new_default'} ) { # && $mode eq 'new' +% @existing = @{ $f->{'m2name_new_default'} }; +% } +% foreach my $name_obj ( @existing ) { +% +% my $ex_label = '<INPUT TYPE="button" VALUE="X" TITLE="Remove this '. +% lc($f->{'m2name_label'}). +% qq(" onClick="remove_$field($fieldnum);"). +% ' STYLE="color:#ff0000;font-weight:bold;'. +% 'padding-left:2px;padding-right:2px"'. +% '> '. ($f->{'m2name_label'} || $field ). ' '; +% +% if ( $f->{'layer_values_callback'} ) { +% my %switches = ( 'mode' => $mode ); +% $layer_values = +% &{ $f->{'layer_values_callback'} }( $cgi, $name_obj, \%switches ); +% } +% warn "layer values: ". Dumper($layer_values) +% if $opt{'debug'}; +% +% my @existing = &{ $include_sub }( +% 'label' => $ex_label, +% 'fieldnum' => $fieldnum, +% 'curr_value' => $name_obj->$col(), +% 'onchange' => $onchange, +% 'layer_values' => $layer_values, +% 'cell_style' => ( $fieldnum ? 'border-top:1px solid black' : '' ), +% ); + + <% include( @existing ) %> +% $fieldnum++; +% $g_row++; +% } +% #$field .= $fieldnum; +% $onchange .= "\nspawn_$field(what);"; +% } else { +% $curr_value = $object->$field(); +% } +% +% my @include = &{ $include_sub }( +% 'label' => $label, +% 'fieldnum' => $fieldnum, +% 'curr_value' => $curr_value, +% 'onchange' => $onchange, +% 'cell_style' => ( $fieldnum ? 'border-top:1px solid black' : '' ), +% ); - <TR> + <% include( @include ) %> - <TD ALIGN="right"> - <% ( $opt{labels} && exists $opt{labels}->{$field} ) - ? $opt{labels}->{$field} - : $field - %> - </TD> +% if ( $f->{'m2name_table'} ) { -% if ( $type eq 'fixed' ) { + <SCRIPT TYPE="text/javascript"> - <TD BGCOLOR="#dddddd"><% $f->{'value'} %></TD> - <INPUT TYPE="hidden" NAME="<% $field %>" VALUE="<% $f->{'value'} %>"> + var rownum = <% $g_row %>; + var fieldnum = <% $fieldnum %>; -% } elsif ( $type eq 'fixedhidden' ) { + function spawn_<%$field%>(what) { - <INPUT TYPE="hidden" NAME="<% $field %>" VALUE="<% $f->{'value'} %>"> + // only spawn if we're the last element... return if not -% } elsif ( $type eq 'checkbox' ) { + var field_regex = /(\d+)$/; + var match = field_regex.exec(what.name); + if ( !match ) { + alert(what.name + " didn't match?!"); + return; + } + if ( match[1] != fieldnum ) { + return; + } - <TD> - <INPUT TYPE="checkbox" NAME="<% $field %>" VALUE="<% $f->{'value'} %>" <% $object->$field() eq $f->{'value'} ? ' CHECKED' : '' %>> - </TD> + // change the label on the last entry & add a remove button + var prev_label = document.getElementById('<% $field %>_label' + fieldnum ); + prev_label.innerHTML = '<INPUT TYPE="button" VALUE="X" TITLE="Remove this <% lc($f->{'m2name_label'}) %>" onClick="remove_<% $field %>(' + fieldnum + ');" STYLE="color:#ff0000;font-weight:bold;padding-left:2px;padding-right:2px" > <% $f->{'m2name_label'} || $field %>'; -% } elsif ( $type eq 'select' ) { + fieldnum++; - <TD> - <SELECT NAME="<% $field %>" -% my $aref = $f->{'value'}{'values'}; -% my $vkey = $f->{'value'}{'vcolumn'}; -% my $ckey = $f->{'value'}{'ccolumn'}; -% foreach my $v (@$aref) { - <OPTION <% ($object->$field() eq $v->$vkey) ? 'SELECTED' : '' %> - VALUE="<% $v->$vkey %>"><% $v->$ckey %></OPTION> -% } - </SELECT> - </TD> + //get the new widget -% } else { +% $include[0] =~ s(^/elements/tr-)(/elements/); +% my @layer_opt = ( @include, +% 'field' => $field."MAGIC_NUMBER", +% 'layer_prefix' => $field."MAGIC_NUMBER.", +% ); - <TD> - <INPUT TYPE="<% $type %>" NAME="<% $field %>" VALUE="<% $object->$field() %>"> - <TD> + var newrow = <% include(@layer_opt, html_only=>1) |js_string %>; -% } +% if ( $type eq 'selectlayers' ) { #until the rest have html/js_only + var newfunc = <% include(@layer_opt, js_only =>1) |js_string %>; +% } else { + var newfunc = ''; +% } + + // substitute in the new field name + var magic_regex = /MAGIC_NUMBER/g; + newrow = newrow.replace( magic_regex, fieldnum ); + newfunc = newfunc.replace( magic_regex, fieldnum ); + + // evaluate new_func + if (window.ActiveXObject) { + window.execScript(newfunc); + } else { /* (window.XMLHttpRequest) */ + //window.eval(newfunc); + setTimeout(newfunc, 0); + } + + // add new row + + var table = document.getElementById('OneTrueTable'); + + var row = table.insertRow(rownum++); + + var label_cell = document.createElement('TD'); - </TR> + label_cell.id = '<% $field %>_label' + fieldnum; + + label_cell.style.textAlign = "right"; + label_cell.style.verticalAlign = "top"; + label_cell.style.borderTop = "1px solid black"; + label_cell.style.paddingTop = "5px"; + + label_cell.innerHTML = '<% $label %>'; + + row.appendChild(label_cell); + + var widget_cell = document.createElement('TD'); + + widget_cell.style.borderTop = "1px solid black"; + widget_cell.style.paddingTop = "3px"; + + widget_cell.innerHTML = newrow; + + row.appendChild(widget_cell); + +% if ( $f->{'m2name_new_js'} ) { + // take out items selected in previous dropdowns + var new_element = document.getElementById("<%$field%>" + fieldnum ); + <% $f->{'m2name_new_js'} %>(new_element); + + if ( new_element.length < 2 ) { + //just the ** Select new **, so don't display the row + row.style.display = 'none'; + } +% } + + } + + function remove_<%$field%>(remove_fieldnum) { + //alert("remove <%$field%> " + remove_fieldnum); + var select = document.getElementById('<%$field%>' + remove_fieldnum); + +% my $warnings = $f->{'m2name_remove_warnings'}; +% if ( $warnings ) { + var sel_value = select.options[select.selectedIndex].value; +% foreach my $value ( keys %$warnings ) { + if ( sel_value == '<% $value %>' ) { + if ( ! confirm( <% $warnings->{$value} |js_string %> ) ) { + return; + } + } +% } +% } + + select.disabled = 'disabled'; // this seems to prevent it from being submitted on tested browsers so far (IE, moz, konq at least) + var label_td = document.getElementById('<%$field%>_label' + remove_fieldnum ); + label_td.parentNode.style.display = 'none'; + +% if ( $f->{m2name_remove_js} ) { + var opt = select.options[select.selectedIndex]; + <% $f->{m2name_remove_js} %>( opt.value, opt.text, 'no_match'); +% } + + } + + </SCRIPT> + +% } % } @@ -226,9 +418,105 @@ <BR> -<INPUT TYPE="submit" VALUE="<% $object->$pkey() ? "Apply changes" : "Add $opt{'name'}" %>"> +<INPUT TYPE="submit" ID="submit" VALUE="<% $object->$pkey() ? "Apply changes" : "Add $opt{'name'}" %>"> </FORM> <% include("/elements/footer.html") %> +<%init> + +my(%opt) = @_; + +my $curuser = $FS::CurrentUser::CurrentUser; + +#false laziness w/process.html +my $table = $opt{'table'}; +my $class = "FS::$table"; +my $pkey = dbdef->table($table)->primary_key; #? $opt{'primary_key'} || +my $fields = $opt{'fields'} + #|| [ grep { $_ ne $pkey } dbdef->table($table)->columns ]; + || [ grep { $_ ne $pkey } fields($table) ]; +#my @actualfields = map { ref($_) ? $_->{'field'} : $_ } @$fields; + +if ( $cgi->param('redirect') ) { + my $session = $cgi->param('redirect'); + my $pref = $curuser->option("redirect$session"); + die "unknown redirect session $session\n" unless length($pref); + $cgi = new CGI($pref); +} + +my $object; +my $mode; +if ( $cgi->param('error') ) { + + $mode = 'error'; + + + $object = $class->new( { + map { $_ => scalar($cgi->param($_)) } fields($table) + }); + + &{$opt{'error_callback'}}($cgi, $object, $fields) + if $opt{'error_callback'}; + +} elsif ( $cgi->keywords || $cgi->param($pkey) ) { #editing + + $mode = 'edit'; + + my $value; + if ( $cgi->param($pkey) ) { + $value = $cgi->param($pkey) + } else { + my( $query ) = $cgi->keywords; + $value = $query; + } + $value =~ /^(\d+)$/ or die "unparsable $pkey"; + $object = qsearchs({ + 'table' => $table, + 'hashref' => { $pkey => $1 }, + 'extra_sql' => ( $opt{'agent_virt'} + ? ' AND '. $curuser->agentnums_sql( + 'null_right' => $opt{'agent_null_right'} + ) + : '' + ), + }); + warn "$table $pkey => $1" + if $opt{'debug'}; + + &{$opt{'edit_callback'}}($cgi, $object, $fields) + if $opt{'edit_callback'}; + +} else { #adding + + $mode = 'new'; + + my $hashref = $opt{'new_hashref_callback'} + ? &{$opt{'new_hashref_callback'}} + : {}; + + $object = $class->new( $hashref ); + + &{$opt{'new_callback'}}($cgi, $object, $fields) + if $opt{'new_callback'}; + +} + +my $action = $object->$pkey() ? 'Edit' : 'Add'; + +my $title = "$action $opt{'name'}"; + +my $viewall_url = $p . ( $opt{'viewall_dir'} || 'search' ) . "/$table.html"; +$viewall_url = $opt{'viewall_url'} if $opt{'viewall_url'}; + +my @menubar = (); +if ( $opt{'menubar'} ) { + @menubar = @{ $opt{'menubar'} }; +} else { + @menubar = ( + #eventually use Lingua::bs to pluralize + "View all $opt{'name'}s" => $viewall_url, + ); +} +</%init> diff --git a/httemplate/edit/invoice_logo.html b/httemplate/edit/invoice_logo.html new file mode 100644 index 0000000..0c45e4b --- /dev/null +++ b/httemplate/edit/invoice_logo.html @@ -0,0 +1,136 @@ +<% include("/elements/header.html", "Edit $type2desc{$type} invoice logo", + menubar( + 'View all invoice templates' => $p.'browse/invoice_template.html' + ) + ) +%> + +% if ( $error ) { + <FONT SIZE="+1" COLOR="#ff0000">Error: <% $error %></FONT> + <BR><BR> +% } + +% if ( $cgi->param('msg') ) { + <FONT SIZE="+1"><B><% $cgi->param('msg') |h %></B></FONT> + <BR><BR> +% } + +% if ( $mode eq 'upload' ) { + <FORM ACTION="invoice_logo.html" METHOD="POST" ENCTYPE="multipart/form-data"> + <INPUT TYPE="hidden" NAME="mode" VALUE="preview"> +% } elsif ( $mode eq 'preview' ) { + <FORM ACTION="process/invoice_logo.html" METHOD="POST"> + <INPUT TYPE="hidden" NAME="preview_session" VALUE="<% $session %>"> +% } + +<INPUT TYPE="hidden" NAME="type" VALUE="<% $type %>"> +<INPUT TYPE="hidden" NAME="name" VALUE="<% $name %>"> + +<% include('/elements/table-grid.html') %> + +<TR> + <TH CLASS="grid" BGCOLOR="#cccccc">Current logo</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">New logo preview</TH> +</TR> + +<TR> + + <TD CLASS="grid" BGCOLOR="#ffffff"> + +% if ( $type eq 'png' ) { + + <IMG SRC="<% $p %>view/logo.cgi?type=png;name=<% $name %>"> + +% } elsif ( $type eq 'eps' ) { + + <i>EPS preview not yet supported</i> + +% } + + </TD> + + <TD CLASS="grid" BGCOLOR="#ffffff"> + +% if ( $mode eq 'upload' ) { + + Upload new logo (PNG format): <INPUT TYPE="file" NAME="new_logo"> + <BR><INPUT TYPE="submit" NAME="submit" VALUE="Upload"> + +% } elsif ( $mode eq 'preview' ) { + + <IMG SRC="<% $p %>view/logo.cgi?type=png;preview_session=<% $session %>"> + +% } + + </TD> + + +</TR> + +</TABLE> + +% if ( $mode eq 'preview' ) { + <BR> + <INPUT TYPE="submit" NAME="submit" VALUE="Change logo"> +% } + +</FORM> + +<% include("/elements/footer.html") %> + +<%once> + +my %type2desc = ( + 'png' => 'online', + 'eps' => 'Print/PDF (typeset)', +); + +</%once> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my $conf = new FS::Conf; + +my $type = $cgi->param('type'); + +$cgi->param('name') =~ /^([^\.\/]*)$/ or die "illegal name"; +my $name = $1; + +$cgi->param('mode') =~ /^(\w*)$/ or die "illegal mode"; +my $mode = $1 || 'upload'; + +my $error = ''; +my $session = ''; +if ( $mode eq 'preview' ) { + + my $fh = $cgi->upload('new_logo'); + + if ( defined $fh ) { + + local $/; + my $logo_data = <$fh>; + + $session = int(rand(4294967296)); #XXX + my $pref = new FS::access_user_pref({ + 'usernum' => $FS::CurrentUser::CurrentUser->usernum, + 'prefname' => "logo_preview$session", + 'prefvalue' => encode_base64($logo_data), + 'expiration' => time + 3600, #1h? 1m? + }); + my $pref_error = $pref->insert; + if ( $pref_error ) { + die "FATAL: couldn't set preview cookie: $pref_error\n"; + } + + } else { + + $mode = 'upload'; + $error = 'No file uploaded'; + + } + +} + +</%init> diff --git a/httemplate/edit/invoice_template.html b/httemplate/edit/invoice_template.html new file mode 100644 index 0000000..851ab5e --- /dev/null +++ b/httemplate/edit/invoice_template.html @@ -0,0 +1,80 @@ +<% include("/elements/header.html", "Edit $type2desc{$type} invoice template", + menubar( + 'View all invoice templates' => $p.'browse/invoice_template.html' + ) + ) +%> + +<FORM ACTION="process/invoice_template.html" METHOD="POST"> +<INPUT TYPE="hidden" NAME="confname" VALUE="<% $confname %>"> + +% if ( $type eq 'html' ) { + +% #init + <SCRIPT TYPE="text/javascript" src="<% $p %>elements/fckeditor/fckeditor.js"> + </SCRIPT> + +% #editor + <SCRIPT TYPE="text/javascript"> + var oFCKeditor = new FCKeditor('value'); + oFCKeditor.Value = <% $value |js_string %>; + + oFCKeditor.BasePath = '<% $p %>elements/fckeditor/'; + oFCKeditor.Config['SkinPath'] = '<% $p %>elements/fckeditor/editor/skins/silver/'; + oFCKeditor.Height = '800'; + oFCKeditor.Config['StartupFocus'] = true; + + oFCKeditor.Create(); + + </SCRIPT> + +% } else { + + <TEXTAREA NAME="value" ROWS=30 COLS=80 WRAP="off"><%$value |h %></TEXTAREA> + +% } + +<BR><BR> +<INPUT TYPE="submit" VALUE="Change template"> + +</FORM> + +<% include("/elements/footer.html") %> + +<%once> + +my %type2desc = ( + 'html' => 'HTML', + 'latex' => 'Print/PDF (typeset)', + 'text' => 'Plaintext', +); + +my %type2base = ( + 'html' => 'invoice_html', + 'latex' => 'invoice_latex', + 'text' => 'invoice_template', +); + +</%once> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my $type = $cgi->param('type'); +my $name = $cgi->param('name'); +my $suffix = $cgi->param('suffix'); + +#XXX type handling, just testing this out for now + +my $conf = new FS::Conf; + +my $value = length($name) + ? join("\n", $conf->config_orbase($type2base{$type}.$suffix, $name) ) + : join("\n", $conf->config($type2base{$type}.$suffix) ); + +my $confname = length($name) + ? $type2base{$type}.$suffix. '_'. $name + : $type2base{$type}.$suffix; + +</%init> diff --git a/httemplate/edit/part_bill_event.cgi b/httemplate/edit/part_bill_event.cgi index 0921a95..ff0e0a3 100755 --- a/httemplate/edit/part_bill_event.cgi +++ b/httemplate/edit/part_bill_event.cgi @@ -504,7 +504,14 @@ Invoice Event #<% $hashref->{eventpart} ? $hashref->{eventpart} : "(NEW)" %> <TABLE BGCOLOR="#cccccc" BORDER=0 WIDTH="100%"> <TR><TD> <TABLE BORDER=0 id="Ctable" style="display:<% $currentreasonclass eq 'C' ? 'inline' : 'none' %>"> -<% include('/elements/tr-select-reason.html', 'creason', 'C', $creason, $newcreasonT, $newcreason) %> +<% include('/elements/tr-select-reason.html', + 'field' => 'creason', + 'reason_class' => 'C', + 'curr_value' => $creason, + 'init_type' => $newcreasonT, + 'init_newreason' => $newcreason + ) +%> </TABLE> </TR></TD> </TABLE> @@ -512,7 +519,14 @@ Invoice Event #<% $hashref->{eventpart} ? $hashref->{eventpart} : "(NEW)" %> <TABLE BGCOLOR="#cccccc" BORDER=0 WIDTH="100%"> <TR><TD> <TABLE BORDER=0 id="Stable" style="display:<% $currentreasonclass eq 'S' ? 'inline' : 'none' %>"> -<% include('/elements/tr-select-reason.html', 'sreason', 'S', $sreason, $newsreasonT, $newsreason) %> +<% include('/elements/tr-select-reason.html', + 'field' => 'sreason', + 'reason_class' => 'S', + 'curr_value' => $sreason, + 'init_type' => $newsreasonT, + 'init_newreason' => $newsreason + ) +%> </TABLE> </TR></TD> </TABLE> diff --git a/httemplate/edit/part_event.html b/httemplate/edit/part_event.html new file mode 100644 index 0000000..c94da61 --- /dev/null +++ b/httemplate/edit/part_event.html @@ -0,0 +1,642 @@ +<% include( 'elements/edit.html', + 'name' => 'Billing event definition', + 'table' => 'part_event', + 'fields' => [ + 'event', + { field => 'eventtable', + type => 'select', + options => [ FS::part_event->eventtables ], + labels => $eventtable_labels, + onchange => 'eventtable_changed', + }, + { field => 'agentnum', + type => 'select-agent', + disable_empty => $disable_empty_agent, + }, + { field => 'check_freq', + type => 'select', + options => [ '1d', '1m' ], + labels => $check_freq_labels, + }, + { field => 'disabled', + type => 'checkbox', + value => 'Y', + }, + { type => 'title', + value => 'Event Conditions', + }, + { field => 'conditionname', + type => 'selectlayers', + options => [ keys %all_conditions ], + labels => \%condition_labels, + onchange => 'condition_changed(what);', + layer_fields => \%condition_fields, + layer_values_callback => $condition_layer_values, + html_between => n_a('action'), + m2name_table => 'part_event_condition', + m2name_namecol => 'conditionname', + m2name_label => 'Condition', + m2name_new_default => \@implicit_condition_objs, + m2name_error_callback => + $condition_error_callback, + m2name_remove_warnings => + \%condition_remove_warnings, + m2name_new_js => 'condition_repop', + m2name_remove_js => 'condition_add', + }, + { type => 'title', + value => 'Event Action', + }, + { field => 'action', + type => 'selectlayers', + options => [ keys %all_actions ], + labels => \%action_labels, + onchange => 'action_changed(what);', + layer_fields => \%action_fields, + layer_values_callback => $action_layer_values, + html_between => n_a('action'), + }, + + ], + 'labels' => { + 'eventpart' => 'Event', + 'event' => 'Event name', + 'eventtable' => 'Type', + 'agentnum' => 'Agent', + 'check_freq' => 'Check frequency', + 'disabled' => 'Disable event', + + 'conditionname' => 'Add new condition', + #'weight', + 'action' => 'Action', + }, + 'viewall_dir' => 'browse', + 'new_callback' => sub { #start empty for new events only + my( $cgi, $object, $fields_listref ) = @_; + unshift @{ $fields_listref->[1]{'options'} }, ''; + }, + 'error_callback' => $error_callback, + + 'agent_virt' => 1, + 'agent_null_right' => 'Edit global billing events', + ) +%> +<SCRIPT TYPE="text/javascript"> + + window.onload = function () { eventtable_changed(document.getElementById('eventtable')) }; + var notonload = 0; + + function eventtable_changed(what) { + +% if ( $JS_DEBUG ) { + alert('eventtable_changed called on ' + what ); +% } + + var eventtable = what.options[what.selectedIndex].value; + var eventdesc = what.options[what.selectedIndex].text; + + //remove the ** Select type ** + if ( what.options[0].value == '' && notonload++ > 0 ) { + what.options[0] = null; + } + + //// + // XXX gray out conditions that can't apply? + //// + + //// + // update condition selects + //// + + for ( var cnum=0; document.getElementById('conditionname'+cnum); cnum++ ) { + var cond_id = 'conditionname' + cnum; + var cond_select = document.getElementById(cond_id); + +% if ( $JS_DEBUG ) { + alert('updating ' + cond_id); +% } + + // save off the current value + var conditionname = cond_select.options[cond_select.selectedIndex].value; + var cond_desc = cond_select.options[cond_select.selectedIndex].text; + + var seen_condition = condition_repop(cond_select); + + var warning = document.getElementById(cond_id + '_warning'); +% if ( $JS_DEBUG ) { + alert('turning off warning; setting style.display of '+ cond_id + + '_warning (' + warning + ') to none'); +% } + warning.style.display = 'none'; + + if ( ! seen_condition && conditionname != '') { + // add the current (not valid) condition back + opt(cond_select, conditionname, cond_desc, true ); + if ( true <% @implicit_conditions + ? ( ' && '. join(' && ', map { "conditionname != '$_'" } + @implicit_conditions + ) + ) + : '' + %> ) { + // turn on a warning and gray out the condition row +% if ( $JS_DEBUG ) { + alert('turning on warning; setting style.display of '+ cond_id + + '_warning (' + warning + ') to none'); +% } + warning.innerHTML = 'Not applicable to ' + eventdesc + ' events'; + warning.style.display = ''; + } + } + + } + + + //// + // update action select + //// + + // save off the current value first!! + var action = what.form.action.options[what.form.action.selectedIndex].value; + var a_desc = what.form.action.options[what.form.action.selectedIndex].text; + var seen_action = false; + + // blank the current action select + for ( var i = what.form.action.length; i >= 0; i-- ) + what.form.action.options[i] = null; + + if ( action == '' ) { + opt(what.form.action, action, a_desc, true ); + } + + // repopulate it +% foreach my $eventtable ( FS::part_event->eventtables ) { +% tie my %actions, 'Tie::IxHash', FS::part_event->actions($eventtable); +% #use Data::Dumper; warn Dumper(%actions); + + if ( eventtable == '<% $eventtable %>' ) { + +% foreach my $action ( keys %actions ) { +% ( my $description = $actions{$action}->{'description'} ) =~ s/'/\\'/g; + + var sel = false; + if ( action == '<% $action %>' ) { + seen_action = true; + sel = true; + } + opt( what.form.action, '<% $action %>', '<% $description %>', sel ); +% } + + } + +% } + + // by default, turn off warnings and enable the submit button + var warning = document.getElementById('action_warning'); + warning.style.display = 'none'; + var submit_button = document.getElementById('submit'); + submit_button.disabled = ''; + + if ( ! seen_action && action != '' ) { + // add the current (not valid) action back + opt( what.form.action, action, a_desc, true ); + // turn on a warning and disable the submit button + //warning.innerHTML = a_desc + ' event not available as a ' + + warning.innerHTML = 'Not available as a ' + eventdesc + ' action'; + warning.style.display = ''; + submit_button.disabled = 'disabled'; + } + + } + + function opt(what,value,text,selected) { + var optionName = new Option(text, value, false, selected); + var length = what.length; + what.options[length] = optionName; + } + + function action_changed(what) { + // remove '** Select new **' + if ( what.options[0].value == '' ) { + what.options[0] = null; + } + // remove the warning, remove the invalid action, enable the submit button + var warning = document.getElementById('action_warning'); + if ( warning.style.display == '' ) { + warning.style.display = 'none'; + what.options[what.length-1] = null; + document.getElementById('submit').disabled = ''; + } + } + + function condition_changed(what) { + // remove '** Select new **' + if ( what.options[0].value == '' ) { + what.options[0] = null; + } + + var previousValue = what.getAttribute('previousValue'); + var previousText = what.getAttribute('previousText'); + var value = what.options[what.selectedIndex].value; + var text = what.options[what.selectedIndex].text; + +% foreach my $value ( keys %condition_remove_warnings ) { + if ( previousValue == '<% $value %>' ) { + if ( !confirm( <% $condition_remove_warnings{$value} |js_string %> ) ) { + for ( var i=0; i < what.length; i++ ) { + if ( what.options[i].value == previousValue ) { + what.selectedIndex = i; + } + } + return false; + } + } +% } + + //alert(previous + ' changed to ' + value); + + var field_regex = /(\d+)$/; + var match = field_regex.exec(what.name); + if ( !match ) { + alert(what.name + " didn't match?!"); + return; + } + + //add the previous condition *back* to all the other selects... + condition_add(previousValue, previousText, match[1]); + + what.setAttribute('previousValue', value); + what.setAttribute('previousText', text); + + // remove the new condition from all other selects + condition_remove(value, match[1]); + + } + + function condition_avail(check_cond, curnum) { + for ( var cnum=0; document.getElementById('conditionname'+cnum); cnum++ ) { + if ( cnum == curnum ) continue; + + var cond_id = 'conditionname' + cnum; + var cond_select = document.getElementById(cond_id); + + //alert("checking " + cond_id + " (" + cond_select.disabled + ")"); + + if ( cond_select.disabled ) continue; + + // the current value + var conditionname = cond_select.options[cond_select.selectedIndex].value; + + if ( check_cond == conditionname ) return false; + + } + + return true; + + } + + function condition_remove(remove_cond, curnum) { + + if ( remove_cond.length == 0 ) return; + + for ( var cnum=0; document.getElementById('conditionname'+cnum); cnum++ ) { + if ( cnum == curnum ) continue; + + var cond_id = 'conditionname' + cnum; + var cond_select = document.getElementById(cond_id); + + //for ( var i = cond_select.length; i >= 0; i-- ) { + for ( var i=0; i < cond_select.length; i++ ) { + if ( cond_select.options[i].value == remove_cond ) { + cond_select.options[i] = null; + } + } + + } + + } + + function condition_add(add_condname, add_conddesc, curnum) { + + if ( add_condname.length == 0 ) return; + + var eventtable_el = document.getElementById('eventtable'); + var eventtable = eventtable_el.options[eventtable_el.selectedIndex].value; + + var in_eventtable = false; + +% foreach my $eventtable ( FS::part_event->eventtables ) { +% tie my %conditions, 'Tie::IxHash', +% FS::part_event_condition->conditions($eventtable); + + if ( eventtable == '<% $eventtable %>' ) { + +% foreach my $conditionname ( keys %conditions ) { +% my $description = $conditions{$conditionname}->{'description'}; +% $description =~ s/'/\\'/g; + + if ( add_condname == '<% $conditionname %>' ) { + in_eventtable = true; + } + +% } + + } + +% } + + if ( ! in_eventtable ) return; + + for ( var cnum=0; document.getElementById('conditionname'+cnum); cnum++ ) { + if ( cnum == curnum ) continue; + + var cond_id = 'conditionname' + cnum; + var cond_select = document.getElementById(cond_id); + + if ( cond_select.disabled ) continue; + + //alert("adding " + add_condname + " to " + cond_id); + + opt(cond_select, add_condname, add_conddesc, false ); + + cond_select.parentNode.parentNode.style.display = ''; + + } + + } + + function condition_repop(cond_select) { + + var eventtable_el = document.getElementById('eventtable'); + var eventtable = eventtable_el.options[eventtable_el.selectedIndex].value; + + // save off the current value + var conditionname = cond_select.options[cond_select.selectedIndex].value; + var cond_desc = cond_select.options[cond_select.selectedIndex].text; + var seen_condition = false; + + if ( cond_select.disabled ) return false; //skip deleted conditions + + var field_regex = /(\d+)$/; + var match = field_regex.exec(cond_select.name); + if ( !match ) { + alert(what.name + " didn't match?!"); + return; + } + var cnum = match[1]; + + // blank the current condition select + for ( var i = cond_select.length; i >= 0; i-- ) + cond_select.options[i] = null; + + if ( conditionname == '' ) { + opt(cond_select, conditionname, cond_desc, true ); + } + + // repopulate it +% foreach my $eventtable ( FS::part_event->eventtables ) { +% tie my %conditions, 'Tie::IxHash', +% FS::part_event_condition->conditions($eventtable); + + if ( eventtable == '<% $eventtable %>' ) { + +% foreach my $conditionname ( keys %conditions ) { +% my $description = $conditions{$conditionname}->{'description'}; +% $description =~ s/'/\\'/g; + + var sel = false; + if ( conditionname == '<% $conditionname %>' ) { + seen_condition = true; + sel = true; + } + + if ( condition_avail("<% $conditionname %>", cnum) ) { + opt(cond_select, '<% $conditionname %>', '<% $description %>', sel); + } + +% } + + } + +% } + + if ( cond_select.length > 1 || cond_select.length == 1 && cond_select.options[0].value.length > 0 ) { + + cond_select.parentNode.parentNode.style.display = ''; + + } else { + cond_select.parentNode.parentNode.style.display = 'none'; + } + + return seen_condition; + + } + +</SCRIPT> +<%once> + +#misc (eventtable, check_freq) + +my $eventtable_labels = FS::part_event->eventtable_labels; +$eventtable_labels->{''} = '** Select type **'; + +my $check_freq_labels = FS::part_event->check_freq_labels; + +#conditions + +tie my %all_conditions, 'Tie::IxHash', + '' => { 'description' => '*** Select new condition ***', }, + FS::part_event_condition->conditions(); + +my %condition_labels = map { $_ => $all_conditions{$_}->{'description'} } + keys %all_conditions; + +#my %condition_fields = map { $_ => $all_conditions{$_}->{option_fields} } +# keys %all_conditions; +my %condition_fields = map { my $c = $_; + tie my %opts, 'Tie::IxHash', + @{ $all_conditions{$c}->{'option_fields'} || []}; + %opts = ( map { ( "$c.$_" => $opts{$_} ); } + keys %opts + ); + ( $c => [ %opts ] ); + } + keys %all_conditions; + +my @implicit_conditions = sort { $all_conditions{$a}->{'implicit_flag'} <=> + $all_conditions{$b}->{'implicit_flag'} + } + grep { $all_conditions{$_}->{'implicit_flag'} } + keys %all_conditions; + +my @implicit_condition_objs = map { + new FS::part_event_condition { + 'conditionname' => $_, + }; + } + @implicit_conditions; + +my %condition_remove_warnings = + map { ( $_ => $all_conditions{$_}->{'remove_warning'} ); } + grep { $all_conditions{$_}->{'remove_warning'} } + keys %all_conditions; + +#actions + +tie my %all_actions, 'Tie::IxHash', + '' => { 'description' => '*** Select event action ***', }, + FS::part_event->actions(); + +my %action_labels = map { $_ => $all_actions{$_}->{'description'} } + keys %all_actions; + +#my %action_fields = map { $_ => $all_actions{$_}->{option_fields} } +# keys %all_actions; +my %action_fields = map { my $action = $_; + tie my %opts, 'Tie::IxHash', + @{ $all_actions{$action}->{option_fields} || [] }; + %opts = ( map { ( "$action.$_" => $opts{$_} ); } + keys %opts + ); + ( $action => [ %opts ] ); + } + keys %all_actions; + +#subs + +sub n_a { + my $t = shift; + + return sub { + my $field = shift; + qq( <FONT ID="${field}_warning" STYLE="display:none" COLOR="#FF0000">). + "Party Party Join us Join us". + '</FONT>'; + }; +} + +my $action_layer_values = sub { + my( $cgi, $part_event ) = @_; + my $action = $cgi->param('action') || $part_event->action; + return {} unless $action; + scalar( #force hashref + { + #map { $_ => { $part_event->options } } + # keys %action_fields + map { my $action = $_; + my %fields = @{ $action_fields{$action} }; + my %obj_opts = $part_event->options; + %obj_opts = map { ( "$action.$_" => $obj_opts{$_} ); } + keys %obj_opts; + my %opts = + map { #false laziness w/process/part_event.html + my $option = $_; + my $value = scalar($cgi->param($_)) || $obj_opts{$_}; + + if ( $option =~ /^(.*)\.reasonnum$/ && $value == -1 ) { + $value = { + 'typenum' => scalar( $cgi->param( "new${option}T" ) ), + 'reason' => scalar( $cgi->param( "new${option}" ) ), + }; + } + + ( $option => $value ); + + } + keys %fields; + ( $action => \%opts ); + } + keys %action_fields + } + ); +}; + +tie my %cgi_conditions, 'Tie::IxHash'; + +my $error_callback = sub { + my( $cgi, $object, $fields_listref ) = @_; + + my @cond_params = grep /^conditionname\d+$/, $cgi->param; + + %cgi_conditions = map { + my $param = $_; + my $conditionname = $cgi->param($param); + $conditionname => { + map { + + my $cgi_key = $_; + $cgi_key =~ /^$param\.$conditionname\.(.*)$/ or die 'wtf!'; + my $key = $1; + #my $value = $cgi->param($_); + + #my $info = $all_conditions->{$conditionname} + my %cond_opts = + @{ $all_conditions{$conditionname}->{'option_fields'} || []}; + my $info = $cond_opts{$key}; + + my $value; + #false laziness w/process/part_event.html + if ( $info->{'type'} =~ /^(select|checkbox)-?multiple$/ + or $info->{'type'} =~ /^select/ && $info->{'multiple'} ) { + $value = { map { $_ => 1 } $cgi->param($cgi_key) }; + } elsif ( $info->{'type'} eq 'freq' ) { + $value = $cgi->param($cgi_key). $cgi->param($cgi_key.'_units'); + } else { + $value = $cgi->param($cgi_key); + } + + $key => $value; + + } grep /^$param\.$conditionname\./, $cgi->param + }; + } grep $cgi->param($_), grep /^conditionname\d+$/, $cgi->param; + +}; + +my $condition_error_callback = sub { + map { + new FS::part_event_condition { 'conditionname' => $_, }; + } keys %cgi_conditions; +}; + +my $condition_layer_values = sub { + #m2name_table option causes this to be + # part_event_condition instead of part_event + my ( $cgi, $part_event_condition, $switches ) = @_; + scalar( #force hashref + { + #map { $_ => { $part_event_condition->options } } + # keys %condition_fields + map { my $conditionname = $_; + my %opts = $switches->{'mode'} eq 'error' + ? %{ $cgi_conditions{$conditionname} || {} } + : $part_event_condition->options; + %opts = ( + map { ( "$conditionname.$_" => $opts{$_} ); } + keys %opts + ); + ( $conditionname => \%opts ); + } + keys %condition_fields + } + ); +}; + + +</%once> +<%init> + +my $curuser = $FS::CurrentUser::CurrentUser; + +die "access denied" + unless $curuser->access_right('Edit billing events') + || $curuser->access_right('Edit global billing events'); + +my $disable_empty_agent= ! $curuser->access_right('Edit global billing events'); + +%cgi_conditions = (); +my $use_cgi_conditions = 0; + +my $JS_DEBUG = 0; + +</%init> diff --git a/httemplate/edit/part_pkg.cgi b/httemplate/edit/part_pkg.cgi index bdd3f30..90e328d 100755 --- a/httemplate/edit/part_pkg.cgi +++ b/httemplate/edit/part_pkg.cgi @@ -89,7 +89,10 @@ Package information <INPUT TYPE="text" NAME="comment" SIZE=32 VALUE="<%$part_pkg->comment%>"> </TD> </TR> - <% include( '/elements/tr-select-pkg_class.html', $part_pkg->classnum ) %> + <% include( '/elements/tr-select-pkg_class.html', + 'curr_value' => $part_pkg->classnum, + ) + %> <TR> <TD ALIGN="right">Promotional code</TD> <TD> @@ -290,7 +293,7 @@ Reseller information % 'form_action' => 'process/part_pkg.cgi', % 'form_elements' => \@form_elements, % 'form_text' => [ qw(pkg comment promo_code clone pkgnum pkgpart), -% qw(pay_weight credit_weight), +% qw(pay_weight credit_weight), #keys(%weight), % @fixups, % ], % 'form_checkbox' => [ qw(setuptax recurtax disabled) ], diff --git a/httemplate/edit/part_referral.html b/httemplate/edit/part_referral.html index 7ce5217..f4572c0 100755 --- a/httemplate/edit/part_referral.html +++ b/httemplate/edit/part_referral.html @@ -1,9 +1,12 @@ <% include( 'elements/edit.html', 'name' => 'Advertising source', 'table' => 'part_referral', - 'fields' => [ 'referral' ], - 'labels' => { 'referral' => 'Advertising source' }, + 'fields' => [ 'referral', + { field=>'agentnum', type=>'select-agent', }, + ], + 'labels' => { 'referral' => 'Advertising source', + 'agentnum' => 'Agent', + }, 'viewall_dir' => 'browse', - 'html_table_bottom' => include('/elements/tr-select-agent.html'), ) %> diff --git a/httemplate/edit/process/access_group.html b/httemplate/edit/process/access_group.html index c803115..581b50f 100644 --- a/httemplate/edit/process/access_group.html +++ b/httemplate/edit/process/access_group.html @@ -10,6 +10,7 @@ 'num_col' => 'rightobjnum', 'name_col' => 'rightname', 'names_list' => [ FS::AccessRight->rights() ], + 'param_style' => 'link_table.value checkboxes', }, ) %> diff --git a/httemplate/edit/process/elements/process.html b/httemplate/edit/process/elements/process.html index e388c67..19d3fbe 100644 --- a/httemplate/edit/process/elements/process.html +++ b/httemplate/edit/process/elements/process.html @@ -1,111 +1,203 @@ -% -% -% # options example... -% # -% ### -% ##req -% ## -% # -% # 'table' => -% # -% # #? 'primary_key' => #required when the dbdef doesn't know...??? -% # #? 'fields' => [] -% # -% ### -% ##opt -% ### -% # -% # 'viewall_dir' => '', #'search' or 'browse', defaults to 'search' -% # OR -% # 'redirect' => 'view/table.cgi?', # value of primary key is appended -% # -% # 'error_redirect' => popurl(2).'edit/table.cgi?', #query string appended -% # -% # 'edit_ext' => 'html', #defaults to 'html', you might want 'cgi' while the -% # #naming is still inconsistent -% # -% # 'copy_on_empty' => [ 'old_field_name', 'another_old_field', ... ], -% # -% # 'clear_on_error' => [ 'form_field1', 'form_field2', ... ], -% # -% # 'process_m2m' => { 'link_table' => 'link_table_name', -% # 'target_table' => 'target_table_name', -% # }, -% # 'process_m2name' => { 'link_table' => 'link_table_name', -% # 'link_static' => { 'column' => 'value' }, -% # 'num_col' => 'column', #if column name is different in -% # #link_table than source_table -% # 'name_col' => 'name_column', -% # 'names_list' => [ 'list', 'names' ], -% # }, -% -% my(%opt) = @_; -% -% #false laziness w/edit.html -% my $table = $opt{'table'}; -% my $class = "FS::$table"; -% my $pkey = dbdef->table($table)->primary_key; #? $opt{'primary_key'} || -% my $fields = $opt{'fields'} -% #|| [ grep { $_ ne $pkey } dbdef->table($table)->columns ]; -% || [ fields($table) ]; -% -% my $pkeyvalue = $cgi->param($pkey); -% -% my $old = qsearchs( $table, { $pkey => $pkeyvalue } ) if $pkeyvalue; -% -% my $new = $class->new( { -% map { -% $_, scalar($cgi->param($_)); -% } @$fields -% } ); -% -% if ($old && exists($opt{'copy_on_empty'})) { -% foreach my $field (@{$opt{'copy_on_empty'}}) { -% $new->set($field, $old->get($field)) -% unless scalar($cgi->param($field)); -% } -% } -% -% my $error; -% if ( $pkeyvalue ) { -% $error = $new->replace($old); -% } else { -% $error = $new->insert; -% $pkeyvalue = $new->getfield($pkey); -% } -% -% if ( !$error && $opt{'process_m2m'} ) { -% $error = $new->process_m2m( %{ $opt{'process_m2m'} }, -% 'params' => scalar($cgi->Vars), -% ); -% } -% -% if ( !$error && $opt{'process_m2name'} ) { -% $error = $new->process_m2name( %{ $opt{'process_m2name'} }, -% 'params' => scalar($cgi->Vars), -% ); -% } -% -% # XXX print?!?! -% -% if ( $error ) { -% $cgi->param('error', $error); -% if (scalar(@{$opt{'clear_on_error'}})) { -% foreach my $field (@{$opt{'clear_on_error'}}) { -% $cgi->param($field, '') -% } -% } -% my $edit_ext = $opt{'edit_ext'} || 'html'; -% my $url = $opt{'error_redirect'} || popurl(2)."$table.$edit_ext?"; -% print $cgi->redirect($url. $cgi->query_string ); -% } elsif ( $opt{'redirect'} ) { -% print $cgi->redirect( $opt{'redirect'}. $pkeyvalue ); -% } else { -% print $cgi->redirect( popurl(3). -% ( $opt{'viewall_dir'} || 'search' ). -% "/$table.html" -% ); -% } -% -% +<%doc> +Example: + + include( 'elements/process.html', + + ### + # required + ### + + 'table' => 'tablename', + + #? 'primary_key' => #required when the dbdef doesn't know...??? + #? 'fields' => [] #"" + + ### + # optional + ### + + 'viewall_dir' => '', #'search' or 'browse', defaults to 'search' + OR + 'redirect' => 'view/table.cgi?', # value of primary key is appended + + 'error_redirect' => popurl(2).'edit/table.cgi?', #query string appended + + 'edit_ext' => 'html', #defaults to 'html', you might want 'cgi' while the + #naming is still inconsistent + + 'copy_on_empty' => [ 'old_field_name', 'another_old_field', ... ], + + 'clear_on_error' => [ 'form_field1', 'form_field2', ... ], + + 'process_m2m' => { 'link_table' => 'link_table_name', + 'target_table' => 'target_table_name', + }, + 'process_m2name' => { 'link_table' => 'link_table_name', + 'link_static' => { 'column' => 'value' }, + 'num_col' => 'column', #if column name is different in + #link_table than source_table + 'name_col' => 'name_column', + 'names_list' => [ 'list', 'names' ], + + 'param_style' => 'link_table.value checkboxes', + #or# + 'param_style' => 'name_colN values', + + + }, + + #supplies arguments to insert() and replace() + # for use with tables that are FS::option_Common + 'args_callback' => sub { my( $cgi, $object ) = @_; }, + + 'debug' => 1, #turns on debugging output + + #agent virtualization + 'agent_virt' => 1, + 'agent_null_right' => 'Access Right Name', + + ) + +</%doc> +<%once> + + my $me = 'process.html:'; + +</%once> +<%init> + +my(%opt) = @_; + +my $curuser = $FS::CurrentUser::CurrentUser; + +#false laziness w/edit.html +my $table = $opt{'table'}; +my $class = "FS::$table"; +my $pkey = dbdef->table($table)->primary_key; #? $opt{'primary_key'} || +my $fields = $opt{'fields'} + #|| [ grep { $_ ne $pkey } dbdef->table($table)->columns ]; + || [ fields($table) ]; + +my $pkeyvalue = $cgi->param($pkey); + +my $old = ''; +if ( $pkeyvalue ) { + $old = qsearchs({ + 'table' => $table, + 'hashref' => { $pkey => $pkeyvalue }, + 'extra_sql' => ( $opt{'agent_virt'} + ? ' AND '. $curuser->agentnums_sql( + 'null_right' => $opt{'agent_null_right'} + ) + : '' + ), + }); +} + +my %hash = map { $_ => scalar($cgi->param($_)) } @$fields; + +my $new = $class->new( \%hash ); + +if ( $opt{'agent_virt'} ) { + die "illegal agentnum" + unless $curuser->agentnums_href->{$new->agentnum} + or $opt{'agent_null_right'} + && ! $new->agentnum + && $curuser->access_right($opt{'agent_null_right'}); +} + +if ($old && exists($opt{'copy_on_empty'})) { + foreach my $field (@{$opt{'copy_on_empty'}}) { + $new->set($field, $old->get($field)) + unless scalar($cgi->param($field)); + } +} + +my $error = $new->check; + +my @args = (); +if ( !$error && $opt{'args_callback'} ) { + @args = &{ $opt{'args_callback'} }( $cgi, $new ); +} + +if ( !$error && $opt{'debug'} ) { + warn "$me updating record in $table table using $class class\n"; + warn Dumper(\%hash); + warn "with args: \n". Dumper(\@args) if @args; +} + +if ( !$error ) { + if ( $pkeyvalue ) { + $error = $new->replace($old, @args); + } else { + $error = $new->insert(@args); + $pkeyvalue = $new->getfield($pkey); + } +} + +if ( !$error && $opt{'process_m2m'} ) { + + if ( $opt{'debug'} ) { + warn "$me processing m2m:\n". Dumper( %{ $opt{'process_m2m'} }, + 'params' => scalar($cgi->Vars), + ); + } + + $error = $new->process_m2m( %{ $opt{'process_m2m'} }, + 'params' => scalar($cgi->Vars), + ); +} + +if ( !$error && $opt{'process_m2name'} ) { + + if ( $opt{'debug'} ) { + warn "$me processing m2name:\n". Dumper( %{ $opt{'process_m2name'} }, + 'params' => scalar($cgi->Vars), + ); + } + + $error = $new->process_m2name( %{ $opt{'process_m2name'} }, + 'params' => scalar($cgi->Vars), + ); +} + +# XXX print?!?! + +if ( $error ) { + $cgi->param('error', $error); + if ( $opt{'clear_on_error'} && scalar(@{$opt{'clear_on_error'}}) ) { + foreach my $field (@{$opt{'clear_on_error'}}) { + $cgi->param($field, '') + } + } + my $edit_ext = $opt{'edit_ext'} || 'html'; + my $url = $opt{'error_redirect'} || popurl(2)."$table.$edit_ext"; + if ( length($cgi->query_string) > 1920 ) { #stupid IE 2083 URL limit + + my $session = int(rand(4294967296)); #XXX + my $pref = new FS::access_user_pref({ + 'usernum' => $FS::CurrentUser::CurrentUser->usernum, + 'prefname' => "redirect$session", + 'prefvalue' => $cgi->query_string, + 'expiration' => time + 3600, #1h? 1m? + }); + my $pref_error = $pref->insert; + if ( $pref_error ) { + die "FATAL: couldn't even set redirect cookie: $pref_error". + " attempting to set redirect$session to ". $cgi->query_string."\n"; + } + print $cgi->redirect("$url?redirect=$session"); + } else { + print $cgi->redirect("$url?". $cgi->query_string ); + } +} elsif ( $opt{'redirect'} ) { + print $cgi->redirect( $opt{'redirect'}. $pkeyvalue ); +} else { + print $cgi->redirect( popurl(3). + ( $opt{'viewall_dir'} || 'search' ). + "/$table.html" + ); +} + +</%init> diff --git a/httemplate/edit/process/invoice_logo.html b/httemplate/edit/process/invoice_logo.html new file mode 100644 index 0000000..d641a99 --- /dev/null +++ b/httemplate/edit/process/invoice_logo.html @@ -0,0 +1,26 @@ +<%init> + +my $curuser = $FS::CurrentUser::CurrentUser; + +die "access denied" + unless $curuser->access_right('Configuration'); + +my $conf = new FS::Conf; + +$cgi->param('type') =~ /^(png|eps)$/ or die "illegal type"; +my $type = $1; + +$cgi->param('name') =~ /^([^\.\/]*)$/ or die "illegal name"; +my $tname = my $name = $1; +$tname = "_$tname" if length($tname); + +$cgi->param('preview_session') =~ /^(\w*)$/ or die "illegal preview_session"; +my $session = $1; +my $data = decode_base64( $curuser->option("logo_preview$session") ); + +$conf->set("logo$name.$type", $data); + +$cgi->redirect(popurl(3). "edit/invoice_logo.html?type=$type;name=$name;msg=Logo%20changed"); + +</%init> + diff --git a/httemplate/edit/process/invoice_template.html b/httemplate/edit/process/invoice_template.html new file mode 100644 index 0000000..6c9371a --- /dev/null +++ b/httemplate/edit/process/invoice_template.html @@ -0,0 +1,15 @@ +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my $conf = new FS::Conf; + +my $confname = $cgi->param('confname'); +my $value = $cgi->param('value'); + +$conf->set($confname, $value); + +$cgi->redirect(popurl(3). 'browse/invoice_template.html'); + +</%init> diff --git a/httemplate/edit/process/part_event.html b/httemplate/edit/process/part_event.html new file mode 100644 index 0000000..428025f --- /dev/null +++ b/httemplate/edit/process/part_event.html @@ -0,0 +1,86 @@ +<% include( 'elements/process.html', + #'debug' => 1, + 'table' => 'part_event', + 'viewall_dir' => 'browse', + 'process_m2name' => + { + 'link_table' => 'part_event_condition', + 'num_col' => 'eventpart', + 'name_col' => 'conditionname', + 'names_list' => [ FS::part_event_condition->all_conditionnames() ], + 'param_style' => 'name_colN values', + 'args_callback' => sub { # FS/FS/m2name_Common.pm + my( $object, $prefix, $params, $listref ) = @_; + #warn "$object $prefix $params $listref\n"; + + my $cond = $object->conditionname; + + my %option_fields = $object->option_fields; + + push @$listref, map { + my $field = $_; + + my $cgi_field = "$prefix$cond.$field"; + + my $value = $params->{$cgi_field}; + + my $info = $option_fields{$_}; + $info = { label=>$info, type=>'text' } + unless ref($info); + + if ( $info->{'type'} =~ + /^(select|checkbox)-?multiple$/ + or $info->{'type'} =~ /^select/ + && $info->{'multiple'} + ) + { + #special processing for compound fields + $value = { map { $_ => 1 } + split(/\0/, $value) + }; + } elsif ( $info->{'type'} eq 'freq' ) { + $value .= $params->{$cgi_field.'_units'}; + } + + #warn "value of $cgi_field is $value\n"; + + ( $field => $value ); + } + keys %option_fields; + }, + }, + + 'args_callback' => sub { + + my( $cgi, $object ) = @_; + + my $prefix = $object->action.'.'; + + map { my $option = $_; + #my $value = scalar( $cgi->param( "$prefix$option" ) ); + my $value = join(',', $cgi->param( "$prefix$option" ) ); + + if ( $option eq 'reasonnum' && $value == -1 ) { + $value = { + 'typenum' => scalar( $cgi->param( "new$prefix${option}T" ) ), + 'reason' => scalar( $cgi->param( "new$prefix${option}" ) ), + }; + } + + ( $option => $value ); + } + @{ $object->option_fields_listref }; + + }, + + 'agent_virt' => 1, + 'agent_null_right' => 'Edit global billing events', +) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Edit billing events') + || $FS::CurrentUser::CurrentUser->access_right('Edit global billing events'); + +</%init> diff --git a/httemplate/edit/process/quick-cust_pkg.cgi b/httemplate/edit/process/quick-cust_pkg.cgi index 7afc9f2..66d02e3 100644 --- a/httemplate/edit/process/quick-cust_pkg.cgi +++ b/httemplate/edit/process/quick-cust_pkg.cgi @@ -1,5 +1,3 @@ -% -% %#untaint custnum %$cgi->param('custnum') =~ /^(\d+)$/ % or die 'illegal custnum '. $cgi->param('custnum'); @@ -9,19 +7,21 @@ %my $pkgpart = $1; % %my @cust_pkg = (); -%my $error = FS::cust_pkg::order($custnum, [ $pkgpart ], [], \@cust_pkg, ); +%my $error = FS::cust_pkg::order($custnum, [ $pkgpart ], [], \@cust_pkg, [ $cgi->param('refnum') ] ); % %if ($error) { -% - -<!-- mason kludge --> -% -% eidiot($error); +% $cgi->param('error', $error); +% print $cgi->redirect(popurl(2). 'misc/order_pkg.html?'. $cgi->query_string ); %} else { -% print $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum". -% "#cust_pkg". $cust_pkg[0]->pkgnum ); -%} -% -% +% my $frag = "cust_pkg". $cust_pkg[0]->pkgnum; +<% header('Package ordered') %> + <SCRIPT TYPE="text/javascript"> + // XXX fancy ajax rebuild table at some point, but a page reload will do for now + // XXX chop off trailing #target and replace... ? + window.top.location = '<% popurl(3). "view/cust_main.cgi?keywords=$custnum;fragment=$frag#$frag" %>'; + </SCRIPT> + + </BODY></HTML> +%} diff --git a/httemplate/edit/reason.html b/httemplate/edit/reason.html index 7c0722c..c652a08 100644 --- a/httemplate/edit/reason.html +++ b/httemplate/edit/reason.html @@ -25,6 +25,8 @@ 'fields' => [ { 'field' => 'reason_type', 'type' => 'select', + #XXX use something more sane than a hashref + #then fix tr-select.html 'value' => { 'vcolumn' => 'typenum', 'ccolumn' => 'type', 'values' => \@types, @@ -32,7 +34,7 @@ }, 'reason', { 'field' => 'class', - 'type' => 'fixedhidden', + 'type' => 'hidden', 'value' => $class, }, { 'field' => 'disabled', |