summaryrefslogtreecommitdiff
path: root/bin/lynx/ca.pl
blob: c6371f7f61a423eb9321ab5aaa21aa8297b24ed4 (plain)
  1. #=====================================================================
  2. # LedgerSMB Small Medium Business Accounting
  3. # Copyright (C) 2006
  4. # This work contains copyrighted information from a number of sources all used
  5. # with permission.
  6. #
  7. # This file contains source code included with or based on SQL-Ledger which
  8. # is Copyright Dieter Simader and DWS Systems Inc. 2000-2005 and licensed
  9. # under the GNU General Public License version 2 or, at your option, any later
  10. # version. For a full list including contact information of contributors,
  11. # maintainers, and copyright holders, see the CONTRIBUTORS file.
  12. #
  13. # Original Copyright Notice from SQL-Ledger 2.6.17 (before the fork):
  14. # Copyright (C) 2001
  15. #
  16. # Author: DWS Systems Inc.
  17. # Web: http://www.sql-ledger.org
  18. #
  19. # Contributors:
  20. #
  21. #
  22. # Author: DWS Systems Inc.
  23. # Web: http://sourceforge.net/projects/ledger-smb/
  24. #
  25. # Contributors:
  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. # module for Chart of Accounts, Income Statement and Balance Sheet
  42. # search and edit transactions posted by the GL, AR and AP
  43. #
  44. #======================================================================
  45. use SL::CA;
  46. 1;
  47. # end of main
  48. # this is for our long dates
  49. # $locale->text('January')
  50. # $locale->text('February')
  51. # $locale->text('March')
  52. # $locale->text('April')
  53. # $locale->text('May ')
  54. # $locale->text('June')
  55. # $locale->text('July')
  56. # $locale->text('August')
  57. # $locale->text('September')
  58. # $locale->text('October')
  59. # $locale->text('November')
  60. # $locale->text('December')
  61. # this is for our short month
  62. # $locale->text('Jan')
  63. # $locale->text('Feb')
  64. # $locale->text('Mar')
  65. # $locale->text('Apr')
  66. # $locale->text('May')
  67. # $locale->text('Jun')
  68. # $locale->text('Jul')
  69. # $locale->text('Aug')
  70. # $locale->text('Sep')
  71. # $locale->text('Oct')
  72. # $locale->text('Nov')
  73. # $locale->text('Dec')
  74. sub chart_of_accounts {
  75. CA->all_accounts(\%myconfig, \%$form);
  76. @column_index = qw(accno gifi_accno description debit credit);
  77. $column_header{accno} = qq|<th class=listtop>|.$locale->text('Account').qq|</th>\n|;
  78. $column_header{gifi_accno} = qq|<th class=listtop>|.$locale->text('GIFI').qq|</th>\n|;
  79. $column_header{description} = qq|<th class=listtop>|.$locale->text('Description').qq|</th>\n|;
  80. $column_header{debit} = qq|<th class=listtop>|.$locale->text('Debit').qq|</th>\n|;
  81. $column_header{credit} = qq|<th class=listtop>|.$locale->text('Credit').qq|</th>\n|;
  82. $form->{title} = $locale->text('Chart of Accounts');
  83. $colspan = $#column_index + 1;
  84. $form->header;
  85. print qq|
  86. <body>
  87. <table border=0 width=100%>
  88. <tr><th class=listtop colspan=$colspan>$form->{title}</th></tr>
  89. <tr height="5"></tr>
  90. <tr class=listheading>|;
  91. for (@column_index) { print $column_header{$_} }
  92. print qq|
  93. </tr>
  94. |;
  95. foreach $ca (@{ $form->{CA} }) {
  96. $description = $form->escape($ca->{description});
  97. $gifi_description = $form->escape($ca->{gifi_description});
  98. $href = 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|;
  99. if ($ca->{charttype} eq "H") {
  100. print qq|<tr class=listheading>|;
  101. for (qw(accno description)) { $column_data{$_} = "<th class=listheading>$ca->{$_}</th>" }
  102. $column_data{gifi_accno} = "<th class=listheading>$ca->{gifi_accno}&nbsp;</th>";
  103. } else {
  104. $i++; $i %= 2;
  105. print qq|<tr class=listrow$i>|;
  106. $column_data{accno} = "<td><a href=$href>$ca->{accno}</a></td>";
  107. $column_data{gifi_accno} = "<td><a href=$href&accounttype=gifi>$ca->{gifi_accno}</a>&nbsp;</td>";
  108. $column_data{description} = "<td>$ca->{description}</td>";
  109. }
  110. $column_data{debit} = "<td align=right>".$form->format_amount(\%myconfig, $ca->{debit}, 2, "&nbsp;")."</td>\n";
  111. $column_data{credit} = "<td align=right>".$form->format_amount(\%myconfig, $ca->{credit}, 2, "&nbsp;")."</td>\n";
  112. $totaldebit += $ca->{debit};
  113. $totalcredit += $ca->{credit};
  114. for (@column_index) { print "$column_data{$_}\n" }
  115. print qq|
  116. </tr>
  117. |;
  118. }
  119. for (qw(accno gifi_accno description)) { $column_data{$_} = "<td>&nbsp;</td>" }
  120. $column_data{debit} = "<th align=right class=listtotal>".$form->format_amount(\%myconfig, $totaldebit, 2, 0)."</th>";
  121. $column_data{credit} = "<th align=right class=listtotal>".$form->format_amount(\%myconfig, $totalcredit, 2, 0)."</th>";
  122. print "<tr class=listtotal>";
  123. for (@column_index) { print "$column_data{$_}\n" }
  124. print qq|
  125. </tr>
  126. <tr>
  127. <td colspan=$colspan><hr size=3 noshade></td>
  128. </tr>
  129. </table>
  130. </body>
  131. </html>
  132. |;
  133. }
  134. sub list {
  135. $form->{title} = $locale->text('List Transactions');
  136. if ($form->{accounttype} eq 'gifi') {
  137. $form->{title} .= " - ".$locale->text('GIFI')." $form->{gifi_accno} - $form->{gifi_description}";
  138. } else {
  139. $form->{title} .= " - ".$locale->text('Account')." $form->{accno} - $form->{description}";
  140. }
  141. # get departments
  142. $form->all_departments(\%myconfig);
  143. if (@{ $form->{all_department} }) {
  144. $form->{selectdepartment} = "<option>\n";
  145. for (@{ $form->{all_department} }) { $form->{selectdepartment} .= qq|<option value="$_->{description}--$_->{id}">$_->{description}\n| }
  146. }
  147. $department = qq|
  148. <tr>
  149. <th align=right nowrap>|.$locale->text('Department').qq|</th>
  150. <td colspan=3><select name=department>$form->{selectdepartment}</select></td>
  151. </tr>
  152. | if $form->{selectdepartment};
  153. if (@{ $form->{all_years} }) {
  154. # accounting years
  155. $form->{selectaccountingyear} = "<option>\n";
  156. for (@{ $form->{all_years} }) { $form->{selectaccountingyear} .= qq|<option>$_\n| }
  157. $form->{selectaccountingmonth} = "<option>\n";
  158. for (sort keys %{ $form->{all_month} }) { $form->{selectaccountingmonth} .= qq|<option value=$_>|.$locale->text($form->{all_month}{$_}).qq|\n| }
  159. $selectfrom = qq|
  160. <tr>
  161. <th align=right>|.$locale->text('Period').qq|</th>
  162. <td colspan=3>
  163. <select name=month>$form->{selectaccountingmonth}</select>
  164. <select name=year>$form->{selectaccountingyear}</select>
  165. <input name=interval class=radio type=radio value=0 checked>&nbsp;|.$locale->text('Current').qq|
  166. <input name=interval class=radio type=radio value=1>&nbsp;|.$locale->text('Month').qq|
  167. <input name=interval class=radio type=radio value=3>&nbsp;|.$locale->text('Quarter').qq|
  168. <input name=interval class=radio type=radio value=12>&nbsp;|.$locale->text('Year').qq|
  169. </td>
  170. </tr>
  171. |;
  172. }
  173. $form->header;
  174. print qq|
  175. <body>
  176. <form method=post action=$form->{script}>
  177. <input type=hidden name=accno value=$form->{accno}>
  178. <input type=hidden name=description value="$form->{description}">
  179. <input type=hidden name=sort value=transdate>
  180. <input type=hidden name=oldsort value=transdate>
  181. <input type=hidden name=accounttype value=$form->{accounttype}>
  182. <input type=hidden name=gifi_accno value=$form->{gifi_accno}>
  183. <input type=hidden name=gifi_description value="$form->{gifi_description}">
  184. <table border=0 width=100%>
  185. <tr><th class=listtop>$form->{title}</th></tr>
  186. <tr height="5"></tr
  187. <tr valign=top>
  188. <td>
  189. <table>
  190. $department
  191. <tr>
  192. <th align=right>|.$locale->text('From').qq|</th>
  193. <td><input name=fromdate size=11 title="$myconfig{dateformat}"></td>
  194. <th align=right>|.$locale->text('To').qq|</th>
  195. <td><input name=todate size=11 title="$myconfig{dateformat}"></td>
  196. </tr>
  197. $selectfrom
  198. <tr>
  199. <th align=right>|.$locale->text('Include in Report').qq|</th>
  200. <td colspan=3>
  201. <input name=l_accno class=checkbox type=checkbox value=Y>&nbsp;|.$locale->text('AR/AP').qq|
  202. <input name=l_subtotal class=checkbox type=checkbox value=Y>&nbsp;|.$locale->text('Subtotal').qq|
  203. </td>
  204. </tr>
  205. </table>
  206. </td>
  207. </tr>
  208. <tr><td><hr size=3 noshade></td></tr>
  209. </table>
  210. <input type=hidden name=login value=$form->{login}>
  211. <input type=hidden name=path value=$form->{path}>
  212. <input type=hidden name=sessionid value=$form->{sessionid}>
  213. <br><input class=submit type=submit name=action value="|.$locale->text('List Transactions').qq|">
  214. </form>
  215. </body>
  216. </html>
  217. |;
  218. }
  219. sub list_transactions {
  220. CA->all_transactions(\%myconfig, \%$form);
  221. $department = $form->escape($form->{department});
  222. $projectnumber = $form->escape($form->{projectnumber});
  223. $title = $form->escape($form->{title});
  224. # construct href
  225. $href = "$form->{script}?action=list_transactions&department=$department&projectnumber=$projectnumber&title=$title";
  226. for (qw(path oldsort accno login sessionid fromdate todate accounttype gifi_accno l_heading l_subtotal l_accno)) { $href .= "&$_=$form->{$_}" }
  227. $drilldown = $href;
  228. $drilldown .= "&sort=$form->{sort}";
  229. $href .= "&direction=$form->{direction}";
  230. $form->sort_order();
  231. $drilldown .= "&direction=$form->{direction}";
  232. $form->{prevreport} = $href unless $form->{prevreport};
  233. $href .= "&prevreport=".$form->escape($form->{prevreport});
  234. $drilldown .= "&prevreport=".$form->escape($form->{prevreport});
  235. # figure out which column comes first
  236. $column_header{transdate} = qq|<th><a class=listheading href=$href&sort=transdate>|.$locale->text('Date').qq|</a></th>|;
  237. $column_header{reference} = qq|<th><a class=listheading href=$href&sort=reference>|.$locale->text('Reference').qq|</a></th>|;
  238. $column_header{description} = qq|<th><a class=listheading href=$href&sort=description>|.$locale->text('Description').qq|</a></th>|;
  239. $column_header{cleared} = qq|<th class=listheading>|.$locale->text('R').qq|</th>|;
  240. $column_header{source} = qq|<th class=listheading>|.$locale->text('Source').qq|</th>|;
  241. $column_header{debit} = qq|<th class=listheading>|.$locale->text('Debit').qq|</th>|;
  242. $column_header{credit} = qq|<th class=listheading>|.$locale->text('Credit').qq|</th>|;
  243. $column_header{balance} = qq|<th class=listheading>|.$locale->text('Balance').qq|</th>|;
  244. $column_header{accno} = qq|<th class=listheading>|.$locale->text('AR/AP').qq|</th>|;
  245. @columns = qw(transdate reference description debit credit);
  246. if ($form->{link} =~ /_paid/) {
  247. @columns = qw(transdate reference description source cleared debit credit);
  248. }
  249. push @columns, "accno" if $form->{l_accno};
  250. @column_index = $form->sort_columns(@columns);
  251. if ($form->{accounttype} eq 'gifi') {
  252. for (qw(accno description)) { $form->{$_} = $form->{"gifi_$_"} }
  253. }
  254. if ($form->{accno}) {
  255. push @column_index, "balance";
  256. }
  257. $form->{title} = ($form->{accounttype} eq 'gifi') ? $locale->text('GIFI') : $locale->text('Account');
  258. $form->{title} .= " $form->{accno} - $form->{description}";
  259. if ($form->{department}) {
  260. ($department) = split /--/, $form->{department};
  261. $options = $locale->text('Department')." : $department<br>";
  262. }
  263. if ($form->{projectnumber}) {
  264. ($projectnumber) = split /--/, $form->{projectnumber};
  265. $options .= $locale->text('Project Number')." : $projectnumber<br>";
  266. }
  267. if ($form->{fromdate} || $form->{todate}) {
  268. if ($form->{fromdate}) {
  269. $fromdate = $locale->date(\%myconfig, $form->{fromdate}, 1);
  270. }
  271. if ($form->{todate}) {
  272. $todate = $locale->date(\%myconfig, $form->{todate}, 1);
  273. }
  274. $form->{period} = "$fromdate - $todate";
  275. } else {
  276. $form->{period} = $locale->date(\%myconfig, $form->current_date(\%myconfig), 1);
  277. }
  278. $form->{period} = "<a href=$form->{prevreport}>$form->{period}</a>" if $form->{prevreport};
  279. $options .= $form->{period};
  280. # construct callback
  281. $department = $form->escape($form->{department},1);
  282. $projectnumber = $form->escape($form->{projectnumber},1);
  283. $title = $form->escape($form->{title},1);
  284. $form->{prevreport} = $form->escape($form->{prevreport},1);
  285. $form->{callback} = "$form->{script}?action=list_transactions&department=$department&projectnumber=$projectnumber&title=$title";
  286. for (qw(path direction oldsort accno login sessionid fromdate todate accounttype gifi_accno l_heading l_subtotal l_accno prevreport)) { $form->{callback} .= "&$_=$form->{$_}" }
  287. $form->header;
  288. print qq|
  289. <body>
  290. <table width=100%>
  291. <tr>
  292. <th class=listtop>$form->{title}</th>
  293. </tr>
  294. <tr height="5"></tr>
  295. <tr>
  296. <td>$options</td>
  297. </tr>
  298. <tr>
  299. <td>
  300. <table width=100%>
  301. <tr class=listheading>
  302. |;
  303. for (@column_index) { print "$column_header{$_}\n" }
  304. print qq|
  305. </tr>
  306. |;
  307. # add sort to callback
  308. $form->{callback} = $form->escape($form->{callback} . "&sort=$form->{sort}");
  309. if (@{ $form->{CA} }) {
  310. $sameitem = $form->{CA}->[0]->{$form->{sort}};
  311. }
  312. $ml = ($form->{category} =~ /(A|E)/) ? -1 : 1;
  313. $ml *= -1 if $form->{contra};
  314. if ($form->{accno} && $form->{balance}) {
  315. for (@column_index) { $column_data{$_} = "<td>&nbsp;</td>" }
  316. $column_data{balance} = "<td align=right>".$form->format_amount(\%myconfig, $form->{balance} * $ml, 2, 0)."</td>";
  317. $i++; $i %= 2;
  318. print qq|
  319. <tr class=listrow$i>
  320. |;
  321. for (@column_index) { print "$column_data{$_}\n" }
  322. print qq|
  323. </tr>
  324. |;
  325. }
  326. foreach $ca (@{ $form->{CA} }) {
  327. if ($form->{l_subtotal} eq 'Y') {
  328. if ($sameitem ne $ca->{$form->{sort}}) {
  329. &ca_subtotal;
  330. }
  331. }
  332. # construct link to source
  333. $href = "<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>";
  334. $column_data{debit} = "<td align=right>".$form->format_amount(\%myconfig, $ca->{debit}, 2, "&nbsp;")."</td>";
  335. $column_data{credit} = "<td align=right>".$form->format_amount(\%myconfig, $ca->{credit}, 2, "&nbsp;")."</td>";
  336. $form->{balance} += $ca->{amount};
  337. $column_data{balance} = "<td align=right>".$form->format_amount(\%myconfig, $form->{balance} * $ml, 2, 0)."</td>";
  338. $subtotaldebit += $ca->{debit};
  339. $subtotalcredit += $ca->{credit};
  340. $totaldebit += $ca->{debit};
  341. $totalcredit += $ca->{credit};
  342. $column_data{transdate} = qq|<td>$ca->{transdate}</td>|;
  343. $column_data{reference} = qq|<td>$href</td>|;
  344. $column_data{description} = qq|<td>$ca->{description}&nbsp;</td>|;
  345. $column_data{cleared} = ($ca->{cleared}) ? qq|<td>*</td>| : qq|<td>&nbsp;</td>|;
  346. $column_data{source} = qq|<td>$ca->{source}&nbsp;</td>|;
  347. $column_data{accno} = qq|<td>|;
  348. for (@{ $ca->{accno} }) { $column_data{accno} .= "<a href=$drilldown&accno=$_>$_</a> " }
  349. $column_data{accno} .= qq|&nbsp;</td>|;
  350. if ($ca->{id} != $sameid) {
  351. $i++; $i %= 2;
  352. }
  353. $sameid = $ca->{id};
  354. print qq|
  355. <tr class=listrow$i>
  356. |;
  357. for (@column_index) { print "$column_data{$_}\n" }
  358. print qq|
  359. </tr>
  360. |;
  361. }
  362. if ($form->{l_subtotal} eq 'Y') {
  363. &ca_subtotal;
  364. }
  365. for (@column_index) { $column_data{$_} = "<td>&nbsp;</td>" }
  366. $column_data{debit} = "<th align=right class=listtotal>".$form->format_amount(\%myconfig, $totaldebit, 2, "&nbsp;")."</th>";
  367. $column_data{credit} = "<th align=right class=listtotal>".$form->format_amount(\%myconfig, $totalcredit, 2, "&nbsp;")."</th>";
  368. $column_data{balance} = "<th align=right class=listtotal>".$form->format_amount(\%myconfig, $form->{balance} * $ml, 2, 0)."</th>";
  369. print qq|
  370. <tr class=listtotal>
  371. |;
  372. for (@column_index) { print "$column_data{$_}\n" }
  373. print qq|
  374. </tr>
  375. </table>
  376. </td>
  377. </tr>
  378. <tr>
  379. <td><hr size=3 noshade></td>
  380. </tr>
  381. </table>
  382. </body>
  383. </html>
  384. |;
  385. }
  386. sub ca_subtotal {
  387. for (@column_index) { $column_data{$_} = "<td>&nbsp;</td>" }
  388. $column_data{debit} = "<th align=right class=listsubtotal>".$form->format_amount(\%myconfig, $subtotaldebit, 2, "&nbsp;") . "</th>";
  389. $column_data{credit} = "<th align=right class=listsubtotal>".$form->format_amount(\%myconfig, $subtotalcredit, 2, "&nbsp;") . "</th>";
  390. $subtotaldebit = 0;
  391. $subtotalcredit = 0;
  392. $sameitem = $ca->{$form->{sort}};
  393. print qq|
  394. <tr class=listsubtotal>
  395. |;
  396. for (@column_index) { print "$column_data{$_}\n" }
  397. print qq|
  398. </tr>
  399. |;
  400. }