enable CardFortress in test database, #71513
[freeside.git] / httemplate / edit / credit-cust_bill_pkg.html
1 <& /elements/header-popup.html, 'Credit line items' &>
2
3 <FORM ACTION="process/credit-cust_bill_pkg.html" METHOD="POST">
4 <INPUT TYPE="hidden" NAME="crednum" VALUE="">
5 <INPUT TYPE="hidden" NAME="custnum" VALUE="<% $custnum |h %>">
6 <INPUT TYPE="hidden" NAME="paybatch" VALUE="">
7 <INPUT TYPE="hidden" NAME="_date" VALUE="<% time %>">
8 <table>
9
10 % my $old_invnum = 0; 
11 %# foreach my $cust_bill_pkg ( @cust_bill_pkg ) {
12 % foreach my $item ( @items ) {
13 %   my( $setuprecur, $cust_bill_pkg ) = @$item;
14
15 %   my $method = $setuprecur eq 'setup' ? 'setup' : 'recur';
16 %   my $amount = $cust_bill_pkg->$method();
17 %   my $credited = $cust_bill_pkg->credited('', '', 'setuprecur'=>$method);
18 %   $amount -= $credited;
19 %   $amount = sprintf('%.2f', $amount);
20 %   next unless $amount > 0;
21
22 %   if ( $cust_bill_pkg->invnum ne $old_invnum ) {
23       <TR><TD COLSPAN=4 BGCOLOR="#f8f8f8">&nbsp;</TD></TR>
24       <TR><TH COLSPAN=4 BGCOLOR="#f8f8f8" ALIGN="left">Invoice #<% $cust_bill_pkg->invnum %> - <% time2str($date_format, $cust_bill_pkg->cust_bill->_date) %></TD></TR>
25 %     $old_invnum = $cust_bill_pkg->invnum;
26 %   }
27
28 %   my $el_name = 'billpkgnum'. $cust_bill_pkg->billpkgnum. '-'. $setuprecur;
29     <TR>
30       <TD>
31         <INPUT TYPE            = "checkbox"
32                NAME            = "<% $el_name %>"
33                ID              = "<% $el_name %>"
34                onClick         = "calc_total(this)"
35                data-billpkgnum = "<% $cust_bill_pkg->billpkgnum %>"
36                data-setuprecur = "<% $setuprecur %>"
37         >
38       </TD>
39       <TD BGCOLOR="#ffffff"><% $cust_bill_pkg->desc |h %></TD>
40 %#    show one-time/setup vs recur vs usage?
41       <TD BGCOLOR="#ffffff" ALIGN="right"><% $money_char. $amount %></TD>
42       <TD ALIGN="right">
43         <% $money_char %><INPUT TYPE     = "text"
44                                 NAME     = "<% $el_name %>-amount"
45                                 ID       = "<% $el_name %>-amount"
46                                 VALUE    = "<% $amount %>"
47                                 SIZE     = 6
48                                 onChange = "calc_total(this)"
49                                 STYLE    = "text-align:right;"
50                                 DISABLED
51                          >
52       </TD>
53     </TR>
54
55 % }
56
57 <TR><TD COLSPAN=4 BGCOLOR="#f8f8f8">&nbsp;</TD></TR>
58 <TR>
59   <TD></TD>
60   <TD ALIGN="right" COLSPAN=2>Subtotal: </TD>
61   <TD ALIGN="right" ID="subtotal_td"><% $money_char %><% sprintf('%.2f', 0) %></TD>
62 </TR>
63 <TR>
64   <TD></TD>
65   <TD ALIGN="right" COLSPAN=2>Taxes: </TD>
66   <TD ALIGN="right" ID="taxtotal_td"><% $money_char %><% sprintf('%.2f', 0) %></TD>
67 </TR>
68 <TR>
69   <TD></TD>
70   <TH ALIGN="right" COLSPAN=2>Total credit amount: </TD>
71   <TH ALIGN="right" ID="total_td"><% $money_char %><% sprintf('%.2f', 0) %></TD>
72 </TR>
73
74 </table>
75
76 <INPUT TYPE="hidden" NAME="amount" ID="total_el" VALUE="0.00">
77
78 <table>
79
80 <& /elements/tr-select-reason.html,
81               'field'          => 'reasonnum',
82               'reason_class'   => 'R',
83               #XXX reconcile both this and show_taxes wanting to enable this
84               'id'             => 'select_reason',
85               'control_button' => 'credit_button',
86               'cgi'            => $cgi,
87 &>
88
89 <TR>
90   <TD ALIGN="right"><% mt('Additional info') |h %></TD>
91   <TD>
92     <INPUT TYPE="text" NAME="addlinfo" VALUE="<% $cgi->param('addlinfo') |h %>">
93   </TD>
94 </TR>
95
96 % if ( $conf->exists('credits-auto-apply-disable') ) {
97         <INPUT TYPE="HIDDEN" NAME="apply" VALUE="no">
98 % } else {
99   <TR>
100     <TD ALIGN="right"><% mt('Apply to selected line items') |h %></TD>
101     <TD><SELECT NAME="apply"><OPTION VALUE="yes" SELECTED><% mt('yes') |h %><OPTION><% mt('no') |h %></SELECT></TD>
102   </TR>
103 % }
104
105 </table>
106
107 <BR>
108 <INPUT TYPE="submit" ID="credit_button" VALUE="Credit" DISABLED>
109
110 </FORM>
111
112 <% include( '/elements/xmlhttp.html',
113             'url' =>  $p.'misc/xmlhttp-cust_bill_pkg-calculate_taxes.html',
114             'subs' => [ 'calculate_taxes' ],
115           )
116 %>
117 <SCRIPT TYPE="text/javascript">
118
119 document.getElementById('select_reason').disabled = true;
120   // start it disabled because no line items are selected yet
121 function show_taxes(arg) {
122   var argsHash = eval('(' + arg + ')');
123
124   //XXX add an 'ErrorMessage' section to the HTML and re-enable
125   //var error = argsHash['error'];
126
127   //var paragraph = document.getElementById('ErrorMessage');
128   //if (error) {
129   //  paragraph.innerHTML = 'Error: ' + error;
130   //  paragraph.style.color = '#ff0000';
131   //} else {
132   //  paragraph.innerHTML = '';
133   //}
134
135   var taxlines = argsHash['taxlines'];
136
137 //XXX display the tax lines? just a total will do for now
138 //
139 //  var table = document.getElementById('ApplicationTable');
140 //
141 //  var aFoundRow = 0;
142 //  for (i = 0; taxlines[i]; i++) {
143 //    var itemdesc = taxlines[i][0];
144 //    var locnum   = taxlines[i][2];
145 //    if (taxlines[i][3]) {
146 //      locnum  = taxlines[i][3];
147 //    }
148 //
149 //    var found = 0;
150 //    for (var row = 2; table.rows[row]; row++) {
151 //      var inputs = table.rows[row].getElementsByTagName('input');
152 //      if (! inputs.length) {
153 //        while ( table.rows[row] ) {
154 //           table.deleteRow(row);
155 //        }
156 //        break;
157 //      }
158 //      if ( inputs.item(4).value == itemdesc && inputs.item(2).value == locnum )
159 //      {
160 //        inputs.item(0).value = taxlines[i][1];
161 //        aFoundRow = found = row;
162 //        break;
163 //      }
164 //    }
165 //    if (! found) {
166 //      var row = table.insertRow(table.rows.length);
167 //      var warning_cell = document.createElement('TD');
168 //      warning_cell.style.color = '#ff0000';
169 //      warning_cell.colSpan = 2;
170 //      warning_cell.innerHTML = 'Calculated Tax - ' + itemdesc + ' - ' +
171 //                               taxlines[i][1] + ' will not be applied';
172 //      row.appendChild(warning_cell);
173 //    }
174 //  }
175 //
176 //  if (aFoundRow) {
177 //    sub_changed(table.rows[aFoundRow].getElementsByTagName('input').item(0));
178 //  }
179
180   var subtotal = parseFloat( argsHash['subtotal'] );
181
182   var taxtotal = parseFloat( argsHash['taxtotal'] );
183   document.getElementById('taxtotal_td').innerHTML =
184     '<% $money_char %>' + taxtotal.toFixed(2);
185
186   var total = subtotal + taxtotal;
187   document.getElementById('total_td').innerHTML =
188     '<% $money_char %>' + total.toFixed(2);
189   document.getElementById('total_el').value = total.toFixed(2);
190
191   //XXX reconcile both this and the reason selector wanteding to enable this
192   if ( total > 0 ) {
193     //document.getElementById('credit_button').disabled = false;
194     document.getElementById('select_reason').disabled = false;
195   }
196     
197 }
198
199 function calc_total(what) {
200
201   //document.getElementById('credit_button').disabled = true;
202   document.getElementById('select_reason').disabled = true;
203
204   var subtotal = 0;
205   // bah, a pain, just using an attribute var re = /^billpkgnum(\d+)$/;
206
207   var el = what.form.elements;
208   var billpkgnums = [];
209   var setuprecurs = [];
210   var amounts = [];
211   for (var i=0; i<el.length; i++) {
212
213     if ( el[i].type == 'checkbox' ) {
214       var amount_el = document.getElementById( el[i].id + '-amount' );
215       if ( el[i].checked ) {
216         amount_el.disabled = false;
217         var amount = amount_el.value;
218         subtotal += parseFloat( amount );
219         amounts.push( amount );
220         billpkgnums.push( el[i].getAttribute('data-billpkgnum') );
221         setuprecurs.push( el[i].getAttribute('data-setuprecur') );
222       } else {
223         amount_el.disabled = true;
224       }
225     }
226
227   }
228
229   document.getElementById('subtotal_td').innerHTML =
230     '<% $money_char %>' + subtotal.toFixed(2);
231
232   var args = new Array(
233     'custnum',     '<% $custnum %>',
234     'subtotal',    subtotal,
235     'billpkgnums', billpkgnums.join(),
236     'setuprecurs', setuprecurs.join(),
237     'amounts',     amounts.join()
238   );
239
240   calculate_taxes( args, show_taxes );
241
242 }
243 </SCRIPT>
244
245 <%init>
246
247 my $curuser = $FS::CurrentUser::CurrentUser;
248 die "access denied" unless $curuser->access_right('Credit line items');
249
250 #a tiny bit of false laziness w/search/cust_bill_pkg.cgi, but we're pretty
251 # specialized and a piece of UI, not a report
252 #slightly more false laziness w/httemplate/edit/elements/ApplicationCommon.html
253 # show_taxes & calc_total here/do_calculate_tax there
254
255 my $conf = new FS::Conf;
256 my $money_char = $conf->config('money_char') || '$';
257 my $date_format = $conf->config('date_format') || '%m/%d/%Y';
258
259 $cgi->param('custnum') =~ /^(\d+)$/ or die 'illegal custnum';
260 my $custnum = $1;
261
262 my $cust_main = qsearchs({
263   'table'     => 'cust_main',
264   'hashref'   => { 'custnum' => $custnum },
265   'extra_sql' => ' AND '. $curuser->agentnums_sql,
266 }) or die 'unknown customer';
267
268 my @cust_bill_pkg = qsearch({
269   'select'    => 'cust_bill_pkg.*',
270   'table'     => 'cust_bill_pkg',
271   'addl_from' => 'LEFT JOIN cust_bill USING (invnum)',
272   'extra_sql' => "WHERE custnum = $custnum ".
273                  "AND (pkgnum != 0 or feepart IS NOT NULL)",
274   'order_by'  => 'ORDER BY invnum ASC, billpkgnum ASC',
275 });
276
277 my @items = map { my %hash = $_->disintegrate;
278                   map [ $_, $hash{$_} ],
279                     keys(%hash);
280                 }
281               @cust_bill_pkg;
282
283 #omit line items which have been previously credited?  would be nice
284
285 </%init>