+ my $cnt = 0;
+ foreach my $svcpart (sort {$a->{svcpart} <=> $b->{svcpart}} @{$pkg->{svcparts}}) {
+ foreach my $service (@{$svcpart->{services}}) {
+ print '<TR>' if ($cnt > 0);
+%>
+ <TD><%=svc_link($svcpart,$service)%></TD>
+ <TD><%=svc_label_link($svcpart,$service)%><BR>( <%=svc_unprovision_link($service)%> )</TD>
+</TR>
+<%
+ $cnt++;
+ }
+ if ($svcpart->{count} < $svcpart->{quantity}) {
+ print qq!<TR>\n! if ($cnt > 0);
+ print qq! <TD COLSPAN=2>!.svc_provision_link($pkg, $svcpart, $conf).qq!</TD>\n</TR>\n!;
+ }
+ }
+}
+print '</TABLE>';
+}
+
+#end display packages
+%>
+
+<SCRIPT>
+function cust_pay_areyousure(href) {
+ if (confirm("Are you sure you want to delete this payment?")
+ == true)
+ window.location.href = href;
+}
+function cust_pay_unapply_areyousure(href) {
+ if (confirm("Are you sure you want to unapply this payment?")
+ == true)
+ window.location.href = href;
+}
+function cust_credit_unapply_areyousure(href) {
+ if (confirm("Are you sure you want to unapply this credit?")
+ == true)
+ window.location.href = href;
+}
+function cust_credit_areyousure(href) {
+ if (confirm("Are you sure you want to delete this credit?")
+ == true)
+ window.location.href = href;
+}
+</SCRIPT>
+
+<% if ( $conf->config('payby-default') ne 'HIDE' ) { %>
+
+ <BR><BR><A NAME="history"><FONT SIZE="+2">Payment History</FONT></A><BR>
+ <A HREF="<%= $p %>edit/cust_pay.cgi?custnum=<%= $custnum %>">Post cash/check payment</A>
+ | <A HREF="<%= $p %>misc/payment.cgi?payby=CARD;custnum=<%= $custnum %>">Process credit card payment</A>
+ | <A HREF="<%= $p %>misc/payment.cgi?payby=CHEK;custnum=<%= $custnum %>">Process electronic check (ACH) payment</A>
+ <BR><A HREF="<%= $p %>edit/cust_credit.cgi?<%= $custnum %>">Post credit</A>
+ <BR>
+
+ <%
+ #get payment history
+ my @history = ();
+
+ #invoices
+ foreach my $cust_bill ($cust_main->cust_bill) {
+ my $pre = ( $cust_bill->owed > 0 )
+ ? '<B><FONT SIZE="+1" COLOR="#FF0000">Open '
+ : '';
+ my $post = ( $cust_bill->owed > 0 ) ? '</FONT></B>' : '';
+ my $invnum = $cust_bill->invnum;
+ push @history, {
+ 'date' => $cust_bill->_date,
+ 'desc' => qq!<A HREF="${p}view/cust_bill.cgi?$invnum">!. $pre.
+ "Invoice #$invnum (Balance \$". $cust_bill->owed. ')'.
+ $post. '</A>',
+ 'charge' => $cust_bill->charged,
+ };
+ }
+
+ #payments (some false laziness w/credits)
+ foreach my $cust_pay ($cust_main->cust_pay) {
+
+ my $payby = $cust_pay->payby;
+ my $payinfo = $payby eq 'CARD'
+ ? $cust_pay->payinfo_masked
+ : $cust_pay->payinfo;
+ my @cust_bill_pay = $cust_pay->cust_bill_pay;
+
+ my $target = "$payby$payinfo";
+ $payby =~ s/^BILL$/Check #/ if $payinfo;
+ $payby =~ s/^BILL$//;
+ $payby =~ s/^(CARD|COMP)$/$1 /;
+ my $info = $payby ? " ($payby$payinfo)" : '';
+
+ my( $pre, $post, $desc, $apply, $ext ) = ( '', '', '', '', '' );
+ if ( scalar(@cust_bill_pay) == 0 ) {
+ #completely unapplied
+ $pre = '<B><FONT COLOR="#FF0000">Unapplied ';
+ $post = '</FONT></B>';
+ $apply = qq! (<A HREF="${p}edit/cust_bill_pay.cgi?!.
+ $cust_pay->paynum. '">apply</A>)';
+ } elsif ( scalar(@cust_bill_pay) == 1 && $cust_pay->unapplied == 0 ) {
+ #applied to one invoice
+ $desc = ' applied to Invoice #'. $cust_bill_pay[0]->invnum;
+ } else {
+ #complicated
+ $desc = '<BR>';
+ foreach my $cust_bill_pay (@cust_bill_pay) {
+ $desc .= ' '.
+ '$'. $cust_bill_pay->amount.
+ ' applied to Invoice #'. $cust_bill_pay->invnum.
+ '<BR>';
+ #' on '. time2str("%D", $cust_bill_pay->_date).
+
+ }
+ if ( $cust_pay->unapplied > 0 ) {
+ $desc .= ' '.
+ '<B><FONT COLOR="#FF0000">$'.
+ $cust_pay->unapplied. ' unapplied</FONT></B>'.
+ qq! (<A HREF="${p}edit/cust_bill_pay.cgi?!.
+ $cust_pay->paynum. '">apply</A>)'.
+ '<BR>';
+ }
+ }
+
+ my $delete = '';
+ if ( $cust_pay->closed !~ /^Y/i && $conf->exists('deletepayments') ) {
+ $delete = qq! (<A HREF="javascript:cust_pay_areyousure('!.
+ qq!${p}misc/delete-cust_pay.cgi?!. $cust_pay->paynum.
+ qq!')">delete</A>)!;
+ }
+
+ my $unapply = '';
+ if ( $cust_pay->closed !~ /^Y/i
+ && $conf->exists('unapplypayments')
+ && scalar(@cust_bill_pay) ) {
+ $unapply = qq! (<A HREF="javascript:cust_pay_unapply_areyousure('!.
+ qq!${p}misc/unapply-cust_pay.cgi?!. $cust_pay->paynum.
+ qq!')">unapply</A>)!;
+ }
+
+ push @history, {
+ 'date' => $cust_pay->_date,
+ 'desc' => $pre. "Payment$post$info$desc".
+ "$apply$delete$unapply",
+ 'payment' => $cust_pay->paid,
+ 'target' => $target,
+ };
+ }
+
+ #credits (some false laziness w/payments)
+ foreach my $cust_credit ($cust_main->cust_credit) {
+
+ my @cust_credit_bill = $cust_credit->cust_credit_bill;
+ my @cust_credit_refund = $cust_credit->cust_credit_refund;
+
+ my( $pre, $post, $desc, $apply, $ext ) = ( '', '', '', '', '' );
+ if ( scalar(@cust_credit_bill) == 0
+ && scalar(@cust_credit_refund) == 0 ) {
+ #completely unapplied
+ $pre = '<B><FONT COLOR="#FF0000">Unapplied ';
+ $post = '</FONT></B>';
+ $apply = qq! (<A HREF="${p}edit/cust_credit_bill.cgi?!.
+ $cust_credit->crednum. '">apply</A>)';
+ } elsif ( scalar(@cust_credit_bill) == 1
+ && scalar(@cust_credit_refund) == 0
+ && $cust_credit->credited == 0 ) {
+ #applied to one invoice
+ $desc = ' applied to Invoice #'. $cust_credit_bill[0]->invnum;
+ } elsif ( scalar(@cust_credit_bill) == 0
+ && scalar(@cust_credit_refund) == 1
+ && $cust_credit->credited == 0 ) {
+ #applied to one refund
+ $desc = ' refunded on '. time2str("%D", $cust_credit_refund[0]->_date);
+ } else {
+ #complicated
+ $desc = '<BR>';
+ foreach my $app ( sort { $a->_date <=> $b->_date }
+ ( @cust_credit_bill, @cust_credit_refund ) ) {
+ if ( $app->isa('FS::cust_credit_bill') ) {
+ $desc .= ' '.
+ '$'. $app->amount.
+ ' applied to Invoice #'. $app->invnum.
+ '<BR>';
+ #' on '. time2str("%D", $app->_date).
+ } elsif ( $app->isa('FS::cust_credit_refund') ) {
+ $desc .= ' '.
+ '$'. $app->amount.
+ ' refunded on'. time2str("%D", $app->_date).
+ '<BR>';
+ } else {
+ die "$app is not a FS::cust_credit_bill or a FS::cust_credit_refund";
+ }
+ }
+ if ( $cust_credit->credited > 0 ) {
+ $desc .= ' <B><FONT COLOR="#FF0000">$'.
+ $cust_credit->credited. ' unapplied</FONT></B>'.
+ qq! (<A HREF="${p}edit/cust_credit_bill.cgi?!.
+ $cust_credit->crednum. '">apply</A>)'.
+ '<BR>';
+ }
+ }