From: Ivan Kohler Date: Sun, 17 Aug 2014 22:38:22 +0000 (-0700) Subject: Merge branch 'master' of git.freeside.biz:/home/git/freeside X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=a618055d3a8cfc55a449847b433dcdc85df92bcd;hp=601432ca6836e10cc4e15b1c055d77ff7f4a0540 Merge branch 'master' of git.freeside.biz:/home/git/freeside --- diff --git a/FS/FS/cust_pkg/Search.pm b/FS/FS/cust_pkg/Search.pm index 543ef1a61..1a9132df6 100644 --- a/FS/FS/cust_pkg/Search.pm +++ b/FS/FS/cust_pkg/Search.pm @@ -17,13 +17,15 @@ Valid parameters are =item agentnum -=item magic +=item status -on hold, active, inactive (or one-time charge), suspended, cancel (or cancelled) +on hold, active, inactive (or one-time charge), suspended, canceled (or cancelled) -=item status +=item magic -on hold, active, inactive (or one-time charge), suspended, cancel (or cancelled) +Equivalent to "status", except that "canceled"/"cancelled" will exclude +packages that were changed into a new package with the same pkgpart (i.e. +location or quantity changes). =item custom @@ -208,6 +210,19 @@ sub search { push @where, FS::cust_pkg->cancelled_sql(); } + + ### special case: "magic" is used in detail links from browse/part_pkg, + # where "cancelled" has the restriction "and not replaced with a package + # of the same pkgpart". Be consistent with that. + ### + + if ( $params->{'magic'} =~ /^cancell?ed$/ ) { + my $new_pkgpart = "SELECT pkgpart FROM cust_pkg AS cust_pkg_next ". + "WHERE cust_pkg_next.change_pkgnum = cust_pkg.pkgnum"; + # ...may not exist, if this was just canceled and not changed; in that + # case give it a "new pkgpart" that never equals the old pkgpart + push @where, "COALESCE(($new_pkgpart), 0) != cust_pkg.pkgpart"; + } ### # parse package class diff --git a/FS/FS/part_export/broadband_snmp.pm b/FS/FS/part_export/broadband_snmp.pm index 9afca0872..0ba275670 100644 --- a/FS/FS/part_export/broadband_snmp.pm +++ b/FS/FS/part_export/broadband_snmp.pm @@ -34,9 +34,10 @@ tie my %options, 'Tie::IxHash', }, 'community' => { label=>'Community', default=>'public' }, - 'action' => { multiple=>1 }, - 'oid' => { multiple=>1 }, - 'value' => { multiple=>1 }, + 'action' => { multiple=>1 }, + 'oid' => { multiple=>1 }, + 'value' => { multiple=>1 }, + 'datatype'=> { multiple=>1 }, 'ip_addr_change_to_new' => { label=>'Send IP address changes to new address', diff --git a/FS/FS/pay_batch/eft_canada.pm b/FS/FS/pay_batch/eft_canada.pm index 64fd2f971..310c400b1 100644 --- a/FS/FS/pay_batch/eft_canada.pm +++ b/FS/FS/pay_batch/eft_canada.pm @@ -66,23 +66,9 @@ my %holiday = ( @config = $conf->config('batchconfig-eft_canada'); } # SFTP login, password, trans code, delay time - my $process_delay; - ($trans_code, $process_delay) = @config[2,3]; - $process_delay ||= 1; # days - - my $pt = time + ($process_delay * 86400); - my @lt = localtime($pt); - while ( $lt[6] == 0 #Sunday - || $lt[6] == 6 #Saturday - || $holiday_yearly{ $lt[4]+1 }{ $lt[3] } - || $holiday{ $lt[5]+1900 }{ $lt[4]+1 }{ $lt[3] } - ) - { - $pt += 86400; - @lt = localtime($pt); - } + ($trans_code) = $config[2]; - $process_date = time2str('%D', $pt); + $process_date = time2str('%D', process_date($conf, $agentnum)); }, delimiter => '', # avoid blank lines for header/footer @@ -124,4 +110,61 @@ my %holiday = ( ); +sub download_note { # is a class method + my $class = shift; + my $pay_batch = shift; + my $conf = FS::Conf->new; + my $agentnum = $pay_batch->agentnum; + my $tomorrow = (localtime(time))[2] >= 10; + my $process_date = process_date($conf, $agentnum); + my $upload_date = $process_date - 86400; + my $date_format = $conf->config('date_format') || '%D'; + + my $note = ''; + if ( $process_date - time < 86400*2 ) { + $note = 'Upload this file before 11:00 AM '. + ($tomorrow ? 'tomorrow' : 'today') . + ' (' . time2str($date_format, $upload_date) . '). '; + } else { + $note = 'Upload this file before 11:00 AM on '. + time2str($date_format, $upload_date) . '. '; + } + $note .= 'Payments will be processed on '. + time2str($date_format, $process_date) . '.'; + + $note; +} + +sub process_date { + my ($conf, $agentnum) = @_; + my @config; + if ( $conf->exists('batch-spoolagent') ) { + @config = $conf->config('batchconfig-eft_canada', $agentnum); + } else { + @config = $conf->config('batchconfig-eft_canada'); + } + + my $process_delay = $config[3] || 1; + + if ( (localtime(time))[2] >= 10 and $process_delay == 1 ) { + # If downloading the batch after 10:00 local time, it likely won't make + # the cutoff for next-day turnaround, and EFT will reject it. + $process_delay++; + } + + my $pt = time + ($process_delay * 86400); + my @lt = localtime($pt); + while ( $lt[6] == 0 #Sunday + || $lt[6] == 6 #Saturday + || $holiday_yearly{ $lt[4]+1 }{ $lt[3] } + || $holiday{ $lt[5]+1900 }{ $lt[4]+1 }{ $lt[3] } + ) + { + $pt += 86400; + @lt = localtime($pt); + } + + $pt; +} + 1; diff --git a/httemplate/browse/part_pkg.cgi b/httemplate/browse/part_pkg.cgi index 63822c7c9..1eb55c88a 100755 --- a/httemplate/browse/part_pkg.cgi +++ b/httemplate/browse/part_pkg.cgi @@ -108,6 +108,14 @@ my $count_cust_pkg = " WHERE cust_pkg.pkgpart = part_pkg.pkgpart AND $agentnums_sql "; +my $count_cust_pkg_cancel = " + SELECT COUNT(*) FROM cust_pkg LEFT JOIN cust_main USING ( custnum ) + LEFT JOIN cust_pkg AS cust_pkg_next + ON (cust_pkg.pkgnum = cust_pkg_next.change_pkgnum) + WHERE cust_pkg.pkgpart = part_pkg.pkgpart + AND $agentnums_sql + AND cust_pkg.cancel IS NOT NULL AND cust_pkg.cancel != 0 +"; $select = " @@ -137,11 +145,16 @@ $select = " AND ( setup IS NULL OR setup = 0 ) ) AS num_on_hold, - ( $count_cust_pkg - AND cancel IS NOT NULL AND cancel != 0 + ( $count_cust_pkg_cancel + AND (cust_pkg_next.pkgnum IS NULL + OR cust_pkg_next.pkgpart != cust_pkg.pkgpart) ) AS num_cancelled "; +# About the num_cancelled expression: packages that were changed, but +# kept the same pkgpart, are considered "moved", not "canceled" (because +# this is the part_pkg UI). We could show the count of those but it's +# probably not interesting. my $html_init = qq! One or more service definitions are grouped together into a package diff --git a/httemplate/edit/elements/part_export/broadband_snmp.html b/httemplate/edit/elements/part_export/broadband_snmp.html index 4c0367c5a..ebb765dee 100644 --- a/httemplate/edit/elements/part_export/broadband_snmp.html +++ b/httemplate/edit/elements/part_export/broadband_snmp.html @@ -29,7 +29,7 @@ function open_select_mib(obj) { nd(1); // if there's already one open, close it var rownum = obj.rownum; - var curr_oid = obj.value || ''; + var curr_oid = obj.form.elements['oid' + rownum].value || ''; var url = '<%$fsurl%>/elements/select-mib-popup.html?' + 'callback=receive_mib;' + 'arg=' + rownum + @@ -66,10 +66,11 @@ function receive_mib(obj, rownum) { - + + - + diff --git a/httemplate/edit/process/part_export.cgi b/httemplate/edit/process/part_export.cgi index e0c470675..7fe3d0369 100644 --- a/httemplate/edit/process/part_export.cgi +++ b/httemplate/edit/process/part_export.cgi @@ -41,7 +41,7 @@ foreach my $option (split(',', $cgi->param('multi_options'))) { foreach my $option (split(',', $cgi->param('multi_options'))) { my $value = ''; foreach my $row (sort keys %{$optionrows{_ALL_}}) { - $value .= ($optionrows{$option}{$row} || '') . "\n"; + $value .= ($optionrows{$option}{$row} // '') . "\n"; } chomp($value); $options{$option} = $value; diff --git a/httemplate/elements/select-mib-popup.html b/httemplate/elements/select-mib-popup.html index bd485ef65..f95ce2b97 100644 --- a/httemplate/elements/select-mib-popup.html +++ b/httemplate/elements/select-mib-popup.html @@ -7,7 +7,7 @@ Object: - + diff --git a/httemplate/misc/xmlhttp-pay_batch-note.html b/httemplate/misc/xmlhttp-pay_batch-note.html new file mode 100644 index 000000000..ef5901631 --- /dev/null +++ b/httemplate/misc/xmlhttp-pay_batch-note.html @@ -0,0 +1,18 @@ +<% $note %>\ +<%init> + +my ($batchnum, $format) = $cgi->param('arg'); + +my $note = ''; +if ( $batchnum =~ /^(\d+)$/ ) { + my $pay_batch = FS::pay_batch->by_key($batchnum); + if ( $pay_batch and $format =~ /^(\w+)$/ ) { + my $class = "FS::pay_batch::$format"; + if ( $class->can('download_note') ) { + # now we can actually do something + $note = $class->download_note($pay_batch); + } + } +} + + diff --git a/httemplate/search/elements/cust_pay_batch_top.html b/httemplate/search/elements/cust_pay_batch_top.html index bf3047769..a773dd009 100644 --- a/httemplate/search/elements/cust_pay_batch_top.html +++ b/httemplate/search/elements/cust_pay_batch_top.html @@ -1,24 +1,43 @@ +<& /elements/xmlhttp.html, + 'url' => $p.'misc/xmlhttp-pay_batch-note.html', + 'subs' => [ 'get_note' ] +&> + % # Download batch % if ( $status eq 'O' % or ( $status eq 'I' and $curuser->access_right('Reprocess batches') ) % or ( $status eq 'R' and $curuser->access_right('Redownload resolved batches') ) % ) { - - - + + % if ( $fixed ) { - + % } % else { -Download batch in format % foreach ( keys %download_formats ) { - + % } - -<& .select_gateway &> + + <& .select_gateway &> % } -

