summaryrefslogtreecommitdiff
path: root/bin/gl.pl
blob: dc6ea83f8295e58e8a9996181b74aa5756382713 (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. # Contributors:
  22. #
  23. #
  24. # Author: DWS Systems Inc.
  25. # Web: http://www.ledgersmb.org/
  26. #
  27. # Contributors:
  28. #
  29. # This program is free software; you can redistribute it and/or modify
  30. # it under the terms of the GNU General Public License as published by
  31. # the Free Software Foundation; either version 2 of the License, or
  32. # (at your option) any later version.
  33. #
  34. # This program is distributed in the hope that it will be useful,
  35. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  36. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  37. # GNU General Public License for more details.
  38. # You should have received a copy of the GNU General Public License
  39. # along with this program; if not, write to the Free Software
  40. # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  41. #======================================================================
  42. #
  43. # Genereal Ledger
  44. #
  45. #======================================================================
  46. use LedgerSMB::GL;
  47. use LedgerSMB::PE;
  48. require "bin/arap.pl";
  49. 1;
  50. # end of main
  51. # this is for our long dates
  52. # $locale->text('January')
  53. # $locale->text('February')
  54. # $locale->text('March')
  55. # $locale->text('April')
  56. # $locale->text('May ')
  57. # $locale->text('June')
  58. # $locale->text('July')
  59. # $locale->text('August')
  60. # $locale->text('September')
  61. # $locale->text('October')
  62. # $locale->text('November')
  63. # $locale->text('December')
  64. # this is for our short month
  65. # $locale->text('Jan')
  66. # $locale->text('Feb')
  67. # $locale->text('Mar')
  68. # $locale->text('Apr')
  69. # $locale->text('May')
  70. # $locale->text('Jun')
  71. # $locale->text('Jul')
  72. # $locale->text('Aug')
  73. # $locale->text('Sep')
  74. # $locale->text('Oct')
  75. # $locale->text('Nov')
  76. # $locale->text('Dec')
  77. sub pos_adjust {
  78. $form->{rowcount} = 3;
  79. require "pos.conf.pl";
  80. $form->{accno_1} = $pos_config{'close_cash_accno'};
  81. $form->{accno_2} = $pos_config{'coa_prefix'};
  82. $form->{accno_3} = $pos_config{'coa_prefix'};
  83. }
  84. sub add_pos_adjust {
  85. $form->{pos_adjust} = 1;
  86. $form->{reference} =
  87. $locale->text("Adjusting Till: (till) Source: (source)");
  88. $form->{description} =
  89. $locale->text("Adjusting till due to data entry error.");
  90. $form->{callback} =
  91. "$form->{script}?action=add_pos_adjust&transfer=$form->{transfer}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}"
  92. unless $form->{callback};
  93. &add;
  94. }
  95. sub add {
  96. $form->{title} = "Add";
  97. $form->{callback} =
  98. "$form->{script}?action=add&transfer=$form->{transfer}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}"
  99. unless $form->{callback};
  100. &create_links;
  101. $form->{reference} = $form->update_defaults(\%myconfig, 'glnumber');
  102. $form->{rowcount} = ( $form->{transfer} ) ? 3 : 9;
  103. if ( $form->{pos_adjust} ) {
  104. &pos_adjust;
  105. }
  106. $form->{oldtransdate} = $form->{transdate};
  107. $form->{focus} = "reference";
  108. # departments
  109. if ( @{ $form->{all_department} } ) {
  110. $form->{selectdepartment} = "<option>\n";
  111. for ( @{ $form->{all_department} } ) {
  112. $form->{selectdepartment} .=
  113. qq|<option value="$_->{description}--$_->{id}">$_->{description}\n|;
  114. }
  115. }
  116. &display_form(1);
  117. }
  118. sub edit {
  119. &create_links;
  120. $form->{locked} =
  121. ( $form->{revtrans} )
  122. ? '1'
  123. : ( $form->datetonum( \%myconfig, $form->{transdate} ) <=
  124. $form->datetonum( \%myconfig, $form->{closedto} ) );
  125. # readonly
  126. if ( !$form->{readonly} ) {
  127. $form->{readonly} = 1
  128. if $myconfig{acs} =~ /General Ledger--Add Transaction/;
  129. }
  130. $form->{title} = "Edit";
  131. $i = 1;
  132. foreach $ref ( @{ $form->{GL} } ) {
  133. $form->{"accno_$i"} = "$ref->{accno}--$ref->{description}";
  134. $form->{"projectnumber_$i"} =
  135. "$ref->{projectnumber}--$ref->{project_id}";
  136. for (qw(fx_transaction source memo)) { $form->{"${_}_$i"} = $ref->{$_} }
  137. if ( $ref->{amount} < 0 ) {
  138. $form->{totaldebit} -= $ref->{amount};
  139. $form->{"debit_$i"} = $ref->{amount} * -1;
  140. }
  141. else {
  142. $form->{totalcredit} += $ref->{amount};
  143. $form->{"credit_$i"} = $ref->{amount};
  144. }
  145. $i++;
  146. }
  147. $form->{rowcount} = $i;
  148. $form->{focus} = "debit_$i";
  149. &form_header;
  150. &display_rows;
  151. &form_footer;
  152. }
  153. sub create_links {
  154. GL->transaction( \%myconfig, \%$form );
  155. for ( @{ $form->{all_accno} } ) {
  156. $form->{selectaccno} .= "<option>$_->{accno}--$_->{description}\n";
  157. }
  158. # projects
  159. if ( @{ $form->{all_project} } ) {
  160. $form->{selectprojectnumber} = "<option>\n";
  161. for ( @{ $form->{all_project} } ) {
  162. $form->{selectprojectnumber} .=
  163. qq|<option value="$_->{projectnumber}--$_->{id}">$_->{projectnumber}\n|;
  164. }
  165. }
  166. # departments
  167. if ( @{ $form->{all_department} } ) {
  168. $form->{department} = "$form->{department}--$form->{department_id}";
  169. $form->{selectdepartment} = "<option>\n";
  170. for ( @{ $form->{all_department} } ) {
  171. $form->{selectdepartment} .=
  172. qq|<option value="$_->{description}--$_->{id}">$_->{description}\n|;
  173. }
  174. }
  175. }
  176. sub search {
  177. $form->{title} = $locale->text('General Ledger Reports');
  178. $colspan = 5;
  179. $form->all_departments( \%myconfig );
  180. # departments
  181. if ( @{ $form->{all_department} } ) {
  182. $form->{selectdepartment} = "<option>\n";
  183. for ( @{ $form->{all_department} } ) {
  184. $form->{selectdepartment} .=
  185. qq|<option value="$_->{description}--$_->{id}">$_->{description}\n|;
  186. }
  187. $l_department =
  188. qq|<input name="l_department" class=checkbox type=checkbox value=Y> |
  189. . $locale->text('Department');
  190. $department = qq|
  191. <tr>
  192. <th align=right nowrap>| . $locale->text('Department') . qq|</th>
  193. <td colspan=$colspan><select name=department>$form->{selectdepartment}</select></td>
  194. </tr>
  195. |;
  196. }
  197. if ( @{ $form->{all_years} } ) {
  198. # accounting years
  199. $form->{selectaccountingyear} = "<option>\n";
  200. for ( @{ $form->{all_years} } ) {
  201. $form->{selectaccountingyear} .= qq|<option>$_\n|;
  202. }
  203. $form->{selectaccountingmonth} = "<option>\n";
  204. for ( sort keys %{ $form->{all_month} } ) {
  205. $form->{selectaccountingmonth} .=
  206. qq|<option value=$_>|
  207. . $locale->text( $form->{all_month}{$_} ) . qq|\n|;
  208. }
  209. $selectfrom = qq|
  210. <tr>
  211. <th align=right>| . $locale->text('Period') . qq|</th>
  212. <td colspan=$colspan>
  213. <select name=month>$form->{selectaccountingmonth}</select>
  214. <select name=year>$form->{selectaccountingyear}</select>
  215. <input name=interval class=radio type=radio value=0 checked>&nbsp;|
  216. . $locale->text('Current') . qq|
  217. <input name=interval class=radio type=radio value=1>&nbsp;|
  218. . $locale->text('Month') . qq|
  219. <input name=interval class=radio type=radio value=3>&nbsp;|
  220. . $locale->text('Quarter') . qq|
  221. <input name=interval class=radio type=radio value=12>&nbsp;|
  222. . $locale->text('Year') . qq|
  223. </td>
  224. </tr>
  225. |;
  226. }
  227. @a = ();
  228. push @a, qq|<input name="l_id" class=checkbox type=checkbox value=Y> |
  229. . $locale->text('ID');
  230. push @a,
  231. qq|<input name="l_transdate" class=checkbox type=checkbox value=Y checked> |
  232. . $locale->text('Date');
  233. push @a,
  234. qq|<input name="l_reference" class=checkbox type=checkbox value=Y checked> |
  235. . $locale->text('Reference');
  236. push @a,
  237. qq|<input name="l_description" class=checkbox type=checkbox value=Y checked> |
  238. . $locale->text('Description');
  239. push @a, qq|<input name="l_notes" class=checkbox type=checkbox value=Y> |
  240. . $locale->text('Notes');
  241. push @a, $l_department if $l_department;
  242. push @a,
  243. qq|<input name="l_debit" class=checkbox type=checkbox value=Y checked> |
  244. . $locale->text('Debit');
  245. push @a,
  246. qq|<input name="l_credit" class=checkbox type=checkbox value=Y checked> |
  247. . $locale->text('Credit');
  248. push @a,
  249. qq|<input name="l_source" class=checkbox type=checkbox value=Y checked> |
  250. . $locale->text('Source');
  251. push @a, qq|<input name="l_memo" class=checkbox type=checkbox value=Y> |
  252. . $locale->text('Memo');
  253. push @a,
  254. qq|<input name="l_accno" class=checkbox type=checkbox value=Y checked> |
  255. . $locale->text('Account');
  256. push @a,
  257. qq|<input name="l_gifi_accno" class=checkbox type=checkbox value=Y> |
  258. . $locale->text('GIFI');
  259. $form->header;
  260. print qq|
  261. <body>
  262. <form method=post action=$form->{script}>
  263. <input type=hidden name=sort value=transdate>
  264. <table width=100%>
  265. <tr>
  266. <th class=listtop>$form->{title}</th>
  267. </tr>
  268. <tr height="5"></tr>
  269. <tr>
  270. <td>
  271. <table>
  272. <tr>
  273. <th align=right>| . $locale->text('Reference') . qq|</th>
  274. <td><input name=reference size=20></td>
  275. </tr>
  276. <tr>
  277. <th align=right>| . $locale->text('Source') . qq|</th>
  278. <td><input name=source size=20></td>
  279. <th align=right>| . $locale->text('Memo') . qq|</th>
  280. <td><input name=memo size=20></td>
  281. </tr>
  282. $department
  283. <tr>
  284. <th align=right>| . $locale->text('Description') . qq|</th>
  285. <td colspan=$colspan><input name=description size=60></td>
  286. </tr>
  287. <tr>
  288. <th align=right>| . $locale->text('Notes') . qq|</th>
  289. <td colspan=$colspan><input name=notes size=60></td>
  290. </tr>
  291. <tr>
  292. <th align=right>| . $locale->text('From') . qq|</th>
  293. <td><input name=datefrom size=11 title="$myconfig{dateformat}"></td>
  294. <th align=right>| . $locale->text('To') . qq|</th>
  295. <td><input name=dateto size=11 title="$myconfig{dateformat}"></td>
  296. </tr>
  297. $selectfrom
  298. <tr>
  299. <th align=right>| . $locale->text('Amount') . qq| >=</th>
  300. <td><input name=amountfrom size=11></td>
  301. <th align=right>| . $locale->text('Amount') . qq| <=</th>
  302. <td><input name=amountto size=11></td>
  303. </tr>
  304. <tr>
  305. <th align=right>| . $locale->text('Include in Report') . qq|</th>
  306. <td colspan=$colspan>
  307. <table>
  308. <tr>
  309. <td>
  310. <input name="category" class=radio type=radio value=X checked>&nbsp;|
  311. . $locale->text('All') . qq|
  312. <input name="category" class=radio type=radio value=A>&nbsp;|
  313. . $locale->text('Asset') . qq|
  314. <input name="category" class=radio type=radio value=L>&nbsp;|
  315. . $locale->text('Liability') . qq|
  316. <input name="category" class=radio type=radio value=Q>&nbsp;|
  317. . $locale->text('Equity') . qq|
  318. <input name="category" class=radio type=radio value=I>&nbsp;|
  319. . $locale->text('Income') . qq|
  320. <input name="category" class=radio type=radio value=E>&nbsp;|
  321. . $locale->text('Expense') . qq|
  322. </td>
  323. </tr>
  324. <tr>
  325. <table>
  326. |;
  327. while (@a) {
  328. print qq|<tr>\n|;
  329. for ( 1 .. 5 ) {
  330. print qq|<td nowrap>| . shift @a;
  331. print qq|</td>\n|;
  332. }
  333. print qq|</tr>\n|;
  334. }
  335. print qq|
  336. <tr>
  337. <td nowrap><input name="l_subtotal" class=checkbox type=checkbox value=Y> |
  338. . $locale->text('Subtotal')
  339. . qq|</td>
  340. </tr>
  341. </table>
  342. </tr>
  343. </table>
  344. </tr>
  345. </table>
  346. </td>
  347. </tr>
  348. <tr>
  349. <td><hr size=3 noshade></td>
  350. </tr>
  351. </table>
  352. <input type=hidden name=nextsub value=generate_report>
  353. |;
  354. $form->hide_form(qw(path login sessionid));
  355. print qq|
  356. <br>
  357. <button class="submit" type="submit" name="action" value="continue">|
  358. . $locale->text('Continue')
  359. . qq|</button>
  360. </form>
  361. |;
  362. if ( $form->{lynx} ) {
  363. require "bin/menu.pl";
  364. &menubar;
  365. }
  366. print qq|
  367. </body>
  368. </html>
  369. |;
  370. }
  371. sub generate_report {
  372. $form->{sort} = "transdate" unless $form->{sort};
  373. $form->{amountfrom} = $form->parse_amount(\%myconfig, $form->{amountfrom});
  374. $form->{amountto} = $form->parse_amount(\%myconfig, $form->{amountto});
  375. GL->all_transactions( \%myconfig, \%$form );
  376. $href =
  377. "$form->{script}?action=generate_report&direction=$form->{direction}&oldsort=$form->{oldsort}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  378. $form->sort_order();
  379. $callback =
  380. "$form->{script}?action=generate_report&direction=$form->{direction}&oldsort=$form->{oldsort}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  381. %acctype = (
  382. 'A' => $locale->text('Asset'),
  383. 'L' => $locale->text('Liability'),
  384. 'Q' => $locale->text('Equity'),
  385. 'I' => $locale->text('Income'),
  386. 'E' => $locale->text('Expense'),
  387. );
  388. $form->{title} = $locale->text('General Ledger');
  389. $ml = ( $form->{category} =~ /(A|E)/ ) ? -1 : 1;
  390. unless ( $form->{category} eq 'X' ) {
  391. $form->{title} .=
  392. " : " . $locale->text( $acctype{ $form->{category} } );
  393. }
  394. if ( $form->{accno} ) {
  395. $href .= "&accno=" . $form->escape( $form->{accno} );
  396. $callback .= "&accno=" . $form->escape( $form->{accno}, 1 );
  397. $option =
  398. $locale->text('Account')
  399. . " : $form->{accno} $form->{account_description}";
  400. }
  401. if ( $form->{gifi_accno} ) {
  402. $href .= "&gifi_accno=" . $form->escape( $form->{gifi_accno} );
  403. $callback .= "&gifi_accno=" . $form->escape( $form->{gifi_accno}, 1 );
  404. $option .= "\n<br>" if $option;
  405. $option .=
  406. $locale->text('GIFI')
  407. . " : $form->{gifi_accno} $form->{gifi_account_description}";
  408. }
  409. if ( $form->{source} ) {
  410. $href .= "&source=" . $form->escape( $form->{source} );
  411. $callback .= "&source=" . $form->escape( $form->{source}, 1 );
  412. $option .= "\n<br>" if $option;
  413. $option .= $locale->text('Source') . " : $form->{source}";
  414. }
  415. if ( $form->{memo} ) {
  416. $href .= "&memo=" . $form->escape( $form->{memo} );
  417. $callback .= "&memo=" . $form->escape( $form->{memo}, 1 );
  418. $option .= "\n<br>" if $option;
  419. $option .= $locale->text('Memo') . " : $form->{memo}";
  420. }
  421. if ( $form->{reference} ) {
  422. $href .= "&reference=" . $form->escape( $form->{reference} );
  423. $callback .= "&reference=" . $form->escape( $form->{reference}, 1 );
  424. $option .= "\n<br>" if $option;
  425. $option .= $locale->text('Reference') . " : $form->{reference}";
  426. }
  427. if ( $form->{department} ) {
  428. $href .= "&department=" . $form->escape( $form->{department} );
  429. $callback .= "&department=" . $form->escape( $form->{department}, 1 );
  430. ($department) = split /--/, $form->{department};
  431. $option .= "\n<br>" if $option;
  432. $option .= $locale->text('Department') . " : $department";
  433. }
  434. if ( $form->{description} ) {
  435. $href .= "&description=" . $form->escape( $form->{description} );
  436. $callback .= "&description=" . $form->escape( $form->{description}, 1 );
  437. $option .= "\n<br>" if $option;
  438. $option .= $locale->text('Description') . " : $form->{description}";
  439. }
  440. if ( $form->{notes} ) {
  441. $href .= "&notes=" . $form->escape( $form->{notes} );
  442. $callback .= "&notes=" . $form->escape( $form->{notes}, 1 );
  443. $option .= "\n<br>" if $option;
  444. $option .= $locale->text('Notes') . " : $form->{notes}";
  445. }
  446. if ( $form->{datefrom} ) {
  447. $href .= "&datefrom=$form->{datefrom}";
  448. $callback .= "&datefrom=$form->{datefrom}";
  449. $option .= "\n<br>" if $option;
  450. $option .=
  451. $locale->text('From') . " "
  452. . $locale->date( \%myconfig, $form->{datefrom}, 1 );
  453. }
  454. if ( $form->{dateto} ) {
  455. $href .= "&dateto=$form->{dateto}";
  456. $callback .= "&dateto=$form->{dateto}";
  457. if ( $form->{datefrom} ) {
  458. $option .= " ";
  459. }
  460. else {
  461. $option .= "\n<br>" if $option;
  462. }
  463. $option .=
  464. $locale->text('To') . " "
  465. . $locale->date( \%myconfig, $form->{dateto}, 1 );
  466. }
  467. if ( $form->{amountfrom} ) {
  468. $href .= "&amountfrom=$form->{amountfrom}";
  469. $callback .= "&amountfrom=$form->{amountfrom}";
  470. $option .= "\n<br>" if $option;
  471. $option .=
  472. $locale->text('Amount') . " >= "
  473. . $form->format_amount( \%myconfig, $form->{amountfrom}, 2 );
  474. }
  475. if ( $form->{amountto} ) {
  476. $href .= "&amountto=$form->{amountto}";
  477. $callback .= "&amountto=$form->{amountto}";
  478. if ( $form->{amountfrom} ) {
  479. $option .= " <= ";
  480. }
  481. else {
  482. $option .= "\n<br>" if $option;
  483. $option .= $locale->text('Amount') . " <= ";
  484. }
  485. $option .= $form->format_amount( \%myconfig, $form->{amountto}, 2 );
  486. }
  487. @columns =
  488. $form->sort_columns(
  489. qw(transdate id reference description notes source memo debit credit accno gifi_accno department)
  490. );
  491. pop @columns if $form->{department};
  492. if ( $form->{link} =~ /_paid/ ) {
  493. @columns =
  494. $form->sort_columns(
  495. qw(transdate id reference description notes source memo cleared debit credit accno gifi_accno)
  496. );
  497. $form->{l_cleared} = "Y";
  498. }
  499. if ( $form->{accno} || $form->{gifi_accno} ) {
  500. @columns = grep !/(accno|gifi_accno)/, @columns;
  501. push @columns, "balance";
  502. $form->{l_balance} = "Y";
  503. }
  504. foreach $item (@columns) {
  505. if ( $form->{"l_$item"} eq "Y" ) {
  506. push @column_index, $item;
  507. # add column to href and callback
  508. $callback .= "&l_$item=Y";
  509. $href .= "&l_$item=Y";
  510. }
  511. }
  512. if ( $form->{l_subtotal} eq 'Y' ) {
  513. $callback .= "&l_subtotal=Y";
  514. $href .= "&l_subtotal=Y";
  515. }
  516. $callback .= "&category=$form->{category}";
  517. $href .= "&category=$form->{category}";
  518. $column_header{id} =
  519. "<th><a class=listheading href=$href&sort=id>"
  520. . $locale->text('ID')
  521. . "</a></th>";
  522. $column_header{transdate} =
  523. "<th><a class=listheading href=$href&sort=transdate>"
  524. . $locale->text('Date')
  525. . "</a></th>";
  526. $column_header{reference} =
  527. "<th><a class=listheading href=$href&sort=reference>"
  528. . $locale->text('Reference')
  529. . "</a></th>";
  530. $column_header{source} =
  531. "<th><a class=listheading href=$href&sort=source>"
  532. . $locale->text('Source')
  533. . "</a></th>";
  534. $column_header{memo} =
  535. "<th><a class=listheading href=$href&sort=memo>"
  536. . $locale->text('Memo')
  537. . "</a></th>";
  538. $column_header{description} =
  539. "<th><a class=listheading href=$href&sort=description>"
  540. . $locale->text('Description')
  541. . "</a></th>";
  542. $column_header{department} =
  543. "<th><a class=listheading href=$href&sort=department>"
  544. . $locale->text('Department')
  545. . "</a></th>";
  546. $column_header{notes} =
  547. "<th class=listheading>" . $locale->text('Notes') . "</th>";
  548. $column_header{debit} =
  549. "<th class=listheading>" . $locale->text('Debit') . "</th>";
  550. $column_header{credit} =
  551. "<th class=listheading>" . $locale->text('Credit') . "</th>";
  552. $column_header{accno} =
  553. "<th><a class=listheading href=$href&sort=accno>"
  554. . $locale->text('Account')
  555. . "</a></th>";
  556. $column_header{gifi_accno} =
  557. "<th><a class=listheading href=$href&sort=gifi_accno>"
  558. . $locale->text('GIFI')
  559. . "</a></th>";
  560. $column_header{balance} = "<th>" . $locale->text('Balance') . "</th>";
  561. $column_header{cleared} = qq|<th>| . $locale->text('R') . qq|</th>|;
  562. $form->header;
  563. print qq|
  564. <body>
  565. <table width=100%>
  566. <tr>
  567. <th class=listtop>$form->{title}</th>
  568. </tr>
  569. <tr height="5"></tr>
  570. <tr>
  571. <td>$option</td>
  572. </tr>
  573. <tr>
  574. <td>
  575. <table width=100%>
  576. <tr class=listheading>
  577. |;
  578. for (@column_index) { print "$column_header{$_}\n" }
  579. print "
  580. </tr>
  581. ";
  582. # add sort to callback
  583. $form->{callback} = "$callback&sort=$form->{sort}";
  584. $callback = $form->escape( $form->{callback} );
  585. $cml = 1;
  586. # initial item for subtotals
  587. if ( @{ $form->{GL} } ) {
  588. $sameitem = $form->{GL}->[0]->{ $form->{sort} };
  589. $cml = -1 if $form->{contra};
  590. }
  591. if ( ( $form->{accno} || $form->{gifi_accno} ) && $form->{balance} ) {
  592. for (@column_index) { $column_data{$_} = "<td>&nbsp;</td>" }
  593. $column_data{balance} = "<td align=right>"
  594. . $form->format_amount( \%myconfig, $form->{balance} * $ml * $cml,
  595. 2, 0 )
  596. . "</td>";
  597. $i++;
  598. $i %= 2;
  599. print qq|
  600. <tr class=listrow$i>
  601. |;
  602. for (@column_index) { print "$column_data{$_}\n" }
  603. print qq|
  604. </tr>
  605. |;
  606. }
  607. # reverse href
  608. $direction = ( $form->{direction} eq 'ASC' ) ? "ASC" : "DESC";
  609. $form->sort_order();
  610. $href =~ s/direction=$form->{direction}/direction=$direction/;
  611. $i = 0;
  612. foreach $ref ( @{ $form->{GL} } ) {
  613. # if item ne sort print subtotal
  614. if ( $form->{l_subtotal} eq 'Y' ) {
  615. if ( $sameitem ne $ref->{ $form->{sort} } ) {
  616. &gl_subtotal;
  617. }
  618. }
  619. $form->{balance} += $ref->{amount};
  620. $subtotaldebit += $ref->{debit};
  621. $subtotalcredit += $ref->{credit};
  622. $totaldebit += $ref->{debit};
  623. $totalcredit += $ref->{credit};
  624. $ref->{debit} =
  625. $form->format_amount( \%myconfig, $ref->{debit}, 2, "&nbsp;" );
  626. $ref->{credit} =
  627. $form->format_amount( \%myconfig, $ref->{credit}, 2, "&nbsp;" );
  628. for (qw(id transdate)) { $column_data{$_} = "<td>$ref->{$_}</td>" }
  629. $column_data{reference} =
  630. "<td><a href=$ref->{module}.pl?action=edit&id=$ref->{id}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}&callback=$callback>$ref->{reference}</td>";
  631. $ref->{notes} =~ s/\r?\n/<br>/g;
  632. for (qw(description source memo notes department)) {
  633. $column_data{$_} = "<td>$ref->{$_}&nbsp;</td>";
  634. }
  635. $column_data{debit} = "<td align=right>$ref->{debit}</td>";
  636. $column_data{credit} = "<td align=right>$ref->{credit}</td>";
  637. $column_data{accno} =
  638. "<td><a href=$href&accno=$ref->{accno}&callback=$callback>$ref->{accno}</a> $ref->{accname}</td>";
  639. $column_data{gifi_accno} =
  640. "<td><a href=$href&gifi_accno=$ref->{gifi_accno}&callback=$callback>$ref->{gifi_accno}</a>&nbsp;</td>";
  641. $column_data{balance} = "<td align=right>"
  642. . $form->format_amount( \%myconfig, $form->{balance} * $ml * $cml,
  643. 2, 0 )
  644. . "</td>";
  645. $column_data{cleared} =
  646. ( $ref->{cleared} ) ? "<td>*</td>" : "<td>&nbsp;</td>";
  647. if ( $ref->{id} != $sameid ) {
  648. $i++;
  649. $i %= 2;
  650. }
  651. print "
  652. <tr class=listrow$i>";
  653. for (@column_index) { print "$column_data{$_}\n" }
  654. print "</tr>";
  655. $sameid = $ref->{id};
  656. }
  657. &gl_subtotal if ( $form->{l_subtotal} eq 'Y' );
  658. for (@column_index) { $column_data{$_} = "<td>&nbsp;</td>" }
  659. $column_data{debit} =
  660. "<th align=right class=listtotal>"
  661. . $form->format_amount( \%myconfig, $totaldebit, 2, "&nbsp;" ) . "</th>";
  662. $column_data{credit} =
  663. "<th align=right class=listtotal>"
  664. . $form->format_amount( \%myconfig, $totalcredit, 2, "&nbsp;" ) . "</th>";
  665. $column_data{balance} =
  666. "<th align=right class=listtotal>"
  667. . $form->format_amount( \%myconfig, $form->{balance} * $ml * $cml, 2, 0 )
  668. . "</th>";
  669. print qq|
  670. <tr class=listtotal>
  671. |;
  672. for (@column_index) { print "$column_data{$_}\n" }
  673. $i = 1;
  674. if ( $myconfig{acs} !~ /General Ledger--General Ledger/ ) {
  675. $button{'General Ledger--Add Transaction'}{code} =
  676. qq|<button class="submit" type="submit" name="action" value="gl_transaction">|
  677. . $locale->text('GL Transaction')
  678. . qq|</button> |;
  679. $button{'General Ledger--Add Transaction'}{order} = $i++;
  680. }
  681. if ( $myconfig{acs} !~ /AR--AR/ ) {
  682. $button{'AR--Add Transaction'}{code} =
  683. qq|<button class="submit" type="submit" name="action" value="ar_transaction">|
  684. . $locale->text('AR Transaction')
  685. . qq|</button> |;
  686. $button{'AR--Add Transaction'}{order} = $i++;
  687. $button{'AR--Sales Invoice'}{code} =
  688. qq|<button class="submit" type="submit" name="action" value="sales_invoice_">|
  689. . $locale->text('Sales Invoice')
  690. . qq|</button> |;
  691. $button{'AR--Sales Invoice'}{order} = $i++;
  692. }
  693. if ( $myconfig{acs} !~ /AP--AP/ ) {
  694. $button{'AP--Add Transaction'}{code} =
  695. qq|<button class="submit" type="submit" name="action" value="ap_transaction">|
  696. . $locale->text('AP Transaction')
  697. . qq|</button> |;
  698. $button{'AP--Add Transaction'}{order} = $i++;
  699. $button{'AP--Vendor Invoice'}{code} =
  700. qq|<button class="submit" type="submit" name="action" value="vendor_invoice_">|
  701. . $locale->text('Vendor Invoice')
  702. . qq|</button> |;
  703. $button{'AP--Vendor Invoice'}{order} = $i++;
  704. }
  705. foreach $item ( split /;/, $myconfig{acs} ) {
  706. delete $button{$item};
  707. }
  708. print qq|
  709. </tr>
  710. </table>
  711. </td>
  712. </tr>
  713. <tr>
  714. <td><hr size=3 noshade></td>
  715. </tr>
  716. </table>
  717. <br>
  718. <form method=post action=$form->{script}>
  719. |;
  720. $form->hide_form(qw(callback path login sessionid));
  721. foreach $item ( sort { $a->{order} <=> $b->{order} } %button ) {
  722. print $item->{code};
  723. }
  724. if ( $form->{lynx} ) {
  725. require "bin/menu.pl";
  726. &menubar;
  727. }
  728. print qq|
  729. </form>
  730. </body>
  731. </html>
  732. |;
  733. }
  734. sub gl_subtotal {
  735. $subtotaldebit =
  736. $form->format_amount( \%myconfig, $subtotaldebit, 2, "&nbsp;" );
  737. $subtotalcredit =
  738. $form->format_amount( \%myconfig, $subtotalcredit, 2, "&nbsp;" );
  739. for (@column_index) { $column_data{$_} = "<td>&nbsp;</td>" }
  740. $column_data{debit} =
  741. "<th align=right class=listsubtotal>$subtotaldebit</td>";
  742. $column_data{credit} =
  743. "<th align=right class=listsubtotal>$subtotalcredit</td>";
  744. print "<tr class=listsubtotal>";
  745. for (@column_index) { print "$column_data{$_}\n" }
  746. print "</tr>";
  747. $subtotaldebit = 0;
  748. $subtotalcredit = 0;
  749. $sameitem = $ref->{ $form->{sort} };
  750. }
  751. sub update {
  752. if ( $form->{transdate} ne $form->{oldtransdate} ) {
  753. if ( $form->{selectprojectnumber} ) {
  754. $form->all_projects( \%myconfig, undef, $form->{transdate} );
  755. if ( @{ $form->{all_project} } ) {
  756. $form->{selectprojectnumber} = "<option>\n";
  757. for ( @{ $form->{all_project} } ) {
  758. $form->{selectprojectnumber} .=
  759. qq|<option value="$_->{projectnumber}--$_->{id}">$_->{projectnumber}\n|;
  760. }
  761. $form->{selectprojectnumber} =
  762. $form->escape( $form->{selectprojectnumber}, 1 );
  763. }
  764. }
  765. $form->{oldtransdate} = $form->{transdate};
  766. }
  767. @a = ();
  768. $count = 0;
  769. @flds = qw(accno debit credit projectnumber fx_transaction source memo);
  770. for $i ( 1 .. $form->{rowcount} ) {
  771. unless ( ( $form->{"debit_$i"} eq "" )
  772. && ( $form->{"credit_$i"} eq "" ) )
  773. {
  774. for (qw(debit credit)) {
  775. $form->{"${_}_$i"} =
  776. $form->parse_amount( \%myconfig, $form->{"${_}_$i"} );
  777. }
  778. push @a, {};
  779. $j = $#a;
  780. for (@flds) { $a[$j]->{$_} = $form->{"${_}_$i"} }
  781. $count++;
  782. }
  783. }
  784. for $i ( 1 .. $count ) {
  785. $j = $i - 1;
  786. for (@flds) { $form->{"${_}_$i"} = $a[$j]->{$_} }
  787. }
  788. for $i ( $count + 1 .. $form->{rowcount} ) {
  789. for (@flds) { delete $form->{"${_}_$i"} }
  790. }
  791. $form->{rowcount} = $count + 1;
  792. &display_form;
  793. }
  794. sub display_form {
  795. my ($init) = @_;
  796. &form_header;
  797. &display_rows($init);
  798. &form_footer;
  799. }
  800. sub display_rows {
  801. my ($init) = @_;
  802. $form->{selectprojectnumber} =
  803. $form->unescape( $form->{selectprojectnumber} )
  804. if $form->{selectprojectnumber};
  805. $form->{totaldebit} = 0;
  806. $form->{totalcredit} = 0;
  807. for $i ( 1 .. $form->{rowcount} ) {
  808. $source = qq|
  809. <td><input name="source_$i" size=10 value="$form->{"source_$i"}"></td>|;
  810. $memo = qq|
  811. <td><input name="memo_$i" value="$form->{"memo_$i"}"></td>|;
  812. if ($init) {
  813. $accno = qq|
  814. <td><select name="accno_$i">$form->{selectaccno}</select></td>|;
  815. if ( $form->{selectprojectnumber} ) {
  816. $project = qq|
  817. <td><select name="projectnumber_$i">$form->{selectprojectnumber}</select></td>|;
  818. }
  819. if ( $form->{transfer} ) {
  820. $fx_transaction = qq|
  821. <td><input name="fx_transaction_$i" class=checkbox type=checkbox value=1></td>
  822. |;
  823. }
  824. }
  825. else {
  826. $form->{totaldebit} += $form->{"debit_$i"};
  827. $form->{totalcredit} += $form->{"credit_$i"};
  828. for (qw(debit credit)) {
  829. $form->{"${_}_$i"} =
  830. ( $form->{"${_}_$i"} )
  831. ? $form->format_amount( \%myconfig, $form->{"${_}_$i"}, 2 )
  832. : "";
  833. }
  834. if ( $i < $form->{rowcount} ) {
  835. $accno = qq|<td>$form->{"accno_$i"}</td>|;
  836. if ( $form->{selectprojectnumber} ) {
  837. $form->{"projectnumber_$i"} = ""
  838. if $form->{selectprojectnumber} !~
  839. /$form->{"projectnumber_$i"}/;
  840. $project = $form->{"projectnumber_$i"};
  841. $project =~ s/--.*//;
  842. $project = qq|<td>$project</td>|;
  843. }
  844. if ( $form->{transfer} ) {
  845. $checked = ( $form->{"fx_transaction_$i"} ) ? "1" : "";
  846. $x = ($checked) ? "x" : "";
  847. $fx_transaction = qq|
  848. <td><input type=hidden name="fx_transaction_$i" value="$checked">$x</td>
  849. |;
  850. }
  851. $form->hide_form( "accno_$i", "projectnumber_$i" );
  852. }
  853. else {
  854. $accno = qq|
  855. <td><select name="accno_$i">$form->{selectaccno}</select></td>|;
  856. if ( $form->{selectprojectnumber} ) {
  857. $project = qq|
  858. <td><select name="projectnumber_$i">$form->{selectprojectnumber}</select></td>|;
  859. }
  860. if ( $form->{transfer} ) {
  861. $fx_transaction = qq|
  862. <td><input name="fx_transaction_$i" class=checkbox type=checkbox value=1></td>
  863. |;
  864. }
  865. }
  866. }
  867. print qq|<tr valign=top>
  868. $accno
  869. $fx_transaction
  870. <td><input name="debit_$i" size=12 value="$form->{"debit_$i"}" accesskey=$i></td>
  871. <td><input name="credit_$i" size=12 value=$form->{"credit_$i"}></td>
  872. $source
  873. $memo
  874. $project
  875. </tr>
  876. |;
  877. }
  878. $form->hide_form(qw(rowcount selectaccno pos_adjust));
  879. print qq|
  880. <input type=hidden name=selectprojectnumber value="|
  881. . $form->escape( $form->{selectprojectnumber}, 1 ) . qq|">|;
  882. }
  883. sub form_header {
  884. $title = $form->{title};
  885. if ( $form->{transfer} ) {
  886. $form->{title} = $locale->text("$title Cash Transfer Transaction");
  887. }
  888. else {
  889. $form->{title} = $locale->text("$title General Ledger Transaction");
  890. }
  891. # $locale->text('Add Cash Transfer Transaction')
  892. # $locale->text('Edit Cash Transfer Transaction')
  893. # $locale->text('Add General Ledger Transaction')
  894. # $locale->text('Edit General Ledger Transaction')
  895. $form->{selectdepartment} = $form->unescape( $form->{selectdepartment} );
  896. $form->{selectdepartment} =~ s/ selected//;
  897. $form->{selectdepartment} =~
  898. s/(<option value="\Q$form->{department}\E")/$1 selected/;
  899. for (qw(reference description notes)) {
  900. $form->{$_} = $form->quote( $form->{$_} );
  901. }
  902. if ( ( $rows = $form->numtextrows( $form->{description}, 50 ) ) > 1 ) {
  903. $description =
  904. qq|<textarea name=description rows=$rows cols=50 wrap=soft>$form->{description}</textarea>|;
  905. }
  906. else {
  907. $description =
  908. qq|<input name=description size=50 value="$form->{description}">|;
  909. }
  910. if ( ( $rows = $form->numtextrows( $form->{notes}, 50 ) ) > 1 ) {
  911. $notes =
  912. qq|<textarea name=notes rows=$rows cols=50 wrap=soft>$form->{notes}</textarea>|;
  913. }
  914. else {
  915. $notes = qq|<input name=notes size=50 value="$form->{notes}">|;
  916. }
  917. $department = qq|
  918. <tr>
  919. <th align=right nowrap>| . $locale->text('Department') . qq|</th>
  920. <td><select name=department>$form->{selectdepartment}</select></td>
  921. <input type=hidden name=selectdepartment value="|
  922. . $form->escape( $form->{selectdepartment}, 1 ) . qq|">
  923. </tr>
  924. | if $form->{selectdepartment};
  925. $project = qq|
  926. <th class=listheading>| . $locale->text('Project') . qq|</th>
  927. | if $form->{selectprojectnumber};
  928. if ( $form->{transfer} ) {
  929. $fx_transaction = qq|
  930. <th class=listheading>| . $locale->text('FX') . qq|</th>
  931. |;
  932. }
  933. $focus = ( $form->{focus} ) ? $form->{focus} : "debit_$form->{rowcount}";
  934. $form->header;
  935. print qq|
  936. <body onload="document.forms[0].${focus}.focus()" />
  937. <form method=post action=$form->{script}>
  938. |;
  939. $form->hide_form(
  940. qw(id transfer selectaccno closedto locked oldtransdate recurring));
  941. print qq|
  942. <input type=hidden name=title value="$title">
  943. <table width=100%>
  944. <tr>
  945. <th class=listtop>$form->{title}</th>
  946. </tr>
  947. <tr height="5"></tr>
  948. <tr>
  949. <td>
  950. <table>
  951. <tr>
  952. <th align=right>| . $locale->text('Reference') . qq|</th>
  953. <td><input name=reference size=20 value="$form->{reference}"></td>
  954. <th align=right>| . $locale->text('Date') . qq|</th>
  955. <td><input name=transdate size=11 title="$myconfig{dateformat}" value=$form->{transdate}></td>
  956. </tr>
  957. $department
  958. <tr>
  959. <th align=right>| . $locale->text('Description') . qq|</th>
  960. <td colspan=3>$description</td>
  961. </tr>
  962. <tr>
  963. <th align=right>| . $locale->text('Notes') . qq|</th>
  964. <td colspan=3>$notes</td>
  965. </tr>
  966. </table>
  967. </td>
  968. </tr>
  969. <tr>
  970. <td>
  971. <table width=100%>
  972. <tr class=listheading>
  973. <th class=listheading>| . $locale->text('Account') . qq|</th>
  974. $fx_transaction
  975. <th class=listheading>| . $locale->text('Debit') . qq|</th>
  976. <th class=listheading>| . $locale->text('Credit') . qq|</th>
  977. <th class=listheading>| . $locale->text('Source') . qq|</th>
  978. <th class=listheading>| . $locale->text('Memo') . qq|</th>
  979. $project
  980. </tr>
  981. |;
  982. }
  983. sub form_footer {
  984. for (qw(totaldebit totalcredit)) {
  985. $form->{$_} =
  986. $form->format_amount( \%myconfig, $form->{$_}, 2, "&nbsp;" );
  987. }
  988. $project = qq|
  989. <th>&nbsp;</th>
  990. | if $form->{selectprojectnumber};
  991. if ( $form->{transfer} ) {
  992. $fx_transaction = qq|
  993. <th>&nbsp;</th>
  994. |;
  995. }
  996. print qq|
  997. <tr class=listtotal>
  998. <th>&nbsp;</th>
  999. $fx_transaction
  1000. <th class=listtotal align=right>$form->{totaldebit}</th>
  1001. <th class=listtotal align=right>$form->{totalcredit}</th>
  1002. <th>&nbsp;</th>
  1003. <th>&nbsp;</th>
  1004. $project
  1005. </tr>
  1006. </table>
  1007. </td>
  1008. </tr>
  1009. <tr>
  1010. <td><hr size=3 noshade></td>
  1011. </tr>
  1012. </table>
  1013. |;
  1014. $form->hide_form(qw(path login sessionid callback));
  1015. $transdate = $form->datetonum( \%myconfig, $form->{transdate} );
  1016. $closedto = $form->datetonum( \%myconfig, $form->{closedto} );
  1017. # type=submit $locale->text('Update')
  1018. # type=submit $locale->text('Post')
  1019. # type=submit $locale->text('Schedule')
  1020. # type=submit $locale->text('Post as new')
  1021. # type=submit $locale->text('Delete')
  1022. if ( !$form->{readonly} ) {
  1023. %button = (
  1024. 'update' =>
  1025. { ndx => 1, key => 'U', value => $locale->text('Update') },
  1026. 'post' => { ndx => 3, key => 'O', value => $locale->text('Post') },
  1027. 'post_as_new' =>
  1028. { ndx => 6, key => 'N', value => $locale->text('Post as new') },
  1029. 'schedule' =>
  1030. { ndx => 7, key => 'H', value => $locale->text('Schedule') },
  1031. 'delete' =>
  1032. { ndx => 8, key => 'D', value => $locale->text('Delete') },
  1033. );
  1034. %a = ();
  1035. if ( $form->{id} ) {
  1036. for ( 'update', 'post_as_new', 'schedule' ) { $a{$_} = 1 }
  1037. if ( !$form->{locked} ) {
  1038. if ( $transdate > $closedto ) {
  1039. for ( 'post', 'delete' ) { $a{$_} = 1 }
  1040. }
  1041. }
  1042. }
  1043. else {
  1044. if ( $transdate > $closedto ) {
  1045. for ( "update", "post", "schedule" ) { $a{$_} = 1 }
  1046. }
  1047. }
  1048. for ( keys %button ) { delete $button{$_} if !$a{$_} }
  1049. for ( sort { $button{$a}->{ndx} <=> $button{$b}->{ndx} } keys %button )
  1050. {
  1051. $form->print_button( \%button, $_ );
  1052. }
  1053. }
  1054. if ( $form->{recurring} ) {
  1055. print qq|<div align=right>| . $locale->text('Scheduled') . qq|</div>|;
  1056. }
  1057. if ( $form->{lynx} ) {
  1058. require "bin/menu.pl";
  1059. &menubar;
  1060. }
  1061. print qq|
  1062. </form>
  1063. </body>
  1064. </html>
  1065. |;
  1066. }
  1067. sub delete {
  1068. $form->header;
  1069. print qq|
  1070. <body>
  1071. <form method=post action=$form->{script}>
  1072. |;
  1073. delete $form->{action};
  1074. $form->hide_form;
  1075. print qq|
  1076. <h2 class=confirm>| . $locale->text('Confirm!') . qq|</h2>
  1077. <h4>|
  1078. . $locale->text( 'Are you sure you want to delete Transaction [_1]',
  1079. $form->{reference} )
  1080. . qq|</h4>
  1081. <button name="action" class="submit" type="submit" value="yes">|
  1082. . $locale->text('Yes')
  1083. . qq|</button>
  1084. </form>
  1085. |;
  1086. }
  1087. sub yes {
  1088. if ( GL->delete_transaction( \%myconfig, \%$form ) ) {
  1089. $form->redirect( $locale->text('Transaction deleted!') );
  1090. }
  1091. else {
  1092. $form->error( $locale->text('Cannot delete transaction!') );
  1093. }
  1094. }
  1095. sub post {
  1096. $form->isblank( "transdate", $locale->text('Transaction Date missing!') );
  1097. $transdate = $form->datetonum( \%myconfig, $form->{transdate} );
  1098. $closedto = $form->datetonum( \%myconfig, $form->{closedto} );
  1099. $form->error(
  1100. $locale->text('Cannot post transaction for a closed period!') )
  1101. if ( $transdate <= $closedto );
  1102. # add up debits and credits
  1103. for $i ( 1 .. $form->{rowcount} ) {
  1104. $dr = $form->parse_amount( \%myconfig, $form->{"debit_$i"} );
  1105. $cr = $form->parse_amount( \%myconfig, $form->{"credit_$i"} );
  1106. if ( $dr && $cr ) {
  1107. $form->error(
  1108. $locale->text(
  1109. 'Cannot post transaction with a debit and credit entry for the same account!'
  1110. )
  1111. );
  1112. }
  1113. $debit += $dr;
  1114. $credit += $cr;
  1115. }
  1116. if ( $form->round_amount( $debit, 2 ) != $form->round_amount( $credit, 2 ) )
  1117. {
  1118. $form->error( $locale->text('Out of balance transaction!') );
  1119. }
  1120. if ( !$form->{repost} ) {
  1121. if ( $form->{id} ) {
  1122. &repost;
  1123. exit;
  1124. }
  1125. }
  1126. if ( GL->post_transaction( \%myconfig, \%$form ) ) {
  1127. $form->redirect( $locale->text('Transaction posted!') );
  1128. }
  1129. else {
  1130. $form->error( $locale->text('Cannot post transaction!') );
  1131. }
  1132. }