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),
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),
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>
37 <% $s ? '<BR>' : '' %>
40 % if ( ( $payby{'CARD'} || $payby{'DCRD'} )
41 % && $curuser->access_right(['Process payment', 'Process credit card payment'])
42 % && ! $cust_main->is_encrypted($cust_main->payinfo)
44 <% $s++ ? ' | ' : '' %>
45 <A HREF="<% $p %>misc/payment.cgi?payby=CARD;custnum=<% $custnum %>"><% mt('Process credit card payment') |h %></A>
48 % if ( ( $payby{'CHEK'} || $payby{'DCHK'} )
49 % && $curuser->access_right(['Process payment', 'Process Echeck payment'])
50 % && ! $cust_main->is_encrypted($cust_main->payinfo)
52 <% $s++ ? ' | ' : '' %>
53 <A HREF="<% $p %>misc/payment.cgi?payby=CHEK;custnum=<% $custnum %>"><% mt('Process electronic check (ACH) payment') |h %></A>
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>
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>
66 <% $s ? '<BR>' : '' %>
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),
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'),
93 <% $s ? '<BR>' : '' %>
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'),
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'),
120 %# someday, perhaps. very few gateways let you do unlinked refunds at all.
121 %# Authorize.net makes you sign a special form
123 %# % if ( ( $payby{'CARD'} || $payby{'DCRD'} )
124 %# % && $curuser->access_right('Process refund')
125 %# % && ! $cust_main->is_encrypted($cust_main->payinfo)
127 %# <% $s++ ? ' | ' : '' %>
128 %# <A HREF="<% $p %>misc/refund.cgi?payby=CARD;custnum=<% $custnum %>">Process credit card refund</A>
131 %# % if ( ( $payby{'CHEK'} || $payby{'DCHK'} )
132 %# % && $curuser->access_right('Process refund')
133 %# % && ! $cust_main->is_encrypted($cust_main->payinfo)
135 %# <% $s++ ? ' | ' : '' %>
136 %# <A HREF="<% $p %>misc/refund.cgi?payby=CHEK;custnum=<% $custnum %>">Process electronic check (ACH) refund</A>
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>
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>
150 <TD ALIGN="right" VALIGN="top">
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 ) {
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>
161 % if ( $num_cust_bill > 0
162 % && $curuser->access_right('View legacy typeset statements')
164 <A HREF="<% $p %>view/cust_main_statement-pdf.cgi?<% $custnum %>"><%
165 mt('Download typeset statement PDF') |h %></A>
168 <A HREF="<% $p %>search/report_cust_bill.html?custnum=<% $custnum %>"><% mt('Invoice reports') |h %></A>
172 %# XXX payments, credits, refund reports
174 %# tax exemption link
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')
180 % if ( $view_exemptions || $add_adjustment ) {
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 ? '|' : '' %>
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'),
196 <A HREF="<% $p %>search/cust_tax_adjustment.html?custnum=<% $custnum %>"><% mt('View tax adjustments') |h %></A>
202 %# batched payment links
204 % if ( ( $conf->exists('batch-enable') || $conf->config('batch-enable_payby') )
205 % && $curuser->access_right('View customer batched payments')
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' ? '|' : '' %>
216 %# pending payment links
218 % if ( $curuser->access_right('View customer pending payments')
219 % && scalar($cust_main->cust_pay_pending)
222 <A HREF="<% $p %>search/cust_pay_pending.html?magic=_date;statusNOT=done;custnum=<% $custnum %>"><% mt('View pending payments') |h %></A><BR>
232 <& /elements/table-grid.html &>
233 % my $bgcolor1 = '#eeeeee';
234 % my $bgcolor2 = '#ffffff';
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>
247 %#display payment history
253 %my $old_history = 0;
256 %foreach my $item ( @history ) {
258 % $lastdate = $item->{'date'};
261 % if ( $item->{'hide'} ) {
262 % $display = ' STYLE="display:none" ';
265 % if ( $bgcolor eq $bgcolor1 ) {
266 % $bgcolor = $bgcolor2;
268 % $bgcolor = $bgcolor1;
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'})
279 % my $payment = exists($item->{'payment'})
280 % ? sprintf("- $money_char\%.2f", $item->{'payment'})
283 % $payment ||= sprintf( "<DEL>- $money_char\%.2f</DEL>",
284 % $item->{'void_payment'}
286 % if exists($item->{'void_payment'});
288 % my $credit = exists($item->{'credit'})
289 % ? sprintf("- $money_char\%.2f", $item->{'credit'})
292 % $credit ||= sprintf( "<DEL>- $money_char\%.2f</DEL>",
293 % $item->{'void_credit'}
295 % if exists($item->{'void_credit'});
297 % my $refund = exists($item->{'refund'})
298 % ? sprintf("$money_char\%.2f", $item->{'refund'})
301 % my $target = exists($item->{'target'}) ? $item->{'target'} : '';
303 % my $showbalance = $money_char . $item->{'balance'};
304 % $showbalance =~ s/^\$\-/- \$/;
306 <TR <% $display ? $display.' ID="old_history'.$old_history++.'"' : ''%>>
307 <TD VALIGN="top" CLASS="grid" BGCOLOR="<% $bgcolor %>">
308 % unless ( !$target || $target{$target}++ ) {
310 <A NAME="<% $target %>">
313 <% time2str($date_format, $item->{'date'}) %>
314 % if ( $target && $target{$target} == 1 ) {
321 <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
322 <% $item->{'desc'} %>
324 <TD VALIGN="top" ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>">
327 <TD VALIGN="top" ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>">
330 <TD VALIGN="top" ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>">
333 <TD VALIGN="top" ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>">
336 <TD VALIGN="top" ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>">
341 % if ( $item->{'balance_forward'} ) {
342 <& .balance_forward_row, $item->{'balance'}, $item->{'date'} &>
346 % if ( $old_history ) {
347 <& .hide_history_row, $old_history++ &>
355 <SCRIPT SRC="<% $fsurl %>elements/page_pref.js"></SCRIPT>
356 <SCRIPT TYPE="text/javascript">
358 function show_history(show) { // but don't update pref
359 var balance_forward_row = document.getElementById('balance_forward_row');
361 balance_forward_row.style.display = show ? 'none' : '';
362 for ( var i = 0; i < <% $old_history %>; i++ ) {
363 var oldRow = document.getElementById('old_history'+i);
364 oldRow.style.display = show ? '' : 'none';
368 function update_show_history (show) {
372 // update user pref (blind post, don't care about the output here)
373 set_page_pref('expand_old_history', '<% $custnum %>', show);
376 $().ready(function() {
377 show_history(<% get_page_pref('expand_old_history', $custnum) %>);
381 <%def .balance_forward_row>
382 % my( $b, $date ) = @_;
383 % ( my $balance_forward = $money_char. $b ) =~ s/^\$\-/- \$/;
385 <TR ID="balance_forward_row">
386 <TD CLASS="grid" BGCOLOR="#dddddd">
387 <% time2str($date_format, $date) %>
390 <TD CLASS="grid" BGCOLOR="#dddddd">
391 <I><% mt("Starting balance on [_1]", time2str($date_format, $date) ) |h %></I>
392 (<A HREF="javascript:void(0);" onClick="update_show_history(true);"><% mt('show prior history') |h %></A>)
395 <TD CLASS="grid" BGCOLOR="#dddddd"></TD>
396 <TD CLASS="grid" BGCOLOR="#dddddd"></TD>
397 <TD CLASS="grid" BGCOLOR="#dddddd"></TD>
398 <TD CLASS="grid" BGCOLOR="#dddddd"></TD>
399 <TD CLASS="grid" BGCOLOR="#dddddd" ALIGN="right"><I><% $balance_forward %></I></TD>
403 <%def .hide_history_row>
405 <TR ID="old_history<% $num %>" STYLE="display: none">
406 <TD CLASS="grid" BGCOLOR="#dddddd"></TD>
407 <TD CLASS="grid" BGCOLOR="#dddddd">
408 <I>(<A HREF="#" onclick="update_show_history(false)"><% mt('hide prior history') |h %></A>)</I>
410 <TD CLASS="grid" BGCOLOR="#dddddd" COLSPAN=5></TD>
415 my $conf = new FS::Conf;
416 my $date_format = $conf->config('date_format') || '%m/%d/%Y';
417 my $money_char = $conf->config('money_char') || '$';
421 my( $cust_main ) = @_;
422 my $custnum = $cust_main->custnum;
424 my $curuser = $FS::CurrentUser::CurrentUser;
426 my @payby = grep /\w/, $conf->config('payby');
427 #@payby = (qw( CARD DCRD CHEK DCHK LECB BILL CASH WEST COMP ))
428 @payby = (qw( CARD DCRD CHEK DCHK LECB BILL CASH COMP ))
430 my %payby = map { $_=>1 } @payby;
433 'Queued' => 'O', #Open
435 'Complete' => 'R', #Resolved
445 ( map { $_ => scalar($conf->config($_)) }
446 qw( card_refund-days date_format )
448 ( map { $_ => $conf->exists($_) }
449 qw( deleteinvoices deletepayments deleterefunds pkg-balances
450 cust_credit_bill_pkg-manual cust_bill_pay_pkg-manual
453 'money_char ' => $money_char,
456 ( map { $_ => $curuser->access_right($_) }
458 'View invoices', 'Void invoices', 'Unvoid invoices', 'Delete invoices', 'Resend invoices',
459 'Apply payment', 'Refund credit card payment', 'Refund Echeck payment',
460 'Post refund', 'Post check refund', 'Post cash refund ', 'Refund payment',
461 'Credit card void', 'Echeck void', 'Void payments', 'Unvoid payments',
462 'Delete payment', 'Unapply payment',
463 'Apply credit', 'Delete credit', 'Unapply credit', 'Void credit', 'Unvoid credit',
465 'Billing event reports', 'View customer billing events',
469 #customer information
470 'total_owed' => $cust_main->total_owed,
471 'total_unapplied_refunds' => $cust_main->total_unapplied_refunds,
472 'has_email_address' => scalar($cust_main->invoicing_list_emailonly),
475 $opt{'date_format'} ||= '%m/%d/%Y';
478 foreach my $legacy_cust_bill ($cust_main->legacy_cust_bill) {
480 'date' => $legacy_cust_bill->_date,
482 'num' => $legacy_cust_bill->legacyid,
483 'desc' => include('payment_history/legacy_invoice.html', $legacy_cust_bill, %opt ),
484 'charge_nobal' => $legacy_cust_bill->charged,
489 my $num_cust_bill = 0;
490 foreach my $cust_bill ($cust_main->cust_bill) {
492 'date' => $cust_bill->_date,
494 'num' => $cust_bill->invnum,
495 'desc' => include('payment_history/invoice.html', $cust_bill, %opt ),
496 'charge' => $cust_bill->charged,
502 foreach my $cust_bill_void ($cust_main->cust_bill_void) {
504 'date' => $cust_bill_void->_date,
506 'num' => $cust_bill_void->invnum,
507 'desc' => include('payment_history/voided_invoice.html', $cust_bill_void, %opt ),
508 'void_charge' => $cust_bill_void->charged,
513 foreach my $cust_statement ($cust_main->cust_statement) {
515 'date' => $cust_statement->_date,
517 'num' => $cust_statement->statementnum,
518 'desc' => include('payment_history/statement.html', $cust_statement, %opt ),
519 #'charge' => $cust_bill->charged,
523 #payments (some false laziness w/credits)
524 foreach my $cust_pay ($cust_main->cust_pay) {
526 'date' => $cust_pay->_date,
528 'num' => $cust_pay->paynum,
529 'desc' => include('payment_history/payment.html', $cust_pay, %opt ),
530 'payment' => $cust_pay->paid,
531 #'target' => $target, #XXX
536 foreach my $cust_pay_pending ($cust_main->cust_pay_pending) {
538 'date' => $cust_pay_pending->_date,
540 'num' => $cust_pay_pending->paypendingnum,
541 'desc' => include('payment_history/pending_payment.html', $cust_pay_pending, %opt ),
542 'void_payment' => $cust_pay_pending->paid,
548 foreach my $cust_pay_void ($cust_main->cust_pay_void) {
550 'date' => $cust_pay_void->_date,
552 'num' => $cust_pay_void->paynum,
553 'desc' => include('payment_history/voided_payment.html', $cust_pay_void, %opt ),
554 'void_payment' => $cust_pay_void->paid,
560 foreach my $cust_credit_void ($cust_main->cust_credit_void) {
562 'date' => $cust_credit_void->_date,
564 'num' => $cust_credit_void->paynum,
565 'desc' => include('payment_history/voided_credit.html', $cust_credit_void, %opt ),
566 'void_credit' => $cust_credit_void->amount,
571 foreach my $cust_pay_pending ($cust_main->cust_pay_pending_attempt) {
573 'date' => $cust_pay_pending->_date,
575 'num' => $cust_pay_pending->paypendingnum,
576 'desc' => include('payment_history/attempted_payment.html', $cust_pay_pending, %opt ),
577 'void_payment' => $cust_pay_pending->paid, #??
578 #'target' => $target, #XXX
581 #declined batch payments
582 foreach my $cust_pay_batch (
583 $cust_main->cust_pay_batch(hashref => {status => 'Declined'})
585 my $pay_batch = $cust_pay_batch->pay_batch;
587 'date' => $pay_batch->upload,
589 'num' => $cust_pay_batch->paybatchnum,
590 'desc' => include('payment_history/attempted_batch_payment.html', $cust_pay_batch, %opt),
591 'void_payment' => $cust_pay_batch->amount,
595 #credits (some false laziness w/payments)
596 foreach my $cust_credit ($cust_main->cust_credit) {
598 'date' => $cust_credit->_date,
600 'num' => $cust_credit->crednum,
601 'desc' => include('payment_history/credit.html', $cust_credit, %opt ),
602 'credit' => $cust_credit->amount,
608 foreach my $cust_refund ($cust_main->cust_refund) {
610 'date' => $cust_refund->_date,
612 'num' => $cust_refund->refundnum,
613 'desc' => include('payment_history/refund.html', $cust_refund, %opt),
614 'refund' => $cust_refund->refund,
619 # sort in forward order first, and calculate running balances
620 my $years = $conf->config('payment_history-years') || 2;
621 my $older_than = time - $years * 31556926; #60*60*24*365.2422
624 @history = sort { $a->{date} <=> $b->{date}
625 or $a->{order} <=> $b->{order}
626 or $a->{num} <=> $b->{num}
632 foreach my $item (@history) {
633 $balance += $item->{'charge'} if exists $item->{'charge'};
634 $balance -= $item->{'payment'} if exists $item->{'payment'};
635 $balance -= $item->{'credit'} if exists $item->{'credit'};
636 $balance += $item->{'refund'} if exists $item->{'refund'};
637 $balance = sprintf("%.2f", $balance);
638 $balance =~ s/^\-0\.00$/0.00/;
639 $item->{'balance'} = $balance;
641 if ( $item->{'date'} < $older_than ) {
643 } elsif ( $history[$i-1]->{'hide'} ) {
644 # this is the end of the hidden section
645 $history[$i-1]->{'balance_forward'} = 1;
649 if ( @history and $history[-1]->{'hide'} ) {
650 # then everything is hidden
651 $history[-1]->{'balance_forward'} = 1;
654 # then sort in user-pref order
655 if ( $curuser->option('history_order') eq 'newest' ) {
656 @history = sort { $b->{date} <=> $a->{date}
657 or $b->{order} <=> $a->{order} #or still forward here?
658 or $b->{num} <=> $a->{num}
661 } # else it's already oldest-first, and there are no other options yet
663 sub translate_payby {
664 my ($payby,$payinfo) = (shift,shift);
666 FS::payby->payby2shortname,
667 BILL => $payinfo ? emt('Check #') : '',
668 CHEK => emt('Electronic check '),
669 PREP => emt('Prepaid card '),
670 CARD => emt('Credit card #'),
671 COMP => emt('Complimentary by '),
672 #CASH => emt('Cash'),
673 #WEST => emt('Western Union'),
674 #MCRD => emt('Manual credit card'),
676 $payby = (exists $payby{$payby}) ? $payby{$payby} : $payby;
680 sub translate_payby_refund {
681 my ($payby,$payinfo) = (shift,shift);
683 FS::payby->payby2shortname,
684 BILL => $payinfo ? emt('Check #') : emt('Check'),
685 CHEK => emt('Electronic check '),
686 CARD => emt('Credit card #'),
687 COMP => emt('Complimentary by '),
689 $payby = (exists $payby{$payby}) ? $payby{$payby} : $payby;
693 sub translate_payinfo {
695 my $payby = $object->payby;
696 my $payinfo = $object->payinfo;
698 if ( $payby eq 'CARD' ) {
699 $payinfo = $object->paymask;
700 } elsif ( $payby eq 'CHEK' ) {
701 #false laziness w/payinfo_Mixin::payby_payinfo_pretty, should use that
702 my( $account, $aba ) = split('@', $object->paymask );
703 if ( $aba =~ /^(\d{5})\.(\d{3})$/ ) { #blame canada
704 my($branch, $routing) = ($1, $2);
705 $payinfo = emt("Routing [_1], Branch [_2], Acct [_3]",
706 $routing, $branch, $account);
708 $payinfo = emt("Routing [_1], Acct [_2]", $aba, $account);
715 sub areyousure_link {
716 my ($url,$msg,$title,$label) = (shift,shift,shift,shift);
717 ' (<A HREF="javascript:areyousure(\''.$url.'\',\''.$msg.'\')" TITLE="'.$title.'" STYLE="white-space: nowrap;">'.$label.'</A>)';