summaryrefslogtreecommitdiff
path: root/bin/am.pl
blob: 1f157780671cdd714b47be6cd82488382d8d4dcc (plain)
  1. #=====================================================================
  2. # LedgerSMB
  3. # Small Medium Business Accounting software
  4. # http://www.ledgersmb.org/
  5. #
  6. #
  7. # Copyright (C) 2006
  8. # This work contains copyrighted information from a number of sources all used
  9. # with permission.
  10. #
  11. # This file contains source code included with or based on SQL-Ledger which
  12. # is Copyright Dieter Simader and DWS Systems Inc. 2000-2005 and licensed
  13. # under the GNU General Public License version 2 or, at your option, any later
  14. # version. For a full list including contact information of contributors,
  15. # maintainers, and copyright holders, see the CONTRIBUTORS file.
  16. #
  17. # Original Copyright Notice from SQL-Ledger 2.6.17 (before the fork):
  18. # Copyright (c) 2001
  19. #
  20. # Author: DWS Systems Inc.
  21. # Web: http://www.sql-ledger.org
  22. #
  23. # Contributors:
  24. #
  25. #======================================================================
  26. #
  27. # This file has NOT undergone whitespace cleanup.
  28. #
  29. #======================================================================
  30. #
  31. # administration
  32. #
  33. #======================================================================
  34. use LedgerSMB::AM;
  35. use LedgerSMB::CA;
  36. use LedgerSMB::Form;
  37. use LedgerSMB::User;
  38. use LedgerSMB::RP;
  39. use LedgerSMB::GL;
  40. use LedgerSMB::Template;
  41. 1;
  42. # end of main
  43. sub add { &{"add_$form->{type}"} }
  44. sub edit { &{"edit_$form->{type}"} }
  45. sub save { &{"save_$form->{type}"} }
  46. sub delete { &{"delete_$form->{type}"} }
  47. sub save_as_new {
  48. delete $form->{id};
  49. &save;
  50. }
  51. sub add_account {
  52. $form->{title} = "Add";
  53. $form->{charttype} = "A";
  54. $form->{callback} =
  55. "$form->{script}?action=list_account&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}"
  56. unless $form->{callback};
  57. my %hiddens;
  58. my @buttons;
  59. my $checked = &account_header(\%hiddens);
  60. &form_footer_buttons(\%hiddens, \@buttons);
  61. my $template = LedgerSMB::Template->new_UI(
  62. user => \%myconfig,
  63. locale => $locale,
  64. template => 'am-account-form');
  65. $template->render({
  66. form => $form,
  67. checked => $checked,
  68. buttons => \@buttons,
  69. hiddens => \%hiddens,
  70. });
  71. }
  72. sub edit_account {
  73. $form->{title} = "Edit";
  74. $form->{accno} =~ s/\\'/'/g;
  75. $form->{accno} =~ s/\\\\/\\/g;
  76. AM->get_account( \%myconfig, \%$form );
  77. foreach my $item ( split( /:/, $form->{link} ) ) {
  78. $form->{$item} = "checked";
  79. }
  80. my %hiddens;
  81. my @buttons;
  82. my $checked = &account_header(\%hiddens);
  83. &form_footer_buttons(\%hiddens, \@buttons);
  84. my $template = LedgerSMB::Template->new_UI(
  85. user => \%myconfig,
  86. locale => $locale,
  87. template => 'am-account-form');
  88. $template->render({
  89. form => $form,
  90. checked => $checked,
  91. buttons => \@buttons,
  92. hiddens => \%hiddens,
  93. });
  94. }
  95. sub account_header {
  96. my $hiddens = shift;
  97. $form->{title} = $locale->text("$form->{title} Account");
  98. my %checked;
  99. $checked{ $form->{charttype} } = "checked";
  100. $checked{contra} = "checked" if $form->{contra};
  101. $checked{"$form->{category}_"} = "checked";
  102. for (qw(accno description)) { $form->{$_} = $form->quote( $form->{$_} ) }
  103. # this is for our parser only!
  104. # type=submit $locale->text('Add Account')
  105. # type=submit $locale->text('Edit Account')
  106. $hiddens->{type} = 'account';
  107. $hiddens->{$_} eq $form->{$_} foreach qw(id inventory_accno_id income_accno_id expense_accno_id fxgain_accno_id fxloss_accno_id);
  108. \%checked;
  109. }
  110. sub form_footer_buttons {
  111. my ($hiddens, $buttons) = @_;
  112. $hiddens->{$_} = $form->{$_} foreach qw(callback path login sessionid);
  113. # type=submit $locale->text('Save')
  114. # type=submit $locale->text('Save as new')
  115. # type=submit $locale->text('Delete')
  116. %button = ();
  117. if ( $form->{id} ) {
  118. $button{'save'} =
  119. { ndx => 3, key => 'S', value => $locale->text('Save') };
  120. $button{'save_as_new'} =
  121. { ndx => 7, key => 'N', value => $locale->text('Save as new') };
  122. if ( $form->{orphaned} ) {
  123. $button{'delete'} =
  124. { ndx => 16, key => 'D', value => $locale->text('Delete') };
  125. }
  126. }
  127. else {
  128. $button{'save'} =
  129. { ndx => 3, key => 'S', value => $locale->text('Save') };
  130. }
  131. for ( sort { $button{$a}->{ndx} <=> $button{$b}->{ndx} } keys %button ) {
  132. push @{$buttons}, {
  133. name => 'action',
  134. value => $_,
  135. accesskey => $button{$_}{key},
  136. title => "$button{$_}{value} [Alt-$button{$_}{key}]",
  137. text => $button{$_}{value},
  138. };
  139. }
  140. ##SC: Temporary removal
  141. ## if ( $form->{lynx} ) {
  142. ## require "bin/menu.pl";
  143. ## &menubar;
  144. ## }
  145. }
  146. sub form_footer {
  147. $form->hide_form(qw(callback path login sessionid));
  148. # type=submit $locale->text('Save')
  149. # type=submit $locale->text('Save as new')
  150. # type=submit $locale->text('Delete')
  151. %button = ();
  152. if ( $form->{id} ) {
  153. $button{'save'} =
  154. { ndx => 3, key => 'S', value => $locale->text('Save') };
  155. $button{'save_as_new'} =
  156. { ndx => 7, key => 'N', value => $locale->text('Save as new') };
  157. if ( $form->{orphaned} ) {
  158. $button{'delete'} =
  159. { ndx => 16, key => 'D', value => $locale->text('Delete') };
  160. }
  161. }
  162. else {
  163. $button{'save'} =
  164. { ndx => 3, key => 'S', value => $locale->text('Save') };
  165. }
  166. for ( sort { $button{$a}->{ndx} <=> $button{$b}->{ndx} } keys %button ) {
  167. $form->print_button( \%button, $_ );
  168. }
  169. if ( $form->{lynx} ) {
  170. require "bin/menu.pl";
  171. &menubar;
  172. }
  173. print qq|
  174. </form>
  175. </body>
  176. </html>
  177. |;
  178. }
  179. sub save_account {
  180. $form->isblank( "accno", $locale->text('Account Number missing!') );
  181. $form->isblank( "category", $locale->text('Account Type missing!') );
  182. # check for conflicting accounts
  183. if ( $form->{AR} || $form->{AP} || $form->{IC} ) {
  184. $a = "";
  185. for (qw(AR AP IC)) { $a .= $form->{$_} }
  186. $form->error(
  187. $locale->text(
  188. 'Cannot set account for more than one of AR, AP or IC')
  189. ) if length $a > 2;
  190. for (
  191. qw(AR_amount AR_tax AR_paid AP_amount AP_tax AP_paid IC_taxpart IC_taxservice IC_sale IC_cogs IC_income IC_expense)
  192. )
  193. {
  194. $form->error(
  195. "$form->{AR}$form->{AP}$form->{IC} "
  196. . $locale->text(
  197. 'account cannot be set to any other type of account')
  198. ) if $form->{$_};
  199. }
  200. }
  201. foreach $item ( "AR", "AP" ) {
  202. $i = 0;
  203. for ( "${item}_amount", "${item}_paid", "${item}_tax" ) {
  204. $i++ if $form->{$_};
  205. }
  206. $form->error(
  207. $locale->text( 'Cannot set multiple options for [_1]', $item ) )
  208. if $i > 1;
  209. }
  210. if ( AM->save_account( \%myconfig, \%$form ) ) {
  211. $form->redirect( $locale->text('Account saved!') );
  212. }
  213. else {
  214. $form->error( $locale->text('Cannot save account!') );
  215. }
  216. }
  217. sub list_account {
  218. CA->all_accounts( \%myconfig, \%$form );
  219. $form->{title} = $locale->text('Chart of Accounts');
  220. # construct callback
  221. $callback =
  222. "$form->{script}?action=list_account&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  223. $form->{callback} = $callback;
  224. @column_index = qw(accno gifi_accno description debit credit link);
  225. $column_header{accno} = $locale->text('Account');
  226. $column_header{gifi_accno} = $locale->text('GIFI');
  227. $column_header{description} = $locale->text('Description');
  228. $column_header{debit} = $locale->text('Debit');
  229. $column_header{credit} = $locale->text('Credit');
  230. $column_header{link} = $locale->text('Link');
  231. # escape callback
  232. $callback = $form->escape($callback);
  233. my @rows;
  234. foreach my $ca ( @{ $form->{CA} } ) {
  235. my %column_data;
  236. $ca->{debit} = " ";
  237. $ca->{credit} = " ";
  238. if ( $ca->{amount} > 0 ) {
  239. $ca->{credit} =
  240. $form->format_amount( \%myconfig, $ca->{amount}, 2, " " );
  241. }
  242. if ( $ca->{amount} < 0 ) {
  243. $ca->{debit} =
  244. $form->format_amount( \%myconfig, -$ca->{amount}, 2, " " );
  245. }
  246. #$ca->{link} =~ s/:/<br>/og;
  247. $gifi_accno = $form->escape( $ca->{gifi_accno} );
  248. if ( $ca->{charttype} eq "H" ) {
  249. $column_data{class} = 'heading';
  250. $column_data{accno} = {
  251. text => $ca->{accno},
  252. href => "$form->{script}?action=edit_account&id=$ca->{id}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}&callback=$callback"};
  253. $column_data{gifi_accno} = {
  254. text => $ca->{gifi_accno},
  255. href => "$form->{script}?action=edit_gifi&accno=$gifi_accno&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}&callback=$callback"};
  256. $column_data{description} = $ca->{description};
  257. $column_data{debit} = " ";
  258. $column_data{credit} = " ";
  259. $column_data{link} = " ";
  260. }
  261. else {
  262. $i++;
  263. $i %= 2;
  264. $column_data{i} = $i;
  265. $column_data{accno} = {
  266. text => $ca->{accno},
  267. href => "$form->{script}?action=edit_account&id=$ca->{id}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}&callback=$callback"};
  268. $column_data{gifi_accno} = {
  269. text => $ca->{gifi_accno},
  270. href => "$form->{script}?action=edit_gifi&accno=$gifi_accno&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}&callback=$callback"};
  271. $column_data{description} = $ca->{description};
  272. $column_data{debit} = $ca->{debit};
  273. $column_data{credit} = $ca->{credit};
  274. $column_data{link} = {text => $ca->{link}, delimiter => ':'};
  275. }
  276. push @rows, \%column_data;
  277. }
  278. my @buttons;
  279. for my $type (qw(CSV XLS ODS)) {
  280. push @buttons, {
  281. name => 'action',
  282. value => lc "${type}_list_account",
  283. text => $locale->text("$type Report"),
  284. type => 'submit',
  285. class => 'submit',
  286. };
  287. }
  288. my %hiddens = (
  289. callback => $callback,
  290. action => 'list_account',
  291. path => $form->{path},
  292. login => $form->{login},
  293. sessionid => $form->{sessionid},
  294. );
  295. my %row_alignment = ('credit' => 'right', 'debit' => 'right');
  296. my $format = uc substr($form->{action}, 0, 3);
  297. my $template = LedgerSMB::Template->new(
  298. user => \%myconfig,
  299. locale => $locale,
  300. path => 'UI',
  301. template => 'form-dynatable',
  302. format => ($format ne 'LIS')? $format: 'HTML');
  303. $template->render({
  304. form => $form,
  305. buttons => \@buttons,
  306. hiddens => \%hiddens,
  307. columns => \@column_index,
  308. heading => \%column_header,
  309. rows => \@rows,
  310. row_alignment => \%row_alignment,
  311. });
  312. }
  313. sub csv_list_account { &list_account }
  314. sub xls_list_account { &list_account }
  315. sub ods_list_account { &list_account }
  316. sub delete_account {
  317. $form->{title} = $locale->text('Delete Account');
  318. foreach $id (
  319. qw(inventory_accno_id income_accno_id expense_accno_id fxgain_accno_id fxloss_accno_id)
  320. )
  321. {
  322. if ( $form->{id} == $form->{$id} ) {
  323. $form->error( $locale->text('Cannot delete default account!') );
  324. }
  325. }
  326. if ( AM->delete_account( \%myconfig, \%$form ) ) {
  327. $form->redirect( $locale->text('Account deleted!') );
  328. }
  329. else {
  330. $form->error( $locale->text('Cannot delete account!') );
  331. }
  332. }
  333. sub list_gifi {
  334. @{ $form->{fields} } = qw(accno description);
  335. $form->{table} = "gifi";
  336. AM->gifi_accounts( \%myconfig, \%$form );
  337. $form->{title} = $locale->text('GIFI');
  338. my %hiddens;
  339. # construct callback
  340. my $callback =
  341. "$form->{script}?action=list_gifi&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  342. $form->{callback} = $callback;
  343. $hiddens{callback} = $callback;
  344. $hiddens{action} = 'list_gifi';
  345. $hiddens{path} = $form->{path};
  346. $hiddens{login} = $form->{login};
  347. $hiddens{sessionid} = $form->{sessionid};
  348. my @column_index = qw(accno description);
  349. my %column_header;
  350. my @rows;
  351. $column_header{accno} = $locale->text('GIFI');
  352. $column_header{description} = $locale->text('Description');
  353. my $i = 0;
  354. foreach $ca ( @{ $form->{ALL} } ) {
  355. my %column_data;
  356. $i++;
  357. $i %= 2;
  358. $column_data{i} = $i;
  359. $accno = $form->escape( $ca->{accno} );
  360. $column_data{accno} = {text => $ca->{accno}, href =>
  361. qq|$form->{script}?action=edit_gifi&coa=1&accno=$accno&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}&callback=$callback|};
  362. $column_data{description} = $ca->{description};
  363. push @rows, \%column_data;
  364. }
  365. my @buttons;
  366. push @buttons, {
  367. name => 'action',
  368. value => 'csv_list_gifi',
  369. text => $locale->text('CSV Report'),
  370. type => 'submit',
  371. class => 'submit',
  372. };
  373. my $template = LedgerSMB::Template->new(
  374. user => \%myconfig,
  375. locale => $locale,
  376. path => 'UI',
  377. template => 'form-dynatable',
  378. format => ($form->{action} =~ /^csv/)? 'CSV': 'HTML');
  379. $template->render({
  380. form => \%$form,
  381. hiddens => \%hiddens,
  382. buttons => \@buttons,
  383. columns => \@column_index,
  384. heading => \%column_header,
  385. rows => \@rows,
  386. });
  387. }
  388. sub csv_list_gifi { &list_gifi }
  389. sub add_gifi {
  390. $form->{title} = "Add";
  391. # construct callback
  392. $form->{callback} =
  393. "$form->{script}?action=list_gifi&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  394. $form->{coa} = 1;
  395. my %hiddens;
  396. my @buttons;
  397. &gifi_header(\%hiddens);
  398. &gifi_footer(\%hiddens, \@buttons);
  399. my $template = LedgerSMB::Template->new_UI(
  400. user => \%myconfig,
  401. locale => $locale,
  402. template => 'am-gifi-form');
  403. $template->render({
  404. form => $form,
  405. buttons => \@buttons,
  406. hiddens => \%hiddens,
  407. });
  408. }
  409. sub edit_gifi {
  410. $form->{title} = "Edit";
  411. AM->get_gifi( \%myconfig, \%$form );
  412. $form->error( $locale->text('Account does not exist!') )
  413. unless $form->{accno};
  414. my %hiddens;
  415. my @buttons;
  416. &gifi_header(\%hiddens);
  417. &gifi_footer(\%hiddens, \@buttons);
  418. my $template = LedgerSMB::Template->new_UI(
  419. user => \%myconfig,
  420. locale => $locale,
  421. template => 'am-gifi-form');
  422. $template->render({
  423. form => $form,
  424. buttons => \@buttons,
  425. hiddens => \%hiddens,
  426. });
  427. }
  428. sub gifi_header {
  429. my $hiddens = shift;
  430. $form->{title} = $locale->text("$form->{title} GIFI");
  431. # $locale->text('Add GIFI')
  432. # $locale->text('Edit GIFI')
  433. for (qw(accno description)) { $form->{$_} = $form->quote( $form->{$_} ) }
  434. $hiddens->{id} = $form->{accno};
  435. $hiddens->{type} = 'gifi';
  436. }
  437. sub gifi_footer {
  438. my ($hiddens, $buttons) = @_;
  439. $hiddens->{$_} = $form->{$_} foreach qw(callback path login sessionid);
  440. # type=submit $locale->text('Save')
  441. # type=submit $locale->text('Copy to COA')
  442. # type=submit $locale->text('Delete')
  443. my %button = ();
  444. $button{'save'} = { ndx => 3, key => 'S', value => $locale->text('Save') };
  445. if ( $form->{accno} ) {
  446. if ( $form->{orphaned} ) {
  447. $button{'delete'} =
  448. { ndx => 16, key => 'D', value => $locale->text('Delete') };
  449. }
  450. }
  451. if ( $form->{coa} ) {
  452. $button{'copy_to_coa'} =
  453. { ndx => 7, key => 'C', value => $locale->text('Copy to COA') };
  454. }
  455. for ( sort { $button{$a}->{ndx} <=> $button{$b}->{ndx} } keys %button ) {
  456. push @{$buttons}, {
  457. name => 'action',
  458. value => $_,
  459. accesskey => $button{$_}{key},
  460. title => "$button{$_}{value} [Alt-$button{$_}{key}]",
  461. text => $button{$_}{value},
  462. };
  463. }
  464. ##SC: Temporary commenting
  465. ## if ( $form->{lynx} ) {
  466. ## require "bin/menu.pl";
  467. ## &menubar;
  468. ## }
  469. }
  470. sub save_gifi {
  471. $form->isblank( "accno", $locale->text('GIFI missing!') );
  472. AM->save_gifi( \%myconfig, \%$form );
  473. $form->redirect( $locale->text('GIFI saved!') );
  474. }
  475. sub copy_to_coa {
  476. $form->isblank( "accno", $locale->text('GIFI missing!') );
  477. AM->save_gifi( \%myconfig, \%$form );
  478. delete $form->{id};
  479. $form->{gifi_accno} = $form->{accno};
  480. $form->{title} = "Add";
  481. $form->{charttype} = "A";
  482. my %hiddens;
  483. my @buttons;
  484. my $checked = &account_header(\%hiddens);
  485. &form_footer_buttons(\%hiddens, \@buttons);
  486. my $template = LedgerSMB::Template->new_UI(
  487. user => \%myconfig,
  488. locale => $locale,
  489. template => 'am-account-form');
  490. $template->render({
  491. form => $form,
  492. checked => $checked,
  493. buttons => \@buttons,
  494. hiddens => \%hiddens,
  495. });
  496. }
  497. sub delete_gifi {
  498. AM->delete_gifi( \%myconfig, \%$form );
  499. $form->redirect( $locale->text('GIFI deleted!') );
  500. }
  501. sub add_department {
  502. $form->{title} = "Add";
  503. $form->{role} = "P";
  504. $form->{callback} =
  505. "$form->{script}?action=add_department&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}"
  506. unless $form->{callback};
  507. &department_header;
  508. &form_footer;
  509. }
  510. sub edit_department {
  511. $form->{title} = "Edit";
  512. AM->get_department( \%myconfig, \%$form );
  513. &department_header;
  514. &form_footer;
  515. }
  516. sub list_department {
  517. AM->departments( \%myconfig, \%$form );
  518. my $href =
  519. "$form->{script}?action=list_department&direction=$form->{direction}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  520. $form->sort_order();
  521. $form->{callback} =
  522. "$form->{script}?action=list_department&direction=$form->{direction}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  523. my $callback = $form->escape( $form->{callback} );
  524. $form->{title} = $locale->text('Departments');
  525. my @column_index = qw(description cost profit);
  526. my %column_header;
  527. $column_header{description} = { text => $locale->text('Description'),
  528. href => $href};
  529. $column_header{cost} = $locale->text('Cost Center');
  530. $column_header{profit} = $locale->text('Profit Center');
  531. my @rows;
  532. my $i = 0;
  533. foreach my $ref ( @{ $form->{ALL} } ) {
  534. my %column_data;
  535. $i++;
  536. $i %= 2;
  537. $column_data{i} = $i;
  538. $column_data{cost} = ( $ref->{role} eq "C" ) ? "*" : " ";
  539. $column_data{profit} = ( $ref->{role} eq "P" ) ? "*" : " ";
  540. $column_data{description} = { text => $ref->{description},
  541. href => qq|$form->{script}?action=edit_department&id=$ref->{id}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}&callback=$callback|,};
  542. push @rows, \%column_data;
  543. }
  544. $form->{type} = "department";
  545. my @hiddens = qw(type callback path login sessionid);
  546. ## SC: removing this for now
  547. #if ( $form->{lynx} ) {
  548. # require "bin/menu.pl";
  549. # &menubar;
  550. #}
  551. my @buttons;
  552. push @buttons, {
  553. name => 'action',
  554. value => 'add_department',
  555. text => $locale->text('Add Department'),
  556. type => 'submit',
  557. class => 'submit',
  558. };
  559. my $template = LedgerSMB::Template->new_UI(
  560. user => \%myconfig,
  561. locale => $locale,
  562. template => 'am-list-departments');
  563. $template->render({
  564. form => $form,
  565. buttons => \@buttons,
  566. columns => \@column_index,
  567. heading => \%column_header,
  568. rows => \@rows,
  569. hiddens => \@hiddens,
  570. });
  571. }
  572. sub department_header {
  573. $form->{title} = $locale->text("$form->{title} Department");
  574. # $locale->text('Add Department')
  575. # $locale->text('Edit Department')
  576. $form->{description} = $form->quote( $form->{description} );
  577. if ( ( $rows = $form->numtextrows( $form->{description}, 60 ) ) > 1 ) {
  578. $description =
  579. qq|<textarea name="description" rows=$rows cols=60 wrap=soft>$form->{description}</textarea>|;
  580. }
  581. else {
  582. $description =
  583. qq|<input name=description size=60 value="$form->{description}">|;
  584. }
  585. $costcenter = "checked" if $form->{role} eq "C";
  586. $profitcenter = "checked" if $form->{role} eq "P";
  587. $form->header;
  588. print qq|
  589. <body>
  590. <form method=post action=$form->{script}>
  591. <input type=hidden name=id value=$form->{id}>
  592. <input type=hidden name=type value=department>
  593. <table width=100%>
  594. <tr>
  595. <th class=listtop colspan=2>$form->{title}</th>
  596. </tr>
  597. <tr height="5"></tr>
  598. <tr>
  599. <th align="right">| . $locale->text('Description') . qq|</th>
  600. <td>$description</td>
  601. </tr>
  602. <tr>
  603. <td></td>
  604. <td><input type=radio style=radio name=role value="C" $costcenter> |
  605. . $locale->text('Cost Center') . qq|
  606. <input type=radio style=radio name=role value="P" $profitcenter> |
  607. . $locale->text('Profit Center') . qq|
  608. </td>
  609. <tr>
  610. <td colspan=2><hr size=3 noshade></td>
  611. </tr>
  612. </table>
  613. |;
  614. }
  615. sub save_department {
  616. $form->isblank( "description", $locale->text('Description missing!') );
  617. AM->save_department( \%myconfig, \%$form );
  618. $form->redirect( $locale->text('Department saved!') );
  619. }
  620. sub delete_department {
  621. AM->delete_department( \%myconfig, \%$form );
  622. $form->redirect( $locale->text('Department deleted!') );
  623. }
  624. sub add_business {
  625. $form->{title} = "Add";
  626. $form->{callback} =
  627. "$form->{script}?action=add_business&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}"
  628. unless $form->{callback};
  629. my %hiddens;
  630. my @buttons;
  631. my $checked = &business_header(\%hiddens);
  632. &form_footer_buttons(\%hiddens, \@buttons);
  633. my $template = LedgerSMB::Template->new_UI(
  634. user => \%myconfig,
  635. locale => $locale,
  636. template => 'am-business-form');
  637. $template->render({
  638. form => $form,
  639. buttons => \@buttons,
  640. hiddens => \%hiddens,
  641. });
  642. }
  643. sub edit_business {
  644. $form->{title} = "Edit";
  645. AM->get_business( \%myconfig, \%$form );
  646. $form->{orphaned} = 1;
  647. my %hiddens;
  648. my @buttons;
  649. my $checked = &business_header(\%hiddens);
  650. &form_footer_buttons(\%hiddens, \@buttons);
  651. my $template = LedgerSMB::Template->new_UI(
  652. user => \%myconfig,
  653. locale => $locale,
  654. template => 'am-business-form');
  655. $template->render({
  656. form => $form,
  657. buttons => \@buttons,
  658. hiddens => \%hiddens,
  659. });
  660. }
  661. sub list_business {
  662. AM->business( \%myconfig, \%$form );
  663. my $href =
  664. "$form->{script}?action=list_business&direction=$form->{direction}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  665. $form->sort_order();
  666. $form->{callback} =
  667. "$form->{script}?action=list_business&direction=$form->{direction}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  668. my $callback = $form->escape( $form->{callback} );
  669. $form->{title} = $locale->text('Type of Business');
  670. my @column_index = qw(description discount);
  671. my %column_header;
  672. $column_header{description} = { text => $locale->text('Description'),
  673. href => $href };
  674. $column_header{discount} = $locale->text('Discount %');
  675. my @rows;
  676. $i = 0;
  677. foreach my $ref ( @{ $form->{ALL} } ) {
  678. my %column_data;
  679. $i++;
  680. $i %= 2;
  681. $column_data{i} = $i;
  682. $column_data{discount} =
  683. $form->format_amount( \%myconfig, $ref->{discount} * 100, 2, " " );
  684. $column_data{description} = { text => $ref->{description}, href =>
  685. qq|$form->{script}?action=edit_business&id=$ref->{id}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}&callback=$callback|};
  686. push @rows, \%column_data;
  687. }
  688. $form->{type} = "business";
  689. my @hiddens = qw(type callback path login sessionid);
  690. ## SC: Temporary removal
  691. ## if ( $form->{lynx} ) {
  692. ## require "bin/menu.pl";
  693. ## &menubar;
  694. ## }
  695. my @buttons;
  696. push @buttons, {
  697. name => 'action',
  698. value => 'add_business',
  699. text => $locale->text('Add Business'),
  700. type => 'submit',
  701. class => 'submit',
  702. };
  703. my $template = LedgerSMB::Template->new_UI(
  704. user => \%myconfig,
  705. locale => $locale,
  706. template => 'am-list-departments');
  707. $template->render({
  708. form => $form,
  709. buttons => \@buttons,
  710. columns => \@column_index,
  711. heading => \%column_header,
  712. rows => \@rows,
  713. hiddens => \@hiddens,
  714. });
  715. }
  716. sub business_header {
  717. my $hiddens = shift;
  718. $form->{title} = $locale->text("$form->{title} Business");
  719. # $locale->text('Add Business')
  720. # $locale->text('Edit Business')
  721. $form->{description} = $form->quote( $form->{description} );
  722. $form->{discount} =
  723. $form->format_amount( \%myconfig, $form->{discount} * 100 );
  724. $hiddens->{id} = $form->{id};
  725. $hiddens->{type} = 'business';
  726. }
  727. sub save_business {
  728. $form->isblank( "description", $locale->text('Description missing!') );
  729. AM->save_business( \%myconfig, \%$form );
  730. $form->redirect( $locale->text('Business saved!') );
  731. }
  732. sub delete_business {
  733. AM->delete_business( \%myconfig, \%$form );
  734. $form->redirect( $locale->text('Business deleted!') );
  735. }
  736. sub add_sic {
  737. $form->{title} = "Add";
  738. $form->{callback} =
  739. "$form->{script}?action=add_sic&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}"
  740. unless $form->{callback};
  741. my %hiddens;
  742. my @buttons;
  743. my $checked = &sic_header(\%hiddens);
  744. &form_footer_buttons(\%hiddens, \@buttons);
  745. my $template = LedgerSMB::Template->new_UI(
  746. user => \%myconfig,
  747. locale => $locale,
  748. template => 'am-sic-form');
  749. $template->render({
  750. form => $form,
  751. heading => $checked,
  752. buttons => \@buttons,
  753. hiddens => \%hiddens,
  754. });
  755. }
  756. sub edit_sic {
  757. $form->{title} = "Edit";
  758. $form->{code} =~ s/\\'/'/g;
  759. $form->{code} =~ s/\\\\/\\/g;
  760. AM->get_sic( \%myconfig, \%$form );
  761. $form->{id} = $form->{code};
  762. $form->{orphaned} = 1;
  763. my %hiddens;
  764. my @buttons;
  765. my $checked = &sic_header(\%hiddens);
  766. &form_footer_buttons(\%hiddens, \@buttons);
  767. my $template = LedgerSMB::Template->new_UI(
  768. user => \%myconfig,
  769. locale => $locale,
  770. template => 'am-sic-form');
  771. $template->render({
  772. form => $form,
  773. heading => $checked,
  774. buttons => \@buttons,
  775. hiddens => \%hiddens,
  776. });
  777. }
  778. sub list_sic {
  779. AM->sic( \%myconfig, \%$form );
  780. my $href =
  781. "$form->{script}?action=list_sic&direction=$form->{direction}&oldsort=$form->{oldsort}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  782. $form->sort_order();
  783. $form->{callback} =
  784. "$form->{script}?action=list_sic&direction=$form->{direction}&oldsort=$form->{oldsort}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  785. my $callback = $form->escape( $form->{callback} );
  786. $form->{title} = $locale->text('Standard Industrial Codes');
  787. my @column_index = $form->sort_columns(qw(code description));
  788. my %column_header;
  789. $column_header{code} = {
  790. href => "$href&sort=code",
  791. text => $locale->text('Code'),
  792. };
  793. $column_header{description} = {
  794. href => "$href&sort=description",
  795. text => $locale->text('Description'),
  796. };
  797. my @rows;
  798. my $i = 0;
  799. foreach $ref ( @{ $form->{ALL} } ) {
  800. my %column_data;
  801. $i++;
  802. $i %= 2;
  803. if ( $ref->{sictype} eq 'H' ) {
  804. $column_data{class} = 'heading';
  805. }
  806. $column_data{i} = $i;
  807. $column_data{code} = {
  808. text => $ref->{code},
  809. href => "$form->{script}?action=edit_sic&code=$ref->{code}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}&callback=$callback",
  810. };
  811. $column_data{description} = $ref->{description};
  812. push @rows, \%column_data;
  813. }
  814. $form->{type} = "sic";
  815. my @hiddens = qw(type callback path login sessionid);
  816. ##SC: Temporary removal
  817. ## if ( $form->{lynx} ) {
  818. ## require "bin/menu.pl";
  819. ## &menubar;
  820. ## }
  821. my @buttons;
  822. push @buttons, {
  823. name => 'action',
  824. value => 'add_sic',
  825. text => $locale->text('Add SIC'),
  826. type => 'submit',
  827. class => 'submit',
  828. };
  829. my $template = LedgerSMB::Template->new_UI(
  830. user => \%myconfig,
  831. locale => $locale,
  832. template => 'am-list-departments');
  833. $template->render({
  834. form => $form,
  835. buttons => \@buttons,
  836. columns => \@column_index,
  837. heading => \%column_header,
  838. rows => \@rows,
  839. hiddens => \@hiddens,
  840. });
  841. }
  842. sub sic_header {
  843. my $hiddens = shift;
  844. $form->{title} = $locale->text("$form->{title} SIC");
  845. # $locale->text('Add SIC')
  846. # $locale->text('Edit SIC')
  847. for (qw(code description)) { $form->{$_} = $form->quote( $form->{$_} ) }
  848. $checked = ( $form->{sictype} eq 'H' ) ? "checked" : "";
  849. $hiddens->{type} = 'sic';
  850. $hiddens->{id} = $form->{code};
  851. $checked;
  852. }
  853. sub save_sic {
  854. $form->isblank( "code", $locale->text('Code missing!') );
  855. $form->isblank( "description", $locale->text('Description missing!') );
  856. AM->save_sic( \%myconfig, \%$form );
  857. $form->redirect( $locale->text('SIC saved!') );
  858. }
  859. sub delete_sic {
  860. AM->delete_sic( \%myconfig, \%$form );
  861. $form->redirect( $locale->text('SIC deleted!') );
  862. }
  863. sub add_language {
  864. $form->{title} = "Add";
  865. $form->{callback} =
  866. "$form->{script}?action=add_language&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}"
  867. unless $form->{callback};
  868. &language_header;
  869. &form_footer;
  870. }
  871. sub edit_language {
  872. $form->{title} = "Edit";
  873. $form->{code} =~ s/\\'/'/g;
  874. $form->{code} =~ s/\\\\/\\/g;
  875. AM->get_language( \%myconfig, \%$form );
  876. $form->{id} = $form->{code};
  877. &language_header;
  878. $form->{orphaned} = 1;
  879. &form_footer;
  880. }
  881. sub list_language {
  882. AM->language( \%myconfig, \%$form );
  883. $href =
  884. "$form->{script}?action=list_language&direction=$form->{direction}&oldsort=$form->{oldsort}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  885. $form->sort_order();
  886. $form->{callback} =
  887. "$form->{script}?action=list_language&direction=$form->{direction}&oldsort=$form->{oldsort}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  888. my $callback = $form->escape( $form->{callback} );
  889. $form->{title} = $locale->text('Languages');
  890. my @column_index = $form->sort_columns(qw(code description));
  891. my %column_header;
  892. $column_header{code} = { text => $locale->text('Code'),
  893. href => "$href&sort=code" };
  894. $column_header{description} = { text => $locale->text('Description'),
  895. href => "$href&sort=description" };
  896. my @rows;
  897. my $i = 0;
  898. foreach my $ref ( @{ $form->{ALL} } ) {
  899. my %column_data;
  900. $i++;
  901. $i %= 2;
  902. $column_data{i} = $i;
  903. $column_data{code} = {text => $ref->{code}, href =>
  904. qq|$form->{script}?action=edit_language&code=$ref->{code}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}&callback=$callback|};
  905. $column_data{description} = $ref->{description};
  906. push @rows, \%column_data;
  907. }
  908. $form->{type} = "language";
  909. my @hiddens = qw(type callback path login sessionid);
  910. ## SC: Temporary removal
  911. ## if ( $form->{lynx} ) {
  912. ## require "bin/menu.pl";
  913. ## &menubar;
  914. ## }
  915. my @buttons;
  916. push @buttons, {
  917. name => 'action',
  918. value => 'add_language',
  919. text => $locale->text('Add Lanugage'),
  920. type => 'submit',
  921. class => 'submit',
  922. };
  923. # SC: I'm not concerned about the wider description as code is 6 chars max
  924. my $template = LedgerSMB::Template->new_UI(
  925. user => \%myconfig,
  926. locale => $locale,
  927. template => 'am-list-departments');
  928. $template->render({
  929. form => $form,
  930. buttons => \@buttons,
  931. columns => \@column_index,
  932. heading => \%column_header,
  933. rows => \@rows,
  934. hiddens => \@hiddens,
  935. });
  936. }
  937. sub language_header {
  938. $form->{title} = $locale->text("$form->{title} Language");
  939. # $locale->text('Add Language')
  940. # $locale->text('Edit Language')
  941. for (qw(code description)) { $form->{$_} = $form->quote( $form->{$_} ) }
  942. $form->header;
  943. print qq|
  944. <body>
  945. <form method=post action=$form->{script}>
  946. <input type=hidden name=type value=language>
  947. <input type=hidden name=id value="$form->{code}">
  948. <table width=100%>
  949. <tr>
  950. <th class=listtop colspan=2>$form->{title}</th>
  951. </tr>
  952. <tr height="5"></tr>
  953. <tr>
  954. <th align="right">| . $locale->text('Code') . qq|</th>
  955. <td><input name=code size=10 value="$form->{code}"></td>
  956. <tr>
  957. <tr>
  958. <th align="right">| . $locale->text('Description') . qq|</th>
  959. <td><input name=description size=60 value="$form->{description}"></td>
  960. </tr>
  961. <td colspan=2><hr size=3 noshade></td>
  962. </tr>
  963. </table>
  964. |;
  965. }
  966. sub save_language {
  967. $form->isblank( "code", $locale->text('Code missing!') );
  968. $form->isblank( "description", $locale->text('Description missing!') );
  969. $form->{code} =~ s/(\.\.|\*)//g;
  970. AM->save_language( \%myconfig, \%$form );
  971. if ( !-d "$myconfig{templates}/$form->{code}" ) {
  972. umask(002);
  973. if ( mkdir "$myconfig{templates}/$form->{code}", oct("771") ) {
  974. umask(007);
  975. opendir TEMPLATEDIR, "$myconfig{templates}"
  976. or $form->error("$myconfig{templates} : $!");
  977. @templates = grep !/^(\.|\.\.)/, readdir TEMPLATEDIR;
  978. closedir TEMPLATEDIR;
  979. foreach $file (@templates) {
  980. if ( -f "$myconfig{templates}/$file" ) {
  981. open( TEMP, '<', "$myconfig{templates}/$file" )
  982. or $form->error("$myconfig{templates}/$file : $!");
  983. open( NEW, '>', "$myconfig{templates}/$form->{code}/$file" )
  984. or $form->error(
  985. "$myconfig{templates}/$form->{code}/$file : $!");
  986. while ( $line = <TEMP> ) {
  987. print NEW $line;
  988. }
  989. close(TEMP);
  990. close(NEW);
  991. }
  992. }
  993. }
  994. else {
  995. $form->error("${templates}/$form->{code} : $!");
  996. }
  997. }
  998. $form->redirect( $locale->text('Language saved!') );
  999. }
  1000. sub delete_language {
  1001. $form->{title} = $locale->text('Confirm!');
  1002. $form->header;
  1003. print qq|
  1004. <body>
  1005. <form method=post action=$form->{script}>
  1006. |;
  1007. for (qw(action nextsub)) { delete $form->{$_} }
  1008. $form->hide_form;
  1009. print qq|
  1010. <h2 class=confirm>$form->{title}</h2>
  1011. <h4>|
  1012. . $locale->text(
  1013. 'Deleting a language will also delete the templates for the language [_1]',
  1014. $form->{invnumber}
  1015. )
  1016. . qq|</h4>
  1017. <input type=hidden name=action value=continue>
  1018. <input type=hidden name=nextsub value=yes_delete_language>
  1019. <button name="action" class="submit" type="submit" value="continue">|
  1020. . $locale->text('Continue')
  1021. . qq|</button>
  1022. </form>
  1023. </body>
  1024. </html>
  1025. |;
  1026. }
  1027. sub yes_delete_language {
  1028. AM->delete_language( \%myconfig, \%$form );
  1029. # delete templates
  1030. $dir = "$myconfig{templates}/$form->{code}";
  1031. if ( -d $dir ) {
  1032. unlink <$dir/*>;
  1033. rmdir "$myconfig{templates}/$form->{code}";
  1034. }
  1035. $form->redirect( $locale->text('Language deleted!') );
  1036. }
  1037. sub display_stylesheet {
  1038. $form->{file} = "css/$myconfig{stylesheet}";
  1039. &display_form;
  1040. }
  1041. sub list_templates {
  1042. AM->language( \%myconfig, \%$form );
  1043. if ( !@{ $form->{ALL} } ) {
  1044. &display_form;
  1045. exit;
  1046. }
  1047. unshift @{ $form->{ALL} },
  1048. { code => '.', description => $locale->text('Default Template') };
  1049. my $href =
  1050. "$form->{script}?action=list_templates&direction=$form->{direction}&oldsort=$form->{oldsort}&file=$form->{file}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  1051. $form->sort_order();
  1052. $form->{callback} =
  1053. "$form->{script}?action=list_templates&direction=$form->{direction}&oldsort=$form->{oldsort}&file=$form->{file}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  1054. my $callback = $form->escape( $form->{callback} );
  1055. chomp $myconfig{templates};
  1056. $form->{file} =~ s/$myconfig{templates}//;
  1057. $form->{file} =~ s/\///;
  1058. $form->{title} = "$form->{format}: $form->{template}";
  1059. my @column_index = $form->sort_columns(qw(code description));
  1060. $column_header{code} = { text => $locale->text('Code'),
  1061. href => "$href&sort=code" };
  1062. $column_header{description} = { text => $locale->text('Description'),
  1063. href => "$href&sort=description" };
  1064. my @rows;
  1065. my $i = 0;
  1066. foreach my $ref ( @{ $form->{ALL} } ) {
  1067. my %column_data;
  1068. $i++;
  1069. $i %= 2;
  1070. $column_data{i} = $i;
  1071. $column_data{code} = { text => $ref->{code}, href =>
  1072. qq|$form->{script}?action=display_form&file=$myconfig{templates}/$ref->{code}/$form->{file}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}&code=$ref->{code}&callback=$callback|};
  1073. $column_data{description} = $ref->{description};
  1074. push @rows, \%column_data;
  1075. }
  1076. $form->{type} = 'language';
  1077. my @hiddens = qw(sessionid login path calllback type);
  1078. ## SC: Temporary removal
  1079. ## if ( $form->{lynx} ) {
  1080. ## require "bin/menu.pl";
  1081. ## &menubar;
  1082. ## }
  1083. # SC: I'm not concerned about the wider description as code is 6 chars max
  1084. my $template = LedgerSMB::Template->new_UI(
  1085. user => \%myconfig,
  1086. locale => $locale,
  1087. template => 'am-list-departments');
  1088. $template->render({
  1089. form => $form,
  1090. columns => \@column_index,
  1091. heading => \%column_header,
  1092. rows => \@rows,
  1093. hiddens => \@hiddens,
  1094. });
  1095. }
  1096. sub display_form {
  1097. AM->load_template( \%myconfig, \%$form );
  1098. $form->{title} = $form->{file};
  1099. $form->{body} =~
  1100. s/<%include (.*?)%>/<a href=$form->{script}\?action=display_form&file=$myconfig{templates}\/$form->{code}\/$1&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}>$1<\/a>/g;
  1101. # if it is anything but html
  1102. if ( $form->{file} !~ /\.html$/ ) {
  1103. $form->{body} = "<pre>\n$form->{body}\n</pre>";
  1104. }
  1105. $form->header;
  1106. print qq|
  1107. <body>
  1108. $form->{body}
  1109. <form method=post action=$form->{script}>
  1110. |;
  1111. $form->{type} = "template";
  1112. $form->hide_form(qw(file type path login sessionid));
  1113. print qq|
  1114. <button name="action" type="submit" class="submit" value="edit">|
  1115. . $locale->text('Edit')
  1116. . qq|</button>|;
  1117. if ( $form->{lynx} ) {
  1118. require "bin/menu.pl";
  1119. &menubar;
  1120. }
  1121. print qq|
  1122. </form>
  1123. </body>
  1124. </html>
  1125. |;
  1126. }
  1127. sub edit_template {
  1128. AM->load_template( \%myconfig, \%$form );
  1129. $form->{title} = $locale->text('Edit Template');
  1130. # convert &nbsp to &amp;nbsp;
  1131. $form->{body} =~ s/&nbsp;/&amp;nbsp;/gi;
  1132. $form->header;
  1133. print qq|
  1134. <body>
  1135. <form method=post action=$form->{script}>
  1136. <input name=file type=hidden value=$form->{file}>
  1137. <input name=type type=hidden value=template>
  1138. <input type=hidden name=path value=$form->{path}>
  1139. <input type=hidden name=login value=$form->{login}>
  1140. <input type=hidden name=sessionid value=$form->{sessionid}>
  1141. <input name=callback type=hidden value="$form->{script}?action=display_form&file=$form->{file}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}">
  1142. <textarea name=body rows=25 cols=70>
  1143. $form->{body}
  1144. </textarea>
  1145. <br>
  1146. <button type="submit" class="submit" name="action" value="save">|
  1147. . $locale->text('Save')
  1148. . qq|</button>|;
  1149. if ( $form->{lynx} ) {
  1150. require "bin/menu.pl";
  1151. &menubar;
  1152. }
  1153. print q|
  1154. </form>
  1155. </body>
  1156. </html>
  1157. |;
  1158. }
  1159. sub save_template {
  1160. AM->save_template( \%myconfig, \%$form );
  1161. $form->redirect( $locale->text('Template saved!') );
  1162. }
  1163. sub defaults {
  1164. # get defaults for account numbers and last numbers
  1165. AM->get_all_defaults( \%$form );
  1166. my %selects = (
  1167. 'FX_loss' => {name => 'FX_loss', options => []},
  1168. 'FX_gain' => {name => 'FX_gain', options => []},
  1169. 'IC_expense' => {name => 'IC_expense', options => []},
  1170. 'IC_income' => {name => 'IC_income', options => []},
  1171. 'IC_inventory' => {name => 'IC_inventory', options => []},
  1172. 'IC' => {name => 'IC', options => []},
  1173. );
  1174. foreach $key ( keys %{ $form->{accno} } ) {
  1175. foreach $accno ( sort keys %{ $form->{accno}{$key} } ) {
  1176. push @{$selects{$key}{options}}, {
  1177. text => "$accno--$form->{accno}{$key}{$accno}{description}",
  1178. value => "$accno--$form->{accno}{$key}{$accno}{description}",
  1179. };
  1180. $selects{$key}{default_values} = "$accno--$form->{accno}{$key}{$accno}{description}" if
  1181. ($form->{defaults}{$key} == $form->{accno}{$key}{$accno}{id});
  1182. }
  1183. }
  1184. for (qw(accno defaults)) { delete $form->{$_} }
  1185. ##SC: temporary commenting out
  1186. ## if ( $form->{lynx} ) {
  1187. ## require "bin/menu.pl";
  1188. ## &menubar;
  1189. ## }
  1190. my %hiddens = (
  1191. path => $form->{path},
  1192. login => $form->{login},
  1193. sessionid => $form->{sessionid},
  1194. type => 'defaults',
  1195. );
  1196. my $template = LedgerSMB::Template->new_UI(
  1197. user => \%myconfig,
  1198. locale => $locale,
  1199. template => 'am-defaults');
  1200. $template->render({
  1201. form => $form,
  1202. hiddens => \%hiddens,
  1203. selects => \%selects,
  1204. });
  1205. }
  1206. sub taxes {
  1207. # get tax account numbers
  1208. AM->taxes( \%myconfig, \%$form );
  1209. $i = 0;
  1210. foreach $ref ( @{ $form->{taxrates} } ) {
  1211. $i++;
  1212. $form->{"taxrate_$i"} =
  1213. $form->format_amount( \%myconfig, $ref->{rate} );
  1214. $form->{"taxdescription_$i"} = $ref->{description};
  1215. for (qw(taxnumber validto pass taxmodulename)) {
  1216. $form->{"${_}_$i"} = $ref->{$_};
  1217. }
  1218. $form->{taxaccounts} .= "$ref->{id}_$i ";
  1219. }
  1220. chop $form->{taxaccounts};
  1221. &display_taxes;
  1222. }
  1223. sub display_taxes {
  1224. $form->{title} = $locale->text('Taxes');
  1225. my %hiddens = (
  1226. path => $form->{path},
  1227. login => $form->{login},
  1228. sessionid => $form->{sessionid},
  1229. type => 'taxes',
  1230. );
  1231. my @rows;
  1232. for ( split( / /, $form->{taxaccounts} ) ) {
  1233. ( $null, $i ) = split /_/, $_;
  1234. $form->{"taxrate_$i"} =
  1235. $form->format_amount( \%myconfig, $form->{"taxrate_$i"} );
  1236. $hiddens{"taxdescription_$i"} = $form->{"taxdescription_$i"};
  1237. my %select = (name => "taxmodule_id_$i", options => []);
  1238. foreach my $taxmodule ( sort keys %$form ) {
  1239. next if ( $taxmodule !~ /^taxmodule_/ );
  1240. next if ( $taxmodule =~ /^taxmodule_id_/ );
  1241. my $modulenum = $taxmodule;
  1242. $modulenum =~ s/^taxmodule_//;
  1243. push @{$select{options}},
  1244. {text => $form->{$taxmodule}, value => $modulenum};
  1245. $select{default_values} = $modulenum
  1246. if $form->{$taxmodule} eq $form->{"taxmodulename_$i"};
  1247. }
  1248. if ( $form->{"taxdescription_$i"} eq $sametax ) {
  1249. push @rows, ["", \%select];
  1250. } else {
  1251. push @rows, [$form->{"taxdescription_$i"}, \%select];
  1252. }
  1253. $sametax = $form->{"taxdescription_$i"};
  1254. }
  1255. $hiddens{taxaccounts} = $form->{taxaccounts};
  1256. foreach my $taxmodule ( sort keys %$form ) {
  1257. next if ( $taxmodule !~ /^taxmodule_/ );
  1258. next if ( $taxmodule =~ /^taxmodule_id_/ );
  1259. $hiddens{$taxmodule};
  1260. }
  1261. ##SC: Temporary removal
  1262. ## if ( $form->{lynx} ) {
  1263. ## require "bin/menu.pl";
  1264. ## &menubar;
  1265. ## }
  1266. my $template = LedgerSMB::Template->new_UI(
  1267. user => \%myconfig,
  1268. locale => $locale,
  1269. template => 'am-taxes');
  1270. $template->render({
  1271. form => $form,
  1272. hiddens => \%hiddens,
  1273. selects => \%selects,
  1274. rows => \@rows,
  1275. });
  1276. }
  1277. sub update {
  1278. @a = split / /, $form->{taxaccounts};
  1279. $ndx = $#a + 1;
  1280. foreach $item (@a) {
  1281. ( $accno, $i ) = split /_/, $item;
  1282. push @t, $accno;
  1283. $form->{"taxmodulename_$i"} =
  1284. $form->{ "taxmodule_" . $form->{"taxmodule_id_$i"} };
  1285. if ( $form->{"validto_$i"} ) {
  1286. $j = $i + 1;
  1287. if ( $form->{"taxdescription_$i"} ne $form->{"taxdescription_$j"} )
  1288. {
  1289. #insert line
  1290. for ( $j = $ndx + 1 ; $j > $i ; $j-- ) {
  1291. $k = $j - 1;
  1292. for (qw(taxrate taxdescription taxnumber validto)) {
  1293. $form->{"${_}_$j"} = $form->{"${_}_$k"};
  1294. }
  1295. }
  1296. $ndx++;
  1297. $k = $i + 1;
  1298. for (qw(taxdescription taxnumber)) {
  1299. $form->{"${_}_$k"} = $form->{"${_}_$i"};
  1300. }
  1301. for (qw(taxrate validto)) { $form->{"${_}_$k"} = "" }
  1302. push @t, $accno;
  1303. }
  1304. }
  1305. else {
  1306. # remove line
  1307. $j = $i + 1;
  1308. if ( $form->{"taxdescription_$i"} eq $form->{"taxdescription_$j"} )
  1309. {
  1310. for ( $j = $i + 1 ; $j <= $ndx ; $j++ ) {
  1311. $k = $j + 1;
  1312. for (qw(taxrate taxdescription taxnumber validto)) {
  1313. $form->{"${_}_$j"} = $form->{"${_}_$k"};
  1314. }
  1315. }
  1316. $ndx--;
  1317. splice @t, $i - 1, 1;
  1318. }
  1319. }
  1320. }
  1321. $i = 1;
  1322. $form->{taxaccounts} = "";
  1323. for (@t) {
  1324. $form->{taxaccounts} .= "${_}_$i ";
  1325. $i++;
  1326. }
  1327. chop $form->{taxaccounts};
  1328. &display_taxes;
  1329. }
  1330. sub config {
  1331. my %selects;
  1332. $selects{dateformat} = {
  1333. name => 'dateformat',
  1334. default_values => $myconfig{dateformat},
  1335. options => [],
  1336. };
  1337. foreach $item (qw(mm-dd-yy mm/dd/yy dd-mm-yy dd/mm/yy dd.mm.yy yyyy-mm-dd))
  1338. {
  1339. push @{$selects{dateformat}{options}}, {text => $item, value => $item};
  1340. }
  1341. $selects{numberformat} = {
  1342. name => 'numberformat',
  1343. default_values => $myconfig{numberformat},
  1344. options => [],
  1345. };
  1346. my @formats = qw(1,000.00 1000.00 1.000,00 1000,00 1'000.00);
  1347. push @formats, '1 000.00';
  1348. foreach $item (@formats) {
  1349. push @{$selects{numberformat}{options}}, {text => $item, value => $item};
  1350. }
  1351. ## for (qw(name company address signature)) {
  1352. ## $myconfig{$_} = $form->quote( $myconfig{$_} );
  1353. ## }
  1354. for (qw(address signature)) { $myconfig{$_} =~ s/\\n/\n/g }
  1355. $selects{countrycode} = {
  1356. name => 'countrycode',
  1357. default_values => ($myconfig{countrycode})? $myconfig{countrycode}: 'en',
  1358. options => [],
  1359. };
  1360. %countrycodes = LedgerSMB::User->country_codes;
  1361. foreach $key ( sort { $countrycodes{$a} cmp $countrycodes{$b} }
  1362. keys %countrycodes )
  1363. {
  1364. push @{$selects{countrycode}{options}}, {
  1365. text => $countrycodes{$key},
  1366. value => $key
  1367. };
  1368. }
  1369. opendir CSS, "css/.";
  1370. @all = grep /.*\.css$/, readdir CSS;
  1371. closedir CSS;
  1372. $selects{stylesheet} = {
  1373. name => 'usestylesheet',
  1374. default_values => $myconfig{stylesheet},
  1375. options => [],
  1376. };
  1377. foreach $item (@all) {
  1378. push @{$selects{stylesheet}{options}}, {text => $item, value => $item};
  1379. }
  1380. push @{$selects{stylesheet}{options}}, {text => 'none', value => '0'};
  1381. if ( %{LedgerSMB::Sysconfig::printer} && ${LedgerSMB::Sysconfig::latex} ) {
  1382. $selects{printer} = {
  1383. name => 'printer',
  1384. default_values => $myconfig{printer},
  1385. options => [],
  1386. };
  1387. foreach $item ( sort keys %{LedgerSMB::Sysconfig::printer} ) {
  1388. push @{$selects{printer}{options}}, {text => $item, value => $item};
  1389. }
  1390. }
  1391. $form->{title} =
  1392. $locale->text( 'Edit Preferences for [_1]', $form->{login} );
  1393. ##SC: Temporary commenting out
  1394. ## if ( $form->{lynx} ) {
  1395. ## require "bin/menu.pl";
  1396. ## &menubar;
  1397. ## }
  1398. my %hiddens = (
  1399. path => $form->{path},
  1400. login => $form->{login},
  1401. sessionid => $form->{sessionid},
  1402. type => 'preferences',
  1403. role => $myconfig{role},
  1404. old_password => $myconfig{password},
  1405. );
  1406. my $template = LedgerSMB::Template->new_UI(
  1407. user => \%myconfig,
  1408. locale => $locale,
  1409. template => 'am-userconfig');
  1410. $template->render({
  1411. form => $form,
  1412. user => \%myconfig,
  1413. hiddens => \%hiddens,
  1414. selects => \%selects,
  1415. });
  1416. }
  1417. sub save_defaults {
  1418. if ( AM->save_defaults( \%myconfig, \%$form ) ) {
  1419. $form->redirect( $locale->text('Defaults saved!') );
  1420. }
  1421. else {
  1422. $form->error( $locale->text('Cannot save defaults!') );
  1423. }
  1424. }
  1425. sub save_taxes {
  1426. if ( AM->save_taxes( \%myconfig, \%$form ) ) {
  1427. $form->redirect( $locale->text('Taxes saved!') );
  1428. }
  1429. else {
  1430. $form->error( $locale->text('Cannot save taxes!') );
  1431. }
  1432. }
  1433. sub save_preferences {
  1434. $form->{stylesheet} = $form->{usestylesheet};
  1435. if ( $form->{new_password} ne $form->{old_password} ) {
  1436. $form->error( $locale->text('Password does not match!') )
  1437. if $form->{new_password} ne $form->{confirm_password};
  1438. }
  1439. if ( AM->save_preferences( \%myconfig, \%$form ) ) {
  1440. $form->info( $locale->text('Preferences saved!') );
  1441. }
  1442. else {
  1443. $form->error( $locale->text('Cannot save preferences!') );
  1444. }
  1445. }
  1446. sub backup {
  1447. if ( $form->{media} eq 'email' ) {
  1448. $form->error(
  1449. $locale->text( 'No email address for [_1]', $myconfig{name} ) )
  1450. unless ( $myconfig{email} );
  1451. }
  1452. $SIG{INT} = 'IGNORE';
  1453. AM->backup(
  1454. \%myconfig, \%$form,
  1455. ${LedgerSMB::Sysconfig::userspath},
  1456. ${LedgerSMB::Sysconfig::gzip}
  1457. );
  1458. if ( $form->{media} eq 'email' ) {
  1459. $form->redirect(
  1460. $locale->text( 'Backup sent to [_1]', $myconfig{email} ) );
  1461. }
  1462. }
  1463. sub audit_control {
  1464. $form->{title} = $locale->text('Audit Control');
  1465. AM->closedto( \%myconfig, \%$form );
  1466. my %checked;
  1467. if ( $form->{revtrans} ) {
  1468. $checked{revtransY} = 'checked';
  1469. } else {
  1470. $checked{revtransN} = 'checked';
  1471. }
  1472. if ( $form->{audittrail} ) {
  1473. $checked{audittrailY} = 'checked';
  1474. } else {
  1475. $checked{audittrailN} = 'checked';
  1476. }
  1477. my %hiddens = (
  1478. path => $form->{path},
  1479. login => $form->{login},
  1480. sessionid => $form->{sessionid},
  1481. );
  1482. my $template = LedgerSMB::Template->new_UI(
  1483. user => \%myconfig,
  1484. locale => $locale,
  1485. template => 'am-audit-control');
  1486. $template->render({
  1487. user => \%myconfig,
  1488. form => $form,
  1489. checked => \%checked,
  1490. hiddens => \%hiddens,
  1491. });
  1492. }
  1493. sub doclose {
  1494. AM->closebooks( \%myconfig, \%$form );
  1495. if ( $form->{revtrans} ) {
  1496. $msg = $locale->text('Transaction reversal enforced for all dates');
  1497. }
  1498. else {
  1499. if ( $form->{closedto} ) {
  1500. $msg =
  1501. $locale->text('Transaction reversal enforced up to [_1]',
  1502. $locale->date( \%myconfig, $form->{closedto}, 1 ));
  1503. }
  1504. else {
  1505. $msg = $locale->text('Books are open');
  1506. }
  1507. }
  1508. $msg .= "<p>";
  1509. if ( $form->{audittrail} ) {
  1510. $msg .= $locale->text('Audit trail enabled');
  1511. }
  1512. else {
  1513. $msg .= $locale->text('Audit trail disabled');
  1514. }
  1515. ##SC: Disabling audit trail deletion
  1516. ## $msg .= "<p>";
  1517. ## if ( $form->{removeaudittrail} ) {
  1518. ## $msg .=
  1519. ## $locale->text('Audit trail removed up to') . " "
  1520. ## . $locale->date( \%myconfig, $form->{removeaudittrail}, 1 );
  1521. ## }
  1522. $form->redirect($msg);
  1523. }
  1524. sub add_warehouse {
  1525. $form->{title} = "Add";
  1526. $form->{callback} =
  1527. "$form->{script}?action=add_warehouse&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}"
  1528. unless $form->{callback};
  1529. &warehouse_header;
  1530. &form_footer;
  1531. }
  1532. sub edit_warehouse {
  1533. $form->{title} = "Edit";
  1534. AM->get_warehouse( \%myconfig, \%$form );
  1535. &warehouse_header;
  1536. &form_footer;
  1537. }
  1538. sub list_warehouse {
  1539. AM->warehouses( \%myconfig, \%$form );
  1540. $href =
  1541. "$form->{script}?action=list_warehouse&direction=$form->{direction}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  1542. $form->sort_order();
  1543. $form->{callback} =
  1544. "$form->{script}?action=list_warehouse&direction=$form->{direction}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  1545. $callback = $form->escape( $form->{callback} );
  1546. $form->{title} = $locale->text('Warehouses');
  1547. @column_index = qw(description);
  1548. $column_header{description} =
  1549. qq|<th width=100%><a class="listheading" href=$href>|
  1550. . $locale->text('Description')
  1551. . qq|</a></th>|;
  1552. $form->header;
  1553. print qq|
  1554. <body>
  1555. <table width=100%>
  1556. <tr>
  1557. <th class=listtop>$form->{title}</th>
  1558. </tr>
  1559. <tr height="5"></tr>
  1560. <tr>
  1561. <td>
  1562. <table width=100%>
  1563. <tr class="listheading">
  1564. |;
  1565. for (@column_index) { print "$column_header{$_}\n" }
  1566. print qq|
  1567. </tr>
  1568. |;
  1569. foreach $ref ( @{ $form->{ALL} } ) {
  1570. $i++;
  1571. $i %= 2;
  1572. print qq|
  1573. <tr valign=top class=listrow$i>
  1574. |;
  1575. $column_data{description} =
  1576. qq|<td><a href=$form->{script}?action=edit_warehouse&id=$ref->{id}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}&callback=$callback>$ref->{description}</td>|;
  1577. for (@column_index) { print "$column_data{$_}\n" }
  1578. print qq|
  1579. </tr>
  1580. |;
  1581. }
  1582. print qq|
  1583. </table>
  1584. </td>
  1585. </tr>
  1586. <tr>
  1587. <td><hr size=3 noshade></td>
  1588. </tr>
  1589. </table>
  1590. <br>
  1591. <form method=post action=$form->{script}>
  1592. |;
  1593. $form->{type} = "warehouse";
  1594. $form->hide_form(qw(type callback path login sessionid));
  1595. print qq|
  1596. <button class="submit" type="submit" name="action" value="add_warehouse">|
  1597. . $locale->text('Add Warehouse')
  1598. . qq|</button>|;
  1599. if ( $form->{lynx} ) {
  1600. require "bin/menu.pl";
  1601. &menubar;
  1602. }
  1603. print qq|
  1604. </form>
  1605. </body>
  1606. </html>
  1607. |;
  1608. }
  1609. sub warehouse_header {
  1610. $form->{title} = $locale->text("$form->{title} Warehouse");
  1611. # $locale->text('Add Warehouse')
  1612. # $locale->text('Edit Warehouse')
  1613. $form->{description} = $form->quote( $form->{description} );
  1614. if ( ( $rows = $form->numtextrows( $form->{description}, 60 ) ) > 1 ) {
  1615. $description =
  1616. qq|<textarea name="description" rows=$rows cols=60 wrap=soft>$form->{description}</textarea>|;
  1617. }
  1618. else {
  1619. $description =
  1620. qq|<input name=description size=60 value="$form->{description}">|;
  1621. }
  1622. $form->header;
  1623. print qq|
  1624. <body>
  1625. <form method=post action=$form->{script}>
  1626. <input type=hidden name=id value=$form->{id}>
  1627. <input type=hidden name=type value=warehouse>
  1628. <table width=100%>
  1629. <tr>
  1630. <th class=listtop colspan=2>$form->{title}</th>
  1631. </tr>
  1632. <tr height="5"></tr>
  1633. <tr>
  1634. <th align="right">| . $locale->text('Description') . qq|</th>
  1635. <td>$description</td>
  1636. </tr>
  1637. <tr>
  1638. <td colspan=2><hr size=3 noshade></td>
  1639. </tr>
  1640. </table>
  1641. |;
  1642. }
  1643. sub save_warehouse {
  1644. $form->isblank( "description", $locale->text('Description missing!') );
  1645. AM->save_warehouse( \%myconfig, \%$form );
  1646. $form->redirect( $locale->text('Warehouse saved!') );
  1647. }
  1648. sub delete_warehouse {
  1649. AM->delete_warehouse( \%myconfig, \%$form );
  1650. $form->redirect( $locale->text('Warehouse deleted!') );
  1651. }
  1652. sub yearend {
  1653. AM->earningsaccounts( \%myconfig, \%$form );
  1654. $chart = "";
  1655. for ( @{ $form->{chart} } ) {
  1656. $chart .= "<option>$_->{accno}--$_->{description}";
  1657. }
  1658. $form->{title} = $locale->text('Yearend');
  1659. $form->header;
  1660. print qq|
  1661. <body>
  1662. <form method=post action=$form->{script}>
  1663. <input type=hidden name=decimalplaces value=2>
  1664. <input type=hidden name=l_accno value=Y>
  1665. <table width=100%>
  1666. <tr>
  1667. <th class=listtop>$form->{title}</th>
  1668. </tr>
  1669. <tr height="5"></tr>
  1670. <tr>
  1671. <td>
  1672. <table>
  1673. <tr>
  1674. <th align="right">| . $locale->text('Yearend') . qq|</th>
  1675. <td><input class="date" name=todate size=11 title="$myconfig{dateformat}" value=$todate></td>
  1676. </tr>
  1677. <tr>
  1678. <th align="right">| . $locale->text('Reference') . qq|</th>
  1679. <td><input name=reference size=20 value="|
  1680. . $locale->text('Yearend')
  1681. . qq|"></td>
  1682. </tr>
  1683. <tr>
  1684. <th align="right">| . $locale->text('Description') . qq|</th>
  1685. <td><textarea name=description rows=3 cols=50 wrap=soft></textarea></td>
  1686. </tr>
  1687. <tr>
  1688. <th align="right">| . $locale->text('Retained Earnings') . qq|</th>
  1689. <td><select name=accno>$chart</select></td>
  1690. </tr>
  1691. <tr>
  1692. <th align="right">| . $locale->text('Method') . qq|</th>
  1693. <td><input name=method class=radio type=radio value=accrual checked>&nbsp;|
  1694. . $locale->text('Accrual')
  1695. . qq|&nbsp;<input name=method class=radio type=radio value=cash>&nbsp;|
  1696. . $locale->text('Cash')
  1697. . qq|</td>
  1698. </tr>
  1699. </table>
  1700. </td>
  1701. </tr>
  1702. </table>
  1703. <hr size=3 noshade>
  1704. <input type=hidden name=nextsub value=generate_yearend>
  1705. |;
  1706. $form->hide_form(qw(path login sessionid));
  1707. print qq|
  1708. <button class="submit" type="submit" name="action" value="continue">|
  1709. . $locale->text('Continue')
  1710. . qq|</button>|;
  1711. }
  1712. sub generate_yearend {
  1713. $form->isblank( "todate", $locale->text('Yearend date missing!') );
  1714. RP->yearend_statement( \%myconfig, \%$form );
  1715. $form->{transdate} = $form->{todate};
  1716. $earnings = 0;
  1717. $form->{rowcount} = 1;
  1718. foreach $key ( keys %{ $form->{I} } ) {
  1719. if ( $form->{I}{$key}{charttype} eq "A" ) {
  1720. $form->{"debit_$form->{rowcount}"} = $form->{I}{$key}{this};
  1721. $earnings += $form->{I}{$key}{this};
  1722. $form->{"accno_$form->{rowcount}"} = $key;
  1723. $form->{rowcount}++;
  1724. $ok = 1;
  1725. }
  1726. }
  1727. foreach $key ( keys %{ $form->{E} } ) {
  1728. if ( $form->{E}{$key}{charttype} eq "A" ) {
  1729. $form->{"credit_$form->{rowcount}"} = $form->{E}{$key}{this} * -1;
  1730. $earnings += $form->{E}{$key}{this};
  1731. $form->{"accno_$form->{rowcount}"} = $key;
  1732. $form->{rowcount}++;
  1733. $ok = 1;
  1734. }
  1735. }
  1736. if ( $earnings > 0 ) {
  1737. $form->{"credit_$form->{rowcount}"} = $earnings;
  1738. $form->{"accno_$form->{rowcount}"} = $form->{accno};
  1739. }
  1740. else {
  1741. $form->{"debit_$form->{rowcount}"} = $earnings * -1;
  1742. $form->{"accno_$form->{rowcount}"} = $form->{accno};
  1743. }
  1744. if ($ok) {
  1745. if ( AM->post_yearend( \%myconfig, \%$form ) ) {
  1746. $form->redirect( $locale->text('Yearend posted!') );
  1747. }
  1748. else {
  1749. $form->error( $locale->text('Yearend posting failed!') );
  1750. }
  1751. }
  1752. else {
  1753. $form->error('Nothing to do!');
  1754. }
  1755. }
  1756. sub company_logo {
  1757. $myconfig{address} =~ s/\\n/<br>/g;
  1758. $myconfig{dbhost} = $locale->text('localhost') unless $myconfig{dbhost};
  1759. $form->{stylesheet} = $myconfig{stylesheet};
  1760. $form->{title} = $locale->text('About');
  1761. # create the logo screen
  1762. $form->header;
  1763. print qq|
  1764. <body>
  1765. <pre>
  1766. </pre>
  1767. <center>
  1768. <a href="http://www.ledgersmb.org/" target="_blank"><img src="images/ledgersmb.png" width="200" height="100" border="0" alt="LedgerSMB Logo" /></a>
  1769. <h1 class="login">| . $locale->text('Version') . qq| $form->{version}</h1>
  1770. <p>
  1771. |.$locale->text('Company').qq| :
  1772. <p>
  1773. <b>
  1774. $myconfig{company}
  1775. <br>$myconfig{address}
  1776. </b>
  1777. <p>
  1778. <table border=0>
  1779. <tr>
  1780. <th align="right">| . $locale->text('User') . qq|</th>
  1781. <td>$myconfig{name}</td>
  1782. </tr>
  1783. <tr>
  1784. <th align="right">| . $locale->text('Dataset') . qq|</th>
  1785. <td>$myconfig{dbname}</td>
  1786. </tr>
  1787. <tr>
  1788. <th align="right">| . $locale->text('Database Host') . qq|</th>
  1789. <td>$myconfig{dbhost}</td>
  1790. </tr>
  1791. </table>
  1792. </center>
  1793. </body>
  1794. </html>
  1795. |;
  1796. }
  1797. sub recurring_transactions {
  1798. # $locale->text('Day')
  1799. # $locale->text('Days')
  1800. # $locale->text('Month')
  1801. # $locale->text('Months')
  1802. # $locale->text('Week')
  1803. # $locale->text('Weeks')
  1804. # $locale->text('Year')
  1805. # $locale->text('Years')
  1806. my %hiddens;
  1807. my %column_header;
  1808. $form->{stylesheet} = $myconfig{stylesheet};
  1809. $form->{title} = $locale->text('Recurring Transactions');
  1810. $column_header{id} = "";
  1811. AM->recurring_transactions( \%myconfig, \%$form );
  1812. $href = "$form->{script}?action=recurring_transactions";
  1813. for (qw(direction oldsort path login sessionid)) {
  1814. $href .= qq|&$_=$form->{$_}|;
  1815. }
  1816. $form->sort_order();
  1817. my @column_index = qw(ndx reference description);
  1818. push @column_index,
  1819. qw(nextdate enddate id amount curr repeat howmany recurringemail recurringprint);
  1820. $column_header{reference} = {
  1821. text => $locale->text('Reference'),
  1822. href => "$href&sort=reference",
  1823. };
  1824. $column_header{ndx} = ' ';
  1825. $column_header{id} = $locale->text('ID');
  1826. $column_header{description} = $locale->text('Description');
  1827. $column_header{nextdate} = {
  1828. text => $locale->text('Next'),
  1829. href => "$href&sort=nextdate",
  1830. };
  1831. $column_header{enddate} = {
  1832. text => $locale->text('Ends'),
  1833. href => "$href&sort=enddate",
  1834. };
  1835. $column_header{amount} = $locale->text('Amount');
  1836. $column_header{curr} = ' ';
  1837. $column_header{repeat} = $locale->text('Every');
  1838. $column_header{howmany} = $locale->text('Times');
  1839. $column_header{recurringemail} = $locale->text('E-mail');
  1840. $column_header{recurringprint} = $locale->text('Print');
  1841. my $i = 1;
  1842. my %tr = (
  1843. ar => $locale->text('AR'),
  1844. ap => $locale->text('AP'),
  1845. gl => $locale->text('GL'),
  1846. so => $locale->text('Sales Orders'),
  1847. po => $locale->text('Purchase Orders'),
  1848. );
  1849. my %f = &formnames;
  1850. my @transactions;
  1851. my $j;
  1852. my $k;
  1853. foreach my $transaction ( sort keys %{ $form->{transactions} } ) {
  1854. my $transaction_count = scalar( @{ $form->{transactions}{$transaction} } );
  1855. push @transactions, {type => $transaction,
  1856. title => "$tr{$transaction} ($transaction_count)",
  1857. transactions => [],
  1858. };
  1859. foreach my $ref ( @{ $form->{transactions}{$transaction} } ) {
  1860. my %column_data;
  1861. for (@column_index) {
  1862. $column_data{$_} = "$ref->{$_}";
  1863. }
  1864. my $unit;
  1865. my $repeat;
  1866. if ( $ref->{repeat} > 1 ) {
  1867. $unit = $locale->text( ucfirst $ref->{unit} );
  1868. $repeat = "$ref->{repeat} $unit";
  1869. }
  1870. else {
  1871. chop $ref->{unit};
  1872. $unit = $locale->text( ucfirst $ref->{unit} );
  1873. $repeat = $unit;
  1874. }
  1875. $column_data{ndx} = '';
  1876. if ( !$ref->{expired} ) {
  1877. if ( $ref->{overdue} <= 0 ) {
  1878. $k++;
  1879. $column_data{ndx} = {
  1880. name => "ndx_$k",
  1881. type => 'checkbox',
  1882. value => $ref->{id},
  1883. checked => 'checked',
  1884. };
  1885. }
  1886. }
  1887. my $reference =
  1888. ( $ref->{reference} )
  1889. ? $ref->{reference}
  1890. : $locale->text('Next Number');
  1891. $column_data{reference} = {
  1892. text => $reference,
  1893. href => qq|$form->{script}?action=edit_recurring&id=$ref->{id}&vc=$ref->{vc}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}&module=$ref->{module}&invoice=$ref->{invoice}&transaction=$ref->{transaction}&recurringnextdate=$ref->{nextdate}|,
  1894. };
  1895. my $module = "$ref->{module}.pl";
  1896. my $type = "";
  1897. if ( $ref->{module} eq 'ar' ) {
  1898. $module = "is.pl" if $ref->{invoice};
  1899. $ref->{amount} /= $ref->{exchangerate};
  1900. }
  1901. if ( $ref->{module} eq 'ap' ) {
  1902. $module = "ir.pl" if $ref->{invoice};
  1903. $ref->{amount} /= $ref->{exchangerate};
  1904. }
  1905. if ( $ref->{module} eq 'oe' ) {
  1906. $type =
  1907. ( $ref->{vc} eq 'customer' )
  1908. ? "sales_order"
  1909. : "purchase_order";
  1910. }
  1911. $column_data{id} = {
  1912. text => $ref->{id},
  1913. href => qq|$module?action=edit&id=$ref->{id}&vc=$ref->{vc}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}&type=$type&readonly=1|,
  1914. };
  1915. $column_data{repeat} = $repeat;
  1916. $column_data{howmany} =
  1917. $form->format_amount( \%myconfig, $ref->{howmany} );
  1918. $column_data{amount} =
  1919. $form->format_amount( \%myconfig, $ref->{amount}, 2 );
  1920. my @temp_split;
  1921. my @f = split /:/, $ref->{recurringemail};
  1922. for ( 0 .. $#f ) {
  1923. push @temp_split, $f{$f[$_]};
  1924. }
  1925. $column_data{recurringemail} = {
  1926. text => join ':', @temp_split,
  1927. delimeter => ':',
  1928. };
  1929. @temp_split = ();
  1930. @f = split /:/, $ref->{recurringprint};
  1931. for ( 0 .. $#f ) {
  1932. push @temp_split, $f{$f[$_]};
  1933. }
  1934. $column_data{recurringprint} = {
  1935. text => join ':', @temp_split,
  1936. delimeter => ':',
  1937. };
  1938. $j++;
  1939. $j %= 2;
  1940. $column_data{i} = $j;
  1941. push @{$transactions[$#transactions]{transactions}}, \%column_data;
  1942. }
  1943. }
  1944. ##SC: Temporary removal
  1945. ## if ( $form->{lynx} ) {
  1946. ## require "bin/menu.pl";
  1947. ## &menubar;
  1948. ## }
  1949. $hiddens{path} = $form->{path};
  1950. $hiddens{login} = $form->{login};
  1951. $hiddens{sessionid} = $form->{sessionid};
  1952. $hiddens{lastndx} = $k;
  1953. my @buttons;
  1954. push @buttons, {
  1955. name => 'action',
  1956. value => 'process_transactions',
  1957. text => $locale->text('Process Transactions'),
  1958. type => 'submit',
  1959. class => 'submit',
  1960. };
  1961. my $template = LedgerSMB::Template->new_UI(
  1962. user => \%myconfig,
  1963. locale => $locale,
  1964. template => 'am-list-recurring');
  1965. $template->render({
  1966. form => $form,
  1967. buttons => \@buttons,
  1968. columns => \@column_index,
  1969. heading => \%column_header,
  1970. transactions => \@transactions,
  1971. hiddens => \%hiddens,
  1972. });
  1973. }
  1974. sub edit_recurring {
  1975. %links = (
  1976. ar => 'create_links',
  1977. ap => 'create_links',
  1978. gl => 'create_links',
  1979. is => 'invoice_links',
  1980. ir => 'invoice_links',
  1981. oe => 'order_links',
  1982. );
  1983. %prepare = (
  1984. is => 'prepare_invoice',
  1985. ir => 'prepare_invoice',
  1986. oe => 'prepare_order',
  1987. );
  1988. $form->{callback} =
  1989. "$form->{script}?action=recurring_transactions&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  1990. $form->{type} = "transaction";
  1991. if ( $form->{module} eq 'ar' ) {
  1992. if ( $form->{invoice} ) {
  1993. $form->{type} = "invoice";
  1994. $form->{module} = "is";
  1995. }
  1996. }
  1997. if ( $form->{module} eq 'ap' ) {
  1998. if ( $form->{invoice} ) {
  1999. $form->{type} = "invoice";
  2000. $form->{module} = "ir";
  2001. }
  2002. }
  2003. if ( $form->{module} eq 'oe' ) {
  2004. %tr = (
  2005. so => sales_order,
  2006. po => purchase_order,
  2007. );
  2008. $form->{type} = $tr{ $form->{transaction} };
  2009. }
  2010. $form->{script} = "$form->{module}.pl";
  2011. do "bin/$form->{script}";
  2012. &{ $links{ $form->{module} } };
  2013. # return if transaction doesn't exist
  2014. $form->redirect unless $form->{recurring};
  2015. if ( $prepare{ $form->{module} } ) {
  2016. &{ $prepare{ $form->{module} } };
  2017. }
  2018. $form->{selectformat} = qq|<option value="html">html\n|;
  2019. if ( ${LedgerSMB::Sysconfig::latex} ) {
  2020. $form->{selectformat} .= qq|
  2021. <option value="postscript">| . $locale->text('Postscript') . qq|
  2022. <option value="pdf">| . $locale->text('PDF');
  2023. }
  2024. &schedule;
  2025. }
  2026. sub process_transactions {
  2027. # save variables
  2028. my $pt = new Form;
  2029. for ( keys %$form ) { $pt->{$_} = $form->{$_} }
  2030. my $defaultprinter;
  2031. while ( my ( $key, $value ) = each %{LedgerSMB::Sysconfig::printer} ) {
  2032. if ( $value =~ /lpr/ ) {
  2033. $defaultprinter = $key;
  2034. last;
  2035. }
  2036. }
  2037. $myconfig{vclimit} = 0;
  2038. %f = &formnames;
  2039. for ( my $i = 1 ; $i <= $pt->{lastndx} ; $i++ ) {
  2040. if ( $pt->{"ndx_$i"} ) {
  2041. $id = $pt->{"ndx_$i"};
  2042. # process transaction
  2043. AM->recurring_details( \%myconfig, \%$pt, $id );
  2044. $header = $form->{header};
  2045. # reset $form
  2046. for ( keys %$form ) { delete $form->{$_}; }
  2047. for (qw(login path sessionid stylesheet timeout)) {
  2048. $form->{$_} = $pt->{$_};
  2049. }
  2050. $form->{id} = $id;
  2051. $form->{header} = $header;
  2052. $form->db_init(\%myconfig);
  2053. # post, print, email
  2054. if ( $pt->{arid} || $pt->{apid} || $pt->{oeid} ) {
  2055. if ( $pt->{arid} || $pt->{apid} ) {
  2056. if ( $pt->{arid} ) {
  2057. $form->{script} =
  2058. ( $pt->{invoice} ) ? "is.pl" : "ar.pl";
  2059. $form->{ARAP} = "AR";
  2060. $form->{module} = "ar";
  2061. $invfld = "sinumber";
  2062. }
  2063. else {
  2064. $form->{script} =
  2065. ( $pt->{invoice} ) ? "ir.pl" : "ap.pl";
  2066. $form->{ARAP} = "AP";
  2067. $form->{module} = "ap";
  2068. $invfld = "vinumber";
  2069. }
  2070. do "bin/$form->{script}";
  2071. if ( $pt->{invoice} ) {
  2072. &invoice_links;
  2073. &prepare_invoice;
  2074. for ( keys %$form ) {
  2075. $form->{$_} = $form->unquote( $form->{$_} );
  2076. }
  2077. }
  2078. else {
  2079. &create_links;
  2080. $form->{type} = "transaction";
  2081. for ( 1 .. $form->{rowcount} - 1 ) {
  2082. $form->{"amount_$_"} =
  2083. $form->format_amount( \%myconfig,
  2084. $form->{"amount_$_"}, 2 );
  2085. }
  2086. for ( 1 .. $form->{paidaccounts} ) {
  2087. $form->{"paid_$_"} =
  2088. $form->format_amount( \%myconfig,
  2089. $form->{"paid_$_"}, 2 );
  2090. }
  2091. }
  2092. delete $form->{"$form->{ARAP}_links"};
  2093. for (qw(acc_trans invoice_details)) { delete $form->{$_} }
  2094. for (
  2095. qw(department employee language month partsgroup project years)
  2096. )
  2097. {
  2098. delete $form->{"all_$_"};
  2099. }
  2100. $form->{invnumber} = $pt->{reference};
  2101. $form->{transdate} = $pt->{nextdate};
  2102. # tax accounts
  2103. $form->all_taxaccounts( \%myconfig, undef,
  2104. $form->{transdate} );
  2105. # calculate duedate
  2106. $form->{duedate} =
  2107. $form->add_date( \%myconfig, $form->{transdate},
  2108. $pt->{overdue}, "days" );
  2109. if ( $pt->{payment} ) {
  2110. # calculate date paid
  2111. for ( $j = 1 ; $j <= $form->{paidaccounts} ; $j++ ) {
  2112. $form->{"datepaid_$j"} =
  2113. $form->add_date( \%myconfig, $form->{transdate},
  2114. $pt->{paid}, "days" );
  2115. ( $form->{"$form->{ARAP}_paid_$j"} ) = split /--/,
  2116. $form->{"$form->{ARAP}_paid_$j"};
  2117. delete $form->{"cleared_$j"};
  2118. }
  2119. $form->{paidaccounts}++;
  2120. }
  2121. else {
  2122. $form->{paidaccounts} = -1;
  2123. }
  2124. for (qw(id recurring intnotes printed emailed queued)) {
  2125. delete $form->{$_};
  2126. }
  2127. ( $form->{ $form->{ARAP} } ) = split /--/,
  2128. $form->{ $form->{ARAP} };
  2129. $form->{invnumber} =
  2130. $form->update_defaults( \%myconfig, "$invfld" )
  2131. unless $form->{invnumber};
  2132. $form->{reference} = $form->{invnumber};
  2133. for (qw(invnumber reference)) {
  2134. $form->{$_} = $form->unquote( $form->{$_} );
  2135. }
  2136. if ( $pt->{invoice} ) {
  2137. if ( $pt->{arid} ) {
  2138. $form->info(
  2139. "\n"
  2140. . $locale->text(
  2141. 'Posting Sales Invoice [_1]',
  2142. $form->{invnumber}
  2143. )
  2144. );
  2145. $ok = IS->post_invoice( \%myconfig, \%$form );
  2146. }
  2147. else {
  2148. $form->info(
  2149. "\n"
  2150. . $locale->text(
  2151. 'Posting Vendor Invoice [_1]',
  2152. $form->{invnumber}
  2153. )
  2154. );
  2155. $ok = IR->post_invoice( \%myconfig, \%$form );
  2156. }
  2157. }
  2158. else {
  2159. if ( $pt->{arid} ) {
  2160. $form->info(
  2161. "\n"
  2162. . $locale->text(
  2163. 'Posting Transaction [_1]',
  2164. $form->{invnumber}
  2165. )
  2166. );
  2167. }
  2168. else {
  2169. $form->info(
  2170. "\n"
  2171. . $locale->text(
  2172. 'Posting Transaction [_1]',
  2173. $form->{invnumber}
  2174. )
  2175. );
  2176. }
  2177. $ok = AA->post_transaction( \%myconfig, \%$form );
  2178. }
  2179. $form->info( " ..... " . $locale->text('done') );
  2180. # print form
  2181. if ( ${LedgerSMB::Sysconfig::latex} && $ok ) {
  2182. $ok = &print_recurring( \%$pt, $defaultprinter );
  2183. }
  2184. &email_recurring( \%$pt ) if $ok;
  2185. }
  2186. else {
  2187. # order
  2188. $form->{script} = "oe.pl";
  2189. $form->{module} = "oe";
  2190. $ordnumber = "ordnumber";
  2191. if ( $pt->{customer_id} ) {
  2192. $form->{vc} = "customer";
  2193. $form->{type} = "sales_order";
  2194. $ordfld = "sonumber";
  2195. $flabel = $locale->text('Sales Order');
  2196. }
  2197. else {
  2198. $form->{vc} = "vendor";
  2199. $form->{type} = "purchase_order";
  2200. $ordfld = "ponumber";
  2201. $flabel = $locale->text('Purchase Order');
  2202. }
  2203. require "bin/$form->{script}";
  2204. &order_links;
  2205. &prepare_order;
  2206. for ( keys %$form ) {
  2207. $form->{$_} = $form->unquote( $form->{$_} );
  2208. }
  2209. $form->{$ordnumber} = $pt->{reference};
  2210. $form->{transdate} = $pt->{nextdate};
  2211. # calculate reqdate
  2212. $form->{reqdate} =
  2213. $form->add_date( \%myconfig, $form->{transdate},
  2214. $pt->{req}, "days" )
  2215. if $form->{reqdate};
  2216. for (qw(id recurring intnotes printed emailed queued)) {
  2217. delete $form->{$_};
  2218. }
  2219. for ( 1 .. $form->{rowcount} ) {
  2220. delete $form->{"orderitems_id_$_"};
  2221. }
  2222. $form->{$ordnumber} =
  2223. $form->update_defaults( \%myconfig, "$ordfld" )
  2224. unless $form->{$ordnumber};
  2225. $form->{reference} = $form->{$ordnumber};
  2226. for ( "$ordnumber", "reference" ) {
  2227. $form->{$_} = $form->unquote( $form->{$_} );
  2228. }
  2229. $form->{closed} = 0;
  2230. $form->info(
  2231. "\n"
  2232. . $locale->text(
  2233. 'Saving [_1] [_2]',
  2234. $flabel, $form->{$ordnumber}
  2235. )
  2236. );
  2237. if ( $ok = OE->save( \%myconfig, \%$form ) ) {
  2238. $form->info( " ..... " . $locale->text('done') );
  2239. }
  2240. else {
  2241. $form->info( " ..... " . $locale->text('failed') );
  2242. }
  2243. # print form
  2244. if ( ${LedgerSMB::Sysconfig::latex} && $ok ) {
  2245. &print_recurring( \%$pt, $defaultprinter );
  2246. }
  2247. &email_recurring( \%$pt );
  2248. }
  2249. }
  2250. else {
  2251. # GL transaction
  2252. GL->transaction( \%myconfig, \%$form );
  2253. $form->{reference} = $pt->{reference};
  2254. $form->{transdate} = $pt->{nextdate};
  2255. $j = 1;
  2256. foreach $ref ( @{ $form->{GL} } ) {
  2257. $form->{"accno_$j"} = "$ref->{accno}--$ref->{description}";
  2258. $form->{"projectnumber_$j"} =
  2259. "$ref->{projectnumber}--$ref->{project_id}"
  2260. if $ref->{project_id};
  2261. $form->{"fx_transaction_$j"} = $ref->{fx_transaction};
  2262. if ( $ref->{amount} < 0 ) {
  2263. $form->{"debit_$j"} = $ref->{amount} * -1;
  2264. }
  2265. else {
  2266. $form->{"credit_$j"} = $ref->{amount};
  2267. }
  2268. $j++;
  2269. }
  2270. $form->{rowcount} = $j;
  2271. for (qw(id recurring)) { delete $form->{$_} }
  2272. $form->info(
  2273. "\n"
  2274. . $locale->text(
  2275. 'Posting GL Transaction [_1]',
  2276. $form->{reference}
  2277. )
  2278. );
  2279. $ok = GL->post_transaction( \%myconfig, \%$form );
  2280. $form->info( " ..... " . $locale->text('done') );
  2281. }
  2282. AM->update_recurring( \%myconfig, \%$pt, $id ) if $ok;
  2283. }
  2284. }
  2285. $form->{callback} =
  2286. "am.pl?action=recurring_transactions&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}&header=$form->{header}";
  2287. $form->redirect;
  2288. }
  2289. sub print_recurring {
  2290. my ( $pt, $defaultprinter ) = @_;
  2291. use List::Util qw(first);
  2292. my %f = &formnames;
  2293. my $ok = 1;
  2294. if ( $pt->{recurringprint} ) {
  2295. @f = split /:/, $pt->{recurringprint};
  2296. for ( $j = 0 ; $j <= $#f ; $j += 3 ) {
  2297. $media = $f[ $j + 2 ];
  2298. $media ||= $myconfig->{printer}
  2299. if ${LedgerSMB::Sysconfig::printer}{ $myconfig->{printer} };
  2300. $media ||= $defaultprinter;
  2301. $form->info( "\n"
  2302. . $locale->text('Printing') . " "
  2303. . $locale->text( $f{ $f[$j] } )
  2304. . " $form->{reference}" );
  2305. @a = (
  2306. "perl", "$form->{script}",
  2307. "action=reprint&module=$form->{module}&type=$form->{type}&login=$form->{login}&path=$form->{path}&sessionid=$form->{sessionid}&id=$form->{id}&formname=$f[$j]&format=$f[$j+1]&media=$media&vc=$form->{vc}&ARAP=$form->{ARAP}"
  2308. );
  2309. $form->error( $locale->text('Invalid redirect') )
  2310. unless first { $_ eq $form->{script} }
  2311. @{LedgerSMB::Sysconfig::scripts};
  2312. $ok = !( system(@a) );
  2313. if ($ok) {
  2314. $form->info( " ..... " . $locale->text('done') );
  2315. }
  2316. else {
  2317. $form->info( " ..... " . $locale->text('failed') );
  2318. last;
  2319. }
  2320. }
  2321. }
  2322. $ok;
  2323. }
  2324. sub email_recurring {
  2325. my ($pt) = @_;
  2326. use List::Util qw(first);
  2327. my %f = &formnames;
  2328. my $ok = 1;
  2329. if ( $pt->{recurringemail} ) {
  2330. @f = split /:/, $pt->{recurringemail};
  2331. for ( $j = 0 ; $j <= $#f ; $j += 2 ) {
  2332. $form->info( "\n"
  2333. . $locale->text('Sending') . " "
  2334. . $locale->text( $f{ $f[$j] } )
  2335. . " $form->{reference}" );
  2336. # no email, bail out
  2337. if ( !$form->{email} ) {
  2338. $form->info(
  2339. " ..... " . $locale->text('E-mail address missing!') );
  2340. last;
  2341. }
  2342. $message = $form->escape( $pt->{message}, 1 );
  2343. @a = (
  2344. "perl", "$form->{script}",
  2345. "action=reprint&module=$form->{module}&type=$form->{type}&login=$form->{login}&path=$form->{path}&sessionid=$form->{sessionid}&id=$form->{id}&formname=$f[$j]&format=$f[$j+1]&media=email&vc=$form->{vc}&ARAP=$form->{ARAP}&message=$message"
  2346. );
  2347. $form->error( $locale->text('Invalid redirect') )
  2348. unless first { $_ eq $form->{script} }
  2349. @{LedgerSMB::Sysconfig::scripts};
  2350. $ok = !( system(@a) );
  2351. if ($ok) {
  2352. $form->info( " ..... " . $locale->text('done') );
  2353. }
  2354. else {
  2355. $form->info( " ..... " . $locale->text('failed') );
  2356. last;
  2357. }
  2358. }
  2359. }
  2360. $ok;
  2361. }
  2362. sub formnames {
  2363. # $locale->text('Transaction')
  2364. # $locale->text('Invoice')
  2365. # $locale->text('Credit Invoice')
  2366. # $locale->text('Debit Invoice')
  2367. # $locale->text('Packing List')
  2368. # $locale->text('Pick List')
  2369. # $locale->text('Sales Order')
  2370. # $locale->text('Work Order')
  2371. # $locale->text('Purchase Order')
  2372. # $locale->text('Bin List')
  2373. my %f = (
  2374. transaction => 'Transaction',
  2375. invoice => 'Invoice',
  2376. credit_invoice => 'Credit Invoice',
  2377. debit_invoice => 'Debit Invoice',
  2378. packing_list => 'Packing List',
  2379. pick_list => 'Pick List',
  2380. sales_order => 'Sales Order',
  2381. work_order => 'Work Order',
  2382. purchase_order => 'Purchase Order',
  2383. bin_list => 'Bin List',
  2384. );
  2385. %f;
  2386. }
  2387. sub continue { &{ $form->{nextsub} } }