summaryrefslogtreecommitdiff
path: root/bin/ca.pl
blob: 1c8a91215f2ef630cce218aa8cb5de46f1c6fd65 (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. # module for Chart of Accounts, Income Statement and Balance Sheet
  44. # search and edit transactions posted by the GL, AR and AP
  45. #
  46. #======================================================================
  47. use LedgerSMB::CA;
  48. 1;
  49. # end of main
  50. # this is for our long dates
  51. # $locale->text('January')
  52. # $locale->text('February')
  53. # $locale->text('March')
  54. # $locale->text('April')
  55. # $locale->text('May ')
  56. # $locale->text('June')
  57. # $locale->text('July')
  58. # $locale->text('August')
  59. # $locale->text('September')
  60. # $locale->text('October')
  61. # $locale->text('November')
  62. # $locale->text('December')
  63. # this is for our short month
  64. # $locale->text('Jan')
  65. # $locale->text('Feb')
  66. # $locale->text('Mar')
  67. # $locale->text('Apr')
  68. # $locale->text('May')
  69. # $locale->text('Jun')
  70. # $locale->text('Jul')
  71. # $locale->text('Aug')
  72. # $locale->text('Sep')
  73. # $locale->text('Oct')
  74. # $locale->text('Nov')
  75. # $locale->text('Dec')
  76. sub chart_of_accounts {
  77. CA->all_accounts( \%myconfig, \%$form );
  78. @column_index = qw(accno gifi_accno description debit credit);
  79. $column_header{accno} =
  80. qq|<th class="listtop">| . $locale->text('Account') . qq|</th>\n|;
  81. $column_header{gifi_accno} =
  82. qq|<th class="listtop">| . $locale->text('GIFI') . qq|</th>\n|;
  83. $column_header{description} =
  84. qq|<th class="listtop">| . $locale->text('Description') . qq|</th>\n|;
  85. $column_header{debit} =
  86. qq|<th class="listtop">| . $locale->text('Debit') . qq|</th>\n|;
  87. $column_header{credit} =
  88. qq|<th class="listtop">| . $locale->text('Credit') . qq|</th>\n|;
  89. $form->{title} = $locale->text('Chart of Accounts');
  90. $colspan = $#column_index + 1;
  91. $form->header;
  92. print qq|
  93. <body>
  94. <table border="0" width="100%">
  95. <tr><th class="listtop" colspan="$colspan">$form->{title}</th></tr>
  96. <tr height="5"></tr>
  97. <tr class="listheading">|;
  98. for (@column_index) { print $column_header{$_} }
  99. print qq|
  100. </tr>
  101. |;
  102. foreach $ca ( @{ $form->{CA} } ) {
  103. $description = $form->escape( $ca->{description} );
  104. $gifi_description = $form->escape( $ca->{gifi_description} );
  105. $href =
  106. qq|$form->{script}?path=$form->{path}&action=list&accno=$ca->{accno}&login=$form->{login}&sessionid=$form->{sessionid}&description=$description&gifi_accno=$ca->{gifi_accno}&gifi_description=$gifi_description|;
  107. if ( $ca->{charttype} eq "H" ) {
  108. print qq|<tr class=listheading>|;
  109. for (qw(accno description)) {
  110. $column_data{$_} = qq|<th class="listheading">$ca->{$_}</th>|;
  111. }
  112. $column_data{gifi_accno} =
  113. qq|<th class="listheading">$ca->{gifi_accno}&nbsp;</th>|;
  114. }
  115. else {
  116. $i++;
  117. $i %= 2;
  118. print qq|<tr class="listrow$i">|;
  119. $column_data{accno} = qq|<td><a href="$href">$ca->{accno}</a></td>|;
  120. $column_data{gifi_accno} =
  121. qq|<td><a href="$href&accounttype=gifi">$ca->{gifi_accno}</a>&nbsp;</td>|;
  122. $column_data{description} = "<td>$ca->{description}</td>";
  123. }
  124. $column_data{debit} =
  125. '<td align="right">'
  126. . $form->format_amount( \%myconfig, $ca->{debit}, 2, "&nbsp;" )
  127. . "</td>\n";
  128. $column_data{credit} =
  129. '<td align="right">'
  130. . $form->format_amount( \%myconfig, $ca->{credit}, 2, "&nbsp;" )
  131. . "</td>\n";
  132. $totaldebit += $ca->{debit};
  133. $totalcredit += $ca->{credit};
  134. for (@column_index) { print "$column_data{$_}\n" }
  135. print qq|
  136. </tr>
  137. |;
  138. }
  139. for (qw(accno gifi_accno description)) {
  140. $column_data{$_} = "<td>&nbsp;</td>";
  141. }
  142. $column_data{debit} =
  143. '<th align="right" class="listtotal">'
  144. . $form->format_amount( \%myconfig, $totaldebit, 2, 0 ) . "</th>";
  145. $column_data{credit} =
  146. '<th align="right" class="listtotal">'
  147. . $form->format_amount( \%myconfig, $totalcredit, 2, 0 ) . "</th>";
  148. print '<tr class="listtotal">';
  149. for (@column_index) { print "$column_data{$_}\n" }
  150. print qq|
  151. </tr>
  152. <tr>
  153. <td colspan="$colspan"><hr size="3" noshade></td>
  154. </tr>
  155. </table>
  156. </body>
  157. </html>
  158. |;
  159. }
  160. sub list {
  161. $form->{title} = $locale->text('List Transactions');
  162. if ( $form->{accounttype} eq 'gifi' ) {
  163. $form->{title} .= " - "
  164. . $locale->text('GIFI')
  165. . " $form->{gifi_accno} - $form->{gifi_description}";
  166. }
  167. else {
  168. $form->{title} .= " - "
  169. . $locale->text('Account')
  170. . " $form->{accno} - $form->{description}";
  171. }
  172. # get departments
  173. $form->all_departments( \%myconfig );
  174. if ( @{ $form->{all_department} } ) {
  175. $form->{selectdepartment} = "<option>\n";
  176. for ( @{ $form->{all_department} } ) {
  177. $form->{selectdepartment} .=
  178. qq|<option value="$_->{description}--$_->{id}">$_->{description}\n|;
  179. }
  180. }
  181. $department = qq|
  182. <tr>
  183. <th align="right" nowrap>| . $locale->text('Department') . qq|</th>
  184. <td colspan="3"><select name="department">$form->{selectdepartment}</select></td>
  185. </tr>
  186. | if $form->{selectdepartment};
  187. if ( @{ $form->{all_years} } ) {
  188. # accounting years
  189. $form->{selectaccountingyear} = "<option>\n";
  190. for ( @{ $form->{all_years} } ) {
  191. $form->{selectaccountingyear} .= qq|<option>$_\n|;
  192. }
  193. $form->{selectaccountingmonth} = "<option>\n";
  194. for ( sort keys %{ $form->{all_month} } ) {
  195. $form->{selectaccountingmonth} .=
  196. qq|<option value="$_">|
  197. . $locale->text( $form->{all_month}{$_} ) . qq|\n|;
  198. }
  199. $selectfrom = qq|
  200. <tr>
  201. <th align="right">| . $locale->text('Period') . qq|</th>
  202. <td colspan="3">
  203. <select name="month">$form->{selectaccountingmonth}</select>
  204. <select name="year">$form->{selectaccountingyear}</select>
  205. <input name="interval" class="radio" type="radio" value="0" checked>&nbsp;|
  206. . $locale->text('Current') . qq|
  207. <input name="interval" class="radio" type="radio" value="1">&nbsp;|
  208. . $locale->text('Month') . qq|
  209. <input name="interval" class="radio" type="radio" value="3">&nbsp;|
  210. . $locale->text('Quarter') . qq|
  211. <input name="interval" class="radio" type="radio" value="12">&nbsp;|
  212. . $locale->text('Year') . qq|
  213. </td>
  214. </tr>
  215. |;
  216. }
  217. $form->header;
  218. print qq|
  219. <body>
  220. <form method="post" action="$form->{script}">
  221. <input type="hidden" name="accno" value="$form->{accno}">
  222. <input type="hidden" name="description" value="$form->{description}">
  223. <input type="hidden" name="sort" value="transdate">
  224. <input type="hidden" name="oldsort" value="transdate">
  225. <input type="hidden" name="accounttype" value="$form->{accounttype}">
  226. <input type="hidden" name="gifi_accno" value="$form->{gifi_accno}">
  227. <input type="hidden" name="gifi_description" value="$form->{gifi_description}">
  228. <table border="0" width="100%">
  229. <tr><th class="listtop">$form->{title}</th></tr>
  230. <tr height="5"></tr>
  231. <tr valign="top">
  232. <td>
  233. <table>
  234. $department
  235. <tr>
  236. <th align="right">| . $locale->text('From') . qq|</th>
  237. <td><input name="fromdate" size="11" title="$myconfig{dateformat}"></td>
  238. <th align="right">| . $locale->text('To') . qq|</th>
  239. <td><input name="todate" size="11" title="$myconfig{dateformat}"></td>
  240. </tr>
  241. $selectfrom
  242. <tr>
  243. <th align="right">| . $locale->text('Include in Report') . qq|</th>
  244. <td colspan="3">
  245. <input name="l_accno" class="checkbox" type="checkbox" value="Y">&nbsp;|
  246. . $locale->text('AR/AP') . qq|
  247. <input name="l_subtotal" class="checkbox" type="checkbox" value="Y">&nbsp;|
  248. . $locale->text('Subtotal') . qq|
  249. </td>
  250. </tr>
  251. </table>
  252. </td>
  253. </tr>
  254. <tr><td><hr size="3" noshade></td></tr>
  255. </table>
  256. <input type="hidden" name="login" value="$form->{login}">
  257. <input type="hidden" name="path" value="$form->{path}">
  258. <input type="hidden" name="sessionid" value="$form->{sessionid}">
  259. <br><button class="submit" type="submit" name="action" value="list_transactions">|
  260. . $locale->text('List Transactions')
  261. . qq|</button>
  262. </form>
  263. </body>
  264. </html>
  265. |;
  266. }
  267. sub list_transactions {
  268. CA->all_transactions( \%myconfig, \%$form );
  269. $department = $form->escape( $form->{department} );
  270. $projectnumber = $form->escape( $form->{projectnumber} );
  271. $title = $form->escape( $form->{title} );
  272. # construct href
  273. $href =
  274. "$form->{script}?action=list_transactions&department=$department&projectnumber=$projectnumber&title=$title";
  275. for (
  276. qw(path oldsort accno login sessionid fromdate todate accounttype gifi_accno l_heading l_subtotal l_accno)
  277. )
  278. {
  279. $href .= "&$_=$form->{$_}";
  280. }
  281. $drilldown = $href;
  282. $drilldown .= "&sort=$form->{sort}";
  283. $href .= "&direction=$form->{direction}";
  284. $form->sort_order();
  285. $drilldown .= "&direction=$form->{direction}";
  286. $form->{prevreport} = $href unless $form->{prevreport};
  287. $href .= "&prevreport=" . $form->escape( $form->{prevreport} );
  288. $drilldown .= "&prevreport=" . $form->escape( $form->{prevreport} );
  289. # figure out which column comes first
  290. $column_header{transdate} =
  291. qq|<th><a class="listheading" href="$href&sort=transdate">|
  292. . $locale->text('Date')
  293. . qq|</a></th>|;
  294. $column_header{reference} =
  295. qq|<th><a class="listheading" href="$href&sort=reference">|
  296. . $locale->text('Reference')
  297. . qq|</a></th>|;
  298. $column_header{description} =
  299. qq|<th><a class="listheadine" href="$href&sort=description">|
  300. . $locale->text('Description')
  301. . qq|</a></th>|;
  302. $column_header{cleared} =
  303. qq|<th class="listheading">| . $locale->text('R') . qq|</th>|;
  304. $column_header{source} =
  305. qq|<th class="listheading">| . $locale->text('Source') . qq|</th>|;
  306. $column_header{debit} =
  307. qq|<th class="listheading">| . $locale->text('Debit') . qq|</th>|;
  308. $column_header{credit} =
  309. qq|<th class="listheading">| . $locale->text('Credit') . qq|</th>|;
  310. $column_header{balance} =
  311. qq|<th class="listheading">| . $locale->text('Balance') . qq|</th>|;
  312. $column_header{accno} =
  313. qq|<th class="listheading">| . $locale->text('AR/AP') . qq|</th>|;
  314. @columns = qw(transdate reference description debit credit);
  315. if ( $form->{link} =~ /_paid/ ) {
  316. @columns =
  317. qw(transdate reference description source cleared debit credit);
  318. }
  319. push @columns, "accno" if $form->{l_accno};
  320. @column_index = $form->sort_columns(@columns);
  321. if ( $form->{accounttype} eq 'gifi' ) {
  322. for (qw(accno description)) { $form->{$_} = $form->{"gifi_$_"} }
  323. }
  324. if ( $form->{accno} ) {
  325. push @column_index, "balance";
  326. }
  327. $form->{title} =
  328. ( $form->{accounttype} eq 'gifi' )
  329. ? $locale->text('GIFI')
  330. : $locale->text('Account');
  331. $form->{title} .= " $form->{accno} - $form->{description}";
  332. if ( $form->{department} ) {
  333. ($department) = split /--/, $form->{department};
  334. $options = $locale->text('Department') . " : $department<br>";
  335. }
  336. if ( $form->{projectnumber} ) {
  337. ($projectnumber) = split /--/, $form->{projectnumber};
  338. $options .= $locale->text('Project Number') . " : $projectnumber<br>";
  339. }
  340. if ( $form->{fromdate} || $form->{todate} ) {
  341. if ( $form->{fromdate} ) {
  342. $fromdate = $locale->date( \%myconfig, $form->{fromdate}, 1 );
  343. }
  344. if ( $form->{todate} ) {
  345. $todate = $locale->date( \%myconfig, $form->{todate}, 1 );
  346. }
  347. $form->{period} = "$fromdate - $todate";
  348. }
  349. else {
  350. $form->{period} =
  351. $locale->date( \%myconfig, $form->current_date( \%myconfig ), 1 );
  352. }
  353. $form->{period} = qq|<a href="$form->{prevreport}">$form->{period}</a>|
  354. if $form->{prevreport};
  355. $options .= $form->{period};
  356. # construct callback
  357. $department = $form->escape( $form->{department}, 1 );
  358. $projectnumber = $form->escape( $form->{projectnumber}, 1 );
  359. $title = $form->escape( $form->{title}, 1 );
  360. $form->{prevreport} = $form->escape( $form->{prevreport}, 1 );
  361. $form->{callback} =
  362. "$form->{script}?action=list_transactions&department=$department&projectnumber=$projectnumber&title=$title";
  363. for (
  364. qw(path direction oldsort accno login sessionid fromdate todate accounttype gifi_accno l_heading l_subtotal l_accno prevreport)
  365. )
  366. {
  367. $form->{callback} .= "&$_=$form->{$_}";
  368. }
  369. $form->header;
  370. print qq|
  371. <body>
  372. <table width="100%">
  373. <tr>
  374. <th class="listtop">$form->{title}</th>
  375. </tr>
  376. <tr height="5"></tr>
  377. <tr>
  378. <td>$options</td>
  379. </tr>
  380. <tr>
  381. <td>
  382. <table width="100%">
  383. <tr class="listheading">
  384. |;
  385. for (@column_index) { print "$column_header{$_}\n" }
  386. print qq|
  387. </tr>
  388. |;
  389. # add sort to callback
  390. $form->{callback} =
  391. $form->escape( $form->{callback} . "&sort=$form->{sort}" );
  392. if ( @{ $form->{CA} } ) {
  393. $sameitem = $form->{CA}->[0]->{ $form->{sort} };
  394. }
  395. $ml = ( $form->{category} =~ /(A|E)/ ) ? -1 : 1;
  396. $ml *= -1 if $form->{contra};
  397. if ( $form->{accno} && $form->{balance} ) {
  398. for (@column_index) { $column_data{$_} = "<td>&nbsp;</td>" }
  399. $column_data{balance} =
  400. '<td align="right">'
  401. . $form->format_amount( \%myconfig, $form->{balance} * $ml, 2, 0 )
  402. . "</td>";
  403. $i++;
  404. $i %= 2;
  405. print qq|
  406. <tr class="listrow$i">
  407. |;
  408. for (@column_index) { print "$column_data{$_}\n" }
  409. print qq|
  410. </tr>
  411. |;
  412. }
  413. foreach $ca ( @{ $form->{CA} } ) {
  414. if ( $form->{l_subtotal} eq 'Y' ) {
  415. if ( $sameitem ne $ca->{ $form->{sort} } ) {
  416. &ca_subtotal;
  417. }
  418. }
  419. # construct link to source
  420. $href =
  421. "<a href=$ca->{module}.pl?path=$form->{path}&action=edit&id=$ca->{id}&login=$form->{login}&sessionid=$form->{sessionid}&callback=$form->{callback}>$ca->{reference}</a>";
  422. $column_data{debit} =
  423. '<td align="right">'
  424. . $form->format_amount( \%myconfig, $ca->{debit}, 2, "&nbsp;" )
  425. . "</td>";
  426. $column_data{credit} =
  427. '<td align="right">'
  428. . $form->format_amount( \%myconfig, $ca->{credit}, 2, "&nbsp;" )
  429. . "</td>";
  430. $form->{balance} += $ca->{amount};
  431. $column_data{balance} =
  432. '<td align="right">'
  433. . $form->format_amount( \%myconfig, $form->{balance} * $ml, 2, 0 )
  434. . "</td>";
  435. $subtotaldebit += $ca->{debit};
  436. $subtotalcredit += $ca->{credit};
  437. $totaldebit += $ca->{debit};
  438. $totalcredit += $ca->{credit};
  439. $column_data{transdate} = qq|<td>$ca->{transdate}</td>|;
  440. $column_data{reference} = qq|<td>$href</td>|;
  441. $column_data{description} = qq|<td>$ca->{description}&nbsp;</td>|;
  442. $column_data{cleared} =
  443. ( $ca->{cleared} ) ? qq|<td>*</td>| : qq|<td>&nbsp;</td>|;
  444. $column_data{source} = qq|<td>$ca->{source}&nbsp;</td>|;
  445. $column_data{accno} = qq|<td>|;
  446. for ( @{ $ca->{accno} } ) {
  447. $column_data{accno} .= qq|<a href="$drilldown&accno=$_">$_</a> |;
  448. }
  449. $column_data{accno} .= qq|&nbsp;</td>|;
  450. if ( $ca->{id} != $sameid ) {
  451. $i++;
  452. $i %= 2;
  453. }
  454. $sameid = $ca->{id};
  455. print qq|
  456. <tr class="listrow$i">
  457. |;
  458. for (@column_index) { print "$column_data{$_}\n" }
  459. print qq|
  460. </tr>
  461. |;
  462. }
  463. if ( $form->{l_subtotal} eq 'Y' ) {
  464. &ca_subtotal;
  465. }
  466. for (@column_index) { $column_data{$_} = "<td>&nbsp;</td>" }
  467. $column_data{debit} =
  468. qq|<th align="right" class="listtotal">|
  469. . $form->format_amount( \%myconfig, $totaldebit, 2, "&nbsp;" ) . "</th>";
  470. $column_data{credit} =
  471. qq|<th align="right" class="listtotal">|
  472. . $form->format_amount( \%myconfig, $totalcredit, 2, "&nbsp;" ) . "</th>";
  473. $column_data{balance} =
  474. qq|<th align="right" class="listtotal">|
  475. . $form->format_amount( \%myconfig, $form->{balance} * $ml, 2, 0 )
  476. . "</th>";
  477. print qq|
  478. <tr class="listtotal">
  479. |;
  480. for (@column_index) { print "$column_data{$_}\n" }
  481. print qq|
  482. </tr>
  483. </table>
  484. </td>
  485. </tr>
  486. <tr>
  487. <td><hr size="3" noshade></td>
  488. </tr>
  489. </table>
  490. </body>
  491. </html>
  492. |;
  493. }
  494. sub ca_subtotal {
  495. for (@column_index) { $column_data{$_} = "<td>&nbsp;</td>" }
  496. $column_data{debit} =
  497. qq|<th align="right" class="listsubtotal">|
  498. . $form->format_amount( \%myconfig, $subtotaldebit, 2, "&nbsp;" )
  499. . "</th>";
  500. $column_data{credit} =
  501. qq|<th align="right" class="listsubtotal">|
  502. . $form->format_amount( \%myconfig, $subtotalcredit, 2, "&nbsp;" )
  503. . "</th>";
  504. $subtotaldebit = 0;
  505. $subtotalcredit = 0;
  506. $sameitem = $ca->{ $form->{sort} };
  507. print qq|
  508. <tr class="listsubtotal">
  509. |;
  510. for (@column_index) { print "$column_data{$_}\n" }
  511. print qq|
  512. </tr>
  513. |;
  514. }