RT# 76093 - Added ability to charge a processing fee when taking a payment on the...
[freeside.git] / httemplate / misc / payment.cgi
1 <& /elements/header.html, mt("Process [_1] payment",$type{$payby})  &>
2 <& /elements/small_custview.html, $cust_main, '', '', popurl(2) . "view/cust_main.cgi" &>
3 <FORM NAME="OneTrueForm" ACTION="process/payment.cgi" METHOD="POST" onSubmit="document.OneTrueForm.process.disabled=true">
4 <INPUT TYPE="hidden" NAME="custnum"   VALUE="<% $custnum %>">
5 <INPUT TYPE="hidden" NAME="payby"     VALUE="<% $payby %>">
6 <INPUT TYPE="hidden" NAME="payunique" VALUE="<% $payunique %>">
7 <INPUT TYPE="hidden" NAME="balance"   VALUE="<% $balance %>">
8
9 <& /elements/init_overlib.html &>
10
11 <% ntable('#cccccc') %>
12
13   <& /elements/tr-amount_fee.html,
14        'amount'             => $amount,
15        'process-pkgpart'    => 
16           scalar($conf->config('manual_process-pkgpart', $cust_main->agentnum)),
17        'process-display'    => scalar($conf->config('manual_process-display')),
18        'process-skip_first' => $conf->exists('manual_process-skip_first'),
19        'num_payments'       => scalar($cust_main->cust_pay), 
20        'surcharge_percentage' =>
21          ( $payby eq 'CARD'
22              ? scalar($conf->config('credit-card-surcharge-percentage', $cust_main->agentnum))
23              : 0
24          ),
25        'surcharge_flatfee' =>
26          ( $payby eq 'CARD'
27              ? scalar($conf->config('credit-card-surcharge-flatfee', $cust_main->agentnum))
28              : 0
29          ),
30          'processing_fee' => scalar($conf->config('processing-fee', $cust_main->agentnum)),
31   &>
32
33 % if ( $conf->exists('part_pkg-term_discounts') ) {
34     <& /elements/tr-select-discount_term.html,
35          'custnum'   => $custnum,
36          'amount_id' => 'amount',
37     &>
38 % }
39
40 % if ( $payby eq 'CARD' ) {
41 %
42 %   my( $payinfo, $paycvv, $month, $year ) = ( '', '', '', '' );
43 %   my $payname = $cust_main->first. ' '. $cust_main->getfield('last');
44 %   if ( $cust_main->payby =~ /^(CARD|DCRD)$/ ) {
45 %     $payinfo = $cust_main->paymask;
46 %     ( $paycvv = $cust_main->paycvv ) =~ s/./*/g;
47 %     ( $month, $year ) = $cust_main->paydate_monthyear;
48 %     $payname = $cust_main->payname if $cust_main->payname;
49 %   } elsif ($disable_payauto_default) {
50 %     $auto = 0;
51 %   }
52
53     <TR>
54       <TH ALIGN="right"><% mt('Card number') |h %></TH>
55       <TD COLSPAN=7>
56         <TABLE>
57           <TR>
58             <TD>
59               <INPUT TYPE="text" NAME="payinfo" SIZE=20 MAXLENGTH=19 VALUE="<%$payinfo%>"<% ($auto && $disable_payauto_default) ? $possibly_uncheck_auto : '' %>> </TD>
60             <TH><% mt('Exp.') |h %></TH>
61             <TD>
62               <SELECT NAME="month">
63 % for ( map{ sprintf('%02d',$_) } (1..12) ) {
64                   <OPTION VALUE="<% $_ %>"<% $_ == $month ? ' SELECTED' : '' %>><% $_ %></OPTION>
65 % } 
66
67               </SELECT>
68             </TD>
69             <TD> / </TD>
70             <TD>
71               <SELECT NAME="year">
72 % my @a = localtime; for ( $a[5]+1900 .. $a[5]+1915 ) { 
73                   <OPTION VALUE="<% $_ %>"<% $_ == $year ? ' SELECTED' : '' %>><% $_ %></OPTION>
74 % } 
75
76               </SELECT>
77             </TD>
78           </TR>
79         </TABLE>
80       </TD>
81     </TR>
82     <TR>
83       <TH ALIGN="right"><% mt('CVV2') |h %></TH>
84       <TD><INPUT TYPE="text" NAME="paycvv" VALUE="<% $paycvv %>" SIZE=4 MAXLENGTH=4>
85           (<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('../docs/cvv2.html', 480, 352, 'cvv2_popup' ), CAPTION, 'CVV2 Help', STICKY, AUTOSTATUSCAP, CLOSECLICK, DRAGGABLE ); return false;"><% mt('help') |h %></A>)
86       </TD>
87     </TR>
88     <TR>
89       <TH ALIGN="right"><% mt('Exact name on card') |h %></TH>
90       <TD><INPUT TYPE="text" SIZE=32 MAXLENGTH=80 NAME="payname" VALUE="<%$payname%>"></TD>
91     </TR>
92
93     <& /elements/location.html,
94                   'object'         => $cust_main->bill_location,
95                   'no_asterisks'   => 1,
96                   'address1_label' => emt('Card billing address'),
97     &>
98
99 % } elsif ( $payby eq 'CHEK' ) {
100 %
101 %   my( $account, $aba, $branch, $payname, $ss, $paytype, $paystate,
102 %       $stateid, $stateid_state )
103 %     = ( '', '', '', '', '', '', '', '', '' );
104 %   if ( $cust_main->payby =~ /^(CHEK|DCHK)$/ ) {
105 %     $cust_main->paymask =~ /^([\dx]+)\@([\d\.x]*)$/i
106 %       or die "unparsable payinfo ". $cust_main->payinfo;
107 %     ($account, $aba) = ($1, $2);
108 %     ($branch,$aba) = split('\.',$aba)
109 %       if $conf->config('echeck-country') eq 'CA';
110 %     $payname = $cust_main->payname;
111 %     $ss = $cust_main->ss;
112 %     $paytype = $cust_main->getfield('paytype');
113 %     $paystate = $cust_main->getfield('paystate');
114 %     $stateid = $cust_main->getfield('stateid');
115 %     $stateid_state = $cust_main->getfield('stateid_state');
116 %   } elsif ($disable_payauto_default) {
117 %     $auto = 0;
118 %   }
119 %
120 %  #false laziness w/{edit,view}/cust_main/billing.html
121 %  my $routing_label = $conf->config('echeck-country') eq 'US'
122 %                        ? 'ABA/Routing number'
123 %                        : 'Routing number';
124 %  my $routing_size      = $conf->config('echeck-country') eq 'CA' ? 4 : 10;
125 %  my $routing_maxlength = $conf->config('echeck-country') eq 'CA' ? 3 : 9;
126
127     <INPUT TYPE="hidden" NAME="month" VALUE="12">
128     <INPUT TYPE="hidden" NAME="year" VALUE="2037">
129     <TR>
130       <TD ALIGN="right"><% mt('Account number') |h %></TD>
131       <TD><INPUT TYPE="text" SIZE=10 NAME="payinfo1" VALUE="<%$account%>"<% ($auto && $disable_payauto_default) ? $possibly_uncheck_auto : '' %>></TD>
132       <TD ALIGN="right"><% mt('Type') |h %></TD>
133       <TD><SELECT NAME="paytype"><% join('', map { qq!<OPTION VALUE="$_" !.($paytype eq $_ ? 'SELECTED' : '').">$_</OPTION>" } @FS::cust_main::paytypes) %></SELECT></TD>
134     </TR>
135     <TR>
136       <TD ALIGN="right"><% mt($routing_label) |h %></TD>
137       <TD>
138         <INPUT TYPE="text" SIZE="<% $routing_size %>" MAXLENGTH="<% $routing_maxlength %>" NAME="payinfo2" VALUE="<%$aba%>"<% ($auto && $disable_payauto_default) ? $possibly_uncheck_auto : '' %>>
139         (<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('../docs/ach.html', 380, 240, 'ach_popup' ), CAPTION, 'ACH Help', STICKY, AUTOSTATUSCAP, CLOSECLICK, DRAGGABLE ); return false;"><% mt('help') |h %></A>)
140       </TD>
141     </TR>
142 %   if ( $conf->config('echeck-country') eq 'CA' ) {
143       <TR>
144         <TD ALIGN="right"><% mt('Branch number') |h %></TD>
145         <TD>
146           <INPUT TYPE="text" NAME="payinfo3" VALUE="<%$branch%>" SIZE=6 MAXLENGTH=5<% ($auto && $disable_payauto_default) ? $possibly_uncheck_auto : '' %>>
147         </TD>
148       </TR>
149 %   }
150     <TR>
151       <TD ALIGN="right"><% mt('Bank name') |h %></TD>
152       <TD><INPUT TYPE="text" NAME="payname" VALUE="<%$payname%>"></TD>
153     </TR>
154
155 %   if ( $conf->exists('show_bankstate') ) {
156       <TR>
157         <TD ALIGN="right"><% mt('Bank state') |h %></TD>
158         <TD><& /elements/select-state.html,
159                          'disable_empty' => 0,
160                          'empty_label'   => emt('(choose)'),
161                          'state'         => $paystate,
162                          'country'       => $cust_main->country,
163                          'prefix'        => 'pay',
164             &>
165         </TD>
166       </TR>
167 %   } else {
168       <INPUT TYPE="hidden" NAME="paystate" VALUE="<% $paystate %>">
169 %   }
170
171 %   if ( $conf->exists('show_ss') ) {
172       <TR>
173         <TD ALIGN="right">
174           <% mt('Account holder') |h %><BR>
175           <% mt('Social security or tax ID #') |h %> 
176         </TD>
177         <TD><INPUT TYPE="text" NAME="ss" VALUE="<% $ss %>"></TD>
178       </TR>
179 %   } else {
180       <INPUT TYPE="hidden" NAME="ss" VALUE="<% $ss %>"></TD>
181 %   }
182
183 %   if ( $conf->exists('show_stateid') ) {
184       <TR>
185         <TD ALIGN="right">
186           <% mt('Account holder') |h %><BR>
187           <% mt("Driver's license or state ID #") |h %> 
188         </TD>
189         <TD><INPUT TYPE="text" NAME="stateid" VALUE="<% $stateid %>"></TD>
190         <TD ALIGN="right"><% mt('State') |h %></TD>
191         <TD><& /elements/select-state.html,
192                          'disable_empty' => 0,
193                          'empty_label'   => emt('(choose)'),
194                          'state'         => $stateid_state,
195                          'country'       => $cust_main->country,
196                          'prefix'        => 'stateid_',
197             &>
198         </TD>
199       </TR>
200 %   } else {
201       <INPUT TYPE="hidden" NAME="stateid" VALUE="<% $stateid %>">
202       <INPUT TYPE="hidden" NAME="stateid_state" VALUE="<% $stateid_state %>">
203 %   }
204
205 % } #end CARD/CHEK-specific section
206
207
208 <TR>
209   <TD COLSPAN=2>
210     <INPUT TYPE="checkbox" CHECKED NAME="save" VALUE="1">
211     <% mt('Remember this information') |h %>
212   </TD>
213 </TR>
214
215 % my $disallow_no_auto_apply = 0;
216 % if ( $conf->exists("batch-enable")
217 %      || grep $payby eq $_, $conf->config('batch-enable_payby')
218 %    ) {
219 %
220 %     if ( grep $payby eq $_, $conf->config('realtime-disable_payby') ) {
221 %       $disallow_no_auto_apply = 1;
222
223           <INPUT TYPE="hidden" NAME="batch" VALUE="1">
224
225 %     } else {
226
227           <TR>
228             <TD COLSPAN=2>
229               <INPUT TYPE="checkbox" NAME="batch" VALUE="1" ID="batch_checkbox" ONCHANGE="change_batch_checkbox()">
230               <% mt('Add to current batch') |h %> 
231             </TD>
232           </TR>
233
234 %     }
235 % }
236
237 <TR>
238   <TD COLSPAN=2>
239     <INPUT ID="auto_checkbox" TYPE="checkbox"<% $auto ? ' CHECKED' : '' %> NAME="auto" VALUE="1" onClick="if (this.checked) { document.OneTrueForm.save.checked=true; }">
240     <% mt("Charge future payments to this [_1] automatically",$type{$payby}) |h %> 
241   </TD>
242 </TR>
243
244 % unless ($disallow_no_auto_apply) {
245 %   # false laziness with edit/cust_pay.cgi
246
247 <TR ID="apply_box_row">
248   <TD COLSPAN=2>
249     <% mt('Auto-apply to invoices') |h %>
250     <SELECT NAME="apply" ID="apply_box">
251       <OPTION VALUE="yes" SELECTED><% mt('yes') |h %></OPTION> 
252       <OPTION VALUE=""><% mt('not now') |h %></OPTION>
253       <OPTION VALUE="never"><% mt('never') |h %></OPTION>
254     </SELECT>
255   </TD>
256 </TR>
257
258 % # this can go away if no_auto_apply handling gets added to batch payment processing
259 <SCRIPT>
260 function change_batch_checkbox () {
261   if (document.getElementById('batch_checkbox').checked) {
262     document.getElementById('apply_box').disabled = true;
263     document.getElementById('apply_box_row').style.display = 'none';
264   } else {
265     document.getElementById('apply_box').disabled = false;
266     document.getElementById('apply_box_row').style.display = '';
267   }
268 }
269 </SCRIPT>
270
271 % }
272
273 % if ($auto && $disable_payauto_default) {
274 <SCRIPT>
275 var unchecked_auto = false;
276 function possibly_uncheck_auto () {
277   if (!unchecked_auto) {
278     unchecked_auto = true;
279     document.getElementById('auto_checkbox').checked = false;
280   }
281 }
282 </SCRIPT>
283 % }
284
285 </TABLE>
286
287 <BR>
288 <INPUT TYPE="submit" NAME="process" VALUE="<% mt('Process payment') |h %>">
289 </FORM>
290
291 <& /elements/footer.html &>
292 <%init>
293
294 die "access denied"
295   unless $FS::CurrentUser::CurrentUser->access_right('Process payment');
296
297 my %type = ( 'CARD' => 'credit card',
298              'CHEK' => 'electronic check (ACH)',
299            );
300
301 $cgi->param('payby') =~ /^(CARD|CHEK)$/
302   or die "unknown payby ". $cgi->param('payby');
303 my $payby = $1;
304
305 $cgi->param('custnum') =~ /^(\d+)$/
306   or die "illegal custnum ". $cgi->param('custnum');
307 my $custnum = $1;
308
309 my $cust_main = qsearchs( 'cust_main', { 'custnum'=>$custnum } );
310 die "unknown custnum $custnum" unless $cust_main;
311
312 my $location = $cust_main->bill_location;
313 # no proper error handling on this anyway, but when we have it,
314 # remember to repopulate fields in $location
315
316 my $balance = $cust_main->balance;
317
318 my $payinfo = '';
319
320 my $conf = new FS::Conf;
321
322 my $auto = ( ( $payby eq 'CARD' && $cust_main->payby ne 'DCRD' ) || ( $payby eq 'CHEK' && $cust_main->payby eq 'CHEK' ) ) ? 1 : 0;
323 my $disable_payauto_default = $conf->exists('disable_payauto_default');
324 my $possibly_uncheck_auto = ' ONCHANGE="possibly_uncheck_auto()"';
325
326 #false laziness w/selfservice make_payment.html shortcut for one-country
327 my %states = map { $_->state => 1 }
328                qsearch('cust_main_county', {
329                  'country' => $conf->config('countrydefault') || 'US'
330                } );
331 my @states = sort { $a cmp $b } keys %states;
332
333 my $amount = '';
334 if ( $balance > 0 ) {
335   # when configured to do so, amount will only auto-fill with balance
336   # if balance represents a single invoice
337   $amount = $balance
338     unless $conf->exists('manual_process-single_invoice_amount')
339       && ($cust_main->open_cust_bill != 1);
340 }
341
342 my $payunique = "webui-payment-". time. "-$$-". rand() * 2**32;
343
344 </%init>