diff options
Diffstat (limited to 'httemplate/edit/process')
94 files changed, 3948 insertions, 0 deletions
diff --git a/httemplate/edit/process/REAL_cust_pkg.cgi b/httemplate/edit/process/REAL_cust_pkg.cgi new file mode 100755 index 000000000..570f0e031 --- /dev/null +++ b/httemplate/edit/process/REAL_cust_pkg.cgi @@ -0,0 +1,49 @@ +%if ( $error ) { +% $cgi->param('error', $error); +<% $cgi->redirect(popurl(2). "REAL_cust_pkg.cgi?". $cgi->query_string ) %> +%} else { +% my $custnum = $new->custnum; +% my $show = $curuser->default_customer_view =~ /^(jumbo|packages)$/ +% ? '' +% : ';show=packages'; +% my $frag = "cust_pkg$pkgnum"; #hack for IE ignoring real #fragment +<% $cgi->redirect(popurl(3). "view/cust_main.cgi?custnum=$custnum$show;fragment=$frag#$frag" ) %> +%} +<%init> + +my $curuser = $FS::CurrentUser::CurrentUser; + +die "access denied" + unless $curuser->access_right('Edit customer package dates'); + +my $pkgnum = $cgi->param('pkgnum') or die; +my $old = qsearchs('cust_pkg',{'pkgnum'=>$pkgnum}); +my %hash = $old->hash; +$hash{$_}= $cgi->param($_) ? parse_datetime($cgi->param($_)) : '' + foreach qw( start_date setup bill last_bill adjourn expire ); + +my @errors = (); + +push @errors, '_bill_areyousure' + if $hash{'bill'} != $old->bill # if the next bill date was changed + && $hash{'bill'} < time # to a date in the past + && ! $cgi->param('bill_areyousure'); # and it wasn't confirmed + +push @errors, '_setup_areyousure' + if ! $hash{'setup'} && $old->setup # if the setup date was removed + && ! $cgi->param('setup_areyousure'); # and it wasn't confirmed + +push @errors, '_start' + if $hash{'start_date'} && !$old->start_date # if a start date was added + && $hash{'setup'}; # but there's a setup date + +my $new; +my $error; +if ( @errors ) { + $error = join(',', @errors); +} else { + $new = new FS::cust_pkg \%hash; + $error = $new->replace($old); +} + +</%init> diff --git a/httemplate/edit/process/access_group.html b/httemplate/edit/process/access_group.html new file mode 100644 index 000000000..2d125c387 --- /dev/null +++ b/httemplate/edit/process/access_group.html @@ -0,0 +1,27 @@ +<% include( 'elements/process.html', + 'table' => 'access_group', + 'viewall_dir' => 'browse', + 'process_m2m' => { 'link_table' => 'access_groupagent', + 'target_table' => 'agent', + }, + 'process_m2name' => { + 'link_table' => 'access_right', + 'link_static' => { 'righttype' => 'FS::access_group', }, + 'num_col' => 'rightobjnum', + 'name_col' => 'rightname', + 'names_list' => [ FS::AccessRight->rights() ], + 'param_style' => 'link_table.value checkboxes', + }, + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +if ( FS::Conf->new->exists('disable_acl_changes') ) { + errorpage('ACL changes disabled in public demo.'); + die "shouldn't be reached"; +} + +</%init> diff --git a/httemplate/edit/process/access_user.html b/httemplate/edit/process/access_user.html new file mode 100644 index 000000000..e6258a9b1 --- /dev/null +++ b/httemplate/edit/process/access_user.html @@ -0,0 +1,26 @@ +% if ( $cgi->param('_password') ne $cgi->param('_password2') ) { +% $cgi->param('error', "The passwords do not match"); +% print $cgi->redirect(popurl(2) . "access_user.html?" . $cgi->query_string); +% } else { +<% include( 'elements/process.html', + 'table' => 'access_user', + 'viewall_dir' => 'browse', + 'copy_on_empty' => [ '_password' ], + 'clear_on_error' => [ '_password', '_password2' ], + 'process_m2m' => { 'link_table' => 'access_usergroup', + 'target_table' => 'access_group', + }, + ) +%> +% } +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +if ( FS::Conf->new->exists('disable_acl_changes') ) { + errorpage('ACL changes disabled in public demo.'); + die "shouldn't be reached"; +} + +</%init> diff --git a/httemplate/edit/process/acct_snarf.html b/httemplate/edit/process/acct_snarf.html new file mode 100644 index 000000000..332ac5228 --- /dev/null +++ b/httemplate/edit/process/acct_snarf.html @@ -0,0 +1,20 @@ +<% include( 'elements/process.html', + 'table' => 'acct_snarf', + 'redirect' => $redirect, + 'noerror_callback' => sub { + my( $cgi, $object ) = @_; + my $error = $object->svc_export; + #shit, not a good place for error handling :/ + die $error if $error; + }, + ) +%> +<%init> + +my $redirect = sub { + my($cgi, $new) = @_; + my $svcnum = $new->svcnum; + popurl(3)."browse/acct_snarf.html?svcnum=$svcnum;snarfnum="; +}; + +</%init> diff --git a/httemplate/edit/process/addr_block/add.cgi b/httemplate/edit/process/addr_block/add.cgi new file mode 100755 index 000000000..39d6348ce --- /dev/null +++ b/httemplate/edit/process/addr_block/add.cgi @@ -0,0 +1,20 @@ +<% include( '../elements/process.html', + 'table' => 'addr_block', + 'redirect' => popurl(4). 'browse/addr_block.cgi?dummy=', + 'error_redirect' => popurl(4). 'browse/addr_block.cgi?', + 'agent_virt' => 1, + 'agent_null_right' => 'Broadband global configuration', + + ) +%> +<%init> + +my $curuser = $FS::CurrentUser::CurrentUser; +die "access denied" + unless $curuser->access_right('Broadband configuration') + || $curuser->access_right('Broadband global configuration'); + +$cgi->param('routernum', 0) # in FS::addr_block::check instead? + unless $cgi->param('routernum'); + +</%init> diff --git a/httemplate/edit/process/addr_block/allocate.cgi b/httemplate/edit/process/addr_block/allocate.cgi new file mode 100755 index 000000000..40d04b369 --- /dev/null +++ b/httemplate/edit/process/addr_block/allocate.cgi @@ -0,0 +1,16 @@ +<% include( '../elements/process.html', + 'table' => 'addr_block', + 'copy_on_empty' => [ fields 'addr_block' ], + 'error_redirect' => popurl(3). 'allocate.html?', + 'popup_reload' => 'Block allocated', + ) +%> +<%init> + +my $conf = new FS::Conf; +my $curuser = $FS::CurrentUser::CurrentUser; +die "access denied" + unless $curuser->access_right('Broadband configuration') + || $curuser->access_right('Broadband global configuration'); + +</%init> diff --git a/httemplate/edit/process/addr_block/deallocate.cgi b/httemplate/edit/process/addr_block/deallocate.cgi new file mode 100755 index 000000000..128824ec7 --- /dev/null +++ b/httemplate/edit/process/addr_block/deallocate.cgi @@ -0,0 +1,20 @@ +<% include( '../elements/process.html', + 'table' => 'addr_block', + 'copy_on_empty' => [ grep { $_ ne 'routernum' } + fields 'addr_block' ], + 'redirect' => popurl(4). 'browse/addr_block.cgi?', + 'error_redirect' => popurl(4). 'browse/addr_block.cgi?', + 'agent_virt' => 1, + 'agent_null_right' => 'Broadband global configuration', + ) +%> +<%init> + +my $conf = new FS::Conf; +my $curuser = $FS::CurrentUser::CurrentUser; +die "access denied" + unless $curuser->access_right('Broadband configuration') + || $curuser->access_right('Broadband global configuration'); + +$cgi->param('routernum', 0); # just to be explicit about what we are doing +</%init> diff --git a/httemplate/edit/process/addr_block/manual_flag.cgi b/httemplate/edit/process/addr_block/manual_flag.cgi new file mode 100755 index 000000000..dc0cbbbf5 --- /dev/null +++ b/httemplate/edit/process/addr_block/manual_flag.cgi @@ -0,0 +1,30 @@ +<% $cgi->redirect(popurl(4). "browse/addr_block.cgi?". $cgi->query_string ) %> +<%init> + +my $curuser = $FS::CurrentUser::CurrentUser; + +die "access denied" + unless $curuser->access_right('Broadband configuration') + || $curuser->access_right('Broadband global configuration'); + +my $error = ''; +$cgi->param('blocknum') =~ /^(\d+)$/ or die "invalid blocknum"; +my $blocknum = $1; + +my $addr_block = qsearchs({ 'table' => 'addr_block', + 'hashref' => { blocknum => $blocknum }, + 'extra_sql' => ' AND '. $curuser->agentnums_sql( + 'null_right' => 'Broadband global configuration' + ), + }) + or $error = "Unknown blocknum: $blocknum"; + +$addr_block->manual_flag($cgi->param('manual_flag')) + unless $error; + +$error ||= $addr_block->replace; + +$cgi->param('error', $error) + if $error; + +</%init> diff --git a/httemplate/edit/process/addr_block/split.cgi b/httemplate/edit/process/addr_block/split.cgi new file mode 100755 index 000000000..045fd30de --- /dev/null +++ b/httemplate/edit/process/addr_block/split.cgi @@ -0,0 +1,27 @@ +<% $cgi->redirect(popurl(4). "browse/addr_block.cgi?". $cgi->query_string ) %> +<%init> + +my $curuser = $FS::CurrentUser::CurrentUser; + +die "access denied" + unless $curuser->access_right('Broadband configuration') + || $curuser->access_right('Broadband global configuration'); + +my $error = ''; +$cgi->param('blocknum') =~ /^(\d+)$/ or die "invalid blocknum"; +my $blocknum = $1; + +my $addr_block = qsearchs({ 'table' => 'addr_block', + 'hashref' => { blocknum => $blocknum }, + 'extra_sql' => ' AND '. $curuser->agentnums_sql( + 'null_right' => 'Broadband global configuration' + ), + }) + or $error = "Unknown blocknum: $blocknum"; + +$error ||= $addr_block->split_block; + +$cgi->param('error', $error) + if $error; + +</%init> diff --git a/httemplate/edit/process/agent.cgi b/httemplate/edit/process/agent.cgi new file mode 100755 index 000000000..e776d281c --- /dev/null +++ b/httemplate/edit/process/agent.cgi @@ -0,0 +1,21 @@ +<% include( 'elements/process.html', + 'table' => 'agent', + 'viewall_dir' => 'browse', + 'viewall_ext' => 'cgi', + 'process_m2m' => { 'link_table' => 'access_groupagent', + 'target_table' => 'access_group', + }, + 'edit_ext' => 'cgi', + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +if ( FS::Conf->new->exists('disable_acl_changes') ) { + errorpage('ACL changes disabled in public demo.'); + die "shouldn't be reached"; +} + +</%init> diff --git a/httemplate/edit/process/agent_payment_gateway.html b/httemplate/edit/process/agent_payment_gateway.html new file mode 100644 index 000000000..5b5fd948a --- /dev/null +++ b/httemplate/edit/process/agent_payment_gateway.html @@ -0,0 +1,29 @@ +<% $cgi->redirect(popurl(3). "browse/agent.cgi") %> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +$cgi->param('agentnum') =~ /(\d+)$/ or die "illegal agentnum"; +my $agent = qsearchs('agent', { 'agentnum' => $1 } ); +die "agentnum $1 not found" unless $agent; + +#my $old + +my @new = map { + my $cardtype = $_; + new FS::agent_payment_gateway { + ( map { $_ => scalar($cgi->param($_)) } + fields('agent_payment_gateway') + ), + 'cardtype' => $cardtype, + }; + } + $cgi->param('cardtype'); + +foreach my $new (@new) { + my $error = $new->insert; + die $error if $error; +} + +</%init> diff --git a/httemplate/edit/process/agent_type.cgi b/httemplate/edit/process/agent_type.cgi new file mode 100755 index 000000000..ad5963b31 --- /dev/null +++ b/httemplate/edit/process/agent_type.cgi @@ -0,0 +1,35 @@ +%if ( $error ) { +% $cgi->param('error', $error); +<% $cgi->redirect(popurl(2). "agent_type.cgi?". $cgi->query_string ) %> +%} else { +<% $cgi->redirect(popurl(3). "browse/agent_type.cgi") %> +%} +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my $typenum = $cgi->param('typenum'); +my $old = qsearchs('agent_type',{'typenum'=>$typenum}) if $typenum; + +my $new = new FS::agent_type ( { + map { + $_, scalar($cgi->param($_)); + } fields('agent_type') +} ); + +my $error; +if ( $typenum ) { + $error = $new->replace($old); +} else { + $error = $new->insert; + $typenum = $new->getfield('typenum'); +} + + $error ||= $new->process_m2m( + 'link_table' => 'type_pkgs', + 'target_table' => 'part_pkg', + 'params' => scalar($cgi->Vars) + ); + +</%init> diff --git a/httemplate/edit/process/bulk-cust_main_county.html b/httemplate/edit/process/bulk-cust_main_county.html new file mode 100644 index 000000000..af9e49500 --- /dev/null +++ b/httemplate/edit/process/bulk-cust_main_county.html @@ -0,0 +1,66 @@ +% if ( $error ) { #better to redirect back to +%# <% $cgi->redirect("$url?". $cgi->query_string ) %> + <% include('/elements/header-popup.html', "Error ${action}ing taxes" ) %> + + <FONT SIZE="+1" COLOR="#ff0000">Error: <% $error |h %></FONT> + <BR><BR> + + </BODY> + </HTML> + +% } else { + <% include('/elements/header-popup.html', "Taxes ${action}ed") %> + + <SCRIPT TYPE="text/javascript"> + window.top.location.reload(); + </SCRIPT> + + </BODY> + </HTML> +% } +<%init> + +$cgi->param('taxnum') =~ /^([\d,]+)$/ + or die 'Guru Meditation #69'; #??? should have been passed in +my @taxnum = split(',', $1); + +$cgi->param('action') =~ /^(add|edit)$/ or die "unknown action"; +my $action = $1; + +my $error = ''; +foreach my $taxnum ( @taxnum ) { + + my $cust_main_county = qsearchs('cust_main_county', { 'taxnum' => $taxnum } ) + or die "unknown taxnum: $taxnum"; + + if ( $action eq 'edit' || $cust_main_county->tax == 0 ) { #let's replace + + foreach (qw( taxname tax exempt_amount setuptax recurtax )) { + $cust_main_county->set( $_ => scalar($cgi->param($_)) ) + } + + $error = $cust_main_county->replace and last; + + } else { #let's insert a new record + + my $new = + new FS::cust_main_county { + ( map { $_ => scalar($cgi->param($_)) } + qw( taxname tax exempt_amount setuptax recurtax ) + ), + ( map { $_ => $cust_main_county->get($_) } + qw( country state county taxclass ) + ) + }; + + $error = $new->insert and last; + + } + +} + +if ( $error ) { + $cgi->param('error', $error); +} + +</%init> diff --git a/httemplate/edit/process/bulk-cust_svc.cgi b/httemplate/edit/process/bulk-cust_svc.cgi new file mode 100644 index 000000000..313b061ff --- /dev/null +++ b/httemplate/edit/process/bulk-cust_svc.cgi @@ -0,0 +1,9 @@ +<% $server->process %> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my $server = new FS::UI::Web::JSRPC 'FS::part_svc::process_bulk_cust_svc', $cgi; + +</%init> diff --git a/httemplate/edit/process/cgp_rule-redirect_all.html b/httemplate/edit/process/cgp_rule-redirect_all.html new file mode 100644 index 000000000..162d857c2 --- /dev/null +++ b/httemplate/edit/process/cgp_rule-redirect_all.html @@ -0,0 +1,24 @@ +<% include('cgp_rule-simplified.html', + 'name' => '#Redirect', + 'priority' => 1, + 'redirect' => 'cgp_rule-redirect_all.html', + 'conditions' => [ + ( $cgi->param('RedirHuman') + ? { conditionname => 'Human Generated', } + : () + ), + ], + 'actions' => [ + { action => ( $cgi->param('KeepToAndCc') + ? 'Mirror To' + : 'Redirect To' + ), + params => scalar($cgi->param('RedirectText')), + }, + ( $cgi->param('RedirKeep') + ? () + : ( { 'action' => 'Discard' } ) + ), + ], + ) +%> diff --git a/httemplate/edit/process/cgp_rule-simplified.html b/httemplate/edit/process/cgp_rule-simplified.html new file mode 100644 index 000000000..60769d4e6 --- /dev/null +++ b/httemplate/edit/process/cgp_rule-simplified.html @@ -0,0 +1,53 @@ +% if ( $error ) { #redirect back to edit... +% $cgi->param('error', $error); +<% $cgi->redirect(popurl(3).'edit/'.$opt{'redirect'}.'?'. $cgi->query_string) %> +% } else { #success XXX better msg talking about vacation vs. redirect all + <% include('/elements/header-popup.html', 'Rule updated') %> + <SCRIPT TYPE="text/javascript"> + window.top.location.reload(); + </SCRIPT> + + </BODY> + </HTML> +% } +<%init> + +my %opt = @_; + +my %hash = ( + 'svcnum' => scalar($cgi->param('svcnum')), + 'name' => $opt{'name'}, +); + +my $cgp_rule = qsearchs('cgp_rule', \%hash); + +my $error = ''; +if ( $cgp_rule ) { #updating + $error = $cgp_rule->delete; +} + +$cgp_rule = new FS::cgp_rule { %hash, 'priority' => $opt{'priority'} }; +$error ||= $cgp_rule->insert; + +foreach my $condition ( @{ $opt{'conditions'} } ) { + my $cgp_rule_condition = new FS::cgp_rule_condition { + %$condition, + 'rulenum' => $cgp_rule->rulenum, + }; + $error ||= $cgp_rule_condition->insert; +} + +foreach my $action ( @{ $opt{'actions'} } ) { + my $cgp_rule_action = new FS::cgp_rule_action { + %$action, + 'rulenum' => $cgp_rule->rulenum, + }; + $error ||= $cgp_rule_action->insert; +} + +unless ( $error ) { + my $export_error = $cgp_rule->svc_export; + die $export_error if $export_error; #error handling sucks wrt this... shouldn't happen though +} + +</%init> diff --git a/httemplate/edit/process/cgp_rule-vacation.html b/httemplate/edit/process/cgp_rule-vacation.html new file mode 100644 index 000000000..f10d72b73 --- /dev/null +++ b/httemplate/edit/process/cgp_rule-vacation.html @@ -0,0 +1,29 @@ +<% include('cgp_rule-simplified.html', + 'name' => '#Vacation', + 'priority' => 2, + 'redirect' => 'cgp_rule-vacation.html', + 'conditions' => [ + { conditionname => 'Human Generated', }, + { conditionname => 'From', + op => 'not in', + params => '#RepliedAddresses', + }, + ( $cgi->param('VacationTill') + ? ( { conditionname => 'Current Date', + op => 'less than', #is less? + params => scalar($cgi->param('VacationTill')), + } + ) + : () + ), + ], + 'actions' => [ + { action => 'Reply with', + params => scalar($cgi->param('VacationText')), + }, + { action => "Remember 'From' in", + params => 'RepliedAddresses', + }, + ], + ) +%> diff --git a/httemplate/edit/process/cgp_rule.html b/httemplate/edit/process/cgp_rule.html new file mode 100644 index 000000000..5326587cb --- /dev/null +++ b/httemplate/edit/process/cgp_rule.html @@ -0,0 +1,30 @@ +<% include( 'elements/process.html', + 'table' => 'cgp_rule', + 'redirect' => $redirect, + 'process_o2m' => [ + { + 'table' => 'cgp_rule_condition', + 'fields' => [qw( conditionname op params )], + }, + { + 'table' => 'cgp_rule_action', + 'fields' => [qw( action params )], + }, + ], + 'noerror_callback' => sub { + my( $cgi, $object ) = @_; + my $error = $object->svc_export; + #shit, not a good place for error handling :/ + die $error if $error; + }, + ) +%> +<%init> + +my $redirect = sub { + my($cgi, $new) = @_; + my $svcnum = $new->svcnum; + popurl(3)."browse/cgp_rule.html?svcnum=$svcnum;rulenum="; +}; + +</%init> diff --git a/httemplate/edit/process/change-cust_pkg.html b/httemplate/edit/process/change-cust_pkg.html new file mode 100644 index 000000000..7356e6122 --- /dev/null +++ b/httemplate/edit/process/change-cust_pkg.html @@ -0,0 +1,46 @@ +% if ($error) { +% $cgi->param('error', $error); +% $cgi->redirect(popurl(3). 'misc/change_pkg.cgi?'. $cgi->query_string ); +% } else { + + <% header("Package changed") %> + <SCRIPT TYPE="text/javascript"> + window.top.location.reload(); + </SCRIPT> + </BODY> + </HTML> + +% } +<%init> + +my $curuser = $FS::CurrentUser::CurrentUser; + +die "access denied" + unless $curuser->access_right('Change customer package'); + +my $cust_pkg = qsearchs({ + #'select' => 'cust_pkg.*', + 'table' => 'cust_pkg', + 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )', + 'hashref' => { 'pkgnum' => scalar($cgi->param('pkgnum')), }, + 'extra_sql' => ' AND '. $curuser->agentnums_sql, +}); +die 'unknown pkgnum' unless $cust_pkg; + +my %change = map { $_ => scalar($cgi->param($_)) } + qw( locationnum pkgpart ); + +if ( $cgi->param('locationnum') == -1 ) { + my $cust_location = new FS::cust_location { + 'custnum' => $cust_pkg->custnum, + map { $_ => scalar($cgi->param($_)) } + qw( address1 address2 city county state zip country ) + }; + $change{'cust_location'} = $cust_location; +} + +my $pkg_or_error = $cust_pkg->change( \%change ); + +my $error = ref($pkg_or_error) ? '' : $pkg_or_error; + +</%init> diff --git a/httemplate/edit/process/cust_bill_pay.cgi b/httemplate/edit/process/cust_bill_pay.cgi new file mode 100755 index 000000000..2845d3233 --- /dev/null +++ b/httemplate/edit/process/cust_bill_pay.cgi @@ -0,0 +1,13 @@ +<% include('elements/ApplicationCommon.html', + 'error_redirect' => 'cust_bill_pay.cgi', + 'src_table' => 'cust_pay', + 'src_thing' => 'payment', + 'link_table' => 'cust_bill_pay', + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Apply payment'); + +</%init> diff --git a/httemplate/edit/process/cust_category.html b/httemplate/edit/process/cust_category.html new file mode 100644 index 000000000..c3a880944 --- /dev/null +++ b/httemplate/edit/process/cust_category.html @@ -0,0 +1,11 @@ +<% include( 'elements/process.html', + 'table' => 'cust_category', + 'viewall_dir' => 'browse', + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +</%init> diff --git a/httemplate/edit/process/cust_class.html b/httemplate/edit/process/cust_class.html new file mode 100644 index 000000000..3f63ea4b3 --- /dev/null +++ b/httemplate/edit/process/cust_class.html @@ -0,0 +1,11 @@ +<% include( 'elements/process.html', + 'table' => 'cust_class', + 'viewall_dir' => 'browse', + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +</%init> diff --git a/httemplate/edit/process/cust_credit.cgi b/httemplate/edit/process/cust_credit.cgi new file mode 100755 index 000000000..8715ad61e --- /dev/null +++ b/httemplate/edit/process/cust_credit.cgi @@ -0,0 +1,63 @@ +%if ( $error ) { +% $cgi->param('reasonnum', $reasonnum); +% $cgi->param('error', $error); +% $dbh->rollback if $oldAutoCommit; +% +<% $cgi->redirect(popurl(2). "cust_credit.cgi?". $cgi->query_string ) %> +% +%} else { +% +% if ( $cgi->param('apply') eq 'yes' ) { +% my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum }) +% or die "unknown custnum $custnum"; +% $cust_main->apply_credits; +% } +% #print $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum"); +% +% $dbh->commit or die $dbh->errstr if $oldAutoCommit; +% +<% header('Credit sucessful') %> + <SCRIPT TYPE="text/javascript"> + window.top.location.reload(); + </SCRIPT> + + </BODY></HTML> +% } +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Post credit'); + +$cgi->param('custnum') =~ /^(\d*)$/ or die "Illegal custnum!"; +my $custnum = $1; + +$cgi->param('reasonnum') =~ /^(-?\d+)$/ or die "Illegal reasonnum"; +my $reasonnum = $1; + +my $oldAutoCommit = $FS::UID::AutoCommit; +local $FS::UID::AutoCommit = 0; +my $dbh = dbh; + +my $error = ''; +if ($reasonnum == -1) { + + $error = 'Enter a new reason (or select an existing one)' + unless $cgi->param('newreasonnum') !~ /^\s*$/; + my $reason = new FS::reason({ 'reason_type' => $cgi->param('newreasonnumT'), + 'reason' => $cgi->param('newreasonnum'), + }); + $error ||= $reason->insert; + $cgi->param('reasonnum', $reason->reasonnum) + unless $error; +} + +unless ($error) { + my $new = new FS::cust_credit ( { + map { + $_, scalar($cgi->param($_)); + } fields('cust_credit') + } ); + $error = $new->insert; +} + +</%init> diff --git a/httemplate/edit/process/cust_credit_bill.cgi b/httemplate/edit/process/cust_credit_bill.cgi new file mode 100755 index 000000000..d3847dc40 --- /dev/null +++ b/httemplate/edit/process/cust_credit_bill.cgi @@ -0,0 +1,19 @@ +<% include('elements/ApplicationCommon.html', + 'error_redirect' => 'cust_credit_bill.cgi', + 'src_table' => 'cust_credit', + 'src_thing' => 'credit', + 'link_table' => 'cust_credit_bill', + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Apply credit'); + +if ( $cgi->param('src_amount') ) { + die "access denied" + unless ( $FS::CurrentUser::CurrentUser->access_right('Post credit') && + $FS::CurrentUser::CurrentUser->access_right('Delete credit') ); +} + +</%init> diff --git a/httemplate/edit/process/cust_credit_refund.cgi b/httemplate/edit/process/cust_credit_refund.cgi new file mode 100755 index 000000000..88420f8ab --- /dev/null +++ b/httemplate/edit/process/cust_credit_refund.cgi @@ -0,0 +1,13 @@ +<% include('elements/ApplicationCommon.html', + 'error_redirect' => 'cust_credit_refund.cgi', + 'src_table' => 'cust_credit', + 'src_thing' => 'credit', + 'link_table' => 'cust_credit_refund', + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Apply credit'); + +</%init> diff --git a/httemplate/edit/process/cust_main.cgi b/httemplate/edit/process/cust_main.cgi new file mode 100755 index 000000000..24cecea64 --- /dev/null +++ b/httemplate/edit/process/cust_main.cgi @@ -0,0 +1,271 @@ +% if ( $error ) { +% $cgi->param('error', $error); +% +<% $cgi->redirect(popurl(2). "cust_main.cgi?". $cgi->query_string ) %> +% +% } else { +% +<% $cgi->redirect(popurl(3). "view/cust_main.cgi?". $new->custnum) %> +% +% } +<%once> + +my $me = '[edit/process/cust_main.cgi]'; +my $DEBUG = 0; + +</%once> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Edit customer'); + +my $conf = new FS::Conf; + +my $error = ''; + +#unmunge stuff + +$cgi->param('tax','') unless defined $cgi->param('tax'); + +$cgi->param('refnum', (split(/:/, ($cgi->param('refnum'))[0] ))[0] ); + +my $payby = $cgi->param('payby'); + +my %noauto = ( + 'CARD' => 'DCRD', + 'CHEK' => 'DCHK', +); +$payby = $noauto{$payby} + if ! $cgi->param('payauto') && exists $noauto{$payby}; + +$cgi->param('payby', $payby); + +if ( $payby ) { + if ( $payby eq 'CHEK' || $payby eq 'DCHK' ) { + $cgi->param('payinfo', + $cgi->param('payinfo1'). '@'. $cgi->param('payinfo2') ); + } + $cgi->param('paydate', + $cgi->param( 'exp_month' ). '-'. $cgi->param( 'exp_year' ) ); +} + +my @invoicing_list = split( /\s*\,\s*/, $cgi->param('invoicing_list') ); +push @invoicing_list, 'POST' if $cgi->param('invoicing_list_POST'); +push @invoicing_list, 'FAX' if $cgi->param('invoicing_list_FAX'); +$cgi->param('invoicing_list', join(',', @invoicing_list) ); + + +#create new record object + +my $new = new FS::cust_main ( { + map { + $_, scalar($cgi->param($_)) +# } qw(custnum agentnum last first ss company address1 address2 city county +# state zip daytime night fax payby payinfo paydate payname tax +# otaker refnum) + } fields('cust_main') +} ); + +if ( defined($cgi->param('same')) && $cgi->param('same') eq "Y" ) { + $new->setfield("ship_$_", '') foreach qw( + last first company address1 address2 city county state zip + country daytime night fax + ); +} + +if ( $cgi->param('no_credit_limit') ) { + $new->setfield('credit_limit', ''); +} + +$new->tagnum( [ $cgi->param('tagnum') ] ); + +my %usedatetime = ( 'birthdate' => 1 ); + +foreach my $dfield (qw( birthdate signupdate )) { + + if ( $cgi->param($dfield) && $cgi->param($dfield) =~ /^([ 0-9\-\/]{0,10})$/) { + + my $value = $1; + my $parsed = ''; + + if ( exists $usedatetime{$dfield} && $usedatetime{$dfield} ) { + + my $format = $conf->config('date_format') || "%m/%d/%Y"; + my $parser = DateTime::Format::Strptime->new( pattern => $format, + time_zone => 'floating', + ); + my $dt = $parser->parse_datetime($value); + if ( $dt ) { + $parsed = $dt->epoch; + } else { + # $error ||= $cgi->param('birthdate') . " is an invalid birthdate:" . $parser->errmsg; + $error ||= "Invalid $dfield: $value"; + } + + } else { + + $parsed = parse_datetime($value) + or $error ||= "Invalid $dfield: $value"; + + } + + $new->setfield( $dfield, $parsed ); + $cgi->param( $dfield, $parsed ); + + } + +} + +$new->setfield('paid', $cgi->param('paid') ) + if $cgi->param('paid'); + +my @exempt_groups = grep /\S/, $conf->config('tax-cust_exempt-groups'); +my @tax_exempt = grep { $cgi->param("tax_$_") eq 'Y' } @exempt_groups; + +#perhaps this stuff should go to cust_main.pm +if ( $new->custnum eq '' ) { + + my $cust_pkg = ''; + my $svc; + + if ( $cgi->param('pkgpart_svcpart') ) { + + my $x = $cgi->param('pkgpart_svcpart'); + $x =~ /^(\d+)_(\d+)$/ or die "illegal pkgpart_svcpart $x\n"; + my($pkgpart, $svcpart) = ($1, $2); + my $part_pkg = qsearchs('part_pkg', { 'pkgpart' => $pkgpart } ); + #false laziness: copied from FS::cust_pkg::order (which should become a + #FS::cust_main method) + my(%part_pkg); + # generate %part_pkg + # $part_pkg{$pkgpart} is true iff $custnum may purchase $pkgpart + my $agent = qsearchs('agent',{'agentnum'=> $new->agentnum }); + + if ( $agent ) { + # $pkgpart_href->{PKGPART} is true iff $custnum may purchase $pkgpart + my $pkgpart_href = $agent->pkgpart_hashref + if $agent; + #eslaf + + # this should wind up in FS::cust_pkg! + $error ||= "Agent ". $new->agentnum. " (type ". $agent->typenum. + ") can't purchase pkgpart ". $pkgpart + #unless $part_pkg{ $pkgpart }; + unless $pkgpart_href->{ $pkgpart } + || $agent->agentnum == $part_pkg->agentnum; + } else { + $error = 'Select agent'; + } + + $cust_pkg = new FS::cust_pkg ( { + #later 'custnum' => $custnum, + 'pkgpart' => $pkgpart, + } ); + #$error ||= $cust_pkg->check; + + #$cust_svc = new FS::cust_svc ( { 'svcpart' => $svcpart } ); + + #$error ||= $cust_svc->check; + + my $part_svc = qsearchs('part_svc', { 'svcpart' => $svcpart } ); + my $svcdb = $part_svc->svcdb; + + if ( $svcdb eq 'svc_acct' ) { + + my %svc_acct = ( + 'svcpart' => $svcpart, + 'username' => scalar($cgi->param('username')), + '_password' => scalar($cgi->param('_password')), + 'popnum' => scalar($cgi->param('popnum')), + ); + $svc_acct{'domsvc'} = $cgi->param('domsvc') + if $cgi->param('domsvc'); + + $svc = new FS::svc_acct \%svc_acct; + + #and just in case you were silly + $svc->svcpart($svcpart); + $svc->username($cgi->param('username')); + $svc->_password($cgi->param('_password')); + $svc->popnum($cgi->param('popnum')); + + } elsif ( $svcdb eq 'svc_phone' ) { + + my %svc_phone = ( + 'svcpart' => $svcpart, + map { $_ => scalar($cgi->param($_)) } + qw( countrycode phonenum sip_password pin phone_name ) + ); + + $svc = new FS::svc_phone \%svc_phone; + + } else { + die "$svcdb not handled on new customer yet"; + } + + #$error ||= $svc_acct->check; + + } + + use Tie::RefHash; + tie my %hash, 'Tie::RefHash'; + %hash = ( $cust_pkg => [ $svc ] ) if $cust_pkg; + $error ||= $new->insert( \%hash, \@invoicing_list, + 'tax_exemption' => \@tax_exempt, + ); + + my $conf = new FS::Conf; + if ( $conf->exists('backend-realtime') && ! $error ) { + + my $berror = $new->bill + || $new->apply_payments_and_credits + || $new->collect( 'realtime' => 1 ); + warn "Warning, error billing during backend-realtime: $berror" if $berror; + + } + +} else { #create old record object + + my $old = qsearchs( 'cust_main', { 'custnum' => $new->custnum } ); + $error ||= "Old record not found!" unless $old; + if ( length($old->paycvv) && $new->paycvv =~ /^\s*\*+\s*$/ ) { + $new->paycvv($old->paycvv); + } + if ($new->ss =~ /xx/) { + $new->ss($old->ss); + } + if ($new->stateid =~ /^xxx/) { + $new->stateid($old->stateid); + } + if ($new->payby =~ /^(CARD|DCRD)$/ && $new->payinfo =~ /xx/) { + $new->payinfo($old->payinfo); + } elsif ($new->payby =~ /^(CHEK|DCHK)$/ && $new->payinfo =~ /xx/) { + #fix for #3085 "edit of customer's routing code only surprisingly causes + #nothing to happen... + # this probably won't do the right thing when we don't have the + # public key (can't actually get the real $old->payinfo) + my($new_account, $new_aba) = split('@', $new->payinfo); + my($old_account, $old_aba) = split('@', $old->payinfo); + $new_account = $old_account if $new_account =~ /xx/; + $new_aba = $old_aba if $new_aba =~ /xx/; + $new->payinfo($new_account.'@'.$new_aba); + } + + if ( ! $conf->exists('cust_main-edit_signupdate') or + ! $new->signupdate ) { + $new->signupdate($old->signupdate); + } + + warn "$me calling $new -> replace( $old, \ @invoicing_list )" if $DEBUG; + local($FS::cust_main::DEBUG) = $DEBUG if $DEBUG; + local($FS::Record::DEBUG) = $DEBUG if $DEBUG; + + $error ||= $new->replace( $old, \@invoicing_list, + 'tax_exemption' => \@tax_exempt, + ); + + warn "$me returned from replace" if $DEBUG; + +} + +</%init> diff --git a/httemplate/edit/process/cust_main_attach.cgi b/httemplate/edit/process/cust_main_attach.cgi new file mode 100644 index 000000000..291135718 --- /dev/null +++ b/httemplate/edit/process/cust_main_attach.cgi @@ -0,0 +1,99 @@ +%if ($error) { +% $cgi->param('error', $error); +<% $cgi->redirect(popurl(2). 'cust_main_attach.cgi?'. $cgi->query_string ) %> +%} else { +% my $act = 'added'; +% $act = 'updated' if ($attachnum); +% $act = 'purged' if($attachnum and $purge); +% $act = 'undeleted' if($attachnum and $undelete); +% $act = 'deleted' if($attachnum and $delete); +<% header('Attachment ' . $act ) %> + <SCRIPT TYPE="text/javascript"> + window.top.location.reload(); + </SCRIPT> + </BODY></HTML> +% } +<%init> + +my $error; +$cgi->param('custnum') =~ /^(\d+)$/ + or die "Illegal custnum: ". $cgi->param('custnum'); +my $custnum = $1; + +$cgi->param('attachnum') =~ /^(\d*)$/ + or die "Illegal attachnum: ". $cgi->param('attachnum'); +my $attachnum = $1; + +my $curuser = $FS::CurrentUser::CurrentUser; + +my $delete = $cgi->param('delete'); +my $undelete = $cgi->param('undelete'); +my $purge = $cgi->param('purge'); + +my $new = new FS::cust_attachment ( { + attachnum => $attachnum, + custnum => $custnum, + _date => time, + usernum => $curuser->usernum, + disabled => '', +}); +my $old; + +if($attachnum) { + $old = qsearchs('cust_attachment', { attachnum => $attachnum }); + if(!$old) { + $error = "Attachnum '$attachnum' not found"; + } + elsif($purge) { # do nothing + } + else { + map { $new->$_($old->$_) } + ('_date', 'otaker', 'body', 'disabled'); + $new->filename($cgi->param('filename') || $old->filename); + $new->mime_type($cgi->param('mime_type') || $old->mime_type); + $new->title($cgi->param('title')); + if($delete and not $old->disabled) { + $new->disabled(time); + } + if($undelete and $old->disabled) { + $new->disabled(''); + } + } +} +else { # This is a new attachment, so require a file. + + my $filename = $cgi->param('file'); + if($filename) { + $new->filename($filename); + $new->mime_type($cgi->uploadInfo($filename)->{'Content-Type'}); + $new->title($cgi->param('title')); + + local $/; + my $fh = $cgi->upload('file'); + $new->body(<$fh>); + } + else { + $error = 'No file uploaded'; + } +} +my $action = 'Add'; +$action = 'Edit' if $attachnum; +$action = 'Delete' if $attachnum and $delete; +$action = 'Undelete' if $attachnum and $undelete; +$action = 'Purge' if $attachnum and $purge; + +$error = 'access denied' unless $curuser->access_right($action . ' attachment'); + +if(!$error) { + if($old and $old->disabled and $purge) { + $error = $old->delete; + } + elsif($old) { + $error = $new->replace($old); + } + else { + $error = $new->insert; + } +} + +</%init> diff --git a/httemplate/edit/process/cust_main_county-collapse.cgi b/httemplate/edit/process/cust_main_county-collapse.cgi new file mode 100755 index 000000000..9608fc919 --- /dev/null +++ b/httemplate/edit/process/cust_main_county-collapse.cgi @@ -0,0 +1,46 @@ +<% $cgi->redirect(popurl(3). "browse/cust_main_county.cgi") %> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my($query) = $cgi->keywords; +$query =~ /^(\d+)$/ or die "Illegal taxnum!"; +my $taxnum = $1; +my $cust_main_county = qsearchs('cust_main_county', { 'taxnum' => $taxnum } ) + or die "Unknown taxnum $taxnum"; + +#really should do this in a .pm & start transaction + +my %search = ( + 'country' => $cust_main_county->country, + 'state' => $cust_main_county->state, + ); + +$search{'county'} = $cust_main_county->county + if $cust_main_county->city; + +foreach my $delete ( qsearch('cust_main_county', \%search) ) { +# unless ( qsearch('cust_main',{ +# 'state' => $cust_main_county->getfield('state'), +# 'county' => $cust_main_county->getfield('county'), +# 'country' => $cust_main_county->getfield('country'), +# } ) ) { + my $error = $delete->delete; + die $error if $error; +# } else { + #should really fix the $cust_main record +# } + +} + +$cust_main_county->taxnum(''); +if ( $cust_main_county->city ) { + $cust_main_county->city(''); +} else { + $cust_main_county->county(''); +} +my $error = $cust_main_county->insert; +die $error if $error; + +</%init> diff --git a/httemplate/edit/process/cust_main_county-expand.cgi b/httemplate/edit/process/cust_main_county-expand.cgi new file mode 100755 index 000000000..9984b08fa --- /dev/null +++ b/httemplate/edit/process/cust_main_county-expand.cgi @@ -0,0 +1,83 @@ +<% include('/elements/header-popup.html', 'Addition successful' ) %> + +<SCRIPT TYPE="text/javascript"> + window.top.location.reload(); +</SCRIPT> + +</BODY> +</HTML> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +$cgi->param('taxnum') =~ /^(\d+)$/ or die "Illegal taxnum!"; +my $taxnum = $1; +my $cust_main_county = qsearchs('cust_main_county',{'taxnum'=>$taxnum}) + or die ("Unknown taxnum!"); + +my @expansion; +if ( $cgi->param('taxclass') ) { + my $sth = dbh->prepare('SELECT taxclass FROM part_pkg_taxclass') + or die dbh->errstr; + $sth->execute or die $sth->errstr; + @expansion = map $_->[0], @{$sth->fetchall_arrayref}; + die "no taxclasses - add one first" unless @expansion;#XXX better err handling +} else { + @expansion = split /[\n\r]{1,2}/, $cgi->param('expansion'); + + #warn scalar(@expansion); + #warn "$_: $expansion[$_]\n" foreach (0..$#expansion); + + @expansion=map { + unless ( /^\s*([\w \!\@\#\$\%\&\(\)\-\+\;\:\'\"\,\.\?\/\=\[\]]+)\s*$/ ) { + $cgi->param('error', "Illegal item in expansion: $_"); + print $cgi->redirect(popurl(2). "cust_main_county-expand.cgi?". $cgi->query_string ); + myexit(); + } + $1; + } @expansion; + +} + +foreach ( @expansion) { + my(%hash)=$cust_main_county->hash; + my($new)=new FS::cust_main_county \%hash; + $new->setfield('taxnum',''); + if ( $cgi->param('taxclass') ) { + $new->setfield('taxclass', $_); + } elsif ( ! $cust_main_county->state ) { + $new->setfield('state',$_); + } elsif ( ! $cust_main_county->county ) { + $new->setfield('county',$_); + } else { + #uppercase cities in the US to try and agree with USPS validation + $new->setfield('city', $new->country eq 'US' ? uc($_) : $_ ); + } + my $error = $new->insert; + die $error if $error; +} + +unless ( qsearch( 'cust_main', { + 'city' => $cust_main_county->city, + 'county' => $cust_main_county->county, + 'state' => $cust_main_county->state, + 'country' => $cust_main_county->country, + } ) + || ! @expansion +) { + my $error = $cust_main_county->delete; + die $error if $error; +} + +if ( $cgi->param('taxclass') ) { + print $cgi->redirect(popurl(3). "browse/cust_main_county.cgi?". + 'city='. uri_escape($cust_main_county->city ).';'. + 'county='. uri_escape($cust_main_county->county ).';'. + 'state='. uri_escape($cust_main_county->state ).';'. + 'country='. uri_escape($cust_main_county->country) + ); + myexit; +} + +</%init> diff --git a/httemplate/edit/process/cust_main_county.html b/httemplate/edit/process/cust_main_county.html new file mode 100644 index 000000000..cb56166c8 --- /dev/null +++ b/httemplate/edit/process/cust_main_county.html @@ -0,0 +1,13 @@ +<% include( 'elements/process.html', + 'table' => 'cust_main_county', + 'popup_reload' => 'Tax changed', #a popup "parent reload" for now + #someday change the individual element and go away instead + ) +%> +<%init> + +my $conf = new FS::Conf; +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +</%init> diff --git a/httemplate/edit/process/cust_main_note.cgi b/httemplate/edit/process/cust_main_note.cgi new file mode 100755 index 000000000..f904c5968 --- /dev/null +++ b/httemplate/edit/process/cust_main_note.cgi @@ -0,0 +1,55 @@ +%if ($error) { +% $cgi->param('error', $error); +<% $cgi->redirect(popurl(2). 'cust_main_note.cgi?'. $cgi->query_string ) %> +%} else { +<% header('Note ' . ($notenum ? 'updated' : 'added') ) %> + <SCRIPT TYPE="text/javascript"> + window.top.location.reload(); + </SCRIPT> + </BODY></HTML> +% } +<%init> + +$cgi->param('custnum') =~ /^(\d+)$/ + or die "Illegal custnum: ". $cgi->param('custnum'); +my $custnum = $1; + +$cgi->param('notenum') =~ /^(\d*)$/ + or die "Illegal notenum: ". $cgi->param('notenum'); +my $notenum = $1; + +my $comment = $cgi->param('comment_html') || + join("<br />\n", + split "(?:\r|\n)+", $cgi->param('comment_plain') + ); + +my $new = new FS::cust_main_note ( { + notenum => $notenum, + custnum => $custnum, + _date => time, + usernum => $FS::CurrentUser::CurrentUser->usernum, + comments => $comment, +} ); + +my $error; +if ($notenum) { + + die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Edit customer note'); + + my $old = qsearchs('cust_main_note', { 'notenum' => $notenum }); + $error = "No such note: $notenum" unless $old; + unless ($error) { + map { $new->$_($old->$_) } ('_date', 'otaker'); + $error = $new->replace($old); + } + +} else { + + die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Add customer note'); + + $error = $new->insert; +} + +</%init> diff --git a/httemplate/edit/process/cust_pay.cgi b/httemplate/edit/process/cust_pay.cgi new file mode 100755 index 000000000..c8b0aa7df --- /dev/null +++ b/httemplate/edit/process/cust_pay.cgi @@ -0,0 +1,57 @@ +%if ($error) { +% $cgi->param('error', $error); +<% $cgi->redirect(popurl(2). 'cust_pay.cgi?'. $cgi->query_string ) %> +%} elsif ( $field eq 'invnum' ) { +<% $cgi->redirect(popurl(3). "view/cust_bill.cgi?$linknum") %> +%} elsif ( $field eq 'custnum' ) { +% if ( $cgi->param('apply') eq 'yes' ) { +% my $cust_main = qsearchs('cust_main', { 'custnum' => $linknum }) +% or die "unknown custnum $linknum"; +% $cust_main->apply_payments( 'manual' => 1 ); +% } +% if ( $link eq 'popup' ) { +% +<% header('Payment entered') %> + <SCRIPT TYPE="text/javascript"> + window.top.location.reload(); + </SCRIPT> + + </BODY></HTML> +% +% } elsif ( $link eq 'custnum' ) { +<% $cgi->redirect(popurl(3). "view/cust_main.cgi?$linknum") %> +% } else { +% die "unknown link $link"; +% } +% +%} +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Post payment'); + +$cgi->param('linknum') =~ /^(\d+)$/ + or die "Illegal linknum: ". $cgi->param('linknum'); +my $linknum = $1; + +$cgi->param('link') =~ /^(custnum|invnum|popup)$/ + or die "Illegal link: ". $cgi->param('link'); +my $field = my $link = $1; +$field = 'custnum' if $field eq 'popup'; + +my $_date = parse_datetime($cgi->param('_date')); + +my $new = new FS::cust_pay ( { + $field => $linknum, + _date => $_date, + map { + $_, scalar($cgi->param($_)); + } qw( paid payby payinfo paybatch + pkgnum discount_term + ) + #} fields('cust_pay') +} ); + +my $error = $new->insert( 'manual' => 1 ); + +</%init> diff --git a/httemplate/edit/process/cust_pay_pending.html b/httemplate/edit/process/cust_pay_pending.html new file mode 100644 index 000000000..1bad6cffe --- /dev/null +++ b/httemplate/edit/process/cust_pay_pending.html @@ -0,0 +1,68 @@ +<% include('/elements/header-popup.html', $title ) %> +% if ( $error ) { + <FONT SIZE="+1" COLOR="#ff0000">Error: <% $error |h %></FONT> +% } else { + <SCRIPT TYPE="text/javascript"> + window.top.location.reload(); + </SCRIPT> +% } +</BODY> +</HTML> +<%init> + +my $curuser = $FS::CurrentUser::CurrentUser; + +die "access denied" + unless $curuser->access_right('Edit customer pending payments'); + +$cgi->param('action') =~ /^(\w+)$/ or die 'illegal action'; +my $action = $1; + +$cgi->param('paypendingnum') =~ /^(\d+)$/ or die 'illegal paypendingnum'; +my $paypendingnum = $1; +my $cust_pay_pending = + qsearchs({ + 'select' => 'cust_pay_pending.*', + 'table' => 'cust_pay_pending', + 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )', + 'hashref' => { 'paypendingnum' => $paypendingnum }, + 'extra_sql' => ' AND '. $curuser->agentnums_sql, + }) + or die 'unknown paypendingnum'; + +my $error; +my $title; +if ( $action eq 'delete' ) { + + $error = $cust_pay_pending->delete; + if ( $error ) { + $title = 'Error deleting pending payment'; + } else { + $title = 'Pending payment deletion sucessful'; + } + +} elsif ( $action eq 'insert_cust_pay' ) { + + $error = $cust_pay_pending->insert_cust_pay; + if ( $error ) { + $title = 'Error completing pending payment'; + } else { + $title = 'Pending payment completed'; + } + +} elsif ( $action eq 'decline' ) { + + $error = $cust_pay_pending->decline; + if ( $error ) { + $title = 'Error declining pending payment'; + } else { + $title = 'Pending payment completed (decline)'; + } + +} else { + + die "unknown action $action"; + +} + +</%init> diff --git a/httemplate/edit/process/cust_pay_refund.cgi b/httemplate/edit/process/cust_pay_refund.cgi new file mode 100755 index 000000000..2616cad8c --- /dev/null +++ b/httemplate/edit/process/cust_pay_refund.cgi @@ -0,0 +1,13 @@ +<% include('elements/ApplicationCommon.html', + 'error_redirect' => 'cust_pay_refund.cgi', + 'src_table' => 'cust_pay', + 'src_thing' => 'payment', + 'link_table' => 'cust_pay_refund', + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Apply payment'); + +</%init> diff --git a/httemplate/edit/process/cust_pkg.cgi b/httemplate/edit/process/cust_pkg.cgi new file mode 100755 index 000000000..c564c417e --- /dev/null +++ b/httemplate/edit/process/cust_pkg.cgi @@ -0,0 +1,42 @@ +% if ($error) { +% $cgi->param('error', $error); +% $cgi->redirect(popurl(3). 'edit/cust_pkg.cgi?'. $cgi->query_string ); +% } else { +<% $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum") %> +% } +<%init> + +my $curuser = $FS::CurrentUser::CurrentUser; + +die "access denied" + unless $curuser->access_right('Bulk change customer packages'); + +my $error = ''; + +#untaint custnum +$cgi->param('custnum') =~ /^(\d+)$/; +my $custnum = $1; + +my @remove_pkgnums = map { + /^(\d+)$/ or die "Illegal remove_pkg value!"; + $1; +} $cgi->param('remove_pkg'); + +my( $action, $error_redirect ) = ( '', '' ); +my @pkgparts = (); + +foreach my $pkgpart ( map /^pkg(\d+)$/ ? $1 : (), $cgi->param ) { + if ( $cgi->param("pkg$pkgpart") =~ /^(\d+)$/ ) { + my $num_pkgs = $1; + while ( $num_pkgs-- ) { + push @pkgparts,$pkgpart; + } + } else { + $error = "Illegal quantity"; + last; + } +} + +$error ||= FS::cust_pkg::order($custnum,\@pkgparts,\@remove_pkgnums); + +</%init> diff --git a/httemplate/edit/process/cust_pkg_detail.html b/httemplate/edit/process/cust_pkg_detail.html new file mode 100644 index 000000000..132ff63c5 --- /dev/null +++ b/httemplate/edit/process/cust_pkg_detail.html @@ -0,0 +1,59 @@ +% if ( $error ) { +<% header('Error') %> +<FONT COLOR="#ff0000"><B><% $error |h %></B></FONT><BR><BR> +<CENTER><INPUT TYPE="BUTTON" VALUE="OK" onClick="parent.cClick()"></CENTER> +</BODY></HTML> +% } else { +<% header($action) %> + <SCRIPT TYPE="text/javascript"> + window.top.location.reload(); + </SCRIPT> + </BODY></HTML> +% } +<%init> + +my %access_right = ( + 'I' => 'Edit customer package invoice details', + 'C' => 'Edit customer package comments', +); + +my %name = ( + 'I' => 'invoice details', + 'C' => 'package comments', +); + +my $curuser = $FS::CurrentUser::CurrentUser; + +$cgi->param('detailtype') =~ /^(\w)$/ or die 'illegal detailtype'; +my $detailtype = $1; + +my $right = $access_right{$detailtype}; +die "access denied" + unless $curuser->access_right($right); + +$cgi->param('pkgnum') =~ /^(\d+)$/ or die 'illegal pkgnum'; +my $pkgnum = $1; + +my $cust_pkg = qsearchs({ + 'table' => 'cust_pkg', + 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )', + 'hashref' => { 'pkgnum' => $pkgnum }, + 'extra_sql' => ' AND '. $curuser->agentnums_sql, +}); + + +my @orig_details = $cust_pkg->cust_pkg_detail($detailtype); + +my $action = ucfirst($name{$detailtype}). + ( scalar(@orig_details) ? ' changed ' : ' added ' ); + +my $param = $cgi->Vars; +my @details = (); +for ( my $row = 0; exists($param->{"detail$row"}); $row++ ) { + push @details, $param->{"detail$row"} + if $param->{"detail$row"} =~ /\S/; +} + +my $error = $cust_pkg->set_cust_pkg_detail($detailtype, @details); + +</%init> diff --git a/httemplate/edit/process/cust_pkg_discount.html b/httemplate/edit/process/cust_pkg_discount.html new file mode 100644 index 000000000..e3249d79c --- /dev/null +++ b/httemplate/edit/process/cust_pkg_discount.html @@ -0,0 +1,47 @@ +% if ($error) { +% $cgi->param('error', $error); +% $cgi->redirect(popurl(3). 'edit/cust_pkg_discount.html?'. $cgi->query_string ); +% } else { + + <% header("Discount applied") %> + <SCRIPT TYPE="text/javascript"> + window.top.location.reload(); + </SCRIPT> + </BODY> + </HTML> + +% } +<%init> + +my $curuser = $FS::CurrentUser::CurrentUser; + +die "access denied" + unless $curuser->access_right('Discount customer package'); + +#this search is really for security wrt agent virt... +#maybe move it to the cust_pkg_discount->insert call? +my $cust_pkg = qsearchs({ + #'select' => 'cust_pkg.*', + 'table' => 'cust_pkg', + 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )', + 'hashref' => { 'pkgnum' => scalar($cgi->param('pkgnum')), }, + 'extra_sql' => ' AND '. $curuser->agentnums_sql, +}); +die 'unknown pkgnum' unless $cust_pkg; + +my $cust_pkg_discount = new FS::cust_pkg_discount { + 'pkgnum' => $cust_pkg->pkgnum, + 'discountnum' => scalar($cgi->param('discountnum')), + 'months_used' => 0, + 'end_date' => '', #XXX + 'otaker' => $curuser->username, + #for the create a new discount case + '_type' => scalar($cgi->param('discountnum__type')), + 'amount' => scalar($cgi->param('discountnum_amount')), + 'percent' => scalar($cgi->param('discountnum_percent')), + 'months' => scalar($cgi->param('discountnum_months')), + #'disabled' => $self->discountnum_disabled, +}; +my $error = $cust_pkg_discount->insert; + +</%init> diff --git a/httemplate/edit/process/cust_refund.cgi b/httemplate/edit/process/cust_refund.cgi new file mode 100755 index 000000000..5749e5346 --- /dev/null +++ b/httemplate/edit/process/cust_refund.cgi @@ -0,0 +1,56 @@ +%if ( $error ) { +% $cgi->param('error', $error); +<% $cgi->redirect(popurl(2). "cust_refund.cgi?". $cgi->query_string ) %> +%} else { +% +% if ( $link eq 'popup' ) { +% +<% header('Refund entered') %> + <SCRIPT TYPE="text/javascript"> + window.top.location.reload(); + </SCRIPT> + + </BODY></HTML> +% } else { +<% $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum") %> +% } +%} +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Refund payment') + || $FS::CurrentUser::CurrentUser->access_right('Post refund'); + +$cgi->param('custnum') =~ /^(\d*)$/ or die "Illegal custnum!"; +my $custnum = $1; +my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ) + or die "unknown custnum $custnum"; + +my $link = $cgi->param('popup') ? 'popup' : ''; + +my $error = ''; +if ( $cgi->param('payby') =~ /^(CARD|CHEK)$/ ) { + my %options = (); + my $bop = $FS::payby::payby2bop{$1}; + $cgi->param('refund') =~ /^(\d*)(\.\d{2})?$/ + or die "illegal refund amount ". $cgi->param('refund'); + my $refund = "$1$2"; + $cgi->param('paynum') =~ /^(\d*)$/ or die "Illegal paynum!"; + my $paynum = $1; + my $reason = $cgi->param('reason'); + my $paydate = $cgi->param('exp_year'). '-'. $cgi->param('exp_month'). '-01'; + $options{'paydate'} = $paydate if $paydate =~ /^\d{2,4}-\d{1,2}-01$/; + $error = $cust_main->realtime_refund_bop( $bop, 'amount' => $refund, + 'paynum' => $paynum, + 'reason' => $reason, + %options ); +} else { + my $new = new FS::cust_refund ( { + map { + $_, scalar($cgi->param($_)); + } fields('cust_refund') #huh? , 'paynum' ) + } ); + $error = $new->insert; +} + +</%init> diff --git a/httemplate/edit/process/cust_svc.cgi b/httemplate/edit/process/cust_svc.cgi new file mode 100644 index 000000000..e22cbb201 --- /dev/null +++ b/httemplate/edit/process/cust_svc.cgi @@ -0,0 +1,30 @@ +%if ( $error ) { +% errorpage($error); +%} else { +% my $svcdb = $new->part_svc->svcdb; +<% $cgi->redirect(popurl(3). "view/$svcdb.cgi?$svcnum") %> +%} +<%init> + +die 'access deined' + unless $FS::CurrentUser::CurrentUser->access_right('Change customer service'); + +my $svcnum = $cgi->param('svcnum'); + +my $old = qsearchs('cust_svc',{'svcnum'=>$svcnum}) if $svcnum; + +my $new = new FS::cust_svc ( { + map { + $_, scalar($cgi->param($_)); + } fields('cust_svc') +} ); + +my $error; +if ( $svcnum ) { + $error=$new->replace($old); +} else { + $error=$new->insert; + $svcnum=$new->getfield('svcnum'); +} + +</%init> diff --git a/httemplate/edit/process/cust_tax_adjustment.html b/httemplate/edit/process/cust_tax_adjustment.html new file mode 100644 index 000000000..204b5b9f7 --- /dev/null +++ b/httemplate/edit/process/cust_tax_adjustment.html @@ -0,0 +1,41 @@ +% if ( $error ) { +% $cgi->param('error', $error ); +<% $cgi->redirect($p.'cust_tax_adjustment.html?'. $cgi->query_string) %> +% } else { +<% header("Tax adjustment added") %> + <SCRIPT TYPE="text/javascript"> + //window.top.location.reload(); + parent.cClick(); + </SCRIPT> + </BODY></HTML> +% } +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Add customer tax adjustment'); + +my $error = ''; +my $conf = new FS::conf; +my $param = $cgi->Vars; + +$param->{"custnum"} =~ /^(\d+)$/ + or $error .= "Illegal customer number " . $param->{"custnum"} . " "; +my $custnum = $1; + +$param->{"amount"} =~ /^\s*(\d*(?:\.?\d{1,2}))\s*$/ + or $error .= "Illegal amount " . $param->{"amount"} . " "; +my $amount = $1; + +unless ( $error ) { + + my $cust_tax_adjustment = new FS::cust_tax_adjustment { + 'custnum' => $custnum, + 'taxname' => $param->{'taxname'}, + 'amount' => $amount, + 'comment' => $param->{'comment'}, + }; + $error = $cust_tax_adjustment->insert; + +} + +</%init> diff --git a/httemplate/edit/process/discount.html b/httemplate/edit/process/discount.html new file mode 100644 index 000000000..eb4e92e9f --- /dev/null +++ b/httemplate/edit/process/discount.html @@ -0,0 +1,12 @@ +<% include( 'elements/process.html', + 'table' => 'discount', + 'viewall_dir' => 'browse', + 'fields' => [ fields('discount'), '_type' ], + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +</%init> diff --git a/httemplate/edit/process/domain_record.cgi b/httemplate/edit/process/domain_record.cgi new file mode 100755 index 000000000..ff0f2d414 --- /dev/null +++ b/httemplate/edit/process/domain_record.cgi @@ -0,0 +1,30 @@ +%if ( $error ) { +% errorpage($error); +%} else { +% my $svcnum = $new->svcnum; +<% $cgi->redirect(popurl(3). "view/svc_domain.cgi?$svcnum") %> +%} +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Edit domain nameservice'); + +my $recnum = $cgi->param('recnum'); + +my $old = qsearchs('domain_record',{'recnum'=>$recnum}) if $recnum; + +my $new = new FS::domain_record ( { + map { + $_, scalar($cgi->param($_)); + } fields('domain_record') +} ); + +my $error; +if ( $recnum ) { + $error=$new->replace($old); +} else { + $error=$new->insert; + $recnum=$new->getfield('recnum'); +} + +</%init> diff --git a/httemplate/edit/process/domreg.cgi b/httemplate/edit/process/domreg.cgi new file mode 100755 index 000000000..a95474e44 --- /dev/null +++ b/httemplate/edit/process/domreg.cgi @@ -0,0 +1,62 @@ +%if ($error) { +% $cgi->param('error', $error); +% errorpage($error); +%} else { +<% $cgi->redirect(popurl(3). "view/svc_domain.cgi?$svcnum") %> +%} +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific? + +$cgi->param('op') =~ /^(register|transfer|revoke|renew)$/ or die "Illegal operation"; +my $operation = $1; +#my($query) = $cgi->keywords; +#$query =~ /^(\d+)$/; +$cgi->param('svcnum') =~ /^(\d*)$/ or die "Illegal svcnum!"; +my $svcnum = $1; +my $svc_domain = qsearchs({ + 'select' => 'svc_domain.*', + 'table' => 'svc_domain', + 'addl_from' => ' LEFT JOIN cust_svc USING ( svcnum ) '. + ' LEFT JOIN cust_pkg USING ( pkgnum ) '. + ' LEFT JOIN cust_main USING ( custnum ) ', + 'hashref' => {'svcnum'=>$svcnum}, + 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql, +}); +die "Unknown svcnum" unless $svc_domain; + +my $cust_svc = qsearchs('cust_svc',{'svcnum'=>$svcnum}); +my $part_svc = qsearchs('part_svc',{'svcpart'=> $cust_svc->svcpart } ); +die "Unknown svcpart" unless $part_svc; + +my $error = ''; + +my @exports = $part_svc->part_export(); + +my $registrar; +my $export; + +# Find the first export that does domain registration +foreach (@exports) { + $export = $_ if $_->can('registrar'); +} + +my $period = 1; # Current OpenSRS export can only handle 1 year registrations + +# If we have a domain registration export, get the registrar object +if ($export) { + if ($operation eq 'register') { + $error = $export->register( $svc_domain, $period ); + } elsif ($operation eq 'transfer') { + $error = $export->transfer( $svc_domain ); + } elsif ($operation eq 'revoke') { + $error = $export->revoke( $svc_domain ); + } elsif ($operation eq 'renew') { + $cgi->param('period') =~ /^(\d+)$/ or die "Illegal renewal period!"; + $period = $1; + $error = $export->renew( $svc_domain, $period ); + } +} + +</%init> diff --git a/httemplate/edit/process/elements/ApplicationCommon.html b/httemplate/edit/process/elements/ApplicationCommon.html new file mode 100644 index 000000000..c7bdd3ea2 --- /dev/null +++ b/httemplate/edit/process/elements/ApplicationCommon.html @@ -0,0 +1,103 @@ +<%doc> + +Examples: + + #cust_bill_pay + include('elements/ApplicationCommon.html', + 'error_redirect' => 'cust_bill_pay.cgi', + 'src_table' => 'cust_pay', + 'src_thing' => 'payment', + 'link_table' => 'cust_bill_pay', + ) + + #cust_credit_bill + include('elements/ApplicationCommon.html', + 'error_redirect' => 'cust_credit_bill.cgi', + 'src_table' => 'cust_credit', + 'src_thing' => 'credit', + 'link_table' => 'cust_credit_bill', + ) + +</%doc> +%if ( $error ) { +% $cgi->param('error', $error); +<% $cgi->redirect(popurl(2). $opt{error_redirect}. '?'. $cgi->query_string ) %> +%} else { +<% header("$src_thing application$to sucessful") %> + <SCRIPT TYPE="text/javascript"> + window.top.location.reload(); + </SCRIPT> + </BODY> + </HTML> +% } +<%init> + +my %opt = @_; + +my $error = ''; + +my $src_thing = ucfirst($opt{'src_thing'}); +my $src_table = $opt{'src_table'}; +my $src_pkey = dbdef->table($src_table)->primary_key; + +my $to = $opt{'link_table'} =~ /refund/ ? ' to Refund' : ''; + +$cgi->param($src_pkey) =~ /^(\d+)$/ or die "Illegal $src_pkey!"; +my $src_pkeyvalue = $1; + +my $src = qsearchs($src_table, { $src_pkey => $src_pkeyvalue } ) + or die "No such $src_pkey: $src_pkeyvalue"; + +my $cust_main = qsearchs('cust_main', { 'custnum' => $src->custnum } ) + or die "Bogus $src_thing: not attached to customer"; + +my $custnum = $cust_main->custnum; + +my @subnames = grep { /.+/ } map { /^subnum(\d+)$/ ? $1 : '' } $cgi->param; +my @subitems = map { [ $cgi->param("subnum$_"), $cgi->param("subamount$_"), $cgi->param("taxXlocationnum$_") ] } + @subnames; +{ local $^W = 0; @subitems = grep { $_->[1] + 0 } @subitems; } + +my %options = (); +$options{subitems} = \@subitems if scalar(@subitems); + +my $oldAutoCommit = $FS::UID::AutoCommit; +local $FS::UID::AutoCommit = 0; +my $dbh = dbh; + +my $new; +# $new = new FS::cust_refund ( { +# 'reason' => 'Refunding payment', #enter reason in UI +# 'refund' => $cgi->param('amount'), +# 'payby' => 'BILL', +# #'_date' => $cgi->param('_date'), +# 'payinfo' => 'Cash', #enter payinfo in UI +# 'paynum' => $paynum, +# } ); +#} else { + + if ($src->amount != $cgi->param('src_amount')) { + $src->amount($cgi->param('src_amount')); + $error = $src->replace; + } + + my $class = 'FS::'. $opt{link_table}; + + $new = $class->new( { + map { + $_ => scalar($cgi->param($_)); + } fields($opt{link_table}) + } ); + +#} + + +$options{manual} = 1; +$error ||= $new->insert( %options ); + +if ($error) { + $dbh->rollback if $oldAutoCommit; +} else { + $dbh->commit or die $dbh->errstr if $oldAutoCommit; +} +</%init> diff --git a/httemplate/edit/process/elements/process.html b/httemplate/edit/process/elements/process.html new file mode 100644 index 000000000..53419cde0 --- /dev/null +++ b/httemplate/edit/process/elements/process.html @@ -0,0 +1,321 @@ +<%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' + 'viewall_ext' => 'html', #'cgi' or 'html', defaults to 'html' + OR + 'redirect' => 'view/table.cgi?', # value of primary key is appended + # (string or coderef returning a string) + OR + 'popup_reload' => 'Momentary success message', #will reload parent window + + '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', ... ], + + #pass an arrayref of hashrefs for multiple m2ms or m2names + #be certain you incorporate m2m_Common if you see error: param + + 'process_m2m' => { 'link_table' => 'link_table_name', + 'target_table' => 'target_table_name', + #optional (see m2m_Common::process_m2m), if not specified + # all CGI params will be passed) + 'params' => + }, + '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', + + + }, + 'process_o2m' => { 'table' => table_name', + 'num_col' => 'column', #if column name is different in + #link_table than source_table + }, + + #checks CGI params and whatever else before much else runs + #return an error string or empty for no error + 'precheck_callback' => sub { my( $cgi ) = @_; }, + + #after everything's inserted + 'noerror_callback' => sub { my( $cgi, $object ) = @_; }, + + #supplies arguments to insert() and replace() + # for use with tables that are FS::option_Common (among other things) + 'args_callback' => sub { my( $cgi, $object ) = @_; }, + + 'debug' => 1, #turns on debugging output + + #agent virtualization + 'agent_virt' => 1, + 'agent_null_right' => 'Access Right Name', + + ) + +</%doc> +%if ( $error ) { +% +% 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"; +% } +% +<% $cgi->redirect("$url?redirect=$session") %> +% +% } else { +% +<% $cgi->redirect("$url?". $cgi->query_string ) %> +% +% } +% +% #different ways of handling success +% +%} elsif ( $opt{'popup_reload'} ) { + + <% include('/elements/header-popup.html', $opt{'popup_reload'} ) %> + + <SCRIPT TYPE="text/javascript"> + window.top.location.reload(); + </SCRIPT> + + </BODY> + </HTML> + +%} else { +% +% $opt{'redirect'} = &{$opt{'redirect'}}($cgi, $new) +% if ref($opt{'redirect'}) eq 'CODE'; +% +% if ( $opt{'redirect'} ) { +% +<% $cgi->redirect( $opt{'redirect'}. $pkeyvalue ) %> +% +% } else { +% +% my $ext = $opt{'viewall_ext'} || 'html'; +% +<% $cgi->redirect( popurl(3). ($opt{viewall_dir}||'search'). "/$table.$ext" ) %> +% +% } +% +%} +% +<%init> + +my $me = 'process.html:'; + +my(%opt) = @_; + +my $curuser = $FS::CurrentUser::CurrentUser; + +my $error = ''; +if ( $opt{'precheck_callback'} ) { + $error = &{ $opt{'precheck_callback'} }( $cgi ); +} + +#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 { my @entry = ( $_ => scalar($cgi->param($_)) ); + $opt{'value_callback'} ? ( $_ => &{ $opt{'value_callback'} }( @entry )) + : ( @entry ) + } @$fields; + +my $new = $class->new( \%hash ); + +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)); + } +} + +if ( $opt{'agent_virt'} ) { + + if ( ! $new->agentnum + && ( ! $opt{'agent_null_right'} + || ! $curuser->access_right($opt{'agent_null_right'}) + ) + ) + { + + $error ||= 'Select an agent'; + + } else { + + die "illegal agentnum" + unless $curuser->agentnums_href->{$new->agentnum} + or $curuser->access_right('View customers of all agents') + or $opt{'agent_null_right'} + && ! $new->agentnum + && $curuser->access_right($opt{'agent_null_right'}); + + } + +} + +$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'} ) { + + my @process_m2m = ref($opt{'process_m2m'}) eq 'ARRAY' + ? @{ $opt{'process_m2m'} } + : ( $opt{'process_m2m'} ); + + foreach my $process_m2m (@process_m2m) { + + $process_m2m->{'params'} ||= scalar($cgi->Vars); + + warn "$me processing m2m:\n". Dumper( %$process_m2m ) + if $opt{'debug'}; + + $error = $new->process_m2m( %$process_m2m ); + } + +} + +if ( !$error && $opt{'process_m2name'} ) { + + my @process_m2name = ref($opt{'process_m2name'}) eq 'ARRAY' + ? @{ $opt{'process_m2name'} } + : ( $opt{'process_m2name'} ); + + + foreach my $process_m2name (@process_m2name) { + + if ( $opt{'debug'} ) { + warn "$me processing m2name:\n". Dumper( %{ $process_m2name }, + 'params' => scalar($cgi->Vars), + ); + } + + $error = $new->process_m2name( %{ $process_m2name }, + 'params' => scalar($cgi->Vars), + ); + } + +} + +if ( !$error && $opt{'process_o2m'} ) { + + my @process_o2m = ref($opt{'process_o2m'}) eq 'ARRAY' + ? @{ $opt{'process_o2m'} } + : ( $opt{'process_o2m'} ); + + + foreach my $process_o2m (@process_o2m) { + + if ( $opt{'debug'} ) { + warn "$me processing o2m:\n". Dumper( %{ $process_o2m }, + 'params' => scalar($cgi->Vars), + ); + } + + $error = $new->process_o2m( %{ $process_o2m }, + 'params' => scalar($cgi->Vars), + ); + } + +} + + +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, '') + } + } + +} else { + + if ( $opt{'noerror_callback'} ) { + &{ $opt{'noerror_callback'} }( $cgi, $new ); + } + +} + +</%init> diff --git a/httemplate/edit/process/elements/svc_Common.html b/httemplate/edit/process/elements/svc_Common.html new file mode 100644 index 000000000..5a8afbd6c --- /dev/null +++ b/httemplate/edit/process/elements/svc_Common.html @@ -0,0 +1,14 @@ +<% include( 'process.html', + 'edit_ext' => 'cgi', + 'redirect' => popurl(3)."view/$table.cgi?", + %opt, + ) +%> +<%init> + +my %opt = @_; +my $table = $opt{'table'}; +$opt{'fields'} ||= [ fields($table) ]; +push @{ $opt{'fields'} }, qw( pkgnum svcpart ); + +</%init> diff --git a/httemplate/edit/process/generic.cgi b/httemplate/edit/process/generic.cgi new file mode 100644 index 000000000..642876386 --- /dev/null +++ b/httemplate/edit/process/generic.cgi @@ -0,0 +1,77 @@ +%if($error) { +% $cgi->param('error', $error); +<% $cgi->redirect($redirect_error . '?' . $cgi->query_string) %> +%} else { +<% $cgi->redirect($redirect_ok) %> +%} +<%doc> + +See elements/process.html, newer and somewhat along the same lines, +though it still makes you setup a process file for the table. +Perhaps safer, perhaps more of a pain in the ass. + +In any case, this is probably pretty deprecated; it is only used by +part_virtual_field.cgi, and so its ACL is hardcoded to 'Configuration'. + +Welcome to generic.cgi. + +This script provides a generic edit/process/ backend for simple table +editing. All it knows how to do is take the values entered into +the script and insert them into the table specified by $cgi->param('table'). +If there's an existing record with the same primary key, it will be +replaced. (Deletion will be added in the future.) + +Special cgi params for this script: +table: the name of the table to be edited. The script will die horribly + if it can't find the table. +redirect_ok: URL to be displayed after a successful edit. The value of + the record's primary key will be passed as a keyword. + Defaults to (freeside root)/view/$table.cgi. +redirect_error: URL to be displayed if there's an error. The original + query string, plus the error message, will be passed. + Defaults to $cgi->referer() (i.e. go back where you + came from). + +</%doc> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my $error; +my $p2 = popurl(2); +my $p3 = popurl(3); +my $table = $cgi->param('table'); +my $dbdef = dbdef or die "Cannot fetch dbdef!"; + +my $dbdef_table = $dbdef->table($table) or die "Cannot fetch schema for $table"; + +my $pkey = $dbdef_table->primary_key or die "Cannot fetch pkey for $table"; +my $pkey_val = $cgi->param($pkey); + + +#warn "new FS::Record ( $table, (hashref) )"; +my $new = FS::Record::new ( "FS::$table", { + map { $_, scalar($cgi->param($_)) } fields($table) +} ); + +#warn 'created $new of class '.ref($new); + +if($pkey_val and (my $old = qsearchs($table, { $pkey, $pkey_val} ))) { + # edit + $error = $new->replace($old); +} else { + #add + $error = $new->insert; + $pkey_val = $new->getfield($pkey); + # New records usually don't have their primary keys set until after + # they've been checked/inserted, so grab the new $pkey_val so we can + # redirect to it. +} + +my $redirect_ok = (($cgi->param('redirect_ok')) ? + $cgi->param('redirect_ok') : $p3."browse/generic.cgi?$table"); +my $redirect_error = (($cgi->param('redirect_error')) ? + $cgi->param('redirect_error') : $cgi->referer()); + +</%init> diff --git a/httemplate/edit/process/inventory_class.html b/httemplate/edit/process/inventory_class.html new file mode 100644 index 000000000..dbf978e72 --- /dev/null +++ b/httemplate/edit/process/inventory_class.html @@ -0,0 +1,11 @@ +<% include( 'elements/process.html', + 'table' => 'inventory_class', + 'viewall_dir' => 'browse', + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +</%init> diff --git a/httemplate/edit/process/invoice_logo.html b/httemplate/edit/process/invoice_logo.html new file mode 100644 index 000000000..524d32542 --- /dev/null +++ b/httemplate/edit/process/invoice_logo.html @@ -0,0 +1,25 @@ +<%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_binary("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 000000000..6c9371ad1 --- /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/mailinglistmember.html b/httemplate/edit/process/mailinglistmember.html new file mode 100644 index 000000000..f1842b8ef --- /dev/null +++ b/httemplate/edit/process/mailinglistmember.html @@ -0,0 +1,6 @@ +<% include( 'elements/process.html', + 'table' => 'mailinglistmember', + 'popup_reload' => 'Member added', + ) +%> +%#XXX ACL diff --git a/httemplate/edit/process/msg_template.html b/httemplate/edit/process/msg_template.html new file mode 100644 index 000000000..70d451b72 --- /dev/null +++ b/httemplate/edit/process/msg_template.html @@ -0,0 +1,13 @@ +<% include( 'elements/process.html', + 'table' => 'msg_template', + 'viewall_dir' => 'browse', + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Edit templates') + || $FS::CurrentUser::CurrentUser->access_right('Edit global templates') + || $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +</%init> diff --git a/httemplate/edit/process/msgcat.cgi b/httemplate/edit/process/msgcat.cgi new file mode 100644 index 000000000..7175fa2b3 --- /dev/null +++ b/httemplate/edit/process/msgcat.cgi @@ -0,0 +1,22 @@ +%if ( $error ) { +% $cgi->param('error',$error); +<% $cgi->redirect($p. "msgcat.cgi?". $cgi->query_string ) %> +%} else { +<% $cgi->redirect(popurl(3). "browse/msgcat.cgi") %> +%} +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my $error; +foreach my $param ( grep { /^\d+$/ } $cgi->param ) { + my $old = qsearchs('msgcat', { msgnum=>$param } ); + next if $old->msg eq $cgi->param($param); #no need to update identical records + my $new = new FS::msgcat { $old->hash }; + $new->msg($cgi->param($param)); + $error = $new->replace($old); + last if $error; +} + +</%init> diff --git a/httemplate/edit/process/part_bill_event.cgi b/httemplate/edit/process/part_bill_event.cgi new file mode 100755 index 000000000..eb0529bb8 --- /dev/null +++ b/httemplate/edit/process/part_bill_event.cgi @@ -0,0 +1,106 @@ +%if ( $error ) { +% $cgi->param('error', $error); +<% $cgi->redirect(popurl(2). "part_bill_event.cgi?". $cgi->query_string ) %> +%} else { +<% $cgi->redirect(popurl(3)."browse/part_bill_event.cgi") %> +%} +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my $eventpart = $cgi->param('eventpart'); + +my $old = qsearchs('part_bill_event',{'eventpart'=>$eventpart}) if $eventpart; + +#s/days/seconds/ +$cgi->param('seconds', int( $cgi->param('days') * 86400 ) ); + +my $error; +if ( ! $cgi->param('plan_weight_eventcode') ) { + $error = "Must select an action"; +} else { + + $cgi->param('plan_weight_eventcode') =~ /^([\w\-]+):(\d+):(.*)$/s + or die "illegal plan_weight_eventcode:". + $cgi->param('plan_weight_eventcode'); + $cgi->param('plan', $1); + $cgi->param('weight', $2); + my $eventcode = $3; + my $plandata = ''; + + my $rnum; + my $rtype; + my $reasonm; + my $class = ''; + $class='c' if ($eventcode =~ /cancel/); + $class='s' if ($eventcode =~ /suspend/); + if ($class) { + $cgi->param("${class}reason") =~ /^(-?\d+)$/ + or $error = "Invalid ${class}reason"; + $rnum = $1; + if ($rnum == -1) { + $cgi->param("new${class}reasonT") =~ /^(\d+)$/ + or $error = "Invalid new${class}reasonT"; + $rtype = $1; + $cgi->param("new${class}reason") =~ /^([\s\w]+)$/ + or $error = "Invalid new${class}reason"; + $reasonm = $1; + } + } + + if ($rnum == -1 && !$error) { + my $reason = new FS::reason ({ 'reason' => $reasonm, + 'reason_type' => $rtype, + }); + $error = $reason->insert; + unless ($error) { + $rnum = $reason->reasonnum; + $cgi->param("${class}reason", $rnum); + $cgi->param("new${class}reason", ''); + $cgi->param("new${class}reasonT", ''); + } + } + + while ( $eventcode =~ /%%%(\w+)%%%/ ) { + my $field = $1; + my $value = join(', ', $cgi->param($field) ); + $cgi->param($field, $value); #in case it errors out + $eventcode =~ s/%%%$field%%%/$value/; + $plandata .= "$field $value\n"; + } + $cgi->param('eventcode', $eventcode); + $cgi->param('plandata', $plandata); + + unless($error) { + + if ( $eventpart ) { + + my $new = new FS::part_bill_event ( { + map { $_ => scalar($cgi->param($_)) } + fields('part_bill_event'), + } ); + $new->setfield('reason' => $rnum); + $error = $new->replace($old); + + } else { + + foreach my $payby ( $cgi->param('payby') ) { + my $new = new FS::part_bill_event ( { + map { $_ => scalar($cgi->param($_)) } + grep { $_ ne 'payby' } + fields('part_bill_event') + } ); + $new->setfield('payby' => $payby); + $new->setfield('reason' => $rnum ); + $error = $new->insert; + last if $error; + } + + } + + } + +} + +</%init> diff --git a/httemplate/edit/process/part_device.html b/httemplate/edit/process/part_device.html new file mode 100644 index 000000000..399991fc8 --- /dev/null +++ b/httemplate/edit/process/part_device.html @@ -0,0 +1,15 @@ +<% include( 'elements/process.html', + 'table' => 'part_device', + 'viewall_dir' => 'browse', + 'process_m2m' => { + 'link_table' => 'export_device', + 'target_table' => 'part_export', + }, + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +</%init> diff --git a/httemplate/edit/process/part_event.html b/httemplate/edit/process/part_event.html new file mode 100644 index 000000000..428025fd1 --- /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/part_export.cgi b/httemplate/edit/process/part_export.cgi new file mode 100644 index 000000000..209419f0b --- /dev/null +++ b/httemplate/edit/process/part_export.cgi @@ -0,0 +1,42 @@ +%if ( $error ) { +% $cgi->param('error', $error ); +<% $cgi->redirect(popurl(2). "part_export.cgi?". $cgi->query_string ) %> +%} else { +<% $cgi->redirect(popurl(3). "browse/part_export.cgi") %> +%} +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my $exportnum = $cgi->param('exportnum'); + +my $old = qsearchs('part_export', { 'exportnum'=>$exportnum } ) if $exportnum; + +#fixup options +#warn join('-', split(',',$cgi->param('options'))); +my %options = map { + my @values = $cgi->param($_); + my $value = scalar(@values) > 1 ? join (' ', @values) : $values[0]; + $value =~ s/\r\n/\n/g; #browsers? (textarea) + $_ => $value; +} split(',', $cgi->param('options')); + +my $new = new FS::part_export ( { + map { + $_, scalar($cgi->param($_)); + } fields('part_export') +} ); + +my $error; +if ( $exportnum ) { + #warn $old; + #warn $exportnum; + #warn $new->machine; + $error = $new->replace($old,\%options); +} else { + $error = $new->insert(\%options); +# $exportnum = $new->exportnum; +} + +</%init> diff --git a/httemplate/edit/process/part_pkg.cgi b/httemplate/edit/process/part_pkg.cgi new file mode 100755 index 000000000..08cc14086 --- /dev/null +++ b/httemplate/edit/process/part_pkg.cgi @@ -0,0 +1,228 @@ +<% include( 'elements/process.html', + #'debug' => 1, + 'table' => 'part_pkg', + 'agent_virt' => 1, + 'agent_null_right' => \@agent_null_right, + 'redirect' => $redirect_callback, + 'viewall_dir' => 'browse', + 'viewall_ext' => 'cgi', + 'edit_ext' => 'cgi', + 'precheck_callback' => $precheck_callback, + 'args_callback' => $args_callback, + 'process_m2m' => \@process_m2m, + ) +%> +<%init> + +my $customizing = ( ! $cgi->param('pkgpart') && $cgi->param('pkgnum') ); + +my $curuser = $FS::CurrentUser::CurrentUser; + +my $edit_global = 'Edit global package definitions'; +my $customize = 'Customize customer package'; + +die "access denied" + unless $curuser->access_right('Edit package definitions') + || $curuser->access_right($edit_global) + || ( $customizing && $curuser->access_right($customize) ); + +my @agent_null_right = ( $edit_global ); +push @agent_null_right, $customize if $customizing; + + +my $precheck_callback = sub { + my( $cgi ) = @_; + + my $conf = new FS::Conf; + + foreach (qw( setuptax recurtax disabled )) { + $cgi->param($_, '') unless defined $cgi->param($_); + } + + return 'Must select a tax class' + if $cgi->param('taxclass') eq '(select)'; + + my @agents = (); + foreach ($cgi->param('agent_type')) { + /^(\d+)$/; + push @agents, $1 if $1; + } + return "At least one agent type must be specified." + unless scalar(@agents) + || ( $cgi->param('clone') && $cgi->param('clone') =~ /^\d+$/ ) + || ( !$cgi->param('pkgpart') && $conf->exists('agent-defaultpkg') ) + || $cgi->param('disabled') + || $cgi->param('agentnum'); + + return ''; + +}; + +my $custnum = ''; + +my $args_callback = sub { + my( $cgi, $new ) = @_; + + my @args = ( 'primary_svc' => scalar($cgi->param('pkg_svc_primary')) ); + + ## + #options + ## + + $cgi->param('plan') =~ /^(\w+)$/ or die 'unparsable plan'; + my $plan = $1; + + tie my %plans, 'Tie::IxHash', %{ FS::part_pkg::plan_info() }; + my $href = $plans{$plan}->{'fields'}; + + my $error = ''; + my $options = $cgi->param($plan."__OPTIONS"); + my @options = split(',', $options); + my %options = + map { my $optionname = $_; + my $param = $plan."__$optionname"; + my $parser = exists($href->{$optionname}{parse}) + ? $href->{$optionname}{parse} + : sub { shift }; + my $value = join(', ', &$parser($cgi->param($param))); + my $check = $href->{$optionname}{check}; + if ( $check && ! &$check($value) ) { + $value = join(', ', $cgi->param($param)); + $error ||= "Illegal ". + ($href->{$optionname}{name}||$optionname). ": $value"; + } + ( $optionname => $value ); + } + grep { $_ !~ /^report_option_/ } + @options; + + foreach ( split(',', $cgi->param('taxproductnums') ) ) { + my $value = $cgi->param("taxproductnum_$_"); + $error ||= "Illegal taxproductnum_$_: $value" + unless ( $value =~ /^\d*$/ ); + $options{"usage_taxproductnum_$_"} = $value; + } + + foreach ( $cgi->param('report_option') ) { + $error ||= "Illegal optional report class: $_" unless ( $_ =~ /^\d*$/ ); + $options{"report_option_$_"} = 1; + } + + $options{$_} = scalar( $cgi->param($_) ) + for (qw( setup_fee recur_fee )); + + push @args, 'options' => \%options; + + ### + #pkg_svc + ### + + my %pkg_svc = map { $_ => scalar($cgi->param("pkg_svc$_")) } + map { $_->svcpart } + qsearch('part_svc', {} ); + + push @args, 'pkg_svc' => \%pkg_svc; + + ### + # cust_pkg and custnum_ref (inserts only) + ### + unless ( $cgi->param('pkgpart') ) { + push @args, 'cust_pkg' => scalar($cgi->param('pkgnum')), + 'custnum_ref' => \$custnum; + } + + #warn "args: ".join('/', @args). "\n"; + + @args; + +}; + +my $redirect_callback = sub { + #my( $cgi, $new ) = @_; + return '' unless $custnum; + my $show = $curuser->default_customer_view =~ /^(jumbo|packages)$/ + ? '' + : ';show=packages'; + #my $frag = "cust_pkg$pkgnum"; #hack for IE ignoring real #fragment + + #can we link back to the specific customized package? it would be nice... + popurl(3). "view/cust_main.cgi?custnum=$custnum$show;dummy="; +}; + +#these should probably move to @args above and be processed by part_pkg.pm... + +$cgi->param('tax_override') =~ /^([\d,]+)$/; +my (@tax_overrides) = (grep "$_", split (",", $1)); + +my @process_m2m = ( + { + 'link_table' => 'part_pkg_taxoverride', + 'target_table' => 'tax_class', + 'params' => \@tax_overrides, + }, + { 'link_table' => 'part_pkg_discount', + 'target_table' => 'discount', + 'params' => [ map $cgi->param($_), + grep /^discountnum/, $cgi->param + ], + }, + { 'link_table' => 'part_pkg_link', + 'target_table' => 'part_pkg', + 'base_field' => 'src_pkgpart', + 'target_field' => 'dst_pkgpart', + 'hashref' => { 'link_type' => 'svc', 'hidden' => '' }, + 'params' => [ map $cgi->param($_), + grep /^svc_dst_pkgpart/, $cgi->param + ], + }, + map { + my $hidden = $_; + { 'link_table' => 'part_pkg_link', + 'target_table' => 'part_pkg', + 'base_field' => 'src_pkgpart', + 'target_field' => 'dst_pkgpart', + 'hashref' => { 'link_type' => 'bill', 'hidden' => $hidden }, + 'params' => [ map { $cgi->param($_) } + grep { my $param = "bill_dst_pkgpart__hidden"; + my $digit = ''; + (($digit) = /^bill_dst_pkgpart(\d+)/ ) && + $cgi->param("$param$digit") eq $hidden; + } + $cgi->param + ], + }, + } ( '', 'Y' ), +); + +foreach my $override_class ($cgi->param) { + next unless $override_class =~ /^tax_override_(\w+)$/; + my $class = $1; + + my (@tax_overrides) = (grep "$_", split (",", $1)) + if $cgi->param($override_class) =~ /^([\d,]+)$/; + + push @process_m2m, { + 'link_table' => 'part_pkg_taxoverride', + 'target_table' => 'tax_class', + 'hashref' => { 'usage_class' => $class }, + 'params' => [ @tax_overrides ], + }; + +} + +my $conf = new FS::Conf; + +if ( $cgi->param('pkgpart') || ! $conf->exists('agent_defaultpkg') ) { + my @agents = (); + foreach ($cgi->param('agent_type')) { + /^(\d+)$/; + push @agents, $1 if $1; + } + push @process_m2m, { + 'link_table' => 'type_pkgs', + 'target_table' => 'agent_type', + 'params' => \@agents, + }; +} + +</%init> diff --git a/httemplate/edit/process/part_pkg_report_option.html b/httemplate/edit/process/part_pkg_report_option.html new file mode 100644 index 000000000..052aabd72 --- /dev/null +++ b/httemplate/edit/process/part_pkg_report_option.html @@ -0,0 +1,11 @@ +<% include( 'elements/process.html', + 'table' => 'part_pkg_report_option', + 'viewall_dir' => 'browse', + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +</%init> diff --git a/httemplate/edit/process/part_pkg_taxclass.html b/httemplate/edit/process/part_pkg_taxclass.html new file mode 100644 index 000000000..b37279fb3 --- /dev/null +++ b/httemplate/edit/process/part_pkg_taxclass.html @@ -0,0 +1,17 @@ +<% include( 'elements/process.html', + 'table' => 'part_pkg_taxclass', + 'redirect' => sub { + my( $cgi, $part_pkg_taxclass ) = @_; + + popurl(3). 'browse/cust_main_county.cgi?'. + 'taxclass='. uri_escape($part_pkg_taxclass->taxclass). + ';dummy='; + }, + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +</%init> diff --git a/httemplate/edit/process/part_referral.html b/httemplate/edit/process/part_referral.html new file mode 100755 index 000000000..40cbc97bf --- /dev/null +++ b/httemplate/edit/process/part_referral.html @@ -0,0 +1,12 @@ +<% include( 'elements/process.html', + 'table' => 'part_referral', + 'viewall_dir' => 'browse', + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Edit advertising sources') + || $FS::CurrentUser::CurrentUser->access_right('Edit global advertising sources'); + +</%init> diff --git a/httemplate/edit/process/part_svc.cgi b/httemplate/edit/process/part_svc.cgi new file mode 100755 index 000000000..65de3fc6c --- /dev/null +++ b/httemplate/edit/process/part_svc.cgi @@ -0,0 +1,9 @@ +<% $server->process %> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my $server = new FS::UI::Web::JSRPC 'FS::part_svc::process', $cgi; + +</%init> diff --git a/httemplate/edit/process/part_tag.html b/httemplate/edit/process/part_tag.html new file mode 100644 index 000000000..077dc4cd9 --- /dev/null +++ b/httemplate/edit/process/part_tag.html @@ -0,0 +1,11 @@ +<% include( 'elements/process.html', + 'table' => 'part_tag', + 'viewall_dir' => 'browse', + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +</%init> diff --git a/httemplate/edit/process/payment_gateway.html b/httemplate/edit/process/payment_gateway.html new file mode 100644 index 000000000..812c988c5 --- /dev/null +++ b/httemplate/edit/process/payment_gateway.html @@ -0,0 +1,22 @@ +<% include( 'elements/process.html', + 'table' => 'payment_gateway', + 'viewall_dir' => 'browse', + 'args_callback' => $args_callback, + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my $args_callback = sub { + my ( $cgi, $new ) = @_; + + my @options = split(/\r?\n/, $cgi->param('gateway_options') ); + pop @options + if scalar(@options) % 2 && $options[-1] =~ /^\s*$/; + (@options) +}; + + +</%init> diff --git a/httemplate/edit/process/phone_device.html b/httemplate/edit/process/phone_device.html new file mode 100644 index 000000000..df9d5e793 --- /dev/null +++ b/httemplate/edit/process/phone_device.html @@ -0,0 +1,18 @@ +<% include( 'elements/process.html', + 'table' => 'phone_device', + 'redirect' => sub { + my( $cgi, $phone_device ) = @_; + popurl(3).'view/svc_phone.cgi?'. + 'svcnum='. $phone_device->svcnum. + ';devicenum='; + }, + ) +%> +<%init> + +# :/ needs agent-virt so you can't futz with arbitrary devices + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific? + +</%init> diff --git a/httemplate/edit/process/pkg_category.html b/httemplate/edit/process/pkg_category.html new file mode 100644 index 000000000..50cd5cb29 --- /dev/null +++ b/httemplate/edit/process/pkg_category.html @@ -0,0 +1,11 @@ +<% include( 'elements/process.html', + 'table' => 'pkg_category', + 'viewall_dir' => 'browse', + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +</%init> diff --git a/httemplate/edit/process/pkg_class.html b/httemplate/edit/process/pkg_class.html new file mode 100644 index 000000000..b196df3f7 --- /dev/null +++ b/httemplate/edit/process/pkg_class.html @@ -0,0 +1,11 @@ +<% include( 'elements/process.html', + 'table' => 'pkg_class', + 'viewall_dir' => 'browse', + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +</%init> diff --git a/httemplate/edit/process/prepay_credit.cgi b/httemplate/edit/process/prepay_credit.cgi new file mode 100644 index 000000000..a55522b86 --- /dev/null +++ b/httemplate/edit/process/prepay_credit.cgi @@ -0,0 +1,63 @@ +%unless ( ref($error) ) { +% $cgi->param('error', $error ); +<% $cgi->redirect(popurl(3). "edit/prepay_credit.cgi?". $cgi->query_string ) %> +% } else { + +<% include('/elements/header.html', "$num prepaid cards generated". + ( $agent ? ' for '.$agent->agent : '' ) + ) +%> + +<FONT SIZE="+1"> +% foreach my $card ( @$error ) { + + <code><% $card %></code> + - + <% $hashref->{amount} ? sprintf('$%.2f', $hashref->{amount} ) : '' %> + <% $hashref->{amount} && $hashref->{seconds} ? 'and' : '' %> + <% $hashref->{seconds} ? duration_exact($hashref->{seconds}) : '' %> + <% $hashref->{upbytes} ? FS::UI::bytecount::bytecount_unexact($hashref->{upbytes}) : '' %> + <% $hashref->{downbytes} ? FS::UI::bytecount::bytecount_unexact($hashref->{downbytes}) : '' %> + <% $hashref->{totalbytes} ? FS::UI::bytecount::bytecount_unexact($hashref->{totalbytes}) : '' %> + <br> +% } + +</FONT> + +<% include('/elements/footer.html') %> + +% } +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my $hashref = {}; + +my $agent = ''; +if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) { + $agent = qsearchs('agent', { 'agentnum' => $hashref->{agentnum}=$1 } ); +} + +my $error = ''; + +my $num = 0; +if ( $cgi->param('num') =~ /^\s*(\d+)\s*$/ ) { + $num = $1; +} else { + $error = 'Illegal number of prepaid cards: '. $cgi->param('num'); +} + +$hashref->{amount} = $cgi->param('amount'); +$hashref->{seconds} = $cgi->param('seconds') * $cgi->param('multiplier'); +$hashref->{upbytes} = $cgi->param('upbytes') * $cgi->param('upmultiplier'); +$hashref->{downbytes} = $cgi->param('downbytes') * $cgi->param('downmultiplier'); +$hashref->{totalbytes} = $cgi->param('totalbytes') * $cgi->param('totalmultiplier'); + +$error ||= FS::prepay_credit::generate( $num, + scalar($cgi->param('type')), + $cgi->param('length'), + $hashref + ); + +</%init> diff --git a/httemplate/edit/process/prospect_main.html b/httemplate/edit/process/prospect_main.html new file mode 100644 index 000000000..34d26421b --- /dev/null +++ b/httemplate/edit/process/prospect_main.html @@ -0,0 +1,34 @@ +<% include('elements/process.html', + 'table' => 'prospect_main', + 'args_callback' => $args_callback, + 'agent_virt' => 1, + 'process_o2m' => { + 'table' => 'contact', + 'fields' => [qw( first last title comment )], + }, + 'redirect' => popurl(3). 'view/prospect_main.html?', + ) +%> +<%init> + +my $args_callback = sub { + my( $cgi, $object ) = @_; + + $cgi->param('locationnum') =~ /^(\-?\d*)$/ + or die 'illegal locationnum '. $cgi->param('locationnum'); + my $locationnum = $1; + + return ( 'cust_location' => '' ) unless $locationnum; + + my $cust_location = new FS::cust_location { + map { $_ => scalar($cgi->param($_)) } + qw( address1 address2 city county state zip country ) + }; + + $cust_location->locationnum($locationnum) unless $locationnum == -1; + + ( 'cust_location' => $cust_location ); + +}; + +</%init> diff --git a/httemplate/edit/process/quick-charge.cgi b/httemplate/edit/process/quick-charge.cgi new file mode 100644 index 000000000..484f6fcc6 --- /dev/null +++ b/httemplate/edit/process/quick-charge.cgi @@ -0,0 +1,75 @@ +% if ( $error ) { +% $cgi->param('error', $error ); +<% $cgi->redirect($p.'quick-charge.html?'. $cgi->query_string) %> +% } else { +<% header("One-time charge added") %> + <SCRIPT TYPE="text/javascript"> + window.top.location.reload(); + </SCRIPT> + </BODY></HTML> +% } +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('One-time charge'); + +my $error = ''; +my $conf = new FS::conf; +my $param = $cgi->Vars; + +my @description = (); +for ( my $row = 0; exists($param->{"description$row"}); $row++ ) { + push @description, $param->{"description$row"} + if ($param->{"description$row"} =~ /\S/); +} + +$param->{"custnum"} =~ /^(\d+)$/ + or $error .= "Illegal customer number " . $param->{"custnum"} . " "; +my $custnum = $1; + +$param->{"amount"} =~ /^\s*(\d*(?:\.?\d{1,2}))\s*$/ + or $error .= "Illegal amount " . $param->{"amount"} . " "; +my $amount = $1; + +my $quantity = 1; +if ( $cgi->param('quantity') =~ /^\s*(\d+)\s*$/ ) { + $quantity = $1; +} + +$param->{'tax_override'} =~ /^\s*([,\d]*)\s*$/ + or $error .= "Illegal tax override " . $param->{"tax_override"} . " "; +my $override = $1; + +if ( $param->{'taxclass'} eq '(select)' ) { + $error .= "Must select a tax class. " + unless ($conf->exists('enable_taxproducts') && + ( $override || $param->{taxproductnum} ) + ); + $cgi->param('taxclass', ''); +} + +unless ( $error ) { + my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ) + or $error .= "Unknown customer number $custnum. "; + + $error ||= $cust_main->charge( { + 'amount' => $amount, + 'quantity' => $quantity, + 'bill_now' => scalar($cgi->param('bill_now')), + 'invoice_terms' => scalar($cgi->param('invoice_terms')), + 'start_date' => ( scalar($cgi->param('start_date')) + ? parse_datetime($cgi->param('start_date')) + : '' + ), + 'no_auto' => scalar($cgi->param('no_auto')), + 'pkg' => scalar($cgi->param('pkg')), + 'setuptax' => scalar($cgi->param('setuptax')), + 'taxclass' => scalar($cgi->param('taxclass')), + 'taxproductnum' => scalar($cgi->param('taxproductnum')), + 'tax_override' => $override, + 'classnum' => scalar($cgi->param('classnum')), + 'additional' => \@description, + } ); +} + +</%init> diff --git a/httemplate/edit/process/quick-cust_pkg.cgi b/httemplate/edit/process/quick-cust_pkg.cgi new file mode 100644 index 000000000..2fde17f5e --- /dev/null +++ b/httemplate/edit/process/quick-cust_pkg.cgi @@ -0,0 +1,84 @@ +%if ($error) { +% $cgi->param('error', $error); +<% $cgi->redirect(popurl(3). 'misc/order_pkg.html?'. $cgi->query_string ) %> +%} else { +% my $frag = "cust_pkg". $cust_pkg->pkgnum; +% my $show = $curuser->default_customer_view =~ /^(jumbo|packages)$/ +% ? '' +% : ';show=packages'; +<% 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?custnum=$custnum$show;fragment=$frag#$frag" %>'; + + </SCRIPT> + + </BODY></HTML> +%} +<%init> + +my $curuser = $FS::CurrentUser::CurrentUser; + +die "access denied" + unless $curuser->access_right('Order customer package'); + +#untaint custnum (probably not necessary, searching for it is escape enough) +$cgi->param('custnum') =~ /^(\d+)$/ + or die 'illegal custnum '. $cgi->param('custnum'); +my $custnum = $1; +my $cust_main = qsearchs({ + 'table' => 'cust_main', + 'hashref' => { 'custnum' => $custnum }, + 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql, +}); +die 'unknown custnum' unless $cust_main; + +#probably not necessary, taken care of by cust_pkg::check +$cgi->param('pkgpart') =~ /^(\d+)$/ + or die 'illegal pkgpart '. $cgi->param('pkgpart'); +my $pkgpart = $1; +$cgi->param('refnum') =~ /^(\d*)$/ + or die 'illegal refnum '. $cgi->param('refnum'); +my $refnum = $1; +$cgi->param('locationnum') =~ /^(\-?\d*)$/ + or die 'illegal locationnum '. $cgi->param('locationnum'); +my $locationnum = $1; +$cgi->param('discountnum') =~ /^(\-?\d*)$/ + or die 'illegal discountnum '. $cgi->param('discountnum'); +my $discountnum = $1; + + +my $cust_pkg = new FS::cust_pkg { + 'custnum' => $custnum, + 'pkgpart' => $pkgpart, + 'start_date' => ( scalar($cgi->param('start_date')) + ? parse_datetime($cgi->param('start_date')) + : '' + ), + 'no_auto' => scalar($cgi->param('no_auto')), + 'refnum' => $refnum, + 'locationnum' => $locationnum, + 'discountnum' => $discountnum, + #for the create a new discount case + 'discountnum__type' => scalar($cgi->param('discountnum__type')), + 'discountnum_amount' => scalar($cgi->param('discountnum_amount')), + 'discountnum_percent' => scalar($cgi->param('discountnum_percent')), + 'discountnum_months' => scalar($cgi->param('discountnum_months')), + #'discountnum_disabled' => scalar($cgi->param('discountnum_disabled')), +}; + +my %opt = ( 'cust_pkg' => $cust_pkg ); + +if ( $locationnum == -1 ) { + my $cust_location = new FS::cust_location { + map { $_ => scalar($cgi->param($_)) } + qw( custnum address1 address2 city county state zip country ) + }; + $opt{'cust_location'} = $cust_location; +} + +my $error = $cust_main->order_pkg( %opt ); + +</%init> diff --git a/httemplate/edit/process/rate.cgi b/httemplate/edit/process/rate.cgi new file mode 100755 index 000000000..48d9322ca --- /dev/null +++ b/httemplate/edit/process/rate.cgi @@ -0,0 +1,9 @@ +<% $server->process %> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my $server = new FS::UI::Web::JSRPC 'FS::rate::process', $cgi; + +</%init> diff --git a/httemplate/edit/process/rate_detail.html b/httemplate/edit/process/rate_detail.html new file mode 100644 index 000000000..6200d615f --- /dev/null +++ b/httemplate/edit/process/rate_detail.html @@ -0,0 +1,13 @@ +<% include( 'elements/process.html', + 'table' => 'rate_detail', + 'popup_reload' => 'Rate changed', #a popup "parent reload" for now + #someday change the individual element and go away instead + ) +%> +<%init> + +my $conf = new FS::Conf; +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +</%init> diff --git a/httemplate/edit/process/rate_region.cgi b/httemplate/edit/process/rate_region.cgi new file mode 100755 index 000000000..d342e605a --- /dev/null +++ b/httemplate/edit/process/rate_region.cgi @@ -0,0 +1,48 @@ +%if ( $error ) { +% $cgi->param('error', $error); +<% $cgi->redirect(popurl(2). "rate_region.cgi?". $cgi->query_string ) %> +%} elsif ( $action eq 'Add' ) { +<% $cgi->redirect(popurl(2). "rate_region.cgi?$regionnum") %> +%} else { +<% $cgi->redirect(popurl(3). "browse/rate_region.html") %> +%} +<%init> + +my $conf = new FS::Conf; +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my $regionnum = $cgi->param('regionnum'); +my $action = $regionnum ? 'Edit' : 'Add'; + +my $old = qsearchs('rate_region', { 'regionnum' => $regionnum } ) if $regionnum; + +my $new = new FS::rate_region ( { + map { + $_, scalar($cgi->param($_)); + } ( fields('rate_region') ) +} ); + +my $countrycode = $cgi->param('countrycode'); +my @npa = split(/\s*,\s*/, $cgi->param('npa')); +$npa[0] = '' unless @npa; +my @rate_prefix = map { + #my($npa,$nxx) = split('-', $_); + s/\D//g; + new FS::rate_prefix { + 'countrycode' => $countrycode, + #'npa' => $npa, + #'nxx' => $nxx, + 'npa' => $_, + } + } @npa; +# we no longer process dest_detail records here +my $error; +if ( $regionnum ) { + $error = $new->replace($old, 'rate_prefix' => \@rate_prefix ); +} else { + $error = $new->insert( 'rate_prefix' => \@rate_prefix ); + $regionnum = $new->getfield('regionnum'); +} + +</%init> diff --git a/httemplate/edit/process/rate_time.cgi b/httemplate/edit/process/rate_time.cgi new file mode 100644 index 000000000..2b00be3ea --- /dev/null +++ b/httemplate/edit/process/rate_time.cgi @@ -0,0 +1,93 @@ +% if ( $error ) { +% $cgi->param('error', $error); +<% $cgi->redirect(popurl(2). "rate_time.cgi?". $cgi->query_string ) %> +% } else { +<% $cgi->redirect(popurl(3). "browse/rate_time.html" ) %> +% } +<%init> +my $error = ''; +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); +my $ratetimenum = $cgi->param('ratetimenum'); +my $ratetimename = $cgi->param('ratetimename'); +my $delete = $cgi->param('delete'); + +my %vars = $cgi->Vars; +#warn Dumper(\%vars)."\n"; + +my $rate_time; + +my %old_ints; +if( $ratetimenum ) { + # editing + $rate_time = FS::rate_time->by_key($ratetimenum); + + # make a list of existing intervals that will be deleted + foreach ($rate_time->intervals) { + $old_ints{$_->intervalnum} = $_; + } + + if ( $delete ) { + $error = $rate_time->delete; + # intervals will be deleted later + } + elsif( $ratetimename ne $rate_time->ratetimename ) { + # the only case where the rate_time itself must be replaced + $rate_time->ratetimename($ratetimename); + $error = $rate_time->replace; + } +} +else { #!$ratetimenum, adding new + $rate_time = FS::rate_time->new({ ratetimename => $ratetimename }); + $error = $rate_time->insert; + $ratetimenum = $rate_time->ratetimenum; +} + +my @new_ints; +if(!$delete and !$error) { + foreach my $i (map { /^sd(\d+)$/ } keys(%vars)) { + my $stime = l2wtime(@vars{"sd$i", "sh$i", "sm$i", "sa$i"}); + my $etime = l2wtime(@vars{"ed$i", "eh$i", "em$i", "ea$i"}); + #warn "$i: $stime - $etime"; + next if !defined($stime) or !defined($etime) or $etime == $stime; + # try to avoid needlessly wiping and replacing intervals every + # time this is edited. + if( %old_ints ) { + my $this_int = qsearchs('rate_time_interval', + { ratetimenum => $ratetimenum, + stime => $stime, + etime => $etime, } ); + if($this_int) { + delete $old_ints{$this_int->intervalnum}; + #warn "not deleting $stime-$etime\n"; + next; #$i + } + } + push @new_ints, FS::rate_time_interval->new({ ratetimenum => $ratetimenum, + stime => $stime, + etime => $etime, } ); + } +} +if(!$error) { + foreach (values(%old_ints)) { + $error = $_->delete; + #warn "deleting ".$_->stime.' '.$_->etime."\n"; + last if $error; + } +} +if(!$error) { + # do this last to avoid overlap errors with deleted intervals + foreach (@new_ints) { + $error = $_->insert; + #warn "inserting $stime-$etime\n"; + last if $error; + } +} + +sub l2wtime { + my ($d, $h, $m, $a) = @_; + $h = ($h % 12) + 24*$d + 12*$a; + $m += 60*$h; + return 60*$m +} +</%init> diff --git a/httemplate/edit/process/reason.html b/httemplate/edit/process/reason.html new file mode 100644 index 000000000..cb79ed254 --- /dev/null +++ b/httemplate/edit/process/reason.html @@ -0,0 +1,12 @@ +<% include( 'elements/process.html', + 'table' => 'reason', + 'redirect' => popurl(3) . 'browse/reason.html?class=' . + $cgi->param('class') . '&', + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +</%init> diff --git a/httemplate/edit/process/reason_type.html b/httemplate/edit/process/reason_type.html new file mode 100644 index 000000000..3172b27c4 --- /dev/null +++ b/httemplate/edit/process/reason_type.html @@ -0,0 +1,12 @@ +<% include( 'elements/process.html', + 'table' => 'reason_type', + 'redirect' => popurl(3) . 'browse/reason_type.html?class=' . + $cgi->param('class') . '&', + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +</%init> diff --git a/httemplate/edit/process/reg_code.cgi b/httemplate/edit/process/reg_code.cgi new file mode 100644 index 000000000..035e10b90 --- /dev/null +++ b/httemplate/edit/process/reg_code.cgi @@ -0,0 +1,45 @@ +%unless ( ref($error) ) { +% $cgi->param('error'. $error ); +<% $cgi->redirect(popurl(3). "edit/reg_code.cgi?". $cgi->query_string ) %> +% } else { + +<% include("/elements/header.html","$num registration codes generated for ". $agent->agent, menubar( + 'View all agents' => popurl(3). 'browse/agent.cgi', +) ) %> + +<PRE><FONT SIZE="+1"> +% foreach my $code ( @$error ) { + <% $code %> +% } +</FONT></PRE> + +<% include('/elements/footer.html') %> +% } +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +$cgi->param('agentnum') =~ /^(\d+)$/ + or errorpage('illegal agentnum '. $cgi->param('agentnum')); +my $agentnum = $1; +my $agent = qsearchs('agent', { 'agentnum' => $agentnum } ); + +my $error = ''; + +my $num = 0; +if ( $cgi->param('num') =~ /^\s*(\d+)\s*$/ ) { + $num = $1; +} else { + $error = 'Illegal number of codes: '. $cgi->param('num'); +} + +my @pkgparts = + map { /^pkgpart(.*)$/; $1 } + grep { $cgi->param($_) } + grep { /^pkgpart/ } + $cgi->param; + +$error ||= $agent->generate_reg_codes($num, \@pkgparts); + +</%init> diff --git a/httemplate/edit/process/router.cgi b/httemplate/edit/process/router.cgi new file mode 100644 index 000000000..3cbb8c58e --- /dev/null +++ b/httemplate/edit/process/router.cgi @@ -0,0 +1,20 @@ +<% include('elements/process.html', + 'table' => 'router', + 'viewall_dir' => 'browse', + 'viewall_ext' => 'cgi', + 'edit_ext' => 'cgi', + 'process_m2m' => { 'link_table' => 'part_svc_router', + 'target_table' => 'part_svc', + }, + 'agent_virt' => 1, + 'agent_null_right' => 'Broadband global configuration', + ) +%> +<%init> +my $curuser = $FS::CurrentUser::CurrentUser; + +die "access denied" + unless $curuser->access_right('Broadband configuration') + || $curuser->access_right('Broadband global configuration'); + +</%init> diff --git a/httemplate/edit/process/svc_Common.html b/httemplate/edit/process/svc_Common.html new file mode 100644 index 000000000..cf5f01f71 --- /dev/null +++ b/httemplate/edit/process/svc_Common.html @@ -0,0 +1,16 @@ +<% include( 'elements/svc_Common.html', + 'table' => $table, + 'redirect' => popurl(3)."view/svc_Common.html?svcdb=$table;svcnum=", + 'error_redirect' => popurl(3)."edit/svc_Common.html?svcdb=$table;", + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific? + +$cgi->param('svcdb') =~ /^(svc_\w+)$/ or die "unparsable svcdb"; +my $table = $1; +require "FS/$table.pm"; + +</%init> diff --git a/httemplate/edit/process/svc_acct.cgi b/httemplate/edit/process/svc_acct.cgi new file mode 100755 index 000000000..ba21ab4b5 --- /dev/null +++ b/httemplate/edit/process/svc_acct.cgi @@ -0,0 +1,83 @@ +%if ( $error ) { +% $cgi->param('error', $error); +<% $cgi->redirect(popurl(2). "svc_acct.cgi?". $cgi->query_string ) %> +%} else { +<% $cgi->redirect(popurl(3). "view/svc_acct.cgi?" . $svcnum ) %> +%} +<%init> +use CGI::Carp; +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific? + +$cgi->param('svcnum') =~ /^(\d*)$/ or die "Illegal svcnum!"; +my $svcnum = $1; + +my $old; +if ( $svcnum ) { + $old = qsearchs('svc_acct', { 'svcnum' => $svcnum } ) + or die "fatal: can't find account (svcnum $svcnum)!"; +} else { + $old = ''; +} + +#unmunge popnum +$cgi->param('popnum', (split(/:/, $cgi->param('popnum') ))[0] ); + +#unmunge usergroup +$cgi->param('usergroup', [ $cgi->param('radius_usergroup') ] ); + +#unmunge bytecounts +foreach (map { $_,$_."_threshold" } qw( upbytes downbytes totalbytes )) { + $cgi->param($_, FS::UI::bytecount::parse_bytecount($cgi->param($_)) ); +} + +#unmunge cgp_accessmodes (falze laziness-ish w/part_svc.pm::process &svc_domain) +unless ( $cgi->param('cgp_accessmodes') ) { + $cgi->param('cgp_accessmodes', + join(' ', + sort map { /^cgp_accessmodes_([\w\/]+)$/ or die "no way"; $1; } + grep $cgi->param($_), + grep /^cgp_accessmodes_([\w\/]+)$/, + $cgi->param() + ) + ); +} + +my %hash = $svcnum ? $old->hash : (); +map { + $hash{$_} = scalar($cgi->param($_)); + #} qw(svcnum pkgnum svcpart username _password popnum uid gid finger dir + # shell quota slipip) + } (fields('svc_acct'), qw ( pkgnum svcpart usergroup )); +my $new = new FS::svc_acct ( \%hash ); + +my $error = ''; + +$new->_password($old->_password) if $old; +if ( $cgi->param('clear_password') eq '*HIDDEN*' + || $cgi->param('clear_password') =~ /^\(.* encrypted\)$/ ) { + die "fatal: no previous account to recall hidden password from!" unless $old; +} else { + $error = $new->set_password($cgi->param('clear_password')); +} + +if ( $svcnum ) { + foreach ( grep { $old->$_ != $new->$_ } + qw( seconds upbytes downbytes totalbytes ) + ) + { + my %hash = map { $_ => $new->$_ } + grep { $new->$_ } + qw( seconds upbytes downbytes totalbytes ); + + $error ||= "invalid $_" foreach grep { $hash{$_} !~ /^-?\d+$/ } keys %hash; + $error ||= $new->set_usage(\%hash); #unoverlimit and trigger radius changes + last; #once is enough + } + $error ||= $new->replace($old); +} else { + $error ||= $new->insert; + $svcnum = $new->svcnum; +} + +</%init> diff --git a/httemplate/edit/process/svc_acct_pop.cgi b/httemplate/edit/process/svc_acct_pop.cgi new file mode 100755 index 000000000..6e823a824 --- /dev/null +++ b/httemplate/edit/process/svc_acct_pop.cgi @@ -0,0 +1,33 @@ +%if ( $error ) { +% $cgi->param('error', $error); +<% $cgi->redirect(popurl(2). "svc_acct_pop.cgi?". $cgi->query_string ) %> +%} else { +<% $cgi->redirect(popurl(3). "browse/svc_acct_pop.cgi") %> +%} +<%init> + +my $curuser = $FS::CurrentUser::CurrentUser; + +die "access denied" + unless $curuser->access_right('Dialup configuration') + || $curuser->access_right('Dialup global configuration'); + +my $popnum = $cgi->param('popnum'); + +my $old = qsearchs('svc_acct_pop',{'popnum'=>$popnum}) if $popnum; + +my $new = new FS::svc_acct_pop ( { + map { + $_, scalar($cgi->param($_)); + } fields('svc_acct_pop') +} ); + +my $error = ''; +if ( $popnum ) { + $error = $new->replace($old); +} else { + $error = $new->insert; + $popnum=$new->getfield('popnum'); +} + +</%init> diff --git a/httemplate/edit/process/svc_broadband.cgi b/httemplate/edit/process/svc_broadband.cgi new file mode 100644 index 000000000..d5c9820bb --- /dev/null +++ b/httemplate/edit/process/svc_broadband.cgi @@ -0,0 +1,8 @@ +<% include('elements/svc_Common.html', 'table' => 'svc_broadband') %> +<%init> +my $curuser = $FS::CurrentUser::CurrentUser; + +die "access denied" + unless $curuser->access_right('Provision customer service'); #something else more specific? + +</%init> diff --git a/httemplate/edit/process/svc_domain-defaultrecords.cgi b/httemplate/edit/process/svc_domain-defaultrecords.cgi new file mode 100644 index 000000000..feb58406c --- /dev/null +++ b/httemplate/edit/process/svc_domain-defaultrecords.cgi @@ -0,0 +1,14 @@ +<% $cgi->redirect(popurl(3). "view/svc_domain.cgi?$svcnum") %> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Edit domain nameservice'); + +my $svcnum = scalar($cgi->param('svcnum')); + +my $svc_domain = qsearchs('svc_domain', { 'svcnum' => $svcnum }) + or die 'unknown svc_domain.svcnum'; + +my $error = $svc_domain->insert_defaultrecords; + +</%init> diff --git a/httemplate/edit/process/svc_domain.cgi b/httemplate/edit/process/svc_domain.cgi new file mode 100755 index 000000000..381339bc8 --- /dev/null +++ b/httemplate/edit/process/svc_domain.cgi @@ -0,0 +1,57 @@ +%if ($error) { +% $cgi->param('error', $error); +<% $cgi->redirect(popurl(2). "svc_domain.cgi?". $cgi->query_string ) %> +%} else { +<% $cgi->redirect(popurl(3). "view/svc_domain.cgi?$svcnum") %> +%} +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific? + +#remove this to actually test the domains! +$FS::svc_domain::whois_hack = 1; + +$cgi->param('svcnum') =~ /^(\d*)$/ or die "Illegal svcnum!"; +my $svcnum = $1; + +#unmunge cgp_accessmodes (falze laziness-ish w/part_svc.pm::process & svc_acct) +unless ( $cgi->param('cgp_accessmodes') ) { + $cgi->param('cgp_accessmodes', + join(' ', + sort map { /^cgp_accessmodes_([\w\/]+)$/ or die "no way"; $1; } + grep $cgi->param($_), + grep /^cgp_accessmodes_([\w\/]+)$/, + $cgi->param() + ) + ); +} + +#unmunge acct_def_cgp_accessmodes (falze laziness-ahoy) +unless ( $cgi->param('acct_def_cgp_accessmodes') ) { + $cgi->param('acct_def_cgp_accessmodes', + join(' ', + sort map { /^acct_def_cgp_accessmodes_([\w\/]+)$/ or die "no way"; $1; } + grep $cgi->param($_), + grep /^acct_def_cgp_accessmodes_([\w\/]+)$/, + $cgi->param() + ) + ); +} + +my $new = new FS::svc_domain ( { + map { + $_, scalar($cgi->param($_)); + #} qw(svcnum pkgnum svcpart domain action) + } ( fields('svc_domain'), qw( pkgnum svcpart action ) ) +} ); + +my $error = ''; +if ($cgi->param('svcnum')) { + $error = $new->replace(); +} else { + $error = $new->insert; + $svcnum = $new->svcnum; +} + +</%init> diff --git a/httemplate/edit/process/svc_external.cgi b/httemplate/edit/process/svc_external.cgi new file mode 100755 index 000000000..673e5a5a0 --- /dev/null +++ b/httemplate/edit/process/svc_external.cgi @@ -0,0 +1,31 @@ +%if ($error) { +% $cgi->param('error', $error); +<% $cgi->redirect(popurl(2). "svc_external.cgi?". $cgi->query_string ) %> +%} else { +<% $cgi->redirect(popurl(3). "view/svc_external.cgi?$svcnum") %> +%} +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific? + +$cgi->param('svcnum') =~ /^(\d*)$/ or die "Illegal svcnum!"; +my $svcnum =$1; + +my $old = qsearchs('svc_external',{'svcnum'=>$svcnum}) if $svcnum; + +my $new = new FS::svc_external ( { + map { + ($_, scalar($cgi->param($_))); + } ( fields('svc_external'), qw( pkgnum svcpart ) ) +} ); + +my $error = ''; +if ( $svcnum ) { + $error = $new->replace($old); +} else { + $error = $new->insert; + $svcnum = $new->getfield('svcnum'); +} + +</%init> diff --git a/httemplate/edit/process/svc_external.html b/httemplate/edit/process/svc_external.html new file mode 100644 index 000000000..3515afc4b --- /dev/null +++ b/httemplate/edit/process/svc_external.html @@ -0,0 +1,10 @@ +<% include( 'elements/svc_Common.html', + 'table' => 'svc_external', + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific? + +</%init> diff --git a/httemplate/edit/process/svc_forward.cgi b/httemplate/edit/process/svc_forward.cgi new file mode 100755 index 000000000..fffad84d6 --- /dev/null +++ b/httemplate/edit/process/svc_forward.cgi @@ -0,0 +1,31 @@ +%if ($error) { +% $cgi->param('error', $error); +<% $cgi->redirect(popurl(2). "svc_forward.cgi?". $cgi->query_string ) %> +%} else { +<% $cgi->redirect(popurl(3). "view/svc_forward.cgi?$svcnum") %> +%} +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific? + +$cgi->param('svcnum') =~ /^(\d*)$/ or die "Illegal svcnum!"; +my $svcnum =$1; + +my $old = qsearchs('svc_forward',{'svcnum'=>$svcnum}) if $svcnum; + +my $new = new FS::svc_forward ( { + map { + ($_, scalar($cgi->param($_))); + } ( fields('svc_forward'), qw( pkgnum svcpart ) ) +} ); + +my $error = ''; +if ( $svcnum ) { + $error = $new->replace($old); +} else { + $error = $new->insert; + $svcnum = $new->getfield('svcnum'); +} + +</%init> diff --git a/httemplate/edit/process/svc_mailinglist.html b/httemplate/edit/process/svc_mailinglist.html new file mode 100644 index 000000000..580f6ccbd --- /dev/null +++ b/httemplate/edit/process/svc_mailinglist.html @@ -0,0 +1,11 @@ +<% include( 'elements/svc_Common.html', + 'table' => 'svc_mailinglist', + 'fields' => [ fields('svc_mailinglist'), 'listname' ], + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific? + +</%init> diff --git a/httemplate/edit/process/svc_phone.html b/httemplate/edit/process/svc_phone.html new file mode 100644 index 000000000..e02ec5ccc --- /dev/null +++ b/httemplate/edit/process/svc_phone.html @@ -0,0 +1,29 @@ +<% include( 'elements/svc_Common.html', + 'table' => 'svc_phone', + 'args_callback' => $args_callback, + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific? + +my $args_callback = sub { + my( $cgi, $object ) = @_; + + my %opt = (); + if ( $cgi->param('locationnum') == -1 ) { + my $cust_location = new FS::cust_location { + map { $_ => scalar($cgi->param($_)) } + qw( custnum address1 address2 city county state zip country ) + }; + $opt{'cust_location'} = $cust_location; + } + + %opt; + +}; + + + +</%init> diff --git a/httemplate/edit/process/svc_www.cgi b/httemplate/edit/process/svc_www.cgi new file mode 100644 index 000000000..f02d25305 --- /dev/null +++ b/httemplate/edit/process/svc_www.cgi @@ -0,0 +1,38 @@ +%if ( $error ) { +% $cgi->param('error', $error); +<% $cgi->redirect(popurl(2). "svc_www.cgi?". $cgi->query_string ) %> +%} else { +<% $cgi->redirect(popurl(3). "view/svc_www.cgi?" . $svcnum ) %> +%} +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific? + +$cgi->param('svcnum') =~ /^(\d*)$/ or die "Illegal svcnum!"; +my $svcnum = $1; + +my $old; +if ( $svcnum ) { + $old = qsearchs('svc_www', { 'svcnum' => $svcnum } ) + or die "fatal: can't find website (svcnum $svcnum)!"; +} else { + $old = ''; +} + +my $new = new FS::svc_www ( { + map { + ($_, scalar($cgi->param($_))); + #} qw(svcnum pkgnum svcpart recnum usersvc) + } ( fields('svc_www'), qw( pkgnum svcpart ) ) +} ); + +my $error; +if ( $svcnum ) { + $error = $new->replace($old); +} else { + $error = $new->insert; + $svcnum = $new->svcnum; +} + +</%init> diff --git a/httemplate/edit/process/tax_class.html b/httemplate/edit/process/tax_class.html new file mode 100644 index 000000000..339c9083e --- /dev/null +++ b/httemplate/edit/process/tax_class.html @@ -0,0 +1,49 @@ +% if ( $error ) { +% $cgi->param('error', $error); +<% $cgi->redirect(popurl(2). "tax_class.html?". $cgi->query_string ) %> +%} else { +<% $cgi->redirect(popurl(3). "browse/tax_rate.cgi?taxclassnum=". uri_escape($tax_class->taxclassnum) ) %> +%} +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my $tax_class = new FS::tax_class { + 'taxclass' => $cgi->param('taxclass'), + 'description' => $cgi->param('description'), +}; + +#maybe this whole thing should be in a transaction. at some point, no biggie +#none of the follow-up stuff will fail unless there's a more serious problem +#than a hanging record in tax_class... + +my $error = $tax_class->insert; + +# all of this is highly dubious at the moment + +#unless ( $error ) { +# #auto-add the new taxclass to any regions that have taxclasses already +# +# my $sth = dbh->prepare(" +# SELECT geocode FROM tax_rate +# WHERE taxclass IS NOT NULL AND taxclass != '' +# GROUP BY geocode +# ") or die dbh->errstr; +# $sth->execute or die $sth->errstr; +# +# while ( my $row = $sth->fetchrow_hashref ) { +# warn "inserting for $row"; +# my $cust_main_county = new FS::tax_rate { +# 'geocode' => $row->{geocode}, +# 'tax' => 0, +# 'taxclassnum' => $tax_class->taxclassnum, +# }; +# $error = $cust_main_county->insert; +# #last if $error; +# die $error if $error; +# } +# +#} + +</%init> diff --git a/httemplate/edit/process/tax_rate.html b/httemplate/edit/process/tax_rate.html new file mode 100644 index 000000000..431e54264 --- /dev/null +++ b/httemplate/edit/process/tax_rate.html @@ -0,0 +1,22 @@ +<% include( 'elements/process.html', + 'table' => 'tax_rate', + 'value_callback' => $value_callback, + 'popup_reload' => 'Tax changed', #a popup "parent reload" for now + #someday change the individual element and go away instead + ) +%> +<%once> + +my $value_callback = sub { my ($field, $value) = @_; + ($field =~ /^(tax|excessrate|usetax|useexcessrate)$/) + ? $value/100 + : $value + }; +</%once> +<%init> + +my $conf = new FS::Conf; +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +</%init> diff --git a/httemplate/edit/process/usage_class.html b/httemplate/edit/process/usage_class.html new file mode 100644 index 000000000..cf50cb762 --- /dev/null +++ b/httemplate/edit/process/usage_class.html @@ -0,0 +1,11 @@ +<% include( 'elements/process.html', + 'table' => 'usage_class', + 'viewall_dir' => 'browse', + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +</%init> |