69571c78ea760337ff51c7d63d11041b889ae6cb
[freeside.git] / httemplate / view / cust_main / payment_history.html
1 <TABLE>
2   <TR>
3     <TD ALIGN="left">
4
5 %# payment links
6
7 % my $s = 0;
8 % if ( $payby{'BILL'} && $curuser->access_right(['Post payment', 'Post check payment' ]) ) { 
9   <% $s++ ? ' | ' : '' %>
10   <& /elements/popup_link-cust_main.html,
11                'label'       => emt('Enter check payment'),
12                'action'      => "${p}edit/cust_pay.cgi?popup=1;payby=BILL",
13                'cust_main'   => $cust_main,
14                'actionlabel' => emt('Enter check payment'),
15                'width'       => ( $opt{'pkg-balances'} ? 763 : 392),
16                'height'      => 392,
17   &>
18 % } 
19
20 % if ( $payby{'CASH'} && $curuser->access_right(['Post payment', 'Post cash payment']) ) { 
21   <% $s++ ? ' | ' : '' %>
22   <& /elements/popup_link-cust_main.html,
23                'label'       => emt('Enter cash payment'),
24                'action'      => "${p}edit/cust_pay.cgi?popup=1;payby=CASH",
25                'cust_main'   => $cust_main,
26                'actionlabel' => emt('Enter cash payment'),
27                'width'       => ( $opt{'pkg-balances'} ? 763 : 392),
28                'height'      => 392,
29   &>
30 % } 
31
32 % if ( $payby{'WEST'} && $curuser->access_right('Post payment') ) { 
33   <% $s++ ? ' | ' : '' %>
34   <A HREF="<% $p %>edit/cust_pay.cgi?payby=WEST;custnum=<% $custnum %>"><% mt('Enter Western Union payment') |h %></A>
35 % } 
36
37 <% $s ? '<BR>' : '' %>
38 % $s=0;
39
40 % if ( ( $payby{'CARD'} || $payby{'DCRD'} )
41 %        && $curuser->access_right(['Process payment', 'Process credit card payment'])
42 %        && ! $cust_main->is_encrypted($cust_main->payinfo)
43 %      ) {
44   <% $s++ ? ' | ' : '' %>
45   <A HREF="<% $p %>misc/payment.cgi?payby=CARD;custnum=<% $custnum %>"><% mt('Process credit card payment') |h %></A>
46 % } 
47
48 % if ( ( $payby{'CHEK'} || $payby{'DCHK'} )
49 %        && $curuser->access_right(['Process payment', 'Process Echeck payment'])
50 %        && ! $cust_main->is_encrypted($cust_main->payinfo)
51 %      ) {
52   <% $s++ ? ' | ' : '' %>
53   <A HREF="<% $p %>misc/payment.cgi?payby=CHEK;custnum=<% $custnum %>"><% mt('Process electronic check (ACH) payment') |h %></A>
54 % } 
55
56 % if ( $payby{'MCRD'} && $curuser->access_right('Post payment') ) { 
57   <% $s++ ? ' | ' : '' %>
58   <A HREF="<% $p %>edit/cust_pay.cgi?payby=MCRD;custnum=<% $custnum %>"><% mt('Post manual (offline/POS) credit card payment') |h %></A>
59 % } 
60
61 % if ( $payby{'MCRD'} && $curuser->access_right('Post payment') ) { 
62   <% $s++ ? ' | ' : '' %>
63   <A HREF="<% $p %>edit/cust_pay.cgi?payby=MCHK;custnum=<% $custnum %>"><% mt('Post manual (offline) electronic check payment') |h %></A>
64 % } 
65
66 <% $s ? '<BR>' : '' %>
67
68 %# credit links
69
70 % $s=0;
71 % if ( $curuser->access_right('Post credit') ) { 
72   <% $s++ ? ' | ' : '' %>
73   <& /elements/popup_link-cust_main.html,
74                'label'       => emt('Enter credit'),
75                'action'      => "${p}edit/cust_credit.cgi",
76                'cust_main'   => $cust_main,
77                'actionlabel' => emt('Enter credit'),
78                'width'       => ( $opt{'pkg-balances'} ? 763 : 616),
79   &>
80 % }
81 % if ( $curuser->access_right('Credit line items') ) { 
82   <% $s++ ? ' | ' : '' %>
83   <& /elements/popup_link-cust_main.html,
84                'label'       => emt('Credit line items'),
85                #'action'      => "${p}search/cust_bill_pkg.cgi?nottax=1;type=select",
86                'action'      => "${p}edit/credit-cust_bill_pkg.html",
87                'cust_main'   => $cust_main,
88                'actionlabel' => emt('Credit line items'),
89                'width'       => 968, #763,
90                'height'      => 575,
91   &>
92 % } 
93 <% $s ? '<BR>' : '' %>
94
95 %# refund links
96
97 % $s = 0;
98 % if ( $payby{'BILL'} && $curuser->access_right(['Post refund', 'Post check refund']) ) { 
99   <% $s++ ? ' | ' : '' %>
100   <& /elements/popup_link-cust_main.html,
101                'label'       => emt('Enter check refund'),
102                'action'      => "${p}edit/cust_refund.cgi?popup=1;payby=BILL",
103                'cust_main'   => $cust_main,
104                'actionlabel' => emt('Enter check refund'),
105                'width'       => 392,
106   &>
107 % } 
108
109 % if ( $payby{'CASH'} && $curuser->access_right(['Post refund', 'Post cash refund']) ) { 
110   <% $s++ ? ' | ' : '' %>
111   <& /elements/popup_link-cust_main.html,
112                'label'       => emt('Enter cash refund'),
113                'action'      => "${p}edit/cust_refund.cgi?popup=1;payby=CASH",
114                'cust_main'   => $cust_main,
115                'actionlabel' => emt('Enter cash refund'),
116                'width'       => 392,
117   &>
118 % } 
119
120 %# someday, perhaps.  very few gateways let you do unlinked refunds at all.
121 %# Authorize.net makes you sign a special form
122 %#
123 %#    % if ( ( $payby{'CARD'} || $payby{'DCRD'} )
124 %#    %        && $curuser->access_right('Process refund')
125 %#    %        && ! $cust_main->is_encrypted($cust_main->payinfo)
126 %#    %      ) {
127 %#      <% $s++ ? ' | ' : '' %>
128 %#      <A HREF="<% $p %>misc/refund.cgi?payby=CARD;custnum=<% $custnum %>">Process credit card refund</A>
129 %#    % } 
130 %#    
131 %#    % if ( ( $payby{'CHEK'} || $payby{'DCHK'} )
132 %#    %        && $curuser->access_right('Process refund')
133 %#    %        && ! $cust_main->is_encrypted($cust_main->payinfo)
134 %#    %      ) {
135 %#      <% $s++ ? ' | ' : '' %>
136 %#      <A HREF="<% $p %>misc/refund.cgi?payby=CHEK;custnum=<% $custnum %>">Process electronic check (ACH) refund</A>
137 %#    % } 
138
139 % if ( $payby{'MCRD'} && $curuser->access_right('Post refund') ) { 
140   <% $s++ ? ' | ' : '' %>
141   <A HREF="<% $p %>edit/cust_refund.cgi?payby=MCRD;custnum=<% $custnum %>"><% mt('Post manual (offline/POS) credit card refund') |h %></A>
142 % } 
143
144 % if ( $payby{'MCHK'} && $curuser->access_right('Post refund') ) { 
145   <% $s++ ? ' | ' : '' %>
146   <A HREF="<% $p %>edit/cust_refund.cgi?payby=MCRD;custnum=<% $custnum %>"><% mt('Post manual (offline) electronic check refund') |h %></A>
147 % } 
148
149     </TD>
150     <TD ALIGN="right" VALIGN="top">
151
152 %# invoice reports, combined statement
153 % if ( $curuser->access_right('List invoices') ) { 
154 %   if ( $curuser->access_right('Resend invoices')
155 %          && $cust_main->invoicing_list_emailonly ) {
156
157   <A HREF="<% $p %>misc/email-customer-statement.html?table=cust_main;agent_virt_agentnum=<% $cust_main->agentnum %>;custnum=<% $custnum %>"><% mt('Email statement to this customer') |h %></A>
158   <BR>
159
160 %   }
161 %   if ( $num_cust_bill > 0
162 %          && $curuser->access_right('View legacy typeset statements')
163 %   ) {
164       <A HREF="<% $p %>view/cust_main_statement-pdf.cgi?<% $custnum %>"><%
165       mt('Download typeset statement PDF') |h %></A>
166       <BR>
167 %   }
168   <A HREF="<% $p %>search/report_cust_bill.html?custnum=<% $custnum %>"><% mt('Invoice reports') |h %></A>
169 % } 
170 <BR>
171
172 %# XXX payments, credits, refund reports
173
174 %# tax exemption link
175
176 % my $view_exemptions = $curuser->access_right('View customer tax exemptions');
177 % my $add_adjustment = ( $conf->exists('enable_tax_adjustments')
178 %                       && $curuser->access_right('Add customer tax adjustment')
179 %                      );
180 % if ( $view_exemptions || $add_adjustment ) {
181
182 %   if ( $view_exemptions ) {
183       <A HREF="<% $p %>search/cust_tax_exempt_pkg.cgi?custnum=<% $custnum %>"><% mt('View tax exemptions') |h %></A>
184       <% $add_adjustment ? '|' : '' %>
185 %   } 
186
187 %   if ( $add_adjustment ) {
188       <& /elements/popup_link.html, {
189            'action' => $p.'edit/cust_tax_adjustment.html?custnum='. $cust_main->custnum,
190            'label'  => emt('Add tax adjustment'),
191            'actionlabel' => emt('Add tax adjustment'),
192            'height' => 200,
193          }
194       &>
195       |
196       <A HREF="<% $p %>search/cust_tax_adjustment.html?custnum=<% $custnum %>"><% mt('View tax adjustments') |h %></A>
197 %   } 
198
199   <BR>
200 % }
201
202 %# batched payment links
203
204 % if ( ( $conf->exists('batch-enable') || $conf->config('batch-enable_payby') )
205 %      && $curuser->access_right('View customer batched payments')
206 %    )
207 % { 
208     <% mt('View batched payments:') |h %> 
209 %   foreach my $status (qw( Queued In-transit Complete All )) {
210       <A HREF="<% $p %>search/cust_pay_batch.cgi?status=<% $status{$status} %>;custnum=<% $custnum %>"><% mt($status) |h %></A> 
211       <% $status ne 'All' ? '|' : '' %>
212 %   }
213     <BR>
214 % } 
215
216 %# pending payment links
217
218 % if ( $curuser->access_right('View customer pending payments')
219 %      && scalar($cust_main->cust_pay_pending)
220 %    )
221 % {
222     <A HREF="<% $p %>search/cust_pay_pending.html?magic=_date;statusNOT=done;custnum=<% $custnum %>"><% mt('View pending payments') |h %></A><BR>
223 % }
224
225     </TD>
226   </TR>
227   <TR>
228     <TD COLSPAN=2>
229
230 %# and now the table
231
232 <& /elements/table-grid.html &>
233 % my $bgcolor1 = '#eeeeee';
234 %   my $bgcolor2 = '#ffffff';
235 %   my $bgcolor = '';
236
237 <TR>
238   <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Date') |h %></TH>
239   <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Description') |h %></TH>
240   <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1><% mt('Invoice') |h %></FONT></TH>
241   <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1><% mt('Payment') |h %></FONT></TH>
242   <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1><% mt('In-house Credit') |h %></FONT></TH>
243   <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1><% mt('Refund') |h %></FONT></TH>
244   <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1><% mt('Balance') |h %></FONT></TH>
245 </TR>
246
247 %#display payment history
248
249 %my %target = ();
250 %
251 %my $hidden = 0;
252 %my $seen = 0;
253 %my $old_history = 0;
254 %my $lastdate = 0;
255 %
256 %foreach my $item ( @history ) {
257 %
258 %  $lastdate = $item->{'date'};
259 %
260 %  my $display = '';
261 %  if ( $item->{'hide'} ) {
262 %    $display = ' STYLE="display:none" ';
263 %  }
264 %
265 %  if ( $bgcolor eq $bgcolor1 ) {
266 %    $bgcolor = $bgcolor2;
267 %  } else {
268 %    $bgcolor = $bgcolor1;
269 %  }
270 %
271 %  my $charge  = exists($item->{'charge'})
272 %                  ? sprintf("$money_char\%.2f", $item->{'charge'})
273 %                  : exists($item->{'charge_nobal'})
274 %                    ? sprintf("$money_char\%.2f", $item->{'charge_nobal'})
275 %                    : exists($item->{'void_charge'})
276 %                      ? sprintf("<DEL>$money_char\%.2f</DEL>", $item->{'void_charge'})
277 %                      : '';
278 %
279 %  my $payment = exists($item->{'payment'})
280 %                  ? sprintf("-&nbsp;$money_char\%.2f", $item->{'payment'})
281 %                  : '';
282 %
283 %  $payment ||= sprintf( "<DEL>-&nbsp;$money_char\%.2f</DEL>",
284 %                        $item->{'void_payment'}
285 %                      )
286 %    if exists($item->{'void_payment'});
287 %
288 %  my $credit  = exists($item->{'credit'})
289 %                  ? sprintf("-&nbsp;$money_char\%.2f", $item->{'credit'})
290 %                  : '';
291 %
292 %  $credit ||= sprintf( "<DEL>-&nbsp;$money_char\%.2f</DEL>",
293 %                       $item->{'void_credit'}
294 %                     )
295 %    if exists($item->{'void_credit'});
296 %
297 %  my $refund  = exists($item->{'refund'})
298 %                  ? sprintf("$money_char\%.2f", $item->{'refund'})
299 %                  : '';
300 %
301 %  my $target = exists($item->{'target'}) ? $item->{'target'} : '';
302 %
303 %  my $showbalance = $money_char . $item->{'balance'};
304 %  $showbalance =~ s/^\$\-/-&nbsp;\$/;
305
306   <TR <% $display ? $display.' ID="old_history'.$old_history++.'"'  : ''%>>
307     <TD VALIGN="top" CLASS="grid" BGCOLOR="<% $bgcolor %>">
308 % unless ( !$target || $target{$target}++ ) { 
309
310         <A NAME="<% $target %>">
311 % } 
312
313       <% time2str($date_format, $item->{'date'}) %>
314 % if ( $target && $target{$target} == 1 ) { 
315
316         </A>
317 % } 
318
319       </FONT>
320     </TD>
321     <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
322       <% $item->{'desc'} %>
323     </TD>
324     <TD VALIGN="top" ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>">
325       <% $charge  %>
326     </TD>
327     <TD VALIGN="top" ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>">
328       <% $payment %>
329     </TD>
330     <TD VALIGN="top" ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>">
331       <% $credit  %>
332     </TD>
333     <TD VALIGN="top" ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>">
334       <% $refund  %>
335     </TD>
336     <TD VALIGN="top" ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>">
337       <% $showbalance %>
338     </TD>
339   </TR>
340
341 % if ( $item->{'balance_forward'} ) {
342 <& .balance_forward_row, $item->{'balance'}, $item->{'date'} &>
343 % } 
344 %} # foreach $item
345
346 </TABLE>
347     </TD>
348   </TR>
349 </TABLE>
350
351 <SCRIPT TYPE="text/javascript">
352
353 function show_history () {
354   //alert('showing history!');
355
356   var balance_forward_row = document.getElementById('balance_forward_row');
357
358   balance_forward_row.style.display = 'none';
359   for ( var i = 0; i < <% $old_history %>; i++ ) {
360     var oldRow = document.getElementById('old_history'+i);
361     oldRow.style.display = '';
362   }
363
364 }
365
366 </SCRIPT>
367 <%def .balance_forward_row>
368 %  my( $b, $date ) = @_;
369 %  ( my $balance_forward = $money_char. $b ) =~ s/^\$\-/-&nbsp;\$/;
370
371    <TR ID="balance_forward_row">
372      <TD CLASS="grid" BGCOLOR="#dddddd">
373        <% time2str($date_format, $date) %>
374      </TD>
375
376      <TD CLASS="grid" BGCOLOR="#dddddd">
377        <I><% mt("Starting balance on [_1]", time2str($date_format, $date) ) |h %></I>
378        (<A HREF="javascript:void(0);" onClick="show_history();"><% mt('show prior history') |h %></A>)
379      </TD>
380
381      <TD CLASS="grid" BGCOLOR="#dddddd"></TD>
382      <TD CLASS="grid" BGCOLOR="#dddddd"></TD>
383      <TD CLASS="grid" BGCOLOR="#dddddd"></TD>
384      <TD CLASS="grid" BGCOLOR="#dddddd"></TD>
385      <TD CLASS="grid" BGCOLOR="#dddddd" ALIGN="right"><I><% $balance_forward %></I></TD>
386
387    </TR>
388 </%def>
389 <%shared>
390 my $conf = new FS::Conf;
391 my $date_format = $conf->config('date_format') || '%m/%d/%Y';
392 my $money_char = $conf->config('money_char') || '$';
393 </%shared>
394 <%init>
395
396 my( $cust_main ) = @_;
397 my $custnum = $cust_main->custnum;
398
399 my $curuser = $FS::CurrentUser::CurrentUser;
400
401 my @payby = grep /\w/, $conf->config('payby');
402 #@payby = (qw( CARD DCRD CHEK DCHK LECB BILL CASH WEST COMP ))
403 @payby = (qw( CARD DCRD CHEK DCHK LECB BILL CASH COMP ))
404   unless @payby;
405 my %payby = map { $_=>1 } @payby;
406
407 my %status = (
408   'Queued'     => 'O', #Open
409   'In-transit' => 'I',
410   'Complete'   => 'R', #Resolved
411   'All'        => '',
412 );
413
414 #get payment history
415 my @history = ();
416
417 my %opt = (
418
419   #config
420   ( map { $_ => scalar($conf->config($_)) }
421         qw( card_refund-days date_format )
422   ),
423   ( map { $_ => $conf->exists($_) } 
424         qw( deleteinvoices deletepayments deleterefunds pkg-balances
425             cust_credit_bill_pkg-manual cust_bill_pay_pkg-manual
426           )
427   ),
428   'money_char             ' => $money_char,
429
430   #rights
431   ( map { $_ => $curuser->access_right($_) }
432       (
433         'View invoices', 'Void invoices', 'Unvoid invoices', 'Delete invoices',
434         'Apply payment', 'Refund credit card payment', 'Refund Echeck payment',
435         'Credit card void', 'Echeck void', 'Void payments', 'Unvoid payments',
436         'Delete payment', 'Unapply payment',
437         'Apply credit', 'Delete credit', 'Unapply credit', 'Void credit', 'Unvoid credit',
438         'Delete refund',
439         'Billing event reports', 'View customer billing events',
440       )
441   ),
442
443   #customer information
444   'total_owed'              => $cust_main->total_owed,
445   'total_unapplied_refunds' => $cust_main->total_unapplied_refunds,
446 );
447
448 $opt{'date_format'} ||= '%m/%d/%Y';
449
450 #legacy invoices
451 foreach my $legacy_cust_bill ($cust_main->legacy_cust_bill) {
452   push @history, {
453     'date'   => $legacy_cust_bill->_date,
454     'order'  => 1,
455     'num'    => $legacy_cust_bill->legacyid,
456     'desc'   => include('payment_history/legacy_invoice.html', $legacy_cust_bill, %opt ),
457     'charge_nobal' => $legacy_cust_bill->charged,
458   };
459 }
460
461 #invoices
462 my $num_cust_bill = 0;
463 foreach my $cust_bill ($cust_main->cust_bill) {
464   push @history, {
465     'date'   => $cust_bill->_date,
466     'order'  => 1,
467     'num'    => $cust_bill->invnum,
468     'desc'   => include('payment_history/invoice.html', $cust_bill, %opt ),
469     'charge' => $cust_bill->charged,
470   };
471   $num_cust_bill++;
472 }
473
474 #voided invoices
475 foreach my $cust_bill_void ($cust_main->cust_bill_void) {
476   push @history, {
477     'date'        => $cust_bill_void->_date,
478     'order'       => 0,
479     'num'         => $cust_bill_void->invnum,
480     'desc'        => include('payment_history/voided_invoice.html', $cust_bill_void, %opt ),
481     'void_charge' => $cust_bill_void->charged,
482   };
483 }
484
485 #statements
486 foreach my $cust_statement ($cust_main->cust_statement) {
487   push @history, {
488     'date'   => $cust_statement->_date,
489     'order'  => 2,
490     'num'    => $cust_statement->statementnum,
491     'desc'   => include('payment_history/statement.html', $cust_statement, %opt ),
492     #'charge' => $cust_bill->charged,
493   };
494 }
495
496 #payments (some false laziness w/credits)
497 foreach my $cust_pay ($cust_main->cust_pay) {
498   push @history, {
499     'date'    => $cust_pay->_date,
500     'order'   => 6,
501     'num'     => $cust_pay->paynum,
502     'desc'    => include('payment_history/payment.html', $cust_pay, %opt ),
503     'payment' => $cust_pay->paid,
504     #'target'  => $target, #XXX
505   };
506 }
507
508 #pending payments 
509 foreach my $cust_pay_pending ($cust_main->cust_pay_pending) {
510   push @history, {
511     'date'    => $cust_pay_pending->_date,
512     'order'   => 4,
513     'num'     => $cust_pay_pending->paypendingnum,
514     'desc'    => include('payment_history/pending_payment.html', $cust_pay_pending, %opt ),
515     'void_payment' => $cust_pay_pending->paid, 
516   };
517 }
518
519
520 #voided payments
521 foreach my $cust_pay_void ($cust_main->cust_pay_void) {
522   push @history, {
523     'date'   => $cust_pay_void->_date,
524     'order'  => 3,
525     'num'    => $cust_pay_void->paynum,
526     'desc'   => include('payment_history/voided_payment.html', $cust_pay_void, %opt ),
527     'void_payment' => $cust_pay_void->paid,
528   };
529
530 }
531
532 #voided credits 
533 foreach my $cust_credit_void ($cust_main->cust_credit_void) {
534   push @history, {
535     'date'        => $cust_credit_void->_date,
536     'order'       => 7,
537     'num'         => $cust_credit_void->paynum,
538     'desc'        => include('payment_history/voided_credit.html', $cust_credit_void, %opt ),
539     'void_credit' => $cust_credit_void->amount,
540   };
541 }
542
543 #declined payments
544 foreach my $cust_pay_pending ($cust_main->cust_pay_pending_attempt) {
545   push @history, {
546     'date'    => $cust_pay_pending->_date,
547     'order'   => 5,
548     'num'     => $cust_pay_pending->paypendingnum,
549     'desc'    => include('payment_history/attempted_payment.html', $cust_pay_pending, %opt ),
550     'void_payment' => $cust_pay_pending->paid, #??
551     #'target'  => $target, #XXX
552   };
553 }
554 #declined batch payments
555 foreach my $cust_pay_batch (
556   $cust_main->cust_pay_batch(hashref => {status => 'Declined'})
557 ) {
558   my $pay_batch = $cust_pay_batch->pay_batch;
559   push @history, {
560     'date'    => $pay_batch->upload,
561     'order'   => 5,
562     'num'     => $cust_pay_batch->paybatchnum,
563     'desc'    => include('payment_history/attempted_batch_payment.html', $cust_pay_batch, %opt),
564     'void_payment' => $cust_pay_batch->amount,
565   };
566 }
567
568 #credits (some false laziness w/payments)
569 foreach my $cust_credit ($cust_main->cust_credit) {
570   push @history, {
571     'date'   => $cust_credit->_date,
572     'order'  => 8,
573     'num'    => $cust_credit->crednum,
574     'desc'   => include('payment_history/credit.html', $cust_credit, %opt ),
575     'credit' => $cust_credit->amount,
576   };
577
578 }
579
580 #refunds
581 foreach my $cust_refund ($cust_main->cust_refund) {
582   push @history, {
583     'date'   => $cust_refund->_date,
584     'order'  => 9,
585     'num'    => $cust_refund->refundnum,
586     'desc'   => include('payment_history/refund.html', $cust_refund, %opt),
587     'refund' => $cust_refund->refund,
588   };
589
590 }
591
592 # sort in forward order first, and calculate running balances
593 my $years =  $conf->config('payment_history-years') || 2;
594 my $older_than = time - $years * 31556926; #60*60*24*365.2422
595 my $balance = 0;
596
597 @history = sort {    $a->{date}  <=> $b->{date}
598                   or $a->{order} <=> $b->{order}
599                   or $a->{num}   <=> $b->{num}
600                 }
601              @history;
602
603 my $i = 0;
604 my $balance_forward;
605 foreach my $item (@history) {
606   $balance += $item->{'charge'}  if exists $item->{'charge'};
607   $balance -= $item->{'payment'} if exists $item->{'payment'};
608   $balance -= $item->{'credit'}  if exists $item->{'credit'};
609   $balance += $item->{'refund'}  if exists $item->{'refund'};
610   $balance = sprintf("%.2f", $balance);
611   $balance =~ s/^\-0\.00$/0.00/;
612   $item->{'balance'} = $balance;
613
614   if ( $item->{'date'} < $older_than ) {
615     $item->{'hide'} = 1;
616   } elsif ( $history[$i-1]->{'hide'} ) {
617     # this is the end of the hidden section
618     $history[$i-1]->{'balance_forward'} = 1;
619   }
620   $i++;
621 }
622 if ( @history and $history[-1]->{'hide'} ) {
623   # then everything is hidden
624   $history[-1]->{'balance_forward'} = 1;
625 }
626
627 # then sort in user-pref order
628 if ( $curuser->option('history_order') eq 'newest' ) {
629   @history = sort {    $b->{date}  <=> $a->{date}
630                     or $b->{order} <=> $a->{order} #or still forward here?
631                     or $b->{num}   <=> $a->{num}
632                   }
633                @history;
634 } # else it's already oldest-first, and there are no other options yet
635
636 sub translate_payby {
637     my ($payby,$payinfo) = (shift,shift);
638     my %payby = (
639         FS::payby->payby2shortname,
640         BILL    => $payinfo ? emt('Check #') : '',
641         CHEK    => emt('Electronic check '),
642         PREP    => emt('Prepaid card '),
643         CARD    => emt('Credit card #'),
644         COMP    => emt('Complimentary by '),
645         #CASH    => emt('Cash'),
646         #WEST    => emt('Western Union'),
647         #MCRD    => emt('Manual credit card'),
648     );
649     $payby = (exists $payby{$payby}) ? $payby{$payby} : $payby; 
650     $payby;
651 };
652
653 sub translate_payby_refund {
654     my ($payby,$payinfo) = (shift,shift);
655     my %payby = (
656         FS::payby->payby2shortname,
657         BILL    => $payinfo ? emt('Check #') : emt('Check'),
658         CHEK    => emt('Electronic check '),
659         CARD    => emt('Credit card #'),
660         COMP    => emt('Complimentary by '),
661     );
662     $payby = (exists $payby{$payby}) ? $payby{$payby} : $payby; 
663     $payby;
664 };
665
666 sub translate_payinfo {
667     my $object = shift;
668     my $payby = $object->payby;
669     my $payinfo = $object->payinfo;
670
671     if ( $payby eq 'CARD' ) {
672         $payinfo = $object->paymask;
673     } elsif ( $payby eq 'CHEK' ) {
674         #false laziness w/payinfo_Mixin::payby_payinfo_pretty, should use that
675         my( $account, $aba ) = split('@', $object->paymask );
676         if ( $aba =~ /^(\d{5})\.(\d{3})$/ ) { #blame canada
677           my($branch, $routing) = ($1, $2);
678           $payinfo = emt("Routing [_1], Branch [_2], Acct [_3]",
679                          $routing, $branch, $account);
680         } else {
681           $payinfo = emt("Routing [_1], Acct [_2]", $aba, $account);
682         }
683     }
684
685     ($payby,$payinfo);
686 }
687
688 sub areyousure_link {
689     my ($url,$msg,$title,$label) = (shift,shift,shift,shift);
690     ' (<A HREF="javascript:areyousure(\''.$url.'\',\''.$msg.'\')" TITLE="'.$title.'">'.$label.'</A>)';
691 }
692
693 </%init>