+
+
+ % } # end of download + +
% # Upload batch % if ( $pay_batch->status eq 'I' @@ -27,44 +46,42 @@ Download batch in format -<% include('/elements/form-file_upload.html', +<& /elements/form-file_upload.html, 'name' => 'FileUpload', 'action' => "${p}misc/upload-batch.cgi", 'num_files' => 1, 'fields' => [ 'batchnum', 'format', 'gatewaynum' ], 'url' => $cgi->self_url, 'message' => 'Batch results uploaded.', -) %> -Upload results
- -<% include('/elements/file-upload.html', +&> + Upload results
+ <& /elements/file-upload.html, 'field' => 'file', 'label' => 'Filename', 'no_table' => 1, -) %> - -
+ &> + +
% if ( $fixed ) { % if ( $fixed eq 'td_eft1464' ) { # special case -Upload in format + Upload in format % } % else { - + % } % } % else { -Upload in format % foreach ( keys(%upload_formats) ) { - + % } - -<& .select_gateway &> + + <& .select_gateway &> % } # if $fixed - +
% } # end upload @@ -74,12 +91,12 @@ Upload results
% and $payby eq 'CHEK' % and $conf->exists('batch-manual_approval') % ) { - +"> +
% } # end manual approval -
% # summary info Batch is <% $statustext{$status} %>
@@ -119,19 +136,19 @@ my $batchnum = $pay_batch->batchnum; my $fixed = $conf->config("batch-fixed_format-$payby"); tie my %download_formats, 'Tie::IxHash', ( -'' => 'Default batch mode', -'NACHA' => '94 byte NACHA', -'csv-td_canada_trust-merchant_pc_batch' => - 'CSV file for TD Canada Trust Merchant PC Batch', -'csv-chase_canada-E-xactBatch' => - 'CSV file for Chase Canada E-xactBatch', -'PAP' => '80 byte file for TD Canada Trust PAP Batch', -'BoM' => 'Bank of Montreal ECA batch', -'ach-spiritone' => 'Spiritone ACH batch', -'paymentech' => 'XML file for Chase Paymentech', -'RBC' => 'Royal Bank of Canada PDS batch', -'td_eft1464' => '1464 byte file for TD Commercial Banking EFT', -'eft_canada' => 'EFT Canada CSV batch', + '' => 'Default batch mode', + 'NACHA' => '94 byte NACHA', + 'csv-td_canada_trust-merchant_pc_batch' => + 'CSV file for TD Canada Trust Merchant PC Batch', + 'csv-chase_canada-E-xactBatch' => + 'CSV file for Chase Canada E-xactBatch', + 'PAP' => '80 byte file for TD Canada Trust PAP Batch', + 'BoM' => 'Bank of Montreal ECA batch', + 'ach-spiritone' => 'Spiritone ACH batch', + 'paymentech' => 'XML file for Chase Paymentech', + 'RBC' => 'Royal Bank of Canada PDS batch', + 'td_eft1464' => '1464 byte file for TD Commercial Banking EFT', + 'eft_canada' => 'EFT Canada CSV batch', # insert new batch formats here ); @@ -150,4 +167,5 @@ my $count_query = "SELECT COUNT(*) FROM cust_pay_batch WHERE batchnum=$batchnum" my $count = FS::Record->scalar_sql($count_query); my $sum_query = "SELECT SUM(amount) FROM cust_pay_batch WHERE batchnum=$batchnum"; my $total = sprintf("%.2f", FS::Record->scalar_sql($sum_query)); + diff --git a/httemplate/view/cust_main/packages/contact.html b/httemplate/view/cust_main/packages/contact.html index 151da01aa..88f8afb4c 100644 --- a/httemplate/view/cust_main/packages/contact.html +++ b/httemplate/view/cust_main/packages/contact.html @@ -10,10 +10,12 @@ ( <%pkg_detach_link($cust_pkg)%> ) % } +
% } elsif ( $show_contact_link && ! $opt{no_links} ) { ( <%pkg_add_contact_link($cust_pkg)%> ) +
% } <%init> diff --git a/httemplate/view/cust_main/packages/hidden.html b/httemplate/view/cust_main/packages/hidden.html index e3bd0fabf..35eda8c46 100644 --- a/httemplate/view/cust_main/packages/hidden.html +++ b/httemplate/view/cust_main/packages/hidden.html @@ -18,13 +18,13 @@ <% time2str('%b %o, %Y', $cust_pkg->get('cancel')) %> % if ( $pkgpart_change ) { - from <% $part_pkg->pkg |h %> - <% $part_pkg->custom_comment |h %> + from <% $popup_link |n %><% $part_pkg->pkg |h %> - <% $part_pkg->custom_comment |h %> % } % if ( $pkgpart_change and $location_change ) {
% } % if ( $location_change ) { - from <% $cust_pkg->location_label %> + from <% $popup_link |n %><% $cust_pkg->location_label %> % } @@ -52,4 +52,14 @@ my $pkgpart_change = ($next->pkgpart != $cust_pkg->pkgpart); my $location_change = ($next->locationnum != $cust_pkg->locationnum); my $both_change = $pkgpart_change && $location_change; +my $onclick = + include('/elements/popup_link_onclick.html', + 'action' => $fsurl.'view/cust_pkg-popup.html?' . $cust_pkg->pkgnum, + 'actionlabel' => 'Package #'.$cust_pkg->pkgnum, + 'width' => '1000', + 'height' => '310', + 'color' => $cust_pkg->statuscolor, + ); +my $popup_link = qq(); + diff --git a/httemplate/view/cust_main/packages/section.html b/httemplate/view/cust_main/packages/section.html index 4980feeac..217e8c556 100755 --- a/httemplate/view/cust_main/packages/section.html +++ b/httemplate/view/cust_main/packages/section.html @@ -4,17 +4,22 @@ <% mt('Package') |h %> <% mt('Status') |h %> <% mt('Contact/Location') |h %> +% if (!$opt{no_services}) { <% mt('Services') |h %> +% } % #$FS::cust_pkg::DEBUG = 2; % foreach my $cust_pkg (@$packages) { +% # if requested, this can override cust_pkg-group_by_location <& .packagerow, $cust_pkg, + %conf_opt, ( map { $_ => $opt{$_} } qw( cust_main bgcolor no_links cust_location_cache before_pkg_callback before_svc_callback after_svc_callback + cust_pkg-group_by_location + no_services )), - %conf_opt &> % } % } else { # there are no packages @@ -30,10 +35,12 @@ <& package.html, %iopt &> <& status.html, %iopt &> - <& contact.html, %iopt &>
+ <& contact.html, %iopt &> <& location.html, %iopt &> +% if (!$iopt{no_services}) { <& services.html, %iopt &> +% } % # insert hidden predecessors to this package, if any % # and a rolldown button to show them diff --git a/httemplate/view/cust_pkg-popup.html b/httemplate/view/cust_pkg-popup.html new file mode 100644 index 000000000..96956c732 --- /dev/null +++ b/httemplate/view/cust_pkg-popup.html @@ -0,0 +1,27 @@ +<& /elements/header-popup.html &> + +<& cust_main/packages/section.html, + 'cust_main' => $cust_main, + 'packages' => [ $cust_pkg ], + 'cust_pkg-group_by_location' => 0, + 'no_services' => 1, +&> +
+ + +<%init> +my $curuser = $FS::CurrentUser::CurrentUser; +my ($pkgnum) = $cgi->keywords; +$pkgnum =~ /^\d+$/ or die "bad pkgnum $pkgnum"; + +my $cust_pkg = qsearchs({ + 'table' => 'cust_pkg', + 'addl_from' => 'JOIN cust_main USING (custnum)', + 'hashref' => { 'pkgnum' => $pkgnum }, + 'extra_sql' => ' AND '.$curuser->agentnums_sql, +}); +die "Package not found" unless $cust_pkg; +my $cust_main = $cust_pkg->cust_main; + +my $title = mt('Package [_1]', $pkgnum); +