summaryrefslogtreecommitdiff
path: root/httemplate/view/cust_main
diff options
context:
space:
mode:
Diffstat (limited to 'httemplate/view/cust_main')
-rw-r--r--httemplate/view/cust_main/billing.html11
-rw-r--r--httemplate/view/cust_main/change_history.html7
-rwxr-xr-xhttemplate/view/cust_main/locations.html10
-rwxr-xr-xhttemplate/view/cust_main/notes.html6
-rwxr-xr-xhttemplate/view/cust_main/packages.html72
-rw-r--r--httemplate/view/cust_main/packages/contact.html87
-rw-r--r--httemplate/view/cust_main/packages/location.html26
-rw-r--r--httemplate/view/cust_main/packages/package.html150
-rwxr-xr-xhttemplate/view/cust_main/packages/section.html81
-rw-r--r--httemplate/view/cust_main/packages/services.html18
-rw-r--r--httemplate/view/cust_main/packages/status.html181
-rw-r--r--httemplate/view/cust_main/payment_history.html165
-rw-r--r--httemplate/view/cust_main/payment_history/attempted_batch_payment.html13
13 files changed, 585 insertions, 242 deletions
diff --git a/httemplate/view/cust_main/billing.html b/httemplate/view/cust_main/billing.html
index 5c46803d2..e286305f4 100644
--- a/httemplate/view/cust_main/billing.html
+++ b/httemplate/view/cust_main/billing.html
@@ -247,6 +247,10 @@
<TD ALIGN="right"><% mt('Email address(es)') |h %></TD>
<TD BGCOLOR="#ffffff">
<% join(', ', grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list ) || $no %>
+% if ( $cust_main->message_noemail ) {
+ <BR>
+ <SPAN STYLE="font-size: small"><% emt('(do not send notices)') %></SPAN>
+% }
</TD>
</TR>
% }
@@ -300,6 +304,13 @@
</TR>
% }
+% if ( $cust_main->currency ) {
+ <TR>
+ <TD ALIGN="right"><% mt('Invoicing currency') |h %></TD>
+ <TD BGCOLOR="#ffffff"><% $cust_main->currency. ': '. code2currency($cust_main->currency) %></TD>
+ </TR>
+% }
+
% if ( $cust_main->locale ) {
% my %locale_info = FS::Locales->locale_info($cust_main->locale);
<TR>
diff --git a/httemplate/view/cust_main/change_history.html b/httemplate/view/cust_main/change_history.html
index ea84b8f75..bf32a49f9 100644
--- a/httemplate/view/cust_main/change_history.html
+++ b/httemplate/view/cust_main/change_history.html
@@ -43,10 +43,12 @@ tie my %tables, 'Tie::IxHash',
'svc_external' => 'External service',
'svc_phone' => 'Phone',
'phone_device' => 'Phone device',
+ 'cust_pkg_discount' => 'Discount',
#? it gets provisioned anyway 'phone_avail' => 'Phone',
;
-my $svc_join = 'JOIN cust_svc USING ( svcnum ) JOIN cust_pkg USING ( pkgnum )';
+my $pkg_join = "JOIN cust_pkg USING ( pkgnum )";
+my $svc_join = "JOIN cust_svc USING ( svcnum ) $pkg_join";
my %table_join = (
'svc_acct' => $svc_join,
@@ -58,6 +60,7 @@ my %table_join = (
'svc_external' => $svc_join,
'svc_phone' => $svc_join,
'phone_device' => $svc_join,
+ 'cust_pkg_discount'=> $pkg_join,
);
@@ -104,7 +107,7 @@ my $conf = new FS::Conf;
my $curuser = $FS::CurrentUser::CurrentUser;
-die "access deined"
+die "access denied"
unless $curuser->access_right('View customer history');
# find out the beginning of this customer history, if possible
diff --git a/httemplate/view/cust_main/locations.html b/httemplate/view/cust_main/locations.html
index b29d0ce4d..7eb52ca46 100755
--- a/httemplate/view/cust_main/locations.html
+++ b/httemplate/view/cust_main/locations.html
@@ -28,15 +28,19 @@ STYLE="padding-bottom: 0px;
% }
<% $loc->location_label %></SPAN>
<SPAN STYLE="float:right;">
-% if ( $locationnum and !$loc->disabled ) {
+% if ( $locationnum && !$loc->disabled && ! $opt{no_links} ) {
<% edit_location_link($locationnum) %>
% }
-% if ( $locationnum and !$loc->disabled and !$active{$locationnum} ) {
+% if ( $locationnum && !$loc->disabled && !$active{$locationnum} && ! $opt{no_links} ) {
&nbsp;<% disable_location_link($locationnum) %>
% }
</SPAN></TH></TR>
% if (@$packages) {
-<& packages/section.html, 'packages' => $packages &>
+ <& packages/section.html,
+ 'packages' => $packages,
+ 'cust_main' => $cust_main,
+ 'no_links' => $opt{no_links}
+ &>
% }
</TABLE><BR>
% } #foreach $locationnum
diff --git a/httemplate/view/cust_main/notes.html b/httemplate/view/cust_main/notes.html
index 1e9f464db..2de68ff46 100755
--- a/httemplate/view/cust_main/notes.html
+++ b/httemplate/view/cust_main/notes.html
@@ -63,7 +63,11 @@
%
% my $edit = '';
% if ($curuser->access_right('Edit customer note') ) {
-% $edit = qq! <A HREF="javascript:void(0);" $clickjs>(!.emt('edit').')</A>';
+% my $delete_url = $fsurl.'misc/delete-note.html?'.$notenum;
+% $edit = qq! <A HREF="javascript:void(0);" $clickjs>(!.emt('edit').')</A>'.
+% qq! <A HREF="$delete_url" !.
+% qq! onclick="return confirm('Delete this note?')">!.
+% '('.emt('delete').')</A>';
% }
%
% if ( $last_classnum != $note->classnum && !$skipheader ) {
diff --git a/httemplate/view/cust_main/packages.html b/httemplate/view/cust_main/packages.html
index 7d7930634..e32fe4c03 100755
--- a/httemplate/view/cust_main/packages.html
+++ b/httemplate/view/cust_main/packages.html
@@ -1,4 +1,33 @@
-% my $s = 0;
+<STYLE TYPE="text/css">
+td.package {
+ vertical-align: top;
+ border-width: 0;
+ border-style: solid;
+ border-color: #bbbbff;
+}
+table.package {
+ border: none;
+ padding: 0;
+ border-spacing: 0;
+ width: 100%;
+}
+table.usage {
+ border: 1px solid black;
+ margin: auto;
+ width: 60%;
+ border-spacing: 0px;
+}
+.shared > * {
+ background-color: #ffffaa;
+}
+.row0 { background-color: #eeeeee; }
+.row1 { background-color: #ffffff; }
+
+</STYLE>
+
+% unless ( $opt{no_links} ) {
+
+% my $s = 0;
% if ( $curuser->access_right('Qualify service') ) {
<% $s++ ? ' | ' : '' %>
@@ -17,21 +46,33 @@
<& one_time_charge_link.html, $cust_main &>
% }
+% if ( $curuser->access_right('Bulk move customer services') ) {
+ <% $s++ ? ' | ' : '' %>
+
+ <& /elements/popup_link-cust_main.html,
+ 'label' => emt('Move services between packages'),
+ 'action' => "${p}edit/bulk-cust_svc-pkgnum.html",
+ 'cust_main' => $cust_main,
+ 'actionlabel' => emt('Move services'),
+ 'width' => 968, #763,
+ 'height' => 575,
+ &>
+
+% }
+
% if ( $curuser->access_right('Bulk change customer packages') ) {
<% $s++ ? ' | ' : '' %>
- <A HREF="<% $p %>edit/cust_pkg.cgi?<% $cust_main->custnum %>"><% mt('Bulk order and cancel packages') |h %></A> (<% mt('preserves services') |h %>)
+ <A HREF="<% $p %>edit/cust_pkg.cgi?<% $cust_main->custnum %>"><% mt('Bulk order and cancel packages') |h %></A>
% }
<BR><BR>
+% } # unless $opt{no_links}
+
<TABLE>
<TR>
<TD ALIGN="left" VALIGN="top">
-% if ( @$packages ) {
-
-<% mt('Current packages') |h %>
-% }
% if ( $cust_main->num_cancelled_pkgs ) {
% if ( $cgi->param('showcancelledpackages') eq '0' #see if it was set by me
% || ( $conf->exists('hidecancelledpackages')
@@ -60,6 +101,9 @@
% }
</TD>
+
+% unless ( $opt{no_links} ) {
+
<TD ALIGN="right">
<A HREF="<%$p%>search/report_cust_pkg.html?custnum=<% $cust_main->custnum %>"><% mt('Package reports') |h %></A>
% if ( $curuser->access_right('Qualify service') ) {
@@ -71,14 +115,18 @@
<% mt('Usage reports:') |h %>
<A HREF="<%$p%>search/report_cdr.html?custnum=<% $cust_main->custnum %>"><% mt('CDRs') |h %></A>
</TD>
+
+% } # unless $opt{no_links}
+
</TR>
<TR>
<TD COLSPAN=2>
-% if ( $conf->exists('cust_pkg-group_by_location') and $show_location ) {
+% if ( $conf->exists('cust_pkg-group_by_location') ) {
<& locations.html,
'cust_main' => $cust_main,
'packages' => $packages,
+ %opt,
&>
% }
% else {
@@ -87,7 +135,7 @@
<& packages/section.html,
'cust_main' => $cust_main,
'packages' => $packages,
- 'show_location' => $show_location,
+ %opt,
&>
</TABLE>
% }
@@ -114,10 +162,6 @@ my $curuser = $FS::CurrentUser::CurrentUser;
my( $packages, $num_old_packages ) = get_packages($cust_main, $conf);
-
-my $show_location = $conf->exists('cust_pkg-always_show_location')
- || (grep $_->locationnum, @$packages); # ? '1' : '0';
-
my $countrydefault = scalar($conf->config('countrydefault')) || 'US';
#subroutines
@@ -178,6 +222,10 @@ sub get_packages {
}
$num_old_packages -= scalar(@packages);
+
+ # don't include supplemental packages in this list; they'll be found from
+ # their main packages
+ @packages = grep !$_->main_pkgnum, @packages;
( \@packages, $num_old_packages );
}
diff --git a/httemplate/view/cust_main/packages/contact.html b/httemplate/view/cust_main/packages/contact.html
new file mode 100644
index 000000000..93985e404
--- /dev/null
+++ b/httemplate/view/cust_main/packages/contact.html
@@ -0,0 +1,87 @@
+% if ( $contact ) {
+ <% $contact->line |h %>
+% if ( $show_change_link && ! $opt{no_links} ) {
+ <FONT SIZE=-1>
+ (&nbsp;<%pkg_change_contact_link($cust_pkg)%>&nbsp;)
+ </FONT>
+% }
+% if ( $show_detach_link && ! $opt{no_links} ) {
+ <FONT SIZE=-1>
+ (&nbsp;<%pkg_detach_link($cust_pkg)%>&nbsp;)
+ </FONT>
+% }
+% } elsif ( $show_contact_link && ! $opt{no_links} ) {
+ <FONT SIZE=-1>
+ (&nbsp;<%pkg_add_contact_link($cust_pkg)%>&nbsp;)
+ </FONT>
+% }
+<%init>
+
+my $conf = new FS::Conf;
+my %opt = @_;
+
+my $cust_pkg = $opt{'cust_pkg'};
+
+my $show_change_link =
+ ! $cust_pkg->get('cancel')
+ && $FS::CurrentUser::CurrentUser->access_right('Change customer package');
+
+my $show_detach_link =
+ ! $cust_pkg->get('cancel')
+ && $FS::CurrentUser::CurrentUser->access_right('Detach customer package');
+
+my $show_contact_link =
+ ! $cust_pkg->get('cancel')
+ ; #&& $FS::CurrentUser::CurrentUser->access_right('Add package contact'); #or something like that
+
+my $contact = $cust_pkg->contact_obj;
+
+sub pkg_change_contact_link {
+ my $cust_pkg = shift;
+ #my $pkgpart = $cust_pkg->pkgpart;
+ include( '/elements/popup_link-cust_pkg.html',
+ 'action' => $p. "misc/change_pkg_contact.html",
+ 'label' => emt('Change'), # contact'),
+ 'actionlabel' => emt('Change'),
+ 'cust_pkg' => $cust_pkg,
+ 'width' => 616,
+ 'height' => 220,
+ );
+}
+
+sub pkg_add_contact_link {
+ my $cust_pkg = shift;
+ #my $pkgpart = $cust_pkg->pkgpart;
+ include( '/elements/popup_link-cust_pkg.html',
+ 'action' => $p. "misc/change_pkg_contact.html",
+ 'label' => emt('Add contact'),
+ 'actionlabel' => emt('Add contact'),
+ 'cust_pkg' => $cust_pkg,
+ 'width' => 616,
+ 'height' => 192,
+ );
+}
+
+sub pkg_detach_link {
+ my $cust_pkg = shift;
+ #my $pkgpart = $cust_pkg->pkgpart;
+ include( '/elements/popup_link-cust_pkg.html',
+ 'action' => $p. "misc/detach_pkg.html",
+ 'label' => emt('Detach'),
+ 'actionlabel' => emt('Detach'),
+ 'cust_pkg' => $cust_pkg,
+ 'width' => 616,
+ 'height' => 684,
+ );
+}
+
+#sub edit_contact_link {
+# my $contactnum = shift;
+# include( '/elements/popup_link.html',
+# 'action' => $p. "edit/cust_contact.cgi?contactnum=$contactnum",
+# 'label' => emt('Edit contact'),
+# 'actionlabel' => emt('Edit'),
+# );
+#}
+
+</%init>
diff --git a/httemplate/view/cust_main/packages/location.html b/httemplate/view/cust_main/packages/location.html
index 34e3a64c3..ab961b79e 100644
--- a/httemplate/view/cust_main/packages/location.html
+++ b/httemplate/view/cust_main/packages/location.html
@@ -1,7 +1,5 @@
-<TD CLASS="inv" BGCOLOR="<% $bgcolor %>" WIDTH="20%">
-
-% unless ( $cust_pkg->locationnum ) {
- <I><FONT SIZE=-1>(<% mt('default service address') |h %>)</FONT><BR>
+% if ( $default ) {
+ <DIV STYLE="font-style: italic; font-size: small">
% }
<% $loc->location_label( 'join_string' => '<BR>',
@@ -24,8 +22,8 @@
</FONT>
% }
-% unless ( $cust_pkg->locationnum ) {
- </I>
+% if ( $default ) {
+ </DIV>
% }
% if ( ! $cust_pkg->get('cancel')
@@ -34,26 +32,28 @@
% {
<BR>
<FONT SIZE=-1>
- (&nbsp;<%pkg_change_location_link($cust_pkg)%>&nbsp;)
-% if ( $cust_pkg->locationnum ) {
+% unless ( $opt{no_links} ) {
+ (&nbsp;<%pkg_change_location_link($cust_pkg)%>&nbsp;)
+% }
+% if ( $cust_pkg->locationnum && ! $opt{no_links} ) {
(&nbsp;<%edit_location_link($cust_pkg->locationnum)%>&nbsp;)
% }
</FONT>
% }
-</TD>
<%init>
my $conf = new FS::Conf;
my %opt = @_;
-my $bgcolor = $opt{'bgcolor'};
my $cust_pkg = $opt{'cust_pkg'};
my $countrydefault = $opt{'countrydefault'} || 'US';
my $statedefault = $opt{'statedefault'}
|| ($countrydefault eq 'US' ? 'CA' : '');
my $loc = $cust_pkg->cust_location_or_main;
+# dubious--they should all have a location now
+my $default = $cust_pkg->locationnum == $opt{'cust_main'}->ship_locationnum;
sub pkg_change_location_link {
my $cust_pkg = shift;
@@ -65,6 +65,8 @@ sub pkg_change_location_link {
'label' => emt('Change location'),
'actionlabel' => emt('Change'),
'cust_pkg' => $cust_pkg,
+ 'width' => 763,
+ 'height' => 380,
);
}
@@ -74,7 +76,9 @@ sub edit_location_link {
'action' => $p. "edit/cust_location.cgi?locationnum=$locationnum",
'label' => emt('Edit location'),
'actionlabel' => emt('Edit'),
- );
+ 'width' => 700,
+ 'height' => 355,
+ );
}
</%init>
diff --git a/httemplate/view/cust_main/packages/package.html b/httemplate/view/cust_main/packages/package.html
index 5d93ad46f..7aad9a44e 100644
--- a/httemplate/view/cust_main/packages/package.html
+++ b/httemplate/view/cust_main/packages/package.html
@@ -1,7 +1,12 @@
-<TD CLASS="inv" BGCOLOR="<% $bgcolor %>" VALIGN="top">
- <TABLE CLASS="inv" BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="100%">
+<TD CLASS="inv package" BGCOLOR="<% $bgcolor %>" VALIGN="top"
+ STYLE="border-left-width: <% $supplemental * 30 %>px">
+ <TABLE CLASS="inv package">
<TR>
<TD COLSPAN=2>
+ <% $opt{before_pkg_callback}
+ ? &{ $opt{before_pkg_callback} }( $cust_pkg )
+ : ''
+ %>
<A NAME="cust_pkg<% $cust_pkg->pkgnum %>"
ID ="cust_pkg<% $cust_pkg->pkgnum %>"
><% $curuser->option('show_pkgnum') ? $cust_pkg->pkgnum.': ' : '' %><B><% $part_pkg->pkg |h %></B></A>
@@ -17,50 +22,54 @@
<B><% $cust_pkg->quantity %></B>
</TD>
</TR>
-% }
+% }
<TR>
<TD COLSPAN=2>
<FONT SIZE=-1>
-% unless ( $cust_pkg->get('cancel') ) {
+% unless ( $cust_pkg->get('cancel') || $opt{no_links} ) {
%
-% my $br = 0;
-% if ( $curuser->access_right('Change customer package') ) {
-% $br=1;
- (&nbsp;<%pkg_change_link($cust_pkg)%>&nbsp;)
-% }
+% if ( $supplemental or $part_pkg->freq eq '0' ) {
+% # Supplemental packages can't be changed independently.
+% # One-time charges don't need to be changed.
+% # For both of those, we only show "Add comments",
+% # and "Add invoice details".
+% } else {
+% # the usual case: links to change package definition,
+% # discount, and customization
+% my $br = 0;
+% if ( $curuser->access_right('Change customer package') ) {
+% $br=1;
+ (&nbsp;<%pkg_change_link($cust_pkg)%>&nbsp;)
+% }
%
-% if ( $curuser->access_right('Edit customer package dates') ) {
-% $br=1;
- (&nbsp;<%pkg_dates_link($cust_pkg)%>&nbsp;)
-% }
+% if ( $curuser->access_right('Discount customer package')
+% && $part_pkg->can_discount
+% && ! scalar($cust_pkg->cust_pkg_discount_active)
+% && ! scalar($cust_pkg->part_pkg->part_pkg_discount)
+% )
+% {
+% $br=1;
+ (&nbsp;<%pkg_discount_link($cust_pkg)%>&nbsp;)
+% }
%
-% if ( $curuser->access_right('Discount customer package')
-% && $part_pkg->can_discount
-% && ! scalar($cust_pkg->cust_pkg_discount_active)
-% && ! scalar($cust_pkg->part_pkg->part_pkg_discount)
-% )
-% {
-% $br=1;
- (&nbsp;<%pkg_discount_link($cust_pkg)%>&nbsp;)
-% }
+% if ( $curuser->access_right('Customize customer package') ) {
+% $br=1;
+ (&nbsp;<%pkg_customize_link($cust_pkg,$part_pkg)%>&nbsp;)
+% }
%
-% if ( $curuser->access_right('Customize customer package') ) {
-% $br=1;
- (&nbsp;<%pkg_customize_link($cust_pkg,$part_pkg)%>&nbsp;)
+ <% $br ? '<BR>' : '' %>
% }
-%
- <% $br ? '<BR>' : '' %>
-% }
-% if ( $cust_pkg->num_cust_event
-% && ( $curuser->access_right('Billing event reports')
-% || $curuser->access_right('View customer billing events')
-% )
-% ) {
- (&nbsp;<%pkg_event_link($cust_pkg)%>&nbsp;)
-% }
+% if ( $cust_pkg->num_cust_event
+% && ( $curuser->access_right('Billing event reports')
+% || $curuser->access_right('View customer billing events')
+% )
+% ) {
+ (&nbsp;<%pkg_event_link($cust_pkg)%>&nbsp;)
+% }
+% } #!$supplemental
</FONT>
</TD>
@@ -86,7 +95,7 @@
<TH BGCOLOR="#dddddd" STYLE="border-bottom: dashed 1px black; padding-bottom: 1px">
<FONT SIZE="-1">
<% mt('Invoice details') |h %>
-% if ( $editi && ! $cust_pkg->get('cancel') ) {
+% if ( $editi && ! $cust_pkg->get('cancel') && ! $opt{no_links} ) {
(<& /elements/popup_link.html, {
'action' => $editlink. 'I',
'label' => emt('edit'),
@@ -108,7 +117,7 @@
</TD>
% } else {
<TD>
-% if ( $editi && ! $cust_pkg->get('cancel') ) {
+% if ( $editi && ! $cust_pkg->get('cancel') && ! $opt{no_links} ) {
<FONT SIZE="-1">
(&nbsp;<% include('/elements/popup_link.html', {
'action' => $editlink. 'I',
@@ -130,7 +139,7 @@
<TH BGCOLOR="#dddddd" STYLE="border-bottom: dashed 1px black; padding-bottom: 1px">
<FONT SIZE="-1">
<% mt('Comments') |h %>
-% if ( $editc ) {
+% if ( $editc && ! $opt{no_links} ) {
(<& /elements/popup_link.html, {
'action' => $editlink. 'C',
'label' => emt('edit'),
@@ -152,7 +161,7 @@
</TD>
% } else {
<TD>
-% if ( $editc ) {
+% if ( $editc && ! $opt{no_links} ) {
<FONT SIZE="-1">
(&nbsp;<& /elements/popup_link.html, {
'action' => $editlink. 'C',
@@ -168,17 +177,45 @@
% }
</TR>
-% if ( $curuser->access_right('Change customer package') and
-% !$cust_pkg->get('cancel') and
-% !$opt{'show_location'}) {
+% if ( $curuser->access_right('Change customer package')
+% && ! $cust_pkg->get('cancel')
+% && ! $supplemental
+% && $part_pkg->freq ne '0'
+% && ! $opt{no_links}
+% )
+% {
<TR>
+% if ( FS::Conf->new->exists('invoice-unitprice') ) {
<TD><FONT SIZE="-1">
- (&nbsp;<% pkg_change_location_link($cust_pkg) %>&nbsp;)
+ (&nbsp;<% pkg_change_quantity_link($cust_pkg) %>&nbsp;)
</FONT></TD>
+% }
</TR>
% }
% }
</TABLE>
+% if ( @cust_pkg_usage ) {
+ <TABLE CLASS="usage inv">
+ <TR><TH COLSPAN=4><% mt('Included usage') %></TH></TR>
+% foreach my $usage (@cust_pkg_usage) {
+% my $part = $usage->part_pkg_usage;
+% my $ratio = 255 * ($usage->minutes / $part->minutes);
+% $ratio = 255 if $ratio > 255; # because rollover
+% my $color = sprintf('STYLE="font-weight: bold; color: #%02x%02x00"', 255 - $ratio, $ratio);
+% my $trstyle = '';
+% $trstyle = ' CLASS="shared"' if $part->shared;
+ <TR<%$trstyle%>>
+ <TD ALIGN="right"><% $part->description %>: </TD>
+ <TD <%$color%> ALIGN="right"><% $usage->minutes %></TD>
+ <TD <%$color%>> / </TD>
+ <TD <%$color%>><% $part->minutes %></TD>
+% if ( $part->shared ) {
+ <TD><I>(shared)</I></TD>
+% }
+ </TR>
+% }
+ </TABLE>
+% }
</TD>
@@ -196,6 +233,18 @@ my $countrydefault = $opt{'countrydefault'} || 'US';
my $statedefault = $opt{'statedefault'}
|| ($countrydefault eq 'US' ? 'CA' : '');
+my $supplemental = $opt{'supplemental'} || 0;
+
+$cust_pkg->pkgnum =~ /^(\d+)$/;
+my $pkgnum = $1;
+my @cust_pkg_usage = qsearch({
+ 'select' => 'cust_pkg_usage.*',
+ 'table' => 'cust_pkg_usage',
+ 'addl_from' => ' JOIN part_pkg_usage USING (pkgusagepart)',
+ 'extra_sql' => " WHERE pkgnum = $1",
+ 'order_by' => ' ORDER BY priority ASC, description ASC',
+});
+
#subroutines
#false laziness w/status.html
@@ -213,6 +262,8 @@ sub pkg_change_link {
'label' => emt('Change package'),
'actionlabel' => emt('Change'),
'cust_pkg' => $cust_pkg,
+ 'width' => 763,
+ 'height' => 380,
);
}
@@ -226,10 +277,21 @@ sub pkg_change_location_link {
'label' => emt('Change location'),
'actionlabel' => emt('Change'),
'cust_pkg' => $cust_pkg,
+ 'width' => 763,
+ 'height' => 380,
);
}
-sub pkg_dates_link { pkg_link('edit/REAL_cust_pkg', emt('Edit dates'), @_ ); }
+sub pkg_change_quantity_link {
+ include( '/elements/popup_link-cust_pkg.html',
+ 'action' => $p. 'edit/cust_pkg_quantity.html?',
+ 'label' => emt('Change quantity'),
+ 'actionlabel' => emt('Change'),
+ 'cust_pkg' => shift,
+ 'width' => 390,
+ 'height' => 220,
+ );
+}
sub pkg_discount_link {
my $cust_pkg = shift or return '';
diff --git a/httemplate/view/cust_main/packages/section.html b/httemplate/view/cust_main/packages/section.html
index 85f0c795a..82d06203b 100755
--- a/httemplate/view/cust_main/packages/section.html
+++ b/httemplate/view/cust_main/packages/section.html
@@ -1,53 +1,50 @@
% if ( @$packages ) {
-% my $bgcolor1 = '#eeeeee';
-% my $bgcolor2 = '#ffffff';
-% my $bgcolor = '';
-
<TR>
% #my $width = $show_location ? 'WIDTH="25%"' : 'WIDTH="33%"';
<TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Package') |h %></TH>
<TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Status') |h %></TH>
-% if ( $show_location ) {
- <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Location') |h %></TH>
-% }
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Contact/Location') |h %></TH>
<TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Services') |h %></TH>
</TR>
% #$FS::cust_pkg::DEBUG = 2;
% foreach my $cust_pkg (@$packages) {
+ <& .packagerow, $cust_pkg,
+ ( map { $_ => $opt{$_} } qw(
+ cust_main bgcolor
+ no_links before_pkg_callback before_svc_callback after_svc_callback
+ )),
+ %conf_opt
+ &>
+% }
+% } else { # there are no packages
+<BR>
+% }
+<%def .packagerow>
%
-% if ( $bgcolor eq $bgcolor1 ) {
-% $bgcolor = $bgcolor2;
-% } else {
-% $bgcolor = $bgcolor1;
-% }
-%
-% my %iopt = (
-% 'bgcolor' => $bgcolor,
-% 'cust_pkg' => $cust_pkg,
-% 'part_pkg' => $cust_pkg->part_pkg,
-% 'cust_main' => $opt{'cust_main'},
-% %conf_opt,
-% );
-%
-
+% my ($cust_pkg, %iopt) = @_;
+% $iopt{'cust_pkg'} = $cust_pkg;
+% $iopt{'part_pkg'} = $cust_pkg->part_pkg;
<!--pkgnum: <% $cust_pkg->pkgnum %>-->
- <TR>
+ <TR CLASS="row<%$row % 2%>">
<& package.html, %iopt &>
- <& status.html, %iopt &>
-% if ( $show_location ) {
- <& location.html, %iopt &>
-% }
+ <& status.html, %iopt &>
+ <TD CLASS="inv" BGCOLOR="<% $iopt{bgcolor} %>" WIDTH="20%" VALIGN="top">
+ <& contact.html, %iopt &><BR>
+ <& location.html, %iopt &>
+ </TD>
<& services.html, %iopt &>
</TR>
-
-% } #foreach $cust_pkg
-%# </TABLE>
-% } #if @$packages
-% else {
-<BR>
+% $row++;
+% # include supplemental packages if any
+% $iopt{'supplemental'} = ($iopt{'supplemental'} || 0) + 1;
+% foreach my $supp_pkg ($cust_pkg->supplemental_pkgs) {
+ <& .packagerow, $supp_pkg, %iopt &>
% }
-
+</%def>
+<%shared>
+my $row = 0;
+</%shared>
<%init>
my %opt = @_;
@@ -56,7 +53,6 @@ my $conf = new FS::Conf;
my $curuser = $FS::CurrentUser::CurrentUser;
my $packages = $opt{'packages'};
-my $show_location = $opt{'show_location'};
# Sort order is hardcoded for now, can change this if needed.
@$packages = sort {
@@ -65,6 +61,15 @@ my $show_location = $opt{'show_location'};
( $a->getfield('pkgnum') <=> $b->getfield('pkgnum') )
} @$packages;
+my %change_custnum = map { $_->change_custnum => 1 }
+ grep { $_->change_custnum }
+ grep { $_->getfield('cancel') }
+ @$packages;
+
+my $pkg_attached = ( scalar(keys %change_custnum) == 1
+ && ! grep { ! $_->getfield('cancel') } @$packages
+ );
+
my $countrydefault = scalar($conf->config('countrydefault')) || 'US';
my %conf_opt = (
@@ -73,6 +78,7 @@ my %conf_opt = (
|| $curuser->option('cust_pkg-display_times')),
#for status.html
'cust_pkg-show_autosuspend' => $conf->exists('cust_pkg-show_autosuspend'),
+ 'pkg_attached' => $pkg_attached,
#for status.html pkg-balances
'pkg-balances' => $conf->exists('pkg-balances'),
'money_char' => ( $conf->config('money_char') || '$' ),
@@ -88,11 +94,8 @@ my %conf_opt = (
'manage_link_text' => scalar($conf->config('svc_broadband-manage_link_text')),
'manage_link_loc' => scalar($conf->config('svc_broadband-manage_link_loc')),
'manage_link-new_window' => $conf->exists('svc_broadband-manage_link-new_window'),
- 'maestro-status_test' => $conf->exists('maestro-status_test'),
- 'cust_pkg-large_pkg_size' => $conf->config('cust_pkg-large_pkg_size'),
+ 'cust_pkg-large_pkg_size' => scalar($conf->config('cust_pkg-large_pkg_size')),
- # for packages.html Change location link
- 'show_location' => $show_location,
);
</%init>
diff --git a/httemplate/view/cust_main/packages/services.html b/httemplate/view/cust_main/packages/services.html
index c0a56d0f3..7dfc0049e 100644
--- a/httemplate/view/cust_main/packages/services.html
+++ b/httemplate/view/cust_main/packages/services.html
@@ -24,7 +24,7 @@ function clearhint_search_cust_svc(obj, str) {
<TD ALIGN="right" VALIGN="top">
% my $href="${p}search/cust_pkg_svc.html?svcpart=".$part_svc->svcpart.
% ";pkgnum=".$cust_pkg->pkgnum;
- <A HREF="<% $href %>"><% $part_svc->svc %></A>
+ <A HREF="<% $href %>"><% $part_svc->svc |h %></A>
</TD>
<TD ALIGN="left" VALIGN="top">
<A HREF="<% $href %>"><B>(<% mt("view all [_1]", $num_cust_svc) |h %>)</B></A>
@@ -74,9 +74,21 @@ function clearhint_search_cust_svc(obj, str) {
<TR>
<TD COLSPAN=3 ALIGN="center" STYLE="padding-bottom:4px;padding-top:0px">
- <B><% svc_provision_link($cust_pkg, $part_svc, \%opt, $curuser) %></B>
+
+ <B>
+% if ( $opt{no_links} ) {
+ <% $part_svc->svc |h %>: <% $part_svc->num_avail %>
+ <% mt('Available') |h %>
+% } else {
+ <% svc_provision_link($cust_pkg, $part_svc, \%opt, $curuser) %>
+% }
+ </B>
+
% if ( $curuser->access_right('Bulk provision customer service')
-% && $part_svc->svcdb eq 'svc_phone' ) {
+% && $part_svc->svcdb eq 'svc_phone'
+% && ! $opt{no_links}
+% )
+% {
% if ( $part_svc->num_avail > 5 ) {
% local $opt{'bulk'} = 1;
<BR><% svc_provision_link($cust_pkg, $part_svc, \%opt, $curuser) %>
diff --git a/httemplate/view/cust_main/packages/status.html b/httemplate/view/cust_main/packages/status.html
index e9017745b..ed360cca4 100644
--- a/httemplate/view/cust_main/packages/status.html
+++ b/httemplate/view/cust_main/packages/status.html
@@ -1,9 +1,11 @@
-<TD CLASS="inv" BGCOLOR="<% $bgcolor %>">
+<TD CLASS="inv" BGCOLOR="<% $bgcolor %>" VALIGN="top">
<TABLE CLASS="inv" BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="100%">
%#this should use cust_pkg->status and cust_pkg->statuscolor eventually
-% if ( $cust_pkg->order_date ) {
+% if ( $supplemental ) {
+ <% pkg_status_row_colspan($cust_pkg, emt('Supplemental'), '', 'color' => '7777FF', %opt) %>
+% } elsif ( $cust_pkg->order_date ) {
<% pkg_status_row($cust_pkg, emt('Ordered'), 'order_date', %opt ) %>
% }
@@ -12,32 +14,29 @@
<% pkg_status_row($cust_pkg, emt('Cancelled'), 'cancel', 'color'=>'FF0000', %opt ) %>
- <% pkg_status_row_colspan( $cust_pkg,
- ( $cpr ? $cpr->reasontext. ' by '. $cpr->otaker : '' ), '',
- 'align'=>'right', 'color'=>'ff0000', 'size'=>'-2', 'colspan'=>$colspan,
- %opt
- )
- %>
+ <% pkg_status_row_detached($cust_pkg, %opt) %>
+
+ <% pkg_reason_row($cust_pkg, $cpr, color => 'ff0000', %opt) %>
% unless ( $cust_pkg->get('setup') ) {
- <% pkg_status_row_colspan( $cust_pkg, emt('Never billed'), '', 'colspan'=>$colspan, %opt, ) %>
+ <% pkg_status_row_colspan( $cust_pkg, emt('Never billed'), '', %opt, ) %>
% } else {
<% pkg_status_row( $cust_pkg, emt('Setup'), 'setup', %opt ) %>
- <% pkg_status_row_changed( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+ <% pkg_status_row_changed( $cust_pkg, %opt ) %>
<% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', %opt, curuser=>$curuser ) %>
<% pkg_status_row_if( $cust_pkg, emt('Suspended'), 'susp', %opt, curuser=>$curuser ) %>
% }
%
-% if ( $part_pkg->freq ) { #?
+% if ( $part_pkg->freq && !$supplemental && !$cust_pkg->change_custnum ) { #?
<TR>
- <TD COLSPAN=<%$colspan%>>
+ <TD COLSPAN=<%$opt{colspan}%>>
<FONT SIZE=-1>
-% if ( $curuser->access_right('Un-cancel customer package') ) {
+% if ( $curuser->access_right('Un-cancel customer package') && ! $opt{no_links} ) {
(&nbsp;<% pkg_uncancel_link($cust_pkg) %>&nbsp;)
% }
<FONT>
@@ -52,26 +51,21 @@
<% pkg_status_row( $cust_pkg, emt('Suspended'), 'susp', 'color'=>'FF9900', %opt ) %>
- <% pkg_status_row_colspan( $cust_pkg,
- ( $cpr ? $cpr->reasontext. ' by '. $cpr->otaker : '' ), '',
- 'align'=>'right', 'color'=>'FF9900', 'size'=>'-2', 'colspan'=>$colspan,
- %opt,
- )
- %>
+ <% pkg_reason_row( $cust_pkg, $cpr, 'color' => 'FF9900', %opt ) %>
- <% pkg_status_row_noauto( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+ <% pkg_status_row_noauto( $cust_pkg, %opt ) %>
- <% pkg_status_row_discount( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+ <% pkg_status_row_discount( $cust_pkg, %opt ) %>
% unless ( $cust_pkg->get('setup') ) {
- <% pkg_status_row_colspan( $cust_pkg, emt('Never billed'), '', 'colspan'=>$colspan, %opt ) %>
+ <% pkg_status_row_colspan( $cust_pkg, emt('Never billed'), '', %opt ) %>
% } else {
<% pkg_status_row($cust_pkg, emt('Setup'), 'setup', %opt ) %>
% }
<% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %>
- <% pkg_status_row_changed( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+ <% pkg_status_row_changed( $cust_pkg, %opt ) %>
<% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', %opt, curuser=>$curuser ) %>
% if ( $cust_pkg->option('suspend_bill', 1)
% || ( $part_pkg->option('suspend_bill', 1)
@@ -85,31 +79,33 @@
<% pkg_status_row_if( $cust_pkg, emt('Expires'), 'expire', %opt, curuser=>$curuser ) %>
<% pkg_status_row_if( $cust_pkg, emt('Contract ends'), 'contract_end', %opt ) %>
- <TR>
- <TD COLSPAN=<%$colspan%>>
- <FONT SIZE=-1>
-% if ( $curuser->access_right('Unsuspend customer package') ) {
- (&nbsp;<% pkg_unsuspend_link($cust_pkg) %>&nbsp;)
- (&nbsp;<% pkg_resume_link($cust_pkg) %>&nbsp;)
-% }
-% if ( $curuser->access_right('Cancel customer package immediately') ) {
- (&nbsp;<% pkg_cancel_link($cust_pkg) %>&nbsp;)
-% }
- </FONT>
- </TD>
- </TR>
-
+% if ( !$supplemental && ! $opt{no_links} ) {
+ <TR>
+ <TD COLSPAN=<%$opt{colspan}%>>
+ <FONT SIZE=-1>
+% if ( $curuser->access_right('Unsuspend customer package') ) {
+ (&nbsp;<% pkg_unsuspend_link($cust_pkg) %>&nbsp;)
+ (&nbsp;<% pkg_resume_link($cust_pkg) %>&nbsp;)
+% }
+% if ( $curuser->access_right('Cancel customer package immediately') ) {
+ (&nbsp;<% pkg_cancel_link($cust_pkg) %>&nbsp;)
+% }
+ </FONT>
+ </TD>
+ </TR>
+% }
+%
% } else { #status: active
%
% unless ( $cust_pkg->get('setup') ) { #not setup
%
% unless ( $part_pkg->freq ) {
- <% pkg_status_row_colspan( $cust_pkg, emt('Not yet billed (one-time charge)'), '', 'colspan'=>$colspan, %opt ) %>
+ <% pkg_status_row_colspan( $cust_pkg, emt('Not yet billed (one-time charge)'), '', %opt ) %>
- <% pkg_status_row_noauto( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+ <% pkg_status_row_noauto( $cust_pkg, %opt ) %>
- <% pkg_status_row_discount( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+ <% pkg_status_row_discount( $cust_pkg, %opt ) %>
<% pkg_status_row_if(
$cust_pkg,
@@ -121,8 +117,9 @@
<% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %>
+% if ( !$supplemental && ! $opt{no_links} ) {
<TR>
- <TD COLSPAN=<%$colspan%>>
+ <TD COLSPAN=<%$opt{colspan}%>>
<FONT SIZE=-1>
% if ( $curuser->access_right('Cancel customer package immediately') ) {
(&nbsp;<% pkg_cancel_link($cust_pkg) %>&nbsp;)
@@ -130,14 +127,15 @@
</FONT>
</TD>
</TR>
+% }
% } else {
- <% pkg_status_row_colspan($cust_pkg, emt("Not yet billed ($billed_or_prepaid [_1])", myfreq($part_pkg) ), '', 'colspan'=>$colspan, %opt ) %>
+ <% pkg_status_row_colspan($cust_pkg, emt("Not yet billed ($billed_or_prepaid [_1])", myfreq($part_pkg) ), '', %opt ) %>
- <% pkg_status_row_noauto( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+ <% pkg_status_row_noauto( $cust_pkg, %opt ) %>
- <% pkg_status_row_discount( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+ <% pkg_status_row_discount( $cust_pkg, %opt ) %>
<% pkg_status_row_if($cust_pkg, emt('Start billing'), 'start_date', %opt) %>
<% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %>
@@ -148,13 +146,13 @@
%
% unless ( $part_pkg->freq ) {
- <% pkg_status_row_colspan($cust_pkg, emt('One-time charge'), '', 'colspan'=>$colspan, %opt ) %>
+ <% pkg_status_row_colspan($cust_pkg, emt('One-time charge'), '', %opt ) %>
<% pkg_status_row($cust_pkg, emt('Billed'), 'setup', %opt) %>
- <% pkg_status_row_noauto( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+ <% pkg_status_row_noauto( $cust_pkg, %opt ) %>
- <% pkg_status_row_discount( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+ <% pkg_status_row_discount( $cust_pkg, %opt ) %>
<% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %>
@@ -170,7 +168,7 @@
<% pkg_status_row_colspan( $cust_pkg,
emt('Overlimit'),
$billed_or_prepaid. '&nbsp;'. myfreq($part_pkg),
- 'color'=>'FFD000', 'colspan'=>$colspan,
+ 'color'=>'FFD000',
%opt
)
%>
@@ -179,15 +177,15 @@
<% pkg_status_row_colspan( $cust_pkg,
emt('Active'),
$billed_or_prepaid. '&nbsp;'. myfreq($part_pkg),
- 'color'=>'00CC00', 'colspan'=>$colspan,
+ 'color'=>'00CC00',
%opt
)
%>
% }
- <% pkg_status_row_noauto( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+ <% pkg_status_row_noauto( $cust_pkg, %opt ) %>
- <% pkg_status_row_discount( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+ <% pkg_status_row_discount( $cust_pkg, %opt ) %>
<% pkg_status_row($cust_pkg, emt('Setup'), 'setup', %opt) %>
@@ -202,7 +200,7 @@
% $cust_pkg->set('autosuspend', $autosuspend) if $autosuspend;
% }
- <% pkg_status_row_changed( $cust_pkg, %opt, 'colspan'=>$colspan ) %>
+ <% pkg_status_row_changed( $cust_pkg, %opt ) %>
<% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', %opt, curuser=>$curuser ) %>
<% pkg_status_row_if( $cust_pkg, $next_bill_or_prepaid_until, 'bill', %opt, curuser=>$curuser ) %>
<% pkg_status_row_if($cust_pkg, emt('Will automatically suspend by'), 'autosuspend', %opt) %>
@@ -212,10 +210,10 @@
<% pkg_status_row_if( $cust_pkg, emt('Expires'), 'expire', %opt, curuser=>$curuser ) %>
<% pkg_status_row_if( $cust_pkg, emt('Contract ends'), 'contract_end', %opt ) %>
-% if ( $part_pkg->freq ) {
+% if ( $part_pkg->freq and !$supplemental && ! $opt{no_links} ) {
<TR>
- <TD COLSPAN=<%$colspan%>>
+ <TD COLSPAN=<%$opt{colspan}%>>
<FONT SIZE=-1>
% if ( $curuser->access_right('Suspend customer package') ) {
(&nbsp;<% pkg_suspend_link($cust_pkg) %>&nbsp;)
@@ -251,8 +249,10 @@ my $bgcolor = $opt{'bgcolor'};
my $cust_pkg = $opt{'cust_pkg'};
my $part_pkg = $opt{'part_pkg'};
my $curuser = $FS::CurrentUser::CurrentUser;
-my $colspan = $opt{'cust_pkg-display_times'} ? 8 : 4;
my $width = $opt{'cust_pkg-display_times'} ? '38%' : '56%';
+my $supplemental = $opt{'supplemental'};
+
+$opt{colspan} = $opt{'cust_pkg-display_times'} ? 8 : 4;
#false laziness w/edit/REAL_cust_pkg.cgi
my( $billed_or_prepaid, $last_bill_or_renewed, $next_bill_or_prepaid_until );
@@ -285,9 +285,27 @@ sub pkg_link {
sub pkg_status_row {
my( $cust_pkg, $title, $field, %opt ) = @_;
+ if ( $field and $cust_pkg->main_pkgnum ) {
+ # for supplemental packages, we mostly only show these if they're
+ # different from the main package
+ my $main_pkg = $cust_pkg-> main_pkg;
+ if ( $main_pkg->get($field) ne $cust_pkg->get($field)
+ # with some exceptions
+ or $field eq 'bill'
+ or $field eq 'last_bill'
+ or $field eq 'setup'
+ or $field eq 'susp'
+ or $field eq 'cancel'
+ ) {
+ # handle it normally
+ } else {
+ return '';
+ }
+ }
+
my $color = $opt{'color'};
- my $html = qq(<TR><TD WIDTH="<%$width%>" ALIGN="right">);
+ my $html = qq(<TR><TD WIDTH="$width" ALIGN="right">);
$html .= qq(<FONT COLOR="#$color"><B>) if length($color);
$html .= qq($title&nbsp;);
$html .= qq(</B></FONT>) if length($color);
@@ -338,7 +356,37 @@ sub pkg_status_row_changed {
'',
'size' => '-1',
'align' => 'right',
- 'colspan' => $opt{'colspan'},
+ );
+ }
+
+ $html;
+}
+
+sub pkg_status_row_detached {
+ my( $cust_pkg, %opt ) = @_;
+
+ return '' unless $cust_pkg->change_custnum;
+
+ my $html = '';
+
+ my $cust_main = $cust_pkg->change_cust_main;
+ if ( $cust_main ) {
+
+ my $cust_link = '<A HREF="cust_main.cgi?'. $cust_pkg->change_custnum. '">'.
+ encode_entities( $cust_main->name ).
+ '</A>';
+
+ my $what = $opt{'pkg_attached'} ? 'Attached' : 'Detached';
+
+ $html .= pkg_status_row_colspan( $cust_pkg,
+ emt("$what to customer #[_1]: ",
+ $cust_pkg->change_custnum
+ ).
+ $cust_link,
+ '',
+ 'size' => '-1',
+ 'align' => 'right',
+ 'colspan' => 4,
);
}
@@ -356,9 +404,7 @@ sub pkg_status_row_noauto {
return '' unless $cust_main->payby =~ /^(CARD|CHEK)$/;
my $what = lc(FS::payby->shortname($cust_main->payby));
- pkg_status_row_colspan( $cust_pkg, emt("No automatic $what charge"), '',
- 'colspan' => $opt{'colspan'},
- );
+ pkg_status_row_colspan( $cust_pkg, emt("No automatic $what charge"), '');
}
sub pkg_status_row_discount {
@@ -382,15 +428,24 @@ sub pkg_status_row_discount {
$cust_pkg_discount->pkgdiscountnum.
'">'.emt('remove discount').'</A>)</FONT>';
- $html .= pkg_status_row_colspan( $cust_pkg, $label, '',
- 'colspan' => $opt{'colspan'},
- );
+ $html .= pkg_status_row_colspan( $cust_pkg, $label, '', %opt );
}
$html;
}
+sub pkg_reason_row {
+ my ($cust_pkg, $cpr, %opt) = @_;
+ return '' if $cust_pkg->main_pkgnum;
+
+ my $reasontext = '';
+ $reasontext = $cpr->reasontext . ' by ' . $cpr->otaker if $cpr;
+ pkg_status_row_colspan( $cust_pkg, $reasontext, '',
+ 'align'=>'right', 'size'=>'-2', %opt
+ );
+}
+
sub pkg_status_row_colspan {
my($cust_pkg, $title, $addl, %opt) = @_;
diff --git a/httemplate/view/cust_main/payment_history.html b/httemplate/view/cust_main/payment_history.html
index 166addbf4..c7bf3748c 100644
--- a/httemplate/view/cust_main/payment_history.html
+++ b/httemplate/view/cust_main/payment_history.html
@@ -34,7 +34,7 @@
<A HREF="<% $p %>edit/cust_pay.cgi?payby=WEST;custnum=<% $custnum %>"><% mt('Enter Western Union payment') |h %></A>
% }
-<BR>
+<% $s ? '<BR>' : '' %>
% $s=0;
% if ( ( $payby{'CARD'} || $payby{'DCRD'} )
@@ -58,11 +58,13 @@
<A HREF="<% $p %>edit/cust_pay.cgi?payby=MCRD;custnum=<% $custnum %>"><% mt('Post manual (offline/POS) credit card payment') |h %></A>
% }
-<BR>
+<% $s ? '<BR>' : '' %>
-%# credit link
+%# credit links
+% $s=0;
% if ( $curuser->access_right('Post credit') ) {
+ <% $s++ ? ' | ' : '' %>
<& /elements/popup_link-cust_main.html,
'label' => emt('Enter credit'),
'action' => "${p}edit/cust_credit.cgi",
@@ -70,8 +72,20 @@
'actionlabel' => emt('Enter credit'),
'width' => 616, #make room for reasons #540 default
&>
- <BR>
+% }
+% if ( $curuser->access_right('Credit line items') ) {
+ <% $s++ ? ' | ' : '' %>
+ <& /elements/popup_link-cust_main.html,
+ 'label' => emt('Credit line items'),
+ #'action' => "${p}search/cust_bill_pkg.cgi?nottax=1;type=select",
+ 'action' => "${p}edit/credit-cust_bill_pkg.html",
+ 'cust_main' => $cust_main,
+ 'actionlabel' => emt('Credit line items'),
+ 'width' => 968, #763,
+ 'height' => 575,
+ &>
% }
+<% $s ? '<BR>' : '' %>
%# refund links
@@ -127,10 +141,9 @@
%# invoice reports, combined statement
% if ( $curuser->access_right('List invoices') ) {
-% if ( $conf->exists('cust_main-print_statement_link')
-% and $num_cust_bill > 0 ) {
+% if ( $num_cust_bill > 0 ) {
<A HREF="<% $p %>view/cust_main_statement-pdf.cgi?<% $custnum %>"><%
- mt('Print a current statement') |h %></A>
+ mt('Download typeset statement PDF') |h %></A>
<BR>
% }
<A HREF="<% $p %>search/report_cust_bill.html?custnum=<% $custnum %>"><% mt('Invoice reports') |h %></A>
@@ -214,57 +227,20 @@
%#display payment history
-%my $money_char = $conf->config('money_char') || '$';
-%
-%sub balance_forward_row {
-% my( $b, $date, $money_char ) = @_;
-% ( my $balance_forward = $money_char. $b ) =~ s/^\$\-/-&nbsp;\$/;
-
- <TR ID="balance_forward_row">
- <TD CLASS="grid" BGCOLOR="#dddddd">
- <% time2str($date_format, $date) %>
- </TD>
-
- <TD CLASS="grid" BGCOLOR="#dddddd">
- <I><% mt("Starting balance on [_1]", time2str($date_format, $date) ) |h %></I>
- (<A HREF="javascript:void(0);" onClick="show_history();"><% mt('show prior history') |h %></A>)
- </TD>
-
- <TD CLASS="grid" BGCOLOR="#dddddd"></TD>
- <TD CLASS="grid" BGCOLOR="#dddddd"></TD>
- <TD CLASS="grid" BGCOLOR="#dddddd"></TD>
- <TD CLASS="grid" BGCOLOR="#dddddd"></TD>
- <TD CLASS="grid" BGCOLOR="#dddddd" ALIGN="right"><I><% $balance_forward %></I></TD>
-
- </TR>
-%}
-%
-%my $balance = 0;
%my %target = ();
%
-%my $years = $conf->config('payment_history-years') || 2;
-%my $older_than = time - $years * 31556926; #60*60*24*365.2422
%my $hidden = 0;
%my $seen = 0;
%my $old_history = 0;
%my $lastdate = 0;
%
-%foreach my $item ( sort { $a->{'date'} <=> $b->{'date'} } @history ) {
+%foreach my $item ( @history ) {
%
% $lastdate = $item->{'date'};
%
-% my $display;
-% if ( $item->{'date'} < $older_than ) {
+% my $display = '';
+% if ( $item->{'hide'} ) {
% $display = ' STYLE="display:none" ';
-% $hidden = 1;
-% } else {
-%
-% $display = '';
-%
-% if ( $hidden && ! $seen++ ) {
-% balance_forward_row($balance, $item->{'date'}, $money_char);
-% }
-%
% }
%
% if ( $bgcolor eq $bgcolor1 ) {
@@ -300,16 +276,8 @@
%
% my $target = exists($item->{'target'}) ? $item->{'target'} : '';
%
-% $balance += $item->{'charge'} if exists $item->{'charge'};
-% $balance -= $item->{'payment'} if exists $item->{'payment'};
-% $balance -= $item->{'credit'} if exists $item->{'credit'};
-% $balance += $item->{'refund'} if exists $item->{'refund'};
-% $balance = sprintf("%.2f", $balance);
-% $balance =~ s/^\-0\.00$/0.00/; #yay ieee fp
-% ( my $showbalance = $money_char. $balance ) =~ s/^\$\-/-&nbsp;\$/;
-%
-%
-
+% my $showbalance = $money_char . $item->{'balance'};
+% $showbalance =~ s/^\$\-/-&nbsp;\$/;
<TR <% $display ? $display.' ID="old_history'.$old_history++.'"' : ''%>>
<TD VALIGN="top" CLASS="grid" BGCOLOR="<% $bgcolor %>">
@@ -345,11 +313,11 @@
<% $showbalance %>
</TD>
</TR>
-% }
-%if ( scalar(@history) && $hidden && ! $seen++ ) {
-% balance_forward_row($balance, $lastdate, $money_char);
-%}
+% if ( $item->{'balance_forward'} ) {
+<& .balance_forward_row, $item->{'balance'}, $item->{'date'} &>
+% }
+%} # foreach $item
</TABLE>
</TD>
@@ -372,14 +340,37 @@ function show_history () {
}
</SCRIPT>
+<%def .balance_forward_row>
+% my( $b, $date ) = @_;
+% ( my $balance_forward = $money_char. $b ) =~ s/^\$\-/-&nbsp;\$/;
-<%init>
+ <TR ID="balance_forward_row">
+ <TD CLASS="grid" BGCOLOR="#dddddd">
+ <% time2str($date_format, $date) %>
+ </TD>
-my( $cust_main ) = @_;
-my $custnum = $cust_main->custnum;
+ <TD CLASS="grid" BGCOLOR="#dddddd">
+ <I><% mt("Starting balance on [_1]", time2str($date_format, $date) ) |h %></I>
+ (<A HREF="javascript:void(0);" onClick="show_history();"><% mt('show prior history') |h %></A>)
+ </TD>
+ <TD CLASS="grid" BGCOLOR="#dddddd"></TD>
+ <TD CLASS="grid" BGCOLOR="#dddddd"></TD>
+ <TD CLASS="grid" BGCOLOR="#dddddd"></TD>
+ <TD CLASS="grid" BGCOLOR="#dddddd"></TD>
+ <TD CLASS="grid" BGCOLOR="#dddddd" ALIGN="right"><I><% $balance_forward %></I></TD>
+
+ </TR>
+</%def>
+<%shared>
my $conf = new FS::Conf;
my $date_format = $conf->config('date_format') || '%m/%d/%Y';
+my $money_char = $conf->config('money_char') || '$';
+</%shared>
+<%init>
+
+my( $cust_main ) = @_;
+my $custnum = $cust_main->custnum;
my $curuser = $FS::CurrentUser::CurrentUser;
@@ -487,6 +478,17 @@ foreach my $cust_pay_pending ($cust_main->cust_pay_pending_attempt) {
#'target' => $target, #XXX
};
}
+#declined batch payments
+foreach my $cust_pay_batch (
+ $cust_main->cust_pay_batch(hashref => {status => 'Declined'})
+) {
+ my $pay_batch = $cust_pay_batch->pay_batch;
+ push @history, {
+ 'date' => $pay_batch->upload,
+ 'desc' => include('payment_history/attempted_batch_payment.html', $cust_pay_batch, %opt),
+ 'void_payment' => $cust_pay_batch->amount,
+ };
+}
#credits (some false laziness w/payments)
foreach my $cust_credit ($cust_main->cust_credit) {
@@ -508,6 +510,41 @@ foreach my $cust_refund ($cust_main->cust_refund) {
}
+# sort in forward order first, and calculate running balances
+my $years = $conf->config('payment_history-years') || 2;
+my $older_than = time - $years * 31556926; #60*60*24*365.2422
+my $balance = 0;
+
+@history = sort { $a->{date} <=> $b->{date} } @history;
+my $i = 0;
+my $balance_forward;
+foreach my $item (@history) {
+ $balance += $item->{'charge'} if exists $item->{'charge'};
+ $balance -= $item->{'payment'} if exists $item->{'payment'};
+ $balance -= $item->{'credit'} if exists $item->{'credit'};
+ $balance += $item->{'refund'} if exists $item->{'refund'};
+ $balance = sprintf("%.2f", $balance);
+ $balance =~ s/^\-0\.00$/0.00/;
+ $item->{'balance'} = $balance;
+
+ if ( $item->{'date'} < $older_than ) {
+ $item->{'hide'} = 1;
+ } elsif ( $history[$i-1]->{'hide'} ) {
+ # this is the end of the hidden section
+ $history[$i-1]->{'balance_forward'} = 1;
+ }
+ $i++;
+}
+if ( @history and $history[-1]->{'hide'} ) {
+ # then everything is hidden
+ $history[-1]->{'balance_forward'} = 1;
+}
+
+# then sort in user-pref order
+if ( $curuser->option('history_order') eq 'newest' ) {
+ @history = sort { $b->{date} <=> $a->{date} } @history;
+} # else it's already oldest-first, and there are no other options yet
+
sub translate_payby {
my ($payby,$payinfo) = (shift,shift);
my %payby = (
diff --git a/httemplate/view/cust_main/payment_history/attempted_batch_payment.html b/httemplate/view/cust_main/payment_history/attempted_batch_payment.html
new file mode 100644
index 000000000..95947f512
--- /dev/null
+++ b/httemplate/view/cust_main/payment_history/attempted_batch_payment.html
@@ -0,0 +1,13 @@
+<I><% mt('Payment attempt') |h %> <% $info |h %></I>
+<%init>
+
+my( $cust_pay_batch, %opt ) = @_;
+
+my ($payby,$payinfo) = translate_payinfo($cust_pay_batch);
+$payby = translate_payby($payby,$payinfo);
+my $info = $payby ? "($payby$payinfo)" : '';
+
+$info .= ': '. $cust_pay_batch->error_message
+ if length($cust_pay_batch->error_message);
+
+</%init>