credits return taxes, but the magic calculation button does not yet work properly...
[freeside.git] / httemplate / edit / elements / ApplicationCommon.html
1 <%doc>
2
3 Examples:
4
5   #cust_bill_pay
6   include('elements/ApplicationCommon.html',
7     'form_action' => 'process/cust_bill_pay.cgi', 
8     'src_table'   => 'cust_pay',
9     'src_thing'   => 'payment',
10     'dst_table'   => 'cust_bill',
11     'dst_thing'   => 'invoice',
12   )
13
14   #cust_credit_bill
15   include('elements/ApplicationCommon.html',
16     'form_action' => 'process/cust_credit_bill.cgi',
17     'src_table'   => 'cust_credit',
18     'src_thing'   => 'credit',
19     'dst_table'   => 'cust_bill',
20     'dst_thing'   => 'invoice',
21   )
22
23   #cust_pay_refund
24   include('elements/ApplicationCommon.html',
25     'form_action' => 'process/cust_pay_refund.cgi',
26     'src_table'   => 'cust_pay',
27     'src_thing'   => 'payment',
28     'dst_table'   => 'cust_refund',
29     'dst_thing'   => 'refund',
30   )
31
32   #cust_credit_refund
33   include('elements/ApplicationCommon.html',
34     'form_action' => 'process/cust_credit_refund.cgi',
35     'src_table'   => 'cust_credit',
36     'src_thing'   => 'credit',
37     'dst_table'   => 'cust_refund',
38     'dst_thing'   => 'refund',
39   )
40
41 </%doc>
42 <% include('/elements/header-popup.html', "Apply $src_thing$to" ) %>
43
44 <% include('/elements/error.html') %>
45
46 <FORM ACTION="<% $p1. $opt{'form_action'} %>" NAME="ApplicationForm" ID="ApplicationForm" METHOD=POST>
47
48 <% $src_thing %> #<B><% $src_pkeyvalue %></B><BR>
49 <INPUT TYPE="hidden" NAME="<% $src_pkey %>" VALUE="<% $src_pkeyvalue %>">
50
51 <TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0>
52
53 <TR>
54   <TD ALIGN="right">Date: </TD>
55   <TD><B><% time2str("%D", $src->_date) %></B></TD>
56 </TR>
57
58 <TR>
59   <TD ALIGN="right">Amount: </TD>
60   <TD><B><% $money_char %><% $src->amount %></B></TD>
61 </TR>
62
63 <TR>
64   <TD ALIGN="right">Unapplied amount: </TD>
65   <TD><B><% $money_char %><% $unapplied %></B></TD>
66 </TR>
67
68 % if ( $src_table eq 'cust_credit' ) {
69     <TR>
70       <TD ALIGN="right">Reason: </TD>
71       <TD><B><% $src->reason %></B></TD>
72     </TR>
73 % }
74
75 </TABLE>
76 <BR>
77
78 <SCRIPT TYPE="text/javascript">
79 function changed(what) {
80   dst = what.options[what.selectedIndex].value;
81
82   if ( dst == '' ) {
83     what.form.submit.disabled=true;
84     return true;
85   }
86
87   what.form.submit.disabled=false;
88
89 % foreach my $dst ( @dst ) {
90
91     if ( dst == <% $dst->$dst_pkey %> ) {
92       what.form.amount.value = "<% min($dst->$dst_unapplied, $unapplied) %>";
93 %     if ($use_sub_dst_thing) {
94         what.form.display_amount.value = "<% min($dst->$dst_unapplied, $unapplied) %>";
95
96         var rownum=0
97         var table = document.getElementById('ApplicationTable');
98         while(table.rows[2]) {
99           table.deleteRow(2);
100         }
101 %       my $app_class = "FS::$link_table";
102 %       my $temp_app = $app_class->new(
103 %         { $src_pkey => $src_pkeyvalue,
104 %           $dst_pkey => $dst->$dst_pkey,
105 %           'amount'  => min($dst->$dst_unapplied, $unapplied),
106 %         }
107 %       );
108 %       my %apphash = ();
109 %       my $listref_or_error = $temp_app->calculate_applications;
110 %       %apphash = map { &{$key_generator}($_), $_ } @$listref_or_error
111 %         if ref($listref_or_error);
112 %       foreach my $cbp ( $dst->open_cust_bill_pkg ) {
113 %         my $desc = $cbp->desc;
114 %         my $total_owed = $cbp->owed_setup + $cbp->owed_recur;
115 %         my $key = &{$key_generator}([ $cbp, 0, {} ]);
116 %         my $amount = exists($apphash{ $key }) ? $apphash{ $key }->[1] : 0;
117 %         unless ( $cbp->pkgnum ) {
118 %           foreach my $taxX ( $cbp->cust_bill_pkg_tax_Xlocation ) {
119 %             my $pkey = $taxX->primary_key;
120 %             my $owed = $taxX->owed;
121 %             my $key = &{$key_generator}([ $cbp, 0, { $pkey => $taxX->$pkey } ]);
122 %             my $toapp = exists($apphash{ $key }) ? $apphash{ $key }->[1] : 0;
123               <% &{$row_generator}( $cbp, $taxX->desc, $owed, $toapp, $taxX->$pkey ) %>
124 %             $total_owed -= $owed;
125 %             $amount -= $toapp;
126 %           }
127 %           $desc .= ' (default)';
128 %         }
129 %         if ( $total_owed > 0 ) {
130             <% &{$row_generator}($cbp, $desc, $total_owed, $amount, '') %>
131 %         }
132 %       }
133 %     }
134     }
135
136 % } 
137
138 }
139
140 function sub_changed(what) {
141
142   var amount = 0;
143   var table = document.getElementById('ApplicationTable');
144   var i = table.rows.length;
145   while(i-- > 2) {
146     var amount_input = table.rows[i].getElementsByTagName('input').item(0);
147     amount += parseFloat( amount_input.value ) || 0; 
148   }
149   what.form.amount.value = parseFloat(amount).toFixed(2);
150   what.form.display_amount.value = parseFloat(amount).toFixed(2);
151
152 }
153 </SCRIPT>
154
155 Apply to:
156
157 <TABLE ID="ApplicationTable" BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0>
158
159 <TR>
160   <TD ALIGN="right"><% $dst_thing %>: </TD>
161   <TD><SELECT NAME="<% $dst_pkey %>" SIZE=1 onChange="changed(this)">
162 <OPTION VALUE="">Select <% $dst_thing %>
163
164 % foreach my $dst ( @dst ) { 
165   <OPTION<% $dst->$dst_pkey eq $dst_pkeyvalue ? ' SELECTED' : '' %> VALUE="<% $dst->$dst_pkey %>">#<% $dst->$dst_pkey %> - <% time2str("%D", $dst->_date) %> - $<% $dst->$dst_unapplied %>
166 % } 
167
168 </SELECT>
169   </TD>
170 </TR>
171
172 <TR>
173   <TD ALIGN="right">Amount: </TD>
174   <TD><% $money_char %><INPUT TYPE="text" NAME="<% $use_sub_dst_thing ? 'display_' : '' %>amount" VALUE="<% $amount %>" SIZE=8 MAXLENGTH=8 <% $use_sub_dst_thing ? 'DISABLED' : '' %> STYLE="text-align:right;"></TD>
175 % if ($use_sub_dst_thing) {
176   <INPUT TYPE="hidden" NAME="amount" VALUE="<% $amount %>" >
177 % }
178 </TR>
179
180 </TABLE>
181
182 <BR>
183 <CENTER><INPUT TYPE="submit" VALUE="Apply" NAME="submit" ID="submit" DISABLED></CENTER>
184
185 </FORM>
186
187 <% include('/elements/footer.html') %>
188
189 <%init>
190
191 my %opt = @_;
192
193 my $conf = new FS::Conf;
194 my $money_char = $conf->config('money_char') || '$';
195
196 my $src_thing = ucfirst($opt{'src_thing'});
197 my $src_table = $opt{'src_table'};
198 my $src_pkey = dbdef->table($src_table)->primary_key;
199
200 my $dst_thing = ucfirst($opt{'dst_thing'});
201 my $dst_table = $opt{'dst_table'};
202 my $dst_pkey = dbdef->table($dst_table)->primary_key;
203 my $dst_unapplied = $dst_table eq 'cust_bill' ? 'owed' : 'unapplied';
204
205 $opt{form_action} =~ /^process\/(.*)\./ or die "bad form action";
206 my $link_table = $1;
207
208 my $use_sub_dst_thing = 0;
209 $use_sub_dst_thing = 1
210   if ( $dst_table eq 'cust_bill' && $conf->exists("${link_table}_pkg-manual") );
211
212 my $to = $dst_table eq 'cust_refund' ? ' to Refund' : '';
213
214 my($src_pkeyvalue, $amount, $dst_pkeyvalue);
215 if ( $cgi->param('error') ) {
216   $src_pkeyvalue = $cgi->param($src_pkey);
217   $amount    = $cgi->param('amount');
218   $dst_pkeyvalue    = $cgi->param($dst_pkey);
219 } else {
220   my($query) = $cgi->keywords;
221   $query =~ /^(\d+)$/;
222   $src_pkeyvalue = $1;
223   $amount = '';
224   $dst_pkeyvalue = '';
225 }
226
227 my $otaker = getotaker;
228
229 my $p1 = popurl(1);
230
231 my $src = qsearchs($src_table, { $src_pkey => $src_pkeyvalue } );
232 die "$src_thing $src_pkeyvalue not found!" unless $src;
233
234 my $unapplied = $src->unapplied;
235
236 my @dst = sort {    $a->_date     <=> $b->_date
237                  or $a->$dst_pkey <=> $b->$dst_pkey
238                }
239           grep { $_->$dst_unapplied != 0 }
240           qsearch($dst_table, { 'custnum' => $src->custnum } );
241
242 my $row_generator = sub {
243   my ($cust_bill_pkg, $desc, $owed, $amount, $taxXnum) = @_;
244   my $id = $cust_bill_pkg->pkgnum || 'Tax';
245   my $billpkgnum = $cust_bill_pkg->billpkgnum;
246
247   $amount = sprintf("%.2f", $amount);
248   qq!
249       var tablebody = document.getElementsByTagName('tbody').item(0);
250       var row = table.insertRow(rownum+2);
251       var pkg_cell = document.createElement('TD');
252       pkg_cell.style.textAlign = 'right';
253       pkg_cell.innerHTML = "$id - $desc - $owed:";
254       var amount_cell = document.createElement('TD');
255       amount_cell.innerHTML = "$money_char";
256       var amount_input = document.createElement('INPUT');
257       amount_input.setAttribute('name', 'subamount'+rownum);
258       amount_input.setAttribute('id',   'subamount'+rownum);
259       amount_input.style.textAlign = 'right';
260       amount_input.setAttribute('size', 8);
261       amount_input.setAttribute('maxlength', 8);
262       amount_input.setAttribute('rownum', rownum);
263       amount_input.setAttribute('value', "$amount");
264       amount_input.setAttribute('onChange', "sub_changed(this);");
265       amount_cell.appendChild(amount_input);
266       var subnum_input = document.createElement('INPUT');
267       subnum_input.setAttribute('name', 'subnum'+rownum);
268       subnum_input.setAttribute('id',   'subnum'+rownum);
269       subnum_input.setAttribute('type', 'hidden');
270       subnum_input.setAttribute('rownum', rownum);
271       subnum_input.setAttribute('value', "$billpkgnum");
272       amount_cell.appendChild(subnum_input);
273       var taxnum_input = document.createElement('INPUT');
274       taxnum_input.setAttribute('name', 'taxXlocationnum'+rownum);
275       taxnum_input.setAttribute('id',   'taxXlocationnum'+rownum);
276       taxnum_input.setAttribute('type', 'hidden');
277       taxnum_input.setAttribute('rownum', rownum);
278       taxnum_input.setAttribute('value', "$taxXnum");
279       amount_cell.appendChild(taxnum_input);
280       row.appendChild(pkg_cell);
281       row.appendChild(amount_cell);
282       rownum++;
283     !;
284 };
285
286 my $key_generator = sub {
287   my $listref = shift;
288   my ($cust_bill_pkg, $amount, $hashref) = @$listref;
289   my $setup_or_recur = $cust_bill_pkg->setup > 0 ? 'setup' : 'recur';
290   my $taxlinenum = $hashref->{billpkgtaxlocationnum} ||
291                    $hashref->{billpkgtaxratelocationnum} ||
292                    '';
293                    
294   join(':', $cust_bill_pkg->billpkgnum, $setup_or_recur, $taxlinenum);
295 };
296
297 </%init>