summaryrefslogtreecommitdiff
path: root/bin/is.pl
blob: 0603db5e2a514f74bbb45564e9bd702875c82bce (plain)
  1. #=====================================================================
  2. # LedgerSMB Small Medium Business Accounting
  3. # http://www.ledgersmb.org/
  4. #
  5. # Copyright (C) 2006
  6. # This work contains copyrighted information from a number of sources all used
  7. # with permission.
  8. #
  9. # This file contains source code included with or based on SQL-Ledger which
  10. # is Copyright Dieter Simader and DWS Systems Inc. 2000-2005 and licensed
  11. # under the GNU General Public License version 2 or, at your option, any later
  12. # version. For a full list including contact information of contributors,
  13. # maintainers, and copyright holders, see the CONTRIBUTORS file.
  14. #
  15. # Original Copyright Notice from SQL-Ledger 2.6.17 (before the fork):
  16. # Copyright (c) 2001
  17. #
  18. # Author: DWS Systems Inc.
  19. # Web: http://www.sql-ledger.org
  20. #
  21. #
  22. #
  23. # Author: DWS Systems Inc.
  24. # Web: http://www.ledgersmb.org/
  25. #
  26. #
  27. # This program is free software; you can redistribute it and/or modify
  28. # it under the terms of the GNU General Public License as published by
  29. # the Free Software Foundation; either version 2 of the License, or
  30. # (at your option) any later version.
  31. #
  32. # This program is distributed in the hope that it will be useful,
  33. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  34. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  35. # GNU General Public License for more details.
  36. # You should have received a copy of the GNU General Public License
  37. # along with this program; if not, write to the Free Software
  38. # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  39. #======================================================================
  40. #
  41. # Inventory invoicing module
  42. #
  43. #======================================================================
  44. use LedgerSMB::IS;
  45. use LedgerSMB::PE;
  46. use LedgerSMB::Tax;
  47. require "bin/arap.pl";
  48. require "bin/io.pl";
  49. 1;
  50. # end of main
  51. sub on_update{}
  52. sub add {
  53. if ($form->{type} eq 'credit_invoice'){
  54. $form->{title} = $locale->text('Add Credit Invoice');
  55. $form->{subtype} = 'credit_invoice';
  56. $form->{reverse} = 1;
  57. } else {
  58. $form->{title} = $locale->text('Add Sales Invoice');
  59. $form->{reverse} = 0;
  60. }
  61. $form->{callback} =
  62. "$form->{script}?action=add&type=$form->{type}&login=$form->{login}&path=$form->{path}&sessionid=$form->{sessionid}"
  63. unless $form->{callback};
  64. &invoice_links;
  65. &prepare_invoice;
  66. &display_form;
  67. }
  68. sub edit {
  69. if ($form->{reverse}) {
  70. $form->{title} = $locale->text('Add Credit Invoice');
  71. $form->{subtype} = 'credit_invoice';
  72. } else {
  73. $form->{title} = $locale->text('Add Sales Invoice');
  74. }
  75. &invoice_links;
  76. &prepare_invoice;
  77. &display_form;
  78. }
  79. sub invoice_links {
  80. $form->{vc} = "customer";
  81. $form->{type} = "invoice";
  82. # create links
  83. $form->create_links( "AR", \%myconfig, "customer", 1 );
  84. # currencies
  85. @curr = split /:/, $form->{currencies};
  86. $form->{defaultcurrency} = $curr[0];
  87. chomp $form->{defaultcurrency};
  88. for (@curr) { $form->{selectcurrency} .= "<option>$_\n" }
  89. if ( @{ $form->{all_customer} } ) {
  90. unless ( $form->{customer_id} ) {
  91. $form->{customer_id} = $form->{all_customer}->[0]->{id};
  92. }
  93. }
  94. AA->get_name( \%myconfig, \%$form );
  95. delete $form->{notes};
  96. IS->retrieve_invoice( \%myconfig, \%$form );
  97. $form->{oldlanguage_code} = $form->{language_code};
  98. $form->get_partsgroup( \%myconfig, { all => 1} );
  99. if ( @{ $form->{all_partsgroup} } ) {
  100. $form->{selectpartsgroup} = "<option>\n";
  101. foreach $ref ( @{ $form->{all_partsgroup} } ) {
  102. if ( $ref->{translation} ) {
  103. $form->{selectpartsgroup} .=
  104. qq|<option value="$ref->{partsgroup}--$ref->{id}">$ref->{translation}\n|;
  105. }
  106. else {
  107. $form->{selectpartsgroup} .=
  108. qq|<option value="$ref->{partsgroup}--$ref->{id}">$ref->{partsgroup}\n|;
  109. }
  110. }
  111. }
  112. if ( @{ $form->{all_project} } ) {
  113. $form->{selectprojectnumber} = "<option>\n";
  114. for ( @{ $form->{all_project} } ) {
  115. $form->{selectprojectnumber} .=
  116. qq|<option value="$_->{projectnumber}--$_->{id}">$_->{projectnumber}\n|;
  117. }
  118. }
  119. $form->{oldcustomer} = "$form->{customer}--$form->{customer_id}";
  120. $form->{oldtransdate} = $form->{transdate};
  121. $form->{selectcustomer} = "";
  122. if ( @{ $form->{all_customer} } ) {
  123. $form->{customer} = "$form->{customer}--$form->{customer_id}";
  124. for ( @{ $form->{all_customer} } ) {
  125. $form->{selectcustomer} .=
  126. qq|<option value="$_->{name}--$_->{id}">$_->{name}\n|;
  127. }
  128. }
  129. # departments
  130. if ( @{ $form->{all_department} } ) {
  131. $form->{selectdepartment} = "<option>\n";
  132. $form->{department} = "$form->{department}--$form->{department_id}"
  133. if $form->{department_id};
  134. for ( @{ $form->{all_department} } ) {
  135. $form->{selectdepartment} .=
  136. qq|<option value="$_->{description}--$_->{id}">$_->{description}\n|;
  137. }
  138. }
  139. $form->{employee} = "$form->{employee}--$form->{employee_id}";
  140. # sales staff
  141. if ( @{ $form->{all_employee} } ) {
  142. $form->{selectemployee} = "";
  143. for ( @{ $form->{all_employee} } ) {
  144. $form->{selectemployee} .=
  145. qq|<option value="$_->{name}--$_->{id}">$_->{name}\n|;
  146. }
  147. }
  148. if ( @{ $form->{all_language} } ) {
  149. $form->{selectlanguage} = "<option>\n";
  150. for ( @{ $form->{all_language} } ) {
  151. $form->{selectlanguage} .=
  152. qq|<option value="$_->{code}">$_->{description}\n|;
  153. }
  154. }
  155. # forex
  156. $form->{forex} = $form->{exchangerate};
  157. $exchangerate = ( $form->{exchangerate} ) ? $form->{exchangerate} : 1;
  158. foreach $key ( keys %{ $form->{AR_links} } ) {
  159. $form->{"select$key"} = "";
  160. foreach $ref ( @{ $form->{AR_links}{$key} } ) {
  161. $form->{"select$key"} .=
  162. "<option>$ref->{accno}--$ref->{description}\n";
  163. }
  164. if ( $key eq "AR_paid" ) {
  165. for $i ( 1 .. scalar @{ $form->{acc_trans}{$key} } ) {
  166. $form->{"AR_paid_$i"} =
  167. "$form->{acc_trans}{$key}->[$i-1]->{accno}--$form->{acc_trans}{$key}->[$i-1]->{description}";
  168. # reverse paid
  169. $form->{"paid_$i"} =
  170. $form->{acc_trans}{$key}->[ $i - 1 ]->{amount} * -1;
  171. $form->{"datepaid_$i"} =
  172. $form->{acc_trans}{$key}->[ $i - 1 ]->{transdate};
  173. $form->{"forex_$i"} = $form->{"exchangerate_$i"} =
  174. $form->{acc_trans}{$key}->[ $i - 1 ]->{exchangerate};
  175. $form->{"source_$i"} =
  176. $form->{acc_trans}{$key}->[ $i - 1 ]->{source};
  177. $form->{"memo_$i"} =
  178. $form->{acc_trans}{$key}->[ $i - 1 ]->{memo};
  179. $form->{"cleared_$i"} =
  180. $form->{acc_trans}{$key}->[ $i - 1 ]->{cleared};
  181. $form->{paidaccounts} = $i;
  182. }
  183. }
  184. else {
  185. $form->{$key} =
  186. "$form->{acc_trans}{$key}->[0]->{accno}--$form->{acc_trans}{$key}->[0]->{description}"
  187. if $form->{acc_trans}{$key}->[0]->{accno};
  188. }
  189. }
  190. for (qw(AR_links acc_trans)) { delete $form->{$_} }
  191. $form->{paidaccounts} = 1 unless ( exists $form->{paidaccounts} );
  192. $form->{AR} = $form->{AR_1} unless $form->{id};
  193. $form->{transdate} = $form->{current_date} if (!$form->{transdate});
  194. $form->{locked} =
  195. ( $form->{revtrans} )
  196. ? '1'
  197. : ( $form->datetonum( \%myconfig, $form->{transdate} ) <=
  198. $form->datetonum( \%myconfig, $form->{closedto} ) );
  199. if ( !$form->{readonly} ) {
  200. $form->{readonly} = 1 if $myconfig{acs} =~ /AR--Sales Invoice/;
  201. }
  202. }
  203. sub prepare_invoice {
  204. $form->{type} = "invoice";
  205. $form->{formname} = "invoice";
  206. $form->{sortby} ||= "runningnumber";
  207. $form->{format} = "postscript" if $myconfig{printer};
  208. $form->{media} = $myconfig{printer};
  209. $form->{selectformname} =
  210. qq|<option value="invoice">|
  211. . $locale->text('Invoice') . qq|
  212. <option value="pick_list">| . $locale->text('Pick List') . qq|
  213. <option value="packing_list">| . $locale->text('Packing List');
  214. $i = 0;
  215. $form->{currency} =~ s/ //g;
  216. $form->{oldcurrency} = $form->{currency};
  217. if ( $form->{id} ) {
  218. for (
  219. qw(invnumber ordnumber ponumber quonumber shippingpoint shipvia notes intnotes)
  220. )
  221. {
  222. $form->{$_} = $form->quote( $form->{$_} );
  223. }
  224. foreach $ref ( @{ $form->{invoice_details} } ) {
  225. $i++;
  226. for ( keys %$ref ) { $form->{"${_}_$i"} = $ref->{$_} }
  227. $form->{"projectnumber_$i"} =
  228. qq|$ref->{projectnumber}--$ref->{project_id}|
  229. if $ref->{project_id};
  230. $form->{"partsgroup_$i"} =
  231. qq|$ref->{partsgroup}--$ref->{partsgroup_id}|
  232. if $ref->{partsgroup_id};
  233. $form->{"discount_$i"} =
  234. $form->format_amount( \%myconfig, $form->{"discount_$i"} * 100 );
  235. ($dec) = ( $form->{"sellprice_$i"} =~ /\.(\d+)/ );
  236. $dec = length $dec;
  237. $decimalplaces = ( $dec > 2 ) ? $dec : 2;
  238. $form->{"sellprice_$i"} =
  239. $form->format_amount( \%myconfig, $form->{"sellprice_$i"},
  240. $decimalplaces );
  241. $form->{"qty_$i"} =
  242. $form->format_amount( \%myconfig, $form->{"qty_$i"} );
  243. $form->{"oldqty_$i"} = $form->{"qty_$i"};
  244. for (qw(partnumber sku description unit)) {
  245. $form->{"${_}_$i"} = $form->quote( $form->{"${_}_$i"} );
  246. }
  247. $form->{rowcount} = $i;
  248. }
  249. }
  250. }
  251. sub form_header {
  252. # set option selected
  253. for (qw(AR currency)) {
  254. $form->{"select$_"} =~ s/ selected//;
  255. $form->{"select$_"} =~
  256. s/option>\Q$form->{$_}\E/option selected>$form->{$_}/;
  257. }
  258. for (qw(customer department employee)) {
  259. $form->{"select$_"} = $form->unescape( $form->{"select$_"} );
  260. $form->{"select$_"} =~ s/ selected//;
  261. $form->{"select$_"} =~ s/(<option value="\Q$form->{$_}\E")/$1 selected/;
  262. }
  263. $form->{exchangerate} =
  264. $form->format_amount( \%myconfig, $form->{exchangerate} );
  265. $exchangerate = qq|<tr>|;
  266. $exchangerate .= qq|
  267. <th align=right nowrap>| . $locale->text('Currency') . qq|</th>
  268. <td><select name=currency>$form->{selectcurrency}</select></td>
  269. | if $form->{defaultcurrency};
  270. $exchangerate .= qq|
  271. <input type=hidden name=selectcurrency value="$form->{selectcurrency}">
  272. <input type=hidden name=defaultcurrency value=$form->{defaultcurrency}>
  273. |;
  274. if ( $form->{defaultcurrency}
  275. && $form->{currency} ne $form->{defaultcurrency} )
  276. {
  277. if ( $form->{forex} ) {
  278. $exchangerate .=
  279. qq|<th align=right>|
  280. . $locale->text('Exchange Rate')
  281. . qq|</th><td>$form->{exchangerate}<input type=hidden name=exchangerate value=$form->{exchangerate}></td>|;
  282. }
  283. else {
  284. $exchangerate .=
  285. qq|<th align=right>|
  286. . $locale->text('Exchange Rate')
  287. . qq|</th><td><input name=exchangerate size=10 value=$form->{exchangerate}></td>|;
  288. }
  289. }
  290. $exchangerate .= qq|
  291. <input type=hidden name=forex value=$form->{forex}>
  292. </tr>
  293. |;
  294. if ( $form->{selectcustomer} ) {
  295. $customer = qq|<select name=customer>$form->{selectcustomer}</select>
  296. <input type=hidden name="selectcustomer" value="|
  297. . $form->escape( $form->{selectcustomer}, 1 ) . qq|">|;
  298. }
  299. else {
  300. $customer = qq|<input name=customer value="$form->{customer}" size=35>|;
  301. }
  302. $department = qq|
  303. <tr>
  304. <th align="right" nowrap>| . $locale->text('Department') . qq|</th>
  305. <td colspan=3><select name=department>$form->{selectdepartment}</select>
  306. <input type=hidden name=selectdepartment value="|
  307. . $form->escape( $form->{selectdepartment}, 1 ) . qq|">
  308. </td>
  309. </tr>
  310. | if $form->{selectdepartment};
  311. $n = ( $form->{creditremaining} < 0 ) ? "0" : "1";
  312. if ( $form->{business} ) {
  313. $business = qq|
  314. <tr>
  315. <th align=right nowrap>| . $locale->text('Business') . qq|</th>
  316. <td>$form->{business}</td>
  317. <td width=10></td>
  318. <th align=right nowrap>| . $locale->text('Trade Discount') . qq|</th>
  319. <td>|
  320. . $form->format_amount( \%myconfig, $form->{tradediscount} * 100 )
  321. . qq| %</td>
  322. </tr>
  323. |;
  324. }
  325. $employee = qq|
  326. <input type=hidden name=employee value="$form->{employee}">
  327. |;
  328. $employee = qq|
  329. <tr>
  330. <th align=right nowrap>| . $locale->text('Salesperson') . qq|</th>
  331. <td><select name=employee>$form->{selectemployee}</select></td>
  332. <input type=hidden name=selectemployee value="|
  333. . $form->escape( $form->{selectemployee}, 1 ) . qq|">
  334. </tr>
  335. | if $form->{selectemployee};
  336. $i = $form->{rowcount} + 1;
  337. $focus = "partnumber_$i";
  338. $form->header;
  339. print qq|
  340. <body onLoad="document.forms[0].${focus}.focus()" />
  341. <form method=post action="$form->{script}">
  342. |;
  343. $form->hide_form(
  344. qw(id type media format printed emailed queued title vc terms discount
  345. creditlimit creditremaining tradediscount business closedto locked
  346. shipped oldtransdate recurring reverse batch_id subtype)
  347. );
  348. print qq|
  349. <table width=100%>
  350. <tr class=listtop>
  351. <th class=listtop>$form->{title}</th>
  352. </tr>
  353. <tr height="5"></tr>
  354. <tr>
  355. <td>
  356. <table width=100%>
  357. <tr valign=top>
  358. <td>
  359. <table>
  360. <tr>
  361. <th align=right nowrap>| . $locale->text('Customer') . qq|</th>
  362. <td colspan=3>$customer</td>
  363. <input type=hidden name=customer_id value=$form->{customer_id}>
  364. <input type=hidden name=oldcustomer value="$form->{oldcustomer}">
  365. </tr>
  366. <tr>
  367. <td></td>
  368. <td colspan=3>
  369. <table>
  370. <tr>
  371. <th align=right nowrap>| . $locale->text('Credit Limit') . qq|</th>
  372. <td>|
  373. . $form->format_amount( \%myconfig, $form->{creditlimit}, 0, "0" )
  374. . qq|</td>
  375. <td width=10></td>
  376. <th align=right nowrap>| . $locale->text('Remaining') . qq|</th>
  377. <td class="plus$n" nowrap>|
  378. . $form->format_amount( \%myconfig, $form->{creditremaining}, 0, "0" )
  379. . qq|</td>
  380. </tr>
  381. $business
  382. </table>
  383. </td>
  384. </tr>
  385. <tr>
  386. <th align=right nowrap>| . $locale->text('Record in') . qq|</th>
  387. <td colspan=3><select name=AR>$form->{selectAR}</select></td>
  388. <input type=hidden name=selectAR value="$form->{selectAR}">
  389. </tr>
  390. $department
  391. $exchangerate
  392. <tr>
  393. <th align=right nowrap>| . $locale->text('Shipping Point') . qq|</th>
  394. <td colspan=3><input name=shippingpoint size=35 value="$form->{shippingpoint}"></td>
  395. </tr>
  396. <tr>
  397. <th align=right nowrap>| . $locale->text('Ship via') . qq|</th>
  398. <td colspan=3><input name=shipvia size=35 value="$form->{shipvia}"></td>
  399. </tr>
  400. </table>
  401. </td>
  402. <td align=right>
  403. <table>
  404. $employee
  405. <tr>
  406. <th align=right nowrap>| . $locale->text('Invoice Number') . qq|</th>
  407. <td><input name=invnumber size=20 value="$form->{invnumber}"></td>
  408. </tr>
  409. <tr>
  410. <th align=right nowrap>| . $locale->text('Order Number') . qq|</th>
  411. <td><input name=ordnumber size=20 value="$form->{ordnumber}"></td>
  412. <input type=hidden name=quonumber value="$form->{quonumber}">
  413. </tr>
  414. <tr>
  415. <th align=right>| . $locale->text('Invoice Date') . qq|</th>
  416. <td><input class="date" name=transdate size=11 title="$myconfig{dateformat}" value=$form->{transdate}></td>
  417. </tr>
  418. <tr>
  419. <th align=right>| . $locale->text('Due Date') . qq|</th>
  420. <td><input class="date" name=duedate size=11 title="$myconfig{dateformat}" value=$form->{duedate}></td>
  421. </tr>
  422. <tr>
  423. <th align=right nowrap>| . $locale->text('PO Number') . qq|</th>
  424. <td><input name=ponumber size=20 value="$form->{ponumber}"></td>
  425. </tr>
  426. </table>
  427. </td>
  428. </tr>
  429. </table>
  430. </td>
  431. </tr>
  432. <tr>
  433. <td>
  434. </td>
  435. </tr>
  436. |;
  437. $form->hide_form(
  438. qw(shiptoname shiptoaddress1 shiptoaddress2 shiptocity shiptostate shiptozipcode shiptocountry shiptocontact shiptophone shiptofax shiptoemail message email subject cc bcc taxaccounts)
  439. );
  440. foreach $item ( split / /, $form->{taxaccounts} ) {
  441. $form->hide_form( "${item}_rate", "${item}_description",
  442. "${item}_taxnumber" );
  443. }
  444. }
  445. sub form_footer {
  446. _calc_taxes();
  447. $form->{invtotal} = $form->{invsubtotal};
  448. if ( ( $rows = $form->numtextrows( $form->{notes}, 35, 8 ) ) < 2 ) {
  449. $rows = 2;
  450. }
  451. if ( ( $introws = $form->numtextrows( $form->{intnotes}, 35, 8 ) ) < 2 ) {
  452. $introws = 2;
  453. }
  454. $rows = ( $rows > $introws ) ? $rows : $introws;
  455. $notes =
  456. qq|<textarea name=notes rows=$rows cols=35 wrap=soft>$form->{notes}</textarea>|;
  457. $intnotes =
  458. qq|<textarea name=intnotes rows=$rows cols=35 wrap=soft>$form->{intnotes}</textarea>|;
  459. $form->{taxincluded} = ( $form->{taxincluded} ) ? "checked" : "";
  460. $taxincluded = "";
  461. if ( $form->{taxaccounts} ) {
  462. $taxincluded = qq|
  463. <tr height="5"></tr>
  464. <tr>
  465. <td align=right>
  466. <input name=taxincluded class=checkbox type=checkbox value=1 $form->{taxincluded}></td><th align=left>|
  467. . $locale->text('Tax Included')
  468. . qq|</th>
  469. </tr>
  470. |;
  471. }
  472. if ( !$form->{taxincluded} ) {
  473. foreach $item (keys %{$form->{taxes}}) {
  474. my $taccno = $item;
  475. $form->{invtotal} += $form->round_amount($form->{taxes}{$item}, 2);
  476. $form->{"${taccno}_total"} =
  477. $form->format_amount( \%myconfig,
  478. $form->round_amount( $form->{taxes}{$item}, 2 ), 2 );
  479. $tax .= qq|
  480. <tr>
  481. <th align=right>$form->{"${taccno}_description"}</th>
  482. <td align=right>$form->{"${taccno}_total"}</td>
  483. </tr>|;
  484. }
  485. $form->{invsubtotal} =
  486. $form->format_amount( \%myconfig, $form->{invsubtotal}, 2, 0 );
  487. $subtotal = qq|
  488. <tr>
  489. <th align=right>| . $locale->text('Subtotal') . qq|</th>
  490. <td align=right>$form->{invsubtotal}</td>
  491. </tr>
  492. |;
  493. }
  494. $form->{oldinvtotal} = $form->{invtotal};
  495. $form->{invtotal} =
  496. $form->format_amount( \%myconfig, $form->{invtotal}, 2, 0 );
  497. my $hold;
  498. if ($form->{on_hold}) {
  499. $hold = qq| <font size="17"><b> This invoice is On Hold </b></font> |;
  500. }
  501. print qq|
  502. <tr>
  503. <td>
  504. <table width=100%>
  505. <tr valign=bottom>
  506. | . $hold . qq|
  507. <td>
  508. <table>
  509. <tr>
  510. <th align=left>| . $locale->text('Notes') . qq|</th>
  511. <th align=left>| . $locale->text('Internal Notes') . qq|</th>
  512. </tr>
  513. <tr valign=top>
  514. <td>$notes</td>
  515. <td>$intnotes</td>
  516. </tr>
  517. </table>
  518. </td>
  519. <td align=right>
  520. <table>
  521. $subtotal
  522. $tax
  523. <tr>
  524. <th align=right>| . $locale->text('Total') . qq|</th>
  525. <td align=right>$form->{invtotal}</td>
  526. </tr>
  527. $taxincluded
  528. </table>
  529. </td>
  530. </tr>
  531. </table>
  532. </td>
  533. </tr>
  534. <tr>
  535. <td>
  536. <table width=100%>
  537. <tr class=listheading>
  538. <th colspan=6 class=listheading>| . $locale->text('Payments') . qq|</th>
  539. </tr>
  540. |;
  541. if ( $form->{currency} eq $form->{defaultcurrency} ) {
  542. @column_index = qw(datepaid source memo paid AR_paid);
  543. }
  544. else {
  545. @column_index = qw(datepaid source memo paid exchangerate AR_paid);
  546. }
  547. $column_data{datepaid} = "<th>" . $locale->text('Date') . "</th>";
  548. $column_data{paid} = "<th>" . $locale->text('Amount') . "</th>";
  549. $column_data{exchangerate} = "<th>" . $locale->text('Exch') . "</th>";
  550. $column_data{AR_paid} = "<th>" . $locale->text('Account') . "</th>";
  551. $column_data{source} = "<th>" . $locale->text('Source') . "</th>";
  552. $column_data{memo} = "<th>" . $locale->text('Memo') . "</th>";
  553. print "
  554. <tr>
  555. ";
  556. for (@column_index) { print "$column_data{$_}\n" }
  557. print "
  558. </tr>
  559. ";
  560. $form->{paidaccounts}++ if ( $form->{"paid_$form->{paidaccounts}"} );
  561. for $i ( 1 .. $form->{paidaccounts} ) {
  562. $form->hide_form("cleared_$i");
  563. print "
  564. <tr>\n";
  565. $form->{"selectAR_paid_$i"} = $form->{selectAR_paid};
  566. $form->{"selectAR_paid_$i"} =~
  567. s/option>\Q$form->{"AR_paid_$i"}\E/option selected>$form->{"AR_paid_$i"}/;
  568. # format amounts
  569. $totalpaid += $form->{"paid_$i"};
  570. $form->{"paid_$i"} =
  571. $form->format_amount( \%myconfig, $form->{"paid_$i"}, 2 );
  572. $form->{"exchangerate_$i"} =
  573. $form->format_amount( \%myconfig, $form->{"exchangerate_$i"} );
  574. $exchangerate = qq|&nbsp;|;
  575. if ( $form->{currency} ne $form->{defaultcurrency} ) {
  576. if ( $form->{"forex_$i"} ) {
  577. $exchangerate =
  578. qq|<input type=hidden name="exchangerate_$i" value=$form->{"exchangerate_$i"}>$form->{"exchangerate_$i"}|;
  579. }
  580. else {
  581. $exchangerate =
  582. qq|<input name="exchangerate_$i" size=10 value=$form->{"exchangerate_$i"}>|;
  583. }
  584. }
  585. $exchangerate .= qq|
  586. <input type=hidden name="forex_$i" value=$form->{"forex_$i"}>
  587. |;
  588. $column_data{paid} =
  589. qq|<td align=center><input name="paid_$i" size=11 value=$form->{"paid_$i"}></td>|;
  590. $column_data{exchangerate} = qq|<td align=center>$exchangerate</td>|;
  591. $column_data{AR_paid} =
  592. qq|<td align=center><select name="AR_paid_$i">$form->{"selectAR_paid_$i"}</select></td>|;
  593. $column_data{datepaid} =
  594. qq|<td align=center><input class="date" name="datepaid_$i" size=11 title="$myconfig{dateformat}" value=$form->{"datepaid_$i"}></td>|;
  595. $column_data{source} =
  596. qq|<td align=center><input name="source_$i" size=11 value="$form->{"source_$i"}"></td>|;
  597. $column_data{memo} =
  598. qq|<td align=center><input name="memo_$i" size=11 value="$form->{"memo_$i"}"></td>|;
  599. for (@column_index) { print qq|$column_data{$_}\n| }
  600. print "
  601. </tr>\n";
  602. }
  603. $form->{oldtotalpaid} = $totalpaid;
  604. $form->hide_form(qw(paidaccounts selectAR_paid oldinvtotal oldtotalpaid));
  605. print qq|
  606. </table>
  607. </td>
  608. </tr>
  609. <tr>
  610. <td><hr size=3 noshade></td>
  611. </tr>
  612. <tr>
  613. <td>
  614. |;
  615. &print_options;
  616. print qq|
  617. </td>
  618. </tr>
  619. </table>
  620. <br>
  621. |;
  622. $transdate = $form->datetonum( \%myconfig, $form->{transdate} );
  623. $closedto = $form->datetonum( \%myconfig, $form->{closedto} );
  624. # type=submit $locale->text('Update')
  625. # type=submit $locale->text('Print')
  626. # type=submit $locale->text('Post')
  627. # type=submit $locale->text('Print and Post')
  628. # type=submit $locale->text('Schedule')
  629. # type=submit $locale->text('Ship to')
  630. # type=submit $locale->text('Post as new')
  631. # type=submit $locale->text('Print and Post as new')
  632. # type=submit $locale->text('E-mail')
  633. # type=submit $locale->text('Delete')
  634. # type=submit $locale->text('Sales Order')
  635. if ( !$form->{readonly} ) {
  636. # changes by Aurynn to add an On Hold button
  637. %button = (
  638. 'update' =>
  639. { ndx => 1, key => 'U', value => $locale->text('Update') },
  640. 'print' =>
  641. { ndx => 2, key => 'P', value => $locale->text('Print') },
  642. 'post' => { ndx => 3, key => 'O', value => $locale->text('Post') },
  643. 'ship_to' =>
  644. { ndx => 4, key => 'T', value => $locale->text('Ship to') },
  645. 'e_mail' =>
  646. { ndx => 5, key => 'E', value => $locale->text('E-mail') },
  647. 'print_and_post' => {
  648. ndx => 6,
  649. key => 'R',
  650. value => $locale->text('Print and Post')
  651. },
  652. 'post_as_new' =>
  653. { ndx => 7, key => 'N', value => $locale->text('Post as new') },
  654. 'print_and_post_as_new' => {
  655. ndx => 8,
  656. key => 'W',
  657. value => $locale->text('Print and Post as new')
  658. },
  659. 'sales_order' =>
  660. { ndx => 9, key => 'L', value => $locale->text('Sales Order') },
  661. 'schedule' =>
  662. { ndx => 10, key => 'H', value => $locale->text('Schedule') },
  663. 'delete' =>
  664. { ndx => 11, key => 'D', value => $locale->text('Delete') },
  665. 'on_hold' =>
  666. { ndx => 12, key => 'O', value => $locale->text('On Hold') },
  667. );
  668. if ( $form->{id} ) {
  669. if ( $form->{locked} || $transdate <= $closedto ) {
  670. for ( "post", "print_and_post", "delete" ) {
  671. delete $button{$_};
  672. }
  673. }
  674. if ( !${LedgerSMB::Sysconfig::latex} ) {
  675. for ( "print_and_post", "print_and_post_as_new" ) {
  676. delete $button{$_};
  677. }
  678. }
  679. }
  680. else {
  681. if ( $transdate > $closedto ) {
  682. # Added on_hold, by Aurynn.
  683. for ( "update", "ship_to", "print", "e_mail", "post",
  684. "schedule", "on_hold" )
  685. {
  686. $allowed{$_} = 1;
  687. }
  688. $a{'print_and_post'} = 1 if ${LedgerSMB::Sysconfig::latex};
  689. for ( keys %button ) { delete $button{$_} if !$allowed{$_} }
  690. }
  691. elsif ($closedto) {
  692. %button = ();
  693. }
  694. }
  695. for ( sort { $button{$a}->{ndx} <=> $button{$b}->{ndx} } keys %button )
  696. {
  697. $form->print_button( \%button, $_ );
  698. }
  699. }
  700. if ( $form->{lynx} ) {
  701. require "bin/menu.pl";
  702. &menubar;
  703. }
  704. $form->hide_form(qw(rowcount callback path login sessionid));
  705. print qq|
  706. </form>
  707. </body>
  708. </html>
  709. |;
  710. }
  711. sub update {
  712. on_update();
  713. $form->{taxes} = {};
  714. $form->{exchangerate} =
  715. $form->parse_amount( \%myconfig, $form->{exchangerate} );
  716. if ( $newname = &check_name(customer) ) {
  717. &rebuild_vc( customer, AR, $form->{transdate}, 1 );
  718. }
  719. if ( $form->{transdate} ne $form->{oldtransdate} ) {
  720. $form->{duedate} =
  721. ( $form->{terms} )
  722. ? $form->current_date( \%myconfig, $form->{transdate},
  723. $form->{terms} * 1 )
  724. : $form->{duedate};
  725. $form->{oldtransdate} = $form->{transdate};
  726. &rebuild_vc( customer, AR, $form->{transdate}, 1 ) if !$newname;
  727. if ( $form->{currency} ne $form->{defaultcurrency} ) {
  728. delete $form->{exchangerate};
  729. $form->{exchangerate} = $exchangerate
  730. if (
  731. $form->{forex} = (
  732. $exchangerate = $form->check_exchangerate(
  733. \%myconfig, $form->{currency},
  734. $form->{transdate}, 'buy'
  735. )
  736. )
  737. );
  738. }
  739. $form->{selectemployee} = "";
  740. if ( @{ $form->{all_employee} } ) {
  741. for ( @{ $form->{all_employee} } ) {
  742. $form->{selectemployee} .=
  743. qq|<option value="$_->{name}--$_->{id}">$_->{name}\n|;
  744. }
  745. }
  746. }
  747. if ( $form->{currency} ne $form->{oldcurrency} ) {
  748. delete $form->{exchangerate};
  749. $form->{exchangerate} = $exchangerate
  750. if (
  751. $form->{forex} = (
  752. $exchangerate = $form->check_exchangerate(
  753. \%myconfig, $form->{currency},
  754. $form->{transdate}, 'buy'
  755. )
  756. )
  757. );
  758. }
  759. $j = 1;
  760. for $i ( 1 .. $form->{paidaccounts} ) {
  761. if ( $form->{"paid_$i"} ) {
  762. for (qw(datepaid source memo cleared)) {
  763. $form->{"${_}_$j"} = $form->{"${_}_$i"};
  764. }
  765. for (qw(paid exchangerate)) {
  766. $form->{"${_}_$j"} =
  767. $form->parse_amount( \%myconfig, $form->{"${_}_$i"} );
  768. }
  769. $form->{"exchangerate_$j"} = $exchangerate
  770. if (
  771. $form->{"forex_$j"} = (
  772. $exchangerate = $form->check_exchangerate(
  773. \%myconfig, $form->{currency},
  774. $form->{"datepaid_$j"}, 'buy'
  775. )
  776. )
  777. );
  778. if ( $j++ != $i ) {
  779. for (qw(datepaid source memo cleared paid exchangerate forex)) {
  780. delete $form->{"${_}_$i"};
  781. }
  782. }
  783. }
  784. else {
  785. for (qw(datepaid source memo cleared paid exchangerate forex)) {
  786. delete $form->{"${_}_$i"};
  787. }
  788. }
  789. }
  790. $form->{paidaccounts} = $j;
  791. $i = $form->{rowcount};
  792. $exchangerate = ( $form->{exchangerate} ) ? $form->{exchangerate} : 1;
  793. for (qw(partsgroup projectnumber)) {
  794. $form->{"select$_"} = $form->unescape( $form->{"select$_"} )
  795. if $form->{"select$_"};
  796. }
  797. # if last row empty, check the form otherwise retrieve new item
  798. if ( ( $form->{"partnumber_$i"} eq "" )
  799. && ( $form->{"description_$i"} eq "" )
  800. && ( $form->{"partsgroup_$i"} eq "" ) )
  801. {
  802. $form->{creditremaining} +=
  803. ( $form->{oldinvtotal} - $form->{oldtotalpaid} );
  804. &check_form;
  805. }
  806. else {
  807. IS->retrieve_item( \%myconfig, \%$form );
  808. $rows = scalar @{ $form->{item_list} };
  809. if ( $form->{language_code} && $rows == 0 ) {
  810. $language_code = $form->{language_code};
  811. $form->{language_code} = "";
  812. IS->retrieve_item( \%myconfig, \%$form );
  813. $form->{language_code} = $language_code;
  814. $rows = scalar @{ $form->{item_list} };
  815. }
  816. if ($rows) {
  817. if ( $rows > 1 ) {
  818. &select_item;
  819. exit;
  820. }
  821. else {
  822. $form->{"qty_$i"} =
  823. ( $form->{"qty_$i"} * 1 ) ? $form->{"qty_$i"} : 1;
  824. $sellprice =
  825. $form->parse_amount( \%myconfig, $form->{"sellprice_$i"} );
  826. for (qw(partnumber description unit)) {
  827. $form->{item_list}[$i]{$_} =
  828. $form->quote( $form->{item_list}[$i]{$_} );
  829. }
  830. for ( keys %{ $form->{item_list}[0] } ) {
  831. $form->{"${_}_$i"} = $form->{item_list}[0]{$_};
  832. }
  833. if (! defined $form->{"discount_$i"}){
  834. $form->{"discount_$i"} = $form->{discount} * 100;
  835. }
  836. if ($sellprice) {
  837. $form->{"sellprice_$i"} = $sellprice;
  838. ($dec) = ( $form->{"sellprice_$i"} =~ /\.(\d+)/ );
  839. $dec = length $dec;
  840. $decimalplaces1 = ( $dec > 2 ) ? $dec : 2;
  841. }
  842. else {
  843. ($dec) = ( $form->{"sellprice_$i"} =~ /\.(\d+)/ );
  844. $dec = length $dec;
  845. $decimalplaces1 = ( $dec > 2 ) ? $dec : 2;
  846. $form->{"sellprice_$i"} /= $exchangerate;
  847. }
  848. ($dec) = ( $form->{"lastcost_$i"} =~ /\.(\d+)/ );
  849. $dec = length $dec;
  850. $decimalplaces2 = ( $dec > 2 ) ? $dec : 2;
  851. # if there is an exchange rate adjust sellprice
  852. for (qw(listprice lastcost)) {
  853. $form->{"${_}_$i"} /= $exchangerate;
  854. }
  855. $amount =
  856. $form->{"sellprice_$i"} * $form->{"qty_$i"} *
  857. ( 1 - $form->{"discount_$i"} / 100 );
  858. for ( split / /, $form->{taxaccounts} ) {
  859. $form->{"${_}_base"} = 0;
  860. }
  861. for ( split / /, $form->{"taxaccounts_$i"} ) {
  862. $form->{"${_}_base"} += $amount;
  863. }
  864. $form->{creditremaining} -= $amount;
  865. for (qw(sellprice listprice)) {
  866. $form->{"${_}_$i"} =
  867. $form->format_amount( \%myconfig, $form->{"${_}_$i"},
  868. $decimalplaces1 );
  869. }
  870. $form->{"lastcost_$i"} =
  871. $form->format_amount( \%myconfig, $form->{"lastcost_$i"},
  872. $decimalplaces2 );
  873. $form->{"oldqty_$i"} = $form->{"qty_$i"};
  874. for (qw(qty discount)) {
  875. $form->{"{_}_$i"} =
  876. $form->format_amount( \%myconfig, $form->{"${_}_$i"} );
  877. }
  878. }
  879. &display_form;
  880. }
  881. else {
  882. # ok, so this is a new part
  883. # ask if it is a part or service item
  884. if ( $form->{"partsgroup_$i"}
  885. && ( $form->{"partsnumber_$i"} eq "" )
  886. && ( $form->{"description_$i"} eq "" ) )
  887. {
  888. $form->{rowcount}--;
  889. &display_form;
  890. }
  891. else {
  892. $form->{"id_$i"} = 0;
  893. $form->{"unit_$i"} = $locale->text('ea');
  894. &new_item;
  895. }
  896. }
  897. }
  898. }
  899. sub post {
  900. $form->isblank( "transdate", $locale->text('Invoice Date missing!') );
  901. $form->isblank( "customer", $locale->text('Customer missing!') );
  902. # if oldcustomer ne customer redo form
  903. if ( &check_name(customer) ) {
  904. &update;
  905. exit;
  906. }
  907. &validate_items;
  908. $closedto = $form->datetonum( \%myconfig, $form->{closedto} );
  909. $transdate = $form->datetonum( \%myconfig, $form->{transdate} );
  910. $form->error( $locale->text('Cannot post invoice for a closed period!') )
  911. if ( $transdate <= $closedto );
  912. $form->isblank( "exchangerate", $locale->text('Exchange rate missing!') )
  913. if ( $form->{currency} ne $form->{defaultcurrency} );
  914. for $i ( 1 .. $form->{paidaccounts} ) {
  915. if ( $form->{"paid_$i"} ) {
  916. $datepaid = $form->datetonum( \%myconfig, $form->{"datepaid_$i"} );
  917. $form->isblank( "datepaid_$i",
  918. $locale->text('Payment date missing!') );
  919. $form->error(
  920. $locale->text('Cannot post payment for a closed period!') )
  921. if ( $datepaid <= $closedto );
  922. if ( $form->{currency} ne $form->{defaultcurrency} ) {
  923. $form->{"exchangerate_$i"} = $form->{exchangerate}
  924. if ( $transdate == $datepaid );
  925. $form->isblank( "exchangerate_$i",
  926. $locale->text('Exchange rate for payment missing!') );
  927. }
  928. }
  929. }
  930. $form->{label} = $locale->text('Invoice');
  931. if ( !$form->{repost} ) {
  932. if ( $form->{id} ) {
  933. &repost;
  934. exit;
  935. }
  936. }
  937. ( $form->{AR} ) = split /--/, $form->{AR};
  938. ( $form->{AR_paid} ) = split /--/, $form->{AR_paid};
  939. if ( IS->post_invoice( \%myconfig, \%$form ) ) {
  940. $form->redirect(
  941. $locale->text( 'Invoice [_1] posted!', $form->{invnumber} ) );
  942. }
  943. else {
  944. $form->error( $locale->text('Cannot post invoice!') );
  945. }
  946. }
  947. sub print_and_post {
  948. $form->error( $locale->text('Select postscript or PDF!') )
  949. if $form->{format} !~ /(postscript|pdf)/;
  950. $form->error( $locale->text('Select a Printer!') )
  951. if $form->{media} eq 'screen';
  952. if ( !$form->{repost} ) {
  953. if ( $form->{id} ) {
  954. $form->{print_and_post} = 1;
  955. &repost;
  956. exit;
  957. }
  958. }
  959. $old_form = new Form;
  960. $form->{display_form} = "post";
  961. for ( keys %$form ) { $old_form->{$_} = $form->{$_} }
  962. $old_form->{rowcount}++;
  963. &print_form($old_form);
  964. }
  965. sub delete {
  966. $form->header;
  967. print qq|
  968. <body>
  969. <form method=post action=$form->{script}>
  970. |;
  971. $form->{action} = "yes";
  972. $form->hide_form;
  973. print qq|
  974. <h2 class=confirm>| . $locale->text('Confirm!') . qq|</h2>
  975. <h4>|
  976. . $locale->text( 'Are you sure you want to delete Invoice Number [_1]?',
  977. $form->{invnumber} )
  978. . qq|
  979. </h4>
  980. <p>
  981. <button name="action" class="submit" type="submit" value="yes">|
  982. . $locale->text('Yes')
  983. . qq|</button>
  984. </form>
  985. |;
  986. }
  987. sub yes {
  988. if (
  989. IS->delete_invoice(
  990. \%myconfig, \%$form, ${LedgerSMB::Sysconfig::spool}
  991. )
  992. )
  993. {
  994. $form->redirect( $locale->text('Invoice deleted!') );
  995. }
  996. else {
  997. $form->error( $locale->text('Cannot delete invoice!') );
  998. }
  999. }
  1000. sub on_hold {
  1001. if ($form->{id}) {
  1002. my $toggled = IS->toggle_on_old($form);
  1003. #&invoice_links(); # is that it?
  1004. &edit(); # it was already IN edit for this to be reached.
  1005. }
  1006. }