summaryrefslogtreecommitdiff
path: root/bin/am.pl
blob: 60c73bf0b7b29d1dae4c585ca3b701125cb3982e (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. my %hiddens;
  869. my @buttons;
  870. &language_header(\%hiddens);
  871. &form_footer_buttons(\%hiddens, \@buttons);
  872. my $template = LedgerSMB::Template->new_UI(
  873. user => \%myconfig,
  874. locale => $locale,
  875. template => 'am-language-form');
  876. $template->render({
  877. form => $form,
  878. buttons => \@buttons,
  879. hiddens => \%hiddens,
  880. });
  881. }
  882. sub edit_language {
  883. $form->{title} = "Edit";
  884. $form->{code} =~ s/\\'/'/g;
  885. $form->{code} =~ s/\\\\/\\/g;
  886. AM->get_language( \%myconfig, \%$form );
  887. $form->{id} = $form->{code};
  888. $form->{orphaned} = 1;
  889. my %hiddens;
  890. my @buttons;
  891. &language_header(\%hiddens);
  892. &form_footer_buttons(\%hiddens, \@buttons);
  893. my $template = LedgerSMB::Template->new_UI(
  894. user => \%myconfig,
  895. locale => $locale,
  896. template => 'am-language-form');
  897. $template->render({
  898. form => $form,
  899. buttons => \@buttons,
  900. hiddens => \%hiddens,
  901. });
  902. }
  903. sub list_language {
  904. AM->language( \%myconfig, \%$form );
  905. $href =
  906. "$form->{script}?action=list_language&direction=$form->{direction}&oldsort=$form->{oldsort}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  907. $form->sort_order();
  908. $form->{callback} =
  909. "$form->{script}?action=list_language&direction=$form->{direction}&oldsort=$form->{oldsort}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  910. my $callback = $form->escape( $form->{callback} );
  911. $form->{title} = $locale->text('Languages');
  912. my @column_index = $form->sort_columns(qw(code description));
  913. my %column_header;
  914. $column_header{code} = { text => $locale->text('Code'),
  915. href => "$href&sort=code" };
  916. $column_header{description} = { text => $locale->text('Description'),
  917. href => "$href&sort=description" };
  918. my @rows;
  919. my $i = 0;
  920. foreach my $ref ( @{ $form->{ALL} } ) {
  921. my %column_data;
  922. $i++;
  923. $i %= 2;
  924. $column_data{i} = $i;
  925. $column_data{code} = {text => $ref->{code}, href =>
  926. qq|$form->{script}?action=edit_language&code=$ref->{code}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}&callback=$callback|};
  927. $column_data{description} = $ref->{description};
  928. push @rows, \%column_data;
  929. }
  930. $form->{type} = "language";
  931. my @hiddens = qw(type callback path login sessionid);
  932. ## SC: Temporary removal
  933. ## if ( $form->{lynx} ) {
  934. ## require "bin/menu.pl";
  935. ## &menubar;
  936. ## }
  937. my @buttons;
  938. push @buttons, {
  939. name => 'action',
  940. value => 'add_language',
  941. text => $locale->text('Add Lanugage'),
  942. type => 'submit',
  943. class => 'submit',
  944. };
  945. # SC: I'm not concerned about the wider description as code is 6 chars max
  946. my $template = LedgerSMB::Template->new_UI(
  947. user => \%myconfig,
  948. locale => $locale,
  949. template => 'am-list-departments');
  950. $template->render({
  951. form => $form,
  952. buttons => \@buttons,
  953. columns => \@column_index,
  954. heading => \%column_header,
  955. rows => \@rows,
  956. hiddens => \@hiddens,
  957. });
  958. }
  959. sub language_header {
  960. my $hiddens = shift;
  961. $form->{title} = $locale->text("$form->{title} Language");
  962. # $locale->text('Add Language')
  963. # $locale->text('Edit Language')
  964. for (qw(code description)) { $form->{$_} = $form->quote( $form->{$_} ) }
  965. $hiddens->{type} = 'language';
  966. $hiddens->{id} = $form->{code};
  967. }
  968. sub save_language {
  969. $form->isblank( "code", $locale->text('Code missing!') );
  970. $form->isblank( "description", $locale->text('Description missing!') );
  971. $form->{code} =~ s/(\.\.|\*)//g;
  972. AM->save_language( \%myconfig, \%$form );
  973. if ( !-d "$myconfig{templates}/$form->{code}" ) {
  974. umask(002);
  975. if ( mkdir "$myconfig{templates}/$form->{code}", oct("771") ) {
  976. umask(007);
  977. opendir TEMPLATEDIR, "$myconfig{templates}"
  978. or $form->error("$myconfig{templates} : $!");
  979. @templates = grep !/^(\.|\.\.)/, readdir TEMPLATEDIR;
  980. closedir TEMPLATEDIR;
  981. foreach $file (@templates) {
  982. if ( -f "$myconfig{templates}/$file" ) {
  983. open( TEMP, '<', "$myconfig{templates}/$file" )
  984. or $form->error("$myconfig{templates}/$file : $!");
  985. open( NEW, '>', "$myconfig{templates}/$form->{code}/$file" )
  986. or $form->error(
  987. "$myconfig{templates}/$form->{code}/$file : $!");
  988. while ( $line = <TEMP> ) {
  989. print NEW $line;
  990. }
  991. close(TEMP);
  992. close(NEW);
  993. }
  994. }
  995. }
  996. else {
  997. $form->error("${templates}/$form->{code} : $!");
  998. }
  999. }
  1000. $form->redirect( $locale->text('Language saved!') );
  1001. }
  1002. sub delete_language {
  1003. $form->{title} = $locale->text('Confirm!');
  1004. for (qw(action nextsub)) { delete $form->{$_} }
  1005. my %hiddens;
  1006. $hiddens{$_} = $form->{$_} foreach keys %$form;
  1007. my @buttons = ({
  1008. name => 'action',
  1009. value => 'yes_delete_language',
  1010. text => $locale->text('Delete Language'),
  1011. });
  1012. my $template = LedgerSMB::Template->new_UI(
  1013. user => \%myconfig,
  1014. locale => $locale,
  1015. template => 'form-confirmation');
  1016. $template->render({
  1017. form => $form,
  1018. buttons => \@buttons,
  1019. hiddens => \%hiddens,
  1020. query => $locale->text(
  1021. 'Deleting a language will also delete the templates for the language [_1]',
  1022. $form->{id}),
  1023. });
  1024. }
  1025. sub yes_delete_language {
  1026. AM->delete_language( \%myconfig, \%$form );
  1027. # delete templates
  1028. $dir = "$myconfig{templates}/$form->{code}";
  1029. if ( -d $dir ) {
  1030. unlink <$dir/*>;
  1031. rmdir "$myconfig{templates}/$form->{code}";
  1032. }
  1033. $form->redirect( $locale->text('Language deleted!') );
  1034. }
  1035. sub display_stylesheet {
  1036. $form->{file} = "css/$myconfig{stylesheet}";
  1037. &display_form;
  1038. }
  1039. sub list_templates {
  1040. AM->language( \%myconfig, \%$form );
  1041. if ( !@{ $form->{ALL} } ) {
  1042. &display_form;
  1043. exit;
  1044. }
  1045. unshift @{ $form->{ALL} },
  1046. { code => '.', description => $locale->text('Default Template') };
  1047. my $href =
  1048. "$form->{script}?action=list_templates&direction=$form->{direction}&oldsort=$form->{oldsort}&file=$form->{file}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  1049. $form->sort_order();
  1050. $form->{callback} =
  1051. "$form->{script}?action=list_templates&direction=$form->{direction}&oldsort=$form->{oldsort}&file=$form->{file}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  1052. my $callback = $form->escape( $form->{callback} );
  1053. chomp $myconfig{templates};
  1054. $form->{file} =~ s/$myconfig{templates}//;
  1055. $form->{file} =~ s/\///;
  1056. $form->{title} = "$form->{format}: $form->{template}";
  1057. my @column_index = $form->sort_columns(qw(code description));
  1058. $column_header{code} = { text => $locale->text('Code'),
  1059. href => "$href&sort=code" };
  1060. $column_header{description} = { text => $locale->text('Description'),
  1061. href => "$href&sort=description" };
  1062. my @rows;
  1063. my $i = 0;
  1064. foreach my $ref ( @{ $form->{ALL} } ) {
  1065. my %column_data;
  1066. $i++;
  1067. $i %= 2;
  1068. $column_data{i} = $i;
  1069. $column_data{code} = { text => $ref->{code}, href =>
  1070. 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|};
  1071. $column_data{description} = $ref->{description};
  1072. push @rows, \%column_data;
  1073. }
  1074. $form->{type} = 'language';
  1075. my @hiddens = qw(sessionid login path calllback type);
  1076. ## SC: Temporary removal
  1077. ## if ( $form->{lynx} ) {
  1078. ## require "bin/menu.pl";
  1079. ## &menubar;
  1080. ## }
  1081. # SC: I'm not concerned about the wider description as code is 6 chars max
  1082. my $template = LedgerSMB::Template->new_UI(
  1083. user => \%myconfig,
  1084. locale => $locale,
  1085. template => 'am-list-departments');
  1086. $template->render({
  1087. form => $form,
  1088. columns => \@column_index,
  1089. heading => \%column_header,
  1090. rows => \@rows,
  1091. hiddens => \@hiddens,
  1092. });
  1093. }
  1094. sub display_form {
  1095. AM->load_template( \%myconfig, \%$form );
  1096. $form->{title} = $form->{file};
  1097. $form->{body} =~
  1098. 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;
  1099. # if it is anything but html
  1100. if ( $form->{file} !~ /\.html$/ ) {
  1101. $form->{body} = "<pre>\n$form->{body}\n</pre>";
  1102. }
  1103. $form->header;
  1104. print qq|
  1105. <body>
  1106. $form->{body}
  1107. <form method=post action=$form->{script}>
  1108. |;
  1109. $form->{type} = "template";
  1110. $form->hide_form(qw(file type path login sessionid));
  1111. print qq|
  1112. <button name="action" type="submit" class="submit" value="edit">|
  1113. . $locale->text('Edit')
  1114. . qq|</button>|;
  1115. if ( $form->{lynx} ) {
  1116. require "bin/menu.pl";
  1117. &menubar;
  1118. }
  1119. print qq|
  1120. </form>
  1121. </body>
  1122. </html>
  1123. |;
  1124. }
  1125. sub edit_template {
  1126. AM->load_template( \%myconfig, \%$form );
  1127. $form->{title} = $locale->text('Edit Template');
  1128. # convert &nbsp to &amp;nbsp;
  1129. $form->{body} =~ s/&nbsp;/&amp;nbsp;/gi;
  1130. $form->header;
  1131. print qq|
  1132. <body>
  1133. <form method=post action=$form->{script}>
  1134. <input name=file type=hidden value=$form->{file}>
  1135. <input name=type type=hidden value=template>
  1136. <input type=hidden name=path value=$form->{path}>
  1137. <input type=hidden name=login value=$form->{login}>
  1138. <input type=hidden name=sessionid value=$form->{sessionid}>
  1139. <input name=callback type=hidden value="$form->{script}?action=display_form&file=$form->{file}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}">
  1140. <textarea name=body rows=25 cols=70>
  1141. $form->{body}
  1142. </textarea>
  1143. <br>
  1144. <button type="submit" class="submit" name="action" value="save">|
  1145. . $locale->text('Save')
  1146. . qq|</button>|;
  1147. if ( $form->{lynx} ) {
  1148. require "bin/menu.pl";
  1149. &menubar;
  1150. }
  1151. print q|
  1152. </form>
  1153. </body>
  1154. </html>
  1155. |;
  1156. }
  1157. sub save_template {
  1158. AM->save_template( \%myconfig, \%$form );
  1159. $form->redirect( $locale->text('Template saved!') );
  1160. }
  1161. sub defaults {
  1162. # get defaults for account numbers and last numbers
  1163. AM->get_all_defaults( \%$form );
  1164. my %selects = (
  1165. 'FX_loss' => {name => 'FX_loss', options => []},
  1166. 'FX_gain' => {name => 'FX_gain', options => []},
  1167. 'IC_expense' => {name => 'IC_expense', options => []},
  1168. 'IC_income' => {name => 'IC_income', options => []},
  1169. 'IC_inventory' => {name => 'IC_inventory', options => []},
  1170. 'IC' => {name => 'IC', options => []},
  1171. );
  1172. foreach $key ( keys %{ $form->{accno} } ) {
  1173. foreach $accno ( sort keys %{ $form->{accno}{$key} } ) {
  1174. push @{$selects{$key}{options}}, {
  1175. text => "$accno--$form->{accno}{$key}{$accno}{description}",
  1176. value => "$accno--$form->{accno}{$key}{$accno}{description}",
  1177. };
  1178. $selects{$key}{default_values} = "$accno--$form->{accno}{$key}{$accno}{description}" if
  1179. ($form->{defaults}{$key} == $form->{accno}{$key}{$accno}{id});
  1180. }
  1181. }
  1182. for (qw(accno defaults)) { delete $form->{$_} }
  1183. ##SC: temporary commenting out
  1184. ## if ( $form->{lynx} ) {
  1185. ## require "bin/menu.pl";
  1186. ## &menubar;
  1187. ## }
  1188. my %hiddens = (
  1189. path => $form->{path},
  1190. login => $form->{login},
  1191. sessionid => $form->{sessionid},
  1192. type => 'defaults',
  1193. );
  1194. my $template = LedgerSMB::Template->new_UI(
  1195. user => \%myconfig,
  1196. locale => $locale,
  1197. template => 'am-defaults');
  1198. $template->render({
  1199. form => $form,
  1200. hiddens => \%hiddens,
  1201. selects => \%selects,
  1202. });
  1203. }
  1204. sub taxes {
  1205. # get tax account numbers
  1206. AM->taxes( \%myconfig, \%$form );
  1207. $i = 0;
  1208. foreach $ref ( @{ $form->{taxrates} } ) {
  1209. $i++;
  1210. $form->{"taxrate_$i"} =
  1211. $form->format_amount( \%myconfig, $ref->{rate} );
  1212. $form->{"taxdescription_$i"} = $ref->{description};
  1213. for (qw(taxnumber validto pass taxmodulename)) {
  1214. $form->{"${_}_$i"} = $ref->{$_};
  1215. }
  1216. $form->{taxaccounts} .= "$ref->{id}_$i ";
  1217. }
  1218. chop $form->{taxaccounts};
  1219. &display_taxes;
  1220. }
  1221. sub display_taxes {
  1222. $form->{title} = $locale->text('Taxes');
  1223. my %hiddens = (
  1224. path => $form->{path},
  1225. login => $form->{login},
  1226. sessionid => $form->{sessionid},
  1227. type => 'taxes',
  1228. );
  1229. my @rows;
  1230. for ( split( / /, $form->{taxaccounts} ) ) {
  1231. ( $null, $i ) = split /_/, $_;
  1232. $form->{"taxrate_$i"} =
  1233. $form->format_amount( \%myconfig, $form->{"taxrate_$i"} );
  1234. $hiddens{"taxdescription_$i"} = $form->{"taxdescription_$i"};
  1235. my %select = (name => "taxmodule_id_$i", options => []);
  1236. foreach my $taxmodule ( sort keys %$form ) {
  1237. next if ( $taxmodule !~ /^taxmodule_/ );
  1238. next if ( $taxmodule =~ /^taxmodule_id_/ );
  1239. my $modulenum = $taxmodule;
  1240. $modulenum =~ s/^taxmodule_//;
  1241. push @{$select{options}},
  1242. {text => $form->{$taxmodule}, value => $modulenum};
  1243. $select{default_values} = $modulenum
  1244. if $form->{$taxmodule} eq $form->{"taxmodulename_$i"};
  1245. }
  1246. if ( $form->{"taxdescription_$i"} eq $sametax ) {
  1247. push @rows, ["", \%select];
  1248. } else {
  1249. push @rows, [$form->{"taxdescription_$i"}, \%select];
  1250. }
  1251. $sametax = $form->{"taxdescription_$i"};
  1252. }
  1253. $hiddens{taxaccounts} = $form->{taxaccounts};
  1254. foreach my $taxmodule ( sort keys %$form ) {
  1255. next if ( $taxmodule !~ /^taxmodule_/ );
  1256. next if ( $taxmodule =~ /^taxmodule_id_/ );
  1257. $hiddens{$taxmodule};
  1258. }
  1259. ##SC: Temporary removal
  1260. ## if ( $form->{lynx} ) {
  1261. ## require "bin/menu.pl";
  1262. ## &menubar;
  1263. ## }
  1264. my $template = LedgerSMB::Template->new_UI(
  1265. user => \%myconfig,
  1266. locale => $locale,
  1267. template => 'am-taxes');
  1268. $template->render({
  1269. form => $form,
  1270. hiddens => \%hiddens,
  1271. selects => \%selects,
  1272. rows => \@rows,
  1273. });
  1274. }
  1275. sub update {
  1276. @a = split / /, $form->{taxaccounts};
  1277. $ndx = $#a + 1;
  1278. foreach $item (@a) {
  1279. ( $accno, $i ) = split /_/, $item;
  1280. push @t, $accno;
  1281. $form->{"taxmodulename_$i"} =
  1282. $form->{ "taxmodule_" . $form->{"taxmodule_id_$i"} };
  1283. if ( $form->{"validto_$i"} ) {
  1284. $j = $i + 1;
  1285. if ( $form->{"taxdescription_$i"} ne $form->{"taxdescription_$j"} )
  1286. {
  1287. #insert line
  1288. for ( $j = $ndx + 1 ; $j > $i ; $j-- ) {
  1289. $k = $j - 1;
  1290. for (qw(taxrate taxdescription taxnumber validto)) {
  1291. $form->{"${_}_$j"} = $form->{"${_}_$k"};
  1292. }
  1293. }
  1294. $ndx++;
  1295. $k = $i + 1;
  1296. for (qw(taxdescription taxnumber)) {
  1297. $form->{"${_}_$k"} = $form->{"${_}_$i"};
  1298. }
  1299. for (qw(taxrate validto)) { $form->{"${_}_$k"} = "" }
  1300. push @t, $accno;
  1301. }
  1302. }
  1303. else {
  1304. # remove line
  1305. $j = $i + 1;
  1306. if ( $form->{"taxdescription_$i"} eq $form->{"taxdescription_$j"} )
  1307. {
  1308. for ( $j = $i + 1 ; $j <= $ndx ; $j++ ) {
  1309. $k = $j + 1;
  1310. for (qw(taxrate taxdescription taxnumber validto)) {
  1311. $form->{"${_}_$j"} = $form->{"${_}_$k"};
  1312. }
  1313. }
  1314. $ndx--;
  1315. splice @t, $i - 1, 1;
  1316. }
  1317. }
  1318. }
  1319. $i = 1;
  1320. $form->{taxaccounts} = "";
  1321. for (@t) {
  1322. $form->{taxaccounts} .= "${_}_$i ";
  1323. $i++;
  1324. }
  1325. chop $form->{taxaccounts};
  1326. &display_taxes;
  1327. }
  1328. sub config {
  1329. my %selects;
  1330. $selects{dateformat} = {
  1331. name => 'dateformat',
  1332. default_values => $myconfig{dateformat},
  1333. options => [],
  1334. };
  1335. foreach $item (qw(mm-dd-yy mm/dd/yy dd-mm-yy dd/mm/yy dd.mm.yy yyyy-mm-dd))
  1336. {
  1337. push @{$selects{dateformat}{options}}, {text => $item, value => $item};
  1338. }
  1339. $selects{numberformat} = {
  1340. name => 'numberformat',
  1341. default_values => $myconfig{numberformat},
  1342. options => [],
  1343. };
  1344. my @formats = qw(1,000.00 1000.00 1.000,00 1000,00 1'000.00);
  1345. push @formats, '1 000.00';
  1346. foreach $item (@formats) {
  1347. push @{$selects{numberformat}{options}}, {text => $item, value => $item};
  1348. }
  1349. ## for (qw(name company address signature)) {
  1350. ## $myconfig{$_} = $form->quote( $myconfig{$_} );
  1351. ## }
  1352. for (qw(address signature)) { $myconfig{$_} =~ s/\\n/\n/g }
  1353. $selects{countrycode} = {
  1354. name => 'countrycode',
  1355. default_values => ($myconfig{countrycode})? $myconfig{countrycode}: 'en',
  1356. options => [],
  1357. };
  1358. %countrycodes = LedgerSMB::User->country_codes;
  1359. foreach $key ( sort { $countrycodes{$a} cmp $countrycodes{$b} }
  1360. keys %countrycodes )
  1361. {
  1362. push @{$selects{countrycode}{options}}, {
  1363. text => $countrycodes{$key},
  1364. value => $key
  1365. };
  1366. }
  1367. opendir CSS, "css/.";
  1368. @all = grep /.*\.css$/, readdir CSS;
  1369. closedir CSS;
  1370. $selects{stylesheet} = {
  1371. name => 'usestylesheet',
  1372. default_values => $myconfig{stylesheet},
  1373. options => [],
  1374. };
  1375. foreach $item (@all) {
  1376. push @{$selects{stylesheet}{options}}, {text => $item, value => $item};
  1377. }
  1378. push @{$selects{stylesheet}{options}}, {text => 'none', value => '0'};
  1379. if ( %{LedgerSMB::Sysconfig::printer} && ${LedgerSMB::Sysconfig::latex} ) {
  1380. $selects{printer} = {
  1381. name => 'printer',
  1382. default_values => $myconfig{printer},
  1383. options => [],
  1384. };
  1385. foreach $item ( sort keys %{LedgerSMB::Sysconfig::printer} ) {
  1386. push @{$selects{printer}{options}}, {text => $item, value => $item};
  1387. }
  1388. }
  1389. $form->{title} =
  1390. $locale->text( 'Edit Preferences for [_1]', $form->{login} );
  1391. ##SC: Temporary commenting out
  1392. ## if ( $form->{lynx} ) {
  1393. ## require "bin/menu.pl";
  1394. ## &menubar;
  1395. ## }
  1396. my %hiddens = (
  1397. path => $form->{path},
  1398. login => $form->{login},
  1399. sessionid => $form->{sessionid},
  1400. type => 'preferences',
  1401. role => $myconfig{role},
  1402. old_password => $myconfig{password},
  1403. );
  1404. my $template = LedgerSMB::Template->new_UI(
  1405. user => \%myconfig,
  1406. locale => $locale,
  1407. template => 'am-userconfig');
  1408. $template->render({
  1409. form => $form,
  1410. user => \%myconfig,
  1411. hiddens => \%hiddens,
  1412. selects => \%selects,
  1413. });
  1414. }
  1415. sub save_defaults {
  1416. if ( AM->save_defaults( \%myconfig, \%$form ) ) {
  1417. $form->redirect( $locale->text('Defaults saved!') );
  1418. }
  1419. else {
  1420. $form->error( $locale->text('Cannot save defaults!') );
  1421. }
  1422. }
  1423. sub save_taxes {
  1424. if ( AM->save_taxes( \%myconfig, \%$form ) ) {
  1425. $form->redirect( $locale->text('Taxes saved!') );
  1426. }
  1427. else {
  1428. $form->error( $locale->text('Cannot save taxes!') );
  1429. }
  1430. }
  1431. sub save_preferences {
  1432. $form->{stylesheet} = $form->{usestylesheet};
  1433. if ( $form->{new_password} ne $form->{old_password} ) {
  1434. $form->error( $locale->text('Password does not match!') )
  1435. if $form->{new_password} ne $form->{confirm_password};
  1436. }
  1437. if ( AM->save_preferences( \%myconfig, \%$form ) ) {
  1438. $form->info( $locale->text('Preferences saved!') );
  1439. }
  1440. else {
  1441. $form->error( $locale->text('Cannot save preferences!') );
  1442. }
  1443. }
  1444. sub backup {
  1445. if ( $form->{media} eq 'email' ) {
  1446. $form->error(
  1447. $locale->text( 'No email address for [_1]', $myconfig{name} ) )
  1448. unless ( $myconfig{email} );
  1449. }
  1450. $SIG{INT} = 'IGNORE';
  1451. AM->backup(
  1452. \%myconfig, \%$form,
  1453. ${LedgerSMB::Sysconfig::userspath},
  1454. ${LedgerSMB::Sysconfig::gzip}
  1455. );
  1456. if ( $form->{media} eq 'email' ) {
  1457. $form->redirect(
  1458. $locale->text( 'Backup sent to [_1]', $myconfig{email} ) );
  1459. }
  1460. }
  1461. sub audit_control {
  1462. $form->{title} = $locale->text('Audit Control');
  1463. AM->closedto( \%myconfig, \%$form );
  1464. my %checked;
  1465. if ( $form->{revtrans} ) {
  1466. $checked{revtransY} = 'checked';
  1467. } else {
  1468. $checked{revtransN} = 'checked';
  1469. }
  1470. if ( $form->{audittrail} ) {
  1471. $checked{audittrailY} = 'checked';
  1472. } else {
  1473. $checked{audittrailN} = 'checked';
  1474. }
  1475. my %hiddens = (
  1476. path => $form->{path},
  1477. login => $form->{login},
  1478. sessionid => $form->{sessionid},
  1479. );
  1480. my $template = LedgerSMB::Template->new_UI(
  1481. user => \%myconfig,
  1482. locale => $locale,
  1483. template => 'am-audit-control');
  1484. $template->render({
  1485. user => \%myconfig,
  1486. form => $form,
  1487. checked => \%checked,
  1488. hiddens => \%hiddens,
  1489. });
  1490. }
  1491. sub doclose {
  1492. AM->closebooks( \%myconfig, \%$form );
  1493. if ( $form->{revtrans} ) {
  1494. $msg = $locale->text('Transaction reversal enforced for all dates');
  1495. }
  1496. else {
  1497. if ( $form->{closedto} ) {
  1498. $msg =
  1499. $locale->text('Transaction reversal enforced up to [_1]',
  1500. $locale->date( \%myconfig, $form->{closedto}, 1 ));
  1501. }
  1502. else {
  1503. $msg = $locale->text('Books are open');
  1504. }
  1505. }
  1506. $msg .= "<p>";
  1507. if ( $form->{audittrail} ) {
  1508. $msg .= $locale->text('Audit trail enabled');
  1509. }
  1510. else {
  1511. $msg .= $locale->text('Audit trail disabled');
  1512. }
  1513. ##SC: Disabling audit trail deletion
  1514. ## $msg .= "<p>";
  1515. ## if ( $form->{removeaudittrail} ) {
  1516. ## $msg .=
  1517. ## $locale->text('Audit trail removed up to') . " "
  1518. ## . $locale->date( \%myconfig, $form->{removeaudittrail}, 1 );
  1519. ## }
  1520. $form->redirect($msg);
  1521. }
  1522. sub add_warehouse {
  1523. $form->{title} = "Add";
  1524. $form->{callback} =
  1525. "$form->{script}?action=add_warehouse&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}"
  1526. unless $form->{callback};
  1527. &warehouse_header;
  1528. &form_footer;
  1529. }
  1530. sub edit_warehouse {
  1531. $form->{title} = "Edit";
  1532. AM->get_warehouse( \%myconfig, \%$form );
  1533. &warehouse_header;
  1534. &form_footer;
  1535. }
  1536. sub list_warehouse {
  1537. AM->warehouses( \%myconfig, \%$form );
  1538. $href =
  1539. "$form->{script}?action=list_warehouse&direction=$form->{direction}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  1540. $form->sort_order();
  1541. $form->{callback} =
  1542. "$form->{script}?action=list_warehouse&direction=$form->{direction}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  1543. $callback = $form->escape( $form->{callback} );
  1544. $form->{title} = $locale->text('Warehouses');
  1545. @column_index = qw(description);
  1546. $column_header{description} =
  1547. qq|<th width=100%><a class="listheading" href=$href>|
  1548. . $locale->text('Description')
  1549. . qq|</a></th>|;
  1550. $form->header;
  1551. print qq|
  1552. <body>
  1553. <table width=100%>
  1554. <tr>
  1555. <th class=listtop>$form->{title}</th>
  1556. </tr>
  1557. <tr height="5"></tr>
  1558. <tr>
  1559. <td>
  1560. <table width=100%>
  1561. <tr class="listheading">
  1562. |;
  1563. for (@column_index) { print "$column_header{$_}\n" }
  1564. print qq|
  1565. </tr>
  1566. |;
  1567. foreach $ref ( @{ $form->{ALL} } ) {
  1568. $i++;
  1569. $i %= 2;
  1570. print qq|
  1571. <tr valign=top class=listrow$i>
  1572. |;
  1573. $column_data{description} =
  1574. 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>|;
  1575. for (@column_index) { print "$column_data{$_}\n" }
  1576. print qq|
  1577. </tr>
  1578. |;
  1579. }
  1580. print qq|
  1581. </table>
  1582. </td>
  1583. </tr>
  1584. <tr>
  1585. <td><hr size=3 noshade></td>
  1586. </tr>
  1587. </table>
  1588. <br>
  1589. <form method=post action=$form->{script}>
  1590. |;
  1591. $form->{type} = "warehouse";
  1592. $form->hide_form(qw(type callback path login sessionid));
  1593. print qq|
  1594. <button class="submit" type="submit" name="action" value="add_warehouse">|
  1595. . $locale->text('Add Warehouse')
  1596. . qq|</button>|;
  1597. if ( $form->{lynx} ) {
  1598. require "bin/menu.pl";
  1599. &menubar;
  1600. }
  1601. print qq|
  1602. </form>
  1603. </body>
  1604. </html>
  1605. |;
  1606. }
  1607. sub warehouse_header {
  1608. $form->{title} = $locale->text("$form->{title} Warehouse");
  1609. # $locale->text('Add Warehouse')
  1610. # $locale->text('Edit Warehouse')
  1611. $form->{description} = $form->quote( $form->{description} );
  1612. if ( ( $rows = $form->numtextrows( $form->{description}, 60 ) ) > 1 ) {
  1613. $description =
  1614. qq|<textarea name="description" rows=$rows cols=60 wrap=soft>$form->{description}</textarea>|;
  1615. }
  1616. else {
  1617. $description =
  1618. qq|<input name=description size=60 value="$form->{description}">|;
  1619. }
  1620. $form->header;
  1621. print qq|
  1622. <body>
  1623. <form method=post action=$form->{script}>
  1624. <input type=hidden name=id value=$form->{id}>
  1625. <input type=hidden name=type value=warehouse>
  1626. <table width=100%>
  1627. <tr>
  1628. <th class=listtop colspan=2>$form->{title}</th>
  1629. </tr>
  1630. <tr height="5"></tr>
  1631. <tr>
  1632. <th align="right">| . $locale->text('Description') . qq|</th>
  1633. <td>$description</td>
  1634. </tr>
  1635. <tr>
  1636. <td colspan=2><hr size=3 noshade></td>
  1637. </tr>
  1638. </table>
  1639. |;
  1640. }
  1641. sub save_warehouse {
  1642. $form->isblank( "description", $locale->text('Description missing!') );
  1643. AM->save_warehouse( \%myconfig, \%$form );
  1644. $form->redirect( $locale->text('Warehouse saved!') );
  1645. }
  1646. sub delete_warehouse {
  1647. AM->delete_warehouse( \%myconfig, \%$form );
  1648. $form->redirect( $locale->text('Warehouse deleted!') );
  1649. }
  1650. sub yearend {
  1651. AM->earningsaccounts( \%myconfig, \%$form );
  1652. $chart = "";
  1653. for ( @{ $form->{chart} } ) {
  1654. $chart .= "<option>$_->{accno}--$_->{description}";
  1655. }
  1656. $form->{title} = $locale->text('Yearend');
  1657. $form->header;
  1658. print qq|
  1659. <body>
  1660. <form method=post action=$form->{script}>
  1661. <input type=hidden name=decimalplaces value=2>
  1662. <input type=hidden name=l_accno value=Y>
  1663. <table width=100%>
  1664. <tr>
  1665. <th class=listtop>$form->{title}</th>
  1666. </tr>
  1667. <tr height="5"></tr>
  1668. <tr>
  1669. <td>
  1670. <table>
  1671. <tr>
  1672. <th align="right">| . $locale->text('Yearend') . qq|</th>
  1673. <td><input class="date" name=todate size=11 title="$myconfig{dateformat}" value=$todate></td>
  1674. </tr>
  1675. <tr>
  1676. <th align="right">| . $locale->text('Reference') . qq|</th>
  1677. <td><input name=reference size=20 value="|
  1678. . $locale->text('Yearend')
  1679. . qq|"></td>
  1680. </tr>
  1681. <tr>
  1682. <th align="right">| . $locale->text('Description') . qq|</th>
  1683. <td><textarea name=description rows=3 cols=50 wrap=soft></textarea></td>
  1684. </tr>
  1685. <tr>
  1686. <th align="right">| . $locale->text('Retained Earnings') . qq|</th>
  1687. <td><select name=accno>$chart</select></td>
  1688. </tr>
  1689. <tr>
  1690. <th align="right">| . $locale->text('Method') . qq|</th>
  1691. <td><input name=method class=radio type=radio value=accrual checked>&nbsp;|
  1692. . $locale->text('Accrual')
  1693. . qq|&nbsp;<input name=method class=radio type=radio value=cash>&nbsp;|
  1694. . $locale->text('Cash')
  1695. . qq|</td>
  1696. </tr>
  1697. </table>
  1698. </td>
  1699. </tr>
  1700. </table>
  1701. <hr size=3 noshade>
  1702. <input type=hidden name=nextsub value=generate_yearend>
  1703. |;
  1704. $form->hide_form(qw(path login sessionid));
  1705. print qq|
  1706. <button class="submit" type="submit" name="action" value="continue">|
  1707. . $locale->text('Continue')
  1708. . qq|</button>|;
  1709. }
  1710. sub generate_yearend {
  1711. $form->isblank( "todate", $locale->text('Yearend date missing!') );
  1712. RP->yearend_statement( \%myconfig, \%$form );
  1713. $form->{transdate} = $form->{todate};
  1714. $earnings = 0;
  1715. $form->{rowcount} = 1;
  1716. foreach $key ( keys %{ $form->{I} } ) {
  1717. if ( $form->{I}{$key}{charttype} eq "A" ) {
  1718. $form->{"debit_$form->{rowcount}"} = $form->{I}{$key}{this};
  1719. $earnings += $form->{I}{$key}{this};
  1720. $form->{"accno_$form->{rowcount}"} = $key;
  1721. $form->{rowcount}++;
  1722. $ok = 1;
  1723. }
  1724. }
  1725. foreach $key ( keys %{ $form->{E} } ) {
  1726. if ( $form->{E}{$key}{charttype} eq "A" ) {
  1727. $form->{"credit_$form->{rowcount}"} = $form->{E}{$key}{this} * -1;
  1728. $earnings += $form->{E}{$key}{this};
  1729. $form->{"accno_$form->{rowcount}"} = $key;
  1730. $form->{rowcount}++;
  1731. $ok = 1;
  1732. }
  1733. }
  1734. if ( $earnings > 0 ) {
  1735. $form->{"credit_$form->{rowcount}"} = $earnings;
  1736. $form->{"accno_$form->{rowcount}"} = $form->{accno};
  1737. }
  1738. else {
  1739. $form->{"debit_$form->{rowcount}"} = $earnings * -1;
  1740. $form->{"accno_$form->{rowcount}"} = $form->{accno};
  1741. }
  1742. if ($ok) {
  1743. if ( AM->post_yearend( \%myconfig, \%$form ) ) {
  1744. $form->redirect( $locale->text('Yearend posted!') );
  1745. }
  1746. else {
  1747. $form->error( $locale->text('Yearend posting failed!') );
  1748. }
  1749. }
  1750. else {
  1751. $form->error('Nothing to do!');
  1752. }
  1753. }
  1754. sub company_logo {
  1755. $myconfig{address} =~ s/\\n/<br>/g;
  1756. $myconfig{dbhost} = $locale->text('localhost') unless $myconfig{dbhost};
  1757. $form->{stylesheet} = $myconfig{stylesheet};
  1758. $form->{title} = $locale->text('About');
  1759. # create the logo screen
  1760. $form->header;
  1761. print qq|
  1762. <body>
  1763. <pre>
  1764. </pre>
  1765. <center>
  1766. <a href="http://www.ledgersmb.org/" target="_blank"><img src="images/ledgersmb.png" width="200" height="100" border="0" alt="LedgerSMB Logo" /></a>
  1767. <h1 class="login">| . $locale->text('Version') . qq| $form->{version}</h1>
  1768. <p>
  1769. |.$locale->text('Company').qq| :
  1770. <p>
  1771. <b>
  1772. $myconfig{company}
  1773. <br>$myconfig{address}
  1774. </b>
  1775. <p>
  1776. <table border=0>
  1777. <tr>
  1778. <th align="right">| . $locale->text('User') . qq|</th>
  1779. <td>$myconfig{name}</td>
  1780. </tr>
  1781. <tr>
  1782. <th align="right">| . $locale->text('Dataset') . qq|</th>
  1783. <td>$myconfig{dbname}</td>
  1784. </tr>
  1785. <tr>
  1786. <th align="right">| . $locale->text('Database Host') . qq|</th>
  1787. <td>$myconfig{dbhost}</td>
  1788. </tr>
  1789. </table>
  1790. </center>
  1791. </body>
  1792. </html>
  1793. |;
  1794. }
  1795. sub recurring_transactions {
  1796. # $locale->text('Day')
  1797. # $locale->text('Days')
  1798. # $locale->text('Month')
  1799. # $locale->text('Months')
  1800. # $locale->text('Week')
  1801. # $locale->text('Weeks')
  1802. # $locale->text('Year')
  1803. # $locale->text('Years')
  1804. my %hiddens;
  1805. my %column_header;
  1806. $form->{stylesheet} = $myconfig{stylesheet};
  1807. $form->{title} = $locale->text('Recurring Transactions');
  1808. $column_header{id} = "";
  1809. AM->recurring_transactions( \%myconfig, \%$form );
  1810. $href = "$form->{script}?action=recurring_transactions";
  1811. for (qw(direction oldsort path login sessionid)) {
  1812. $href .= qq|&$_=$form->{$_}|;
  1813. }
  1814. $form->sort_order();
  1815. my @column_index = qw(ndx reference description);
  1816. push @column_index,
  1817. qw(nextdate enddate id amount curr repeat howmany recurringemail recurringprint);
  1818. $column_header{reference} = {
  1819. text => $locale->text('Reference'),
  1820. href => "$href&sort=reference",
  1821. };
  1822. $column_header{ndx} = ' ';
  1823. $column_header{id} = $locale->text('ID');
  1824. $column_header{description} = $locale->text('Description');
  1825. $column_header{nextdate} = {
  1826. text => $locale->text('Next'),
  1827. href => "$href&sort=nextdate",
  1828. };
  1829. $column_header{enddate} = {
  1830. text => $locale->text('Ends'),
  1831. href => "$href&sort=enddate",
  1832. };
  1833. $column_header{amount} = $locale->text('Amount');
  1834. $column_header{curr} = ' ';
  1835. $column_header{repeat} = $locale->text('Every');
  1836. $column_header{howmany} = $locale->text('Times');
  1837. $column_header{recurringemail} = $locale->text('E-mail');
  1838. $column_header{recurringprint} = $locale->text('Print');
  1839. my $i = 1;
  1840. my %tr = (
  1841. ar => $locale->text('AR'),
  1842. ap => $locale->text('AP'),
  1843. gl => $locale->text('GL'),
  1844. so => $locale->text('Sales Orders'),
  1845. po => $locale->text('Purchase Orders'),
  1846. );
  1847. my %f = &formnames;
  1848. my @transactions;
  1849. my $j;
  1850. my $k;
  1851. foreach my $transaction ( sort keys %{ $form->{transactions} } ) {
  1852. my $transaction_count = scalar( @{ $form->{transactions}{$transaction} } );
  1853. push @transactions, {type => $transaction,
  1854. title => "$tr{$transaction} ($transaction_count)",
  1855. transactions => [],
  1856. };
  1857. foreach my $ref ( @{ $form->{transactions}{$transaction} } ) {
  1858. my %column_data;
  1859. for (@column_index) {
  1860. $column_data{$_} = "$ref->{$_}";
  1861. }
  1862. my $unit;
  1863. my $repeat;
  1864. if ( $ref->{repeat} > 1 ) {
  1865. $unit = $locale->text( ucfirst $ref->{unit} );
  1866. $repeat = "$ref->{repeat} $unit";
  1867. }
  1868. else {
  1869. chop $ref->{unit};
  1870. $unit = $locale->text( ucfirst $ref->{unit} );
  1871. $repeat = $unit;
  1872. }
  1873. $column_data{ndx} = '';
  1874. if ( !$ref->{expired} ) {
  1875. if ( $ref->{overdue} <= 0 ) {
  1876. $k++;
  1877. $column_data{ndx} = {
  1878. name => "ndx_$k",
  1879. type => 'checkbox',
  1880. value => $ref->{id},
  1881. checked => 'checked',
  1882. };
  1883. }
  1884. }
  1885. my $reference =
  1886. ( $ref->{reference} )
  1887. ? $ref->{reference}
  1888. : $locale->text('Next Number');
  1889. $column_data{reference} = {
  1890. text => $reference,
  1891. 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}|,
  1892. };
  1893. my $module = "$ref->{module}.pl";
  1894. my $type = "";
  1895. if ( $ref->{module} eq 'ar' ) {
  1896. $module = "is.pl" if $ref->{invoice};
  1897. $ref->{amount} /= $ref->{exchangerate};
  1898. }
  1899. if ( $ref->{module} eq 'ap' ) {
  1900. $module = "ir.pl" if $ref->{invoice};
  1901. $ref->{amount} /= $ref->{exchangerate};
  1902. }
  1903. if ( $ref->{module} eq 'oe' ) {
  1904. $type =
  1905. ( $ref->{vc} eq 'customer' )
  1906. ? "sales_order"
  1907. : "purchase_order";
  1908. }
  1909. $column_data{id} = {
  1910. text => $ref->{id},
  1911. href => qq|$module?action=edit&id=$ref->{id}&vc=$ref->{vc}&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}&type=$type&readonly=1|,
  1912. };
  1913. $column_data{repeat} = $repeat;
  1914. $column_data{howmany} =
  1915. $form->format_amount( \%myconfig, $ref->{howmany} );
  1916. $column_data{amount} =
  1917. $form->format_amount( \%myconfig, $ref->{amount}, 2 );
  1918. my @temp_split;
  1919. my @f = split /:/, $ref->{recurringemail};
  1920. for ( 0 .. $#f ) {
  1921. push @temp_split, $f{$f[$_]};
  1922. }
  1923. $column_data{recurringemail} = {
  1924. text => join ':', @temp_split,
  1925. delimeter => ':',
  1926. };
  1927. @temp_split = ();
  1928. @f = split /:/, $ref->{recurringprint};
  1929. for ( 0 .. $#f ) {
  1930. push @temp_split, $f{$f[$_]};
  1931. }
  1932. $column_data{recurringprint} = {
  1933. text => join ':', @temp_split,
  1934. delimeter => ':',
  1935. };
  1936. $j++;
  1937. $j %= 2;
  1938. $column_data{i} = $j;
  1939. push @{$transactions[$#transactions]{transactions}}, \%column_data;
  1940. }
  1941. }
  1942. ##SC: Temporary removal
  1943. ## if ( $form->{lynx} ) {
  1944. ## require "bin/menu.pl";
  1945. ## &menubar;
  1946. ## }
  1947. $hiddens{path} = $form->{path};
  1948. $hiddens{login} = $form->{login};
  1949. $hiddens{sessionid} = $form->{sessionid};
  1950. $hiddens{lastndx} = $k;
  1951. my @buttons;
  1952. push @buttons, {
  1953. name => 'action',
  1954. value => 'process_transactions',
  1955. text => $locale->text('Process Transactions'),
  1956. type => 'submit',
  1957. class => 'submit',
  1958. };
  1959. my $template = LedgerSMB::Template->new_UI(
  1960. user => \%myconfig,
  1961. locale => $locale,
  1962. template => 'am-list-recurring');
  1963. $template->render({
  1964. form => $form,
  1965. buttons => \@buttons,
  1966. columns => \@column_index,
  1967. heading => \%column_header,
  1968. transactions => \@transactions,
  1969. hiddens => \%hiddens,
  1970. });
  1971. }
  1972. sub edit_recurring {
  1973. %links = (
  1974. ar => 'create_links',
  1975. ap => 'create_links',
  1976. gl => 'create_links',
  1977. is => 'invoice_links',
  1978. ir => 'invoice_links',
  1979. oe => 'order_links',
  1980. );
  1981. %prepare = (
  1982. is => 'prepare_invoice',
  1983. ir => 'prepare_invoice',
  1984. oe => 'prepare_order',
  1985. );
  1986. $form->{callback} =
  1987. "$form->{script}?action=recurring_transactions&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}";
  1988. $form->{type} = "transaction";
  1989. if ( $form->{module} eq 'ar' ) {
  1990. if ( $form->{invoice} ) {
  1991. $form->{type} = "invoice";
  1992. $form->{module} = "is";
  1993. }
  1994. }
  1995. if ( $form->{module} eq 'ap' ) {
  1996. if ( $form->{invoice} ) {
  1997. $form->{type} = "invoice";
  1998. $form->{module} = "ir";
  1999. }
  2000. }
  2001. if ( $form->{module} eq 'oe' ) {
  2002. %tr = (
  2003. so => sales_order,
  2004. po => purchase_order,
  2005. );
  2006. $form->{type} = $tr{ $form->{transaction} };
  2007. }
  2008. $form->{script} = "$form->{module}.pl";
  2009. do "bin/$form->{script}";
  2010. &{ $links{ $form->{module} } };
  2011. # return if transaction doesn't exist
  2012. $form->redirect unless $form->{recurring};
  2013. if ( $prepare{ $form->{module} } ) {
  2014. &{ $prepare{ $form->{module} } };
  2015. }
  2016. $form->{selectformat} = qq|<option value="html">html\n|;
  2017. if ( ${LedgerSMB::Sysconfig::latex} ) {
  2018. $form->{selectformat} .= qq|
  2019. <option value="postscript">| . $locale->text('Postscript') . qq|
  2020. <option value="pdf">| . $locale->text('PDF');
  2021. }
  2022. &schedule;
  2023. }
  2024. sub process_transactions {
  2025. # save variables
  2026. my $pt = new Form;
  2027. for ( keys %$form ) { $pt->{$_} = $form->{$_} }
  2028. my $defaultprinter;
  2029. while ( my ( $key, $value ) = each %{LedgerSMB::Sysconfig::printer} ) {
  2030. if ( $value =~ /lpr/ ) {
  2031. $defaultprinter = $key;
  2032. last;
  2033. }
  2034. }
  2035. $myconfig{vclimit} = 0;
  2036. %f = &formnames;
  2037. for ( my $i = 1 ; $i <= $pt->{lastndx} ; $i++ ) {
  2038. if ( $pt->{"ndx_$i"} ) {
  2039. $id = $pt->{"ndx_$i"};
  2040. # process transaction
  2041. AM->recurring_details( \%myconfig, \%$pt, $id );
  2042. $header = $form->{header};
  2043. # reset $form
  2044. for ( keys %$form ) { delete $form->{$_}; }
  2045. for (qw(login path sessionid stylesheet timeout)) {
  2046. $form->{$_} = $pt->{$_};
  2047. }
  2048. $form->{id} = $id;
  2049. $form->{header} = $header;
  2050. $form->db_init(\%myconfig);
  2051. # post, print, email
  2052. if ( $pt->{arid} || $pt->{apid} || $pt->{oeid} ) {
  2053. if ( $pt->{arid} || $pt->{apid} ) {
  2054. if ( $pt->{arid} ) {
  2055. $form->{script} =
  2056. ( $pt->{invoice} ) ? "is.pl" : "ar.pl";
  2057. $form->{ARAP} = "AR";
  2058. $form->{module} = "ar";
  2059. $invfld = "sinumber";
  2060. }
  2061. else {
  2062. $form->{script} =
  2063. ( $pt->{invoice} ) ? "ir.pl" : "ap.pl";
  2064. $form->{ARAP} = "AP";
  2065. $form->{module} = "ap";
  2066. $invfld = "vinumber";
  2067. }
  2068. do "bin/$form->{script}";
  2069. if ( $pt->{invoice} ) {
  2070. &invoice_links;
  2071. &prepare_invoice;
  2072. for ( keys %$form ) {
  2073. $form->{$_} = $form->unquote( $form->{$_} );
  2074. }
  2075. }
  2076. else {
  2077. &create_links;
  2078. $form->{type} = "transaction";
  2079. for ( 1 .. $form->{rowcount} - 1 ) {
  2080. $form->{"amount_$_"} =
  2081. $form->format_amount( \%myconfig,
  2082. $form->{"amount_$_"}, 2 );
  2083. }
  2084. for ( 1 .. $form->{paidaccounts} ) {
  2085. $form->{"paid_$_"} =
  2086. $form->format_amount( \%myconfig,
  2087. $form->{"paid_$_"}, 2 );
  2088. }
  2089. }
  2090. delete $form->{"$form->{ARAP}_links"};
  2091. for (qw(acc_trans invoice_details)) { delete $form->{$_} }
  2092. for (
  2093. qw(department employee language month partsgroup project years)
  2094. )
  2095. {
  2096. delete $form->{"all_$_"};
  2097. }
  2098. $form->{invnumber} = $pt->{reference};
  2099. $form->{transdate} = $pt->{nextdate};
  2100. # tax accounts
  2101. $form->all_taxaccounts( \%myconfig, undef,
  2102. $form->{transdate} );
  2103. # calculate duedate
  2104. $form->{duedate} =
  2105. $form->add_date( \%myconfig, $form->{transdate},
  2106. $pt->{overdue}, "days" );
  2107. if ( $pt->{payment} ) {
  2108. # calculate date paid
  2109. for ( $j = 1 ; $j <= $form->{paidaccounts} ; $j++ ) {
  2110. $form->{"datepaid_$j"} =
  2111. $form->add_date( \%myconfig, $form->{transdate},
  2112. $pt->{paid}, "days" );
  2113. ( $form->{"$form->{ARAP}_paid_$j"} ) = split /--/,
  2114. $form->{"$form->{ARAP}_paid_$j"};
  2115. delete $form->{"cleared_$j"};
  2116. }
  2117. $form->{paidaccounts}++;
  2118. }
  2119. else {
  2120. $form->{paidaccounts} = -1;
  2121. }
  2122. for (qw(id recurring intnotes printed emailed queued)) {
  2123. delete $form->{$_};
  2124. }
  2125. ( $form->{ $form->{ARAP} } ) = split /--/,
  2126. $form->{ $form->{ARAP} };
  2127. $form->{invnumber} =
  2128. $form->update_defaults( \%myconfig, "$invfld" )
  2129. unless $form->{invnumber};
  2130. $form->{reference} = $form->{invnumber};
  2131. for (qw(invnumber reference)) {
  2132. $form->{$_} = $form->unquote( $form->{$_} );
  2133. }
  2134. if ( $pt->{invoice} ) {
  2135. if ( $pt->{arid} ) {
  2136. $form->info(
  2137. "\n"
  2138. . $locale->text(
  2139. 'Posting Sales Invoice [_1]',
  2140. $form->{invnumber}
  2141. )
  2142. );
  2143. $ok = IS->post_invoice( \%myconfig, \%$form );
  2144. }
  2145. else {
  2146. $form->info(
  2147. "\n"
  2148. . $locale->text(
  2149. 'Posting Vendor Invoice [_1]',
  2150. $form->{invnumber}
  2151. )
  2152. );
  2153. $ok = IR->post_invoice( \%myconfig, \%$form );
  2154. }
  2155. }
  2156. else {
  2157. if ( $pt->{arid} ) {
  2158. $form->info(
  2159. "\n"
  2160. . $locale->text(
  2161. 'Posting Transaction [_1]',
  2162. $form->{invnumber}
  2163. )
  2164. );
  2165. }
  2166. else {
  2167. $form->info(
  2168. "\n"
  2169. . $locale->text(
  2170. 'Posting Transaction [_1]',
  2171. $form->{invnumber}
  2172. )
  2173. );
  2174. }
  2175. $ok = AA->post_transaction( \%myconfig, \%$form );
  2176. }
  2177. $form->info( " ..... " . $locale->text('done') );
  2178. # print form
  2179. if ( ${LedgerSMB::Sysconfig::latex} && $ok ) {
  2180. $ok = &print_recurring( \%$pt, $defaultprinter );
  2181. }
  2182. &email_recurring( \%$pt ) if $ok;
  2183. }
  2184. else {
  2185. # order
  2186. $form->{script} = "oe.pl";
  2187. $form->{module} = "oe";
  2188. $ordnumber = "ordnumber";
  2189. if ( $pt->{customer_id} ) {
  2190. $form->{vc} = "customer";
  2191. $form->{type} = "sales_order";
  2192. $ordfld = "sonumber";
  2193. $flabel = $locale->text('Sales Order');
  2194. }
  2195. else {
  2196. $form->{vc} = "vendor";
  2197. $form->{type} = "purchase_order";
  2198. $ordfld = "ponumber";
  2199. $flabel = $locale->text('Purchase Order');
  2200. }
  2201. require "bin/$form->{script}";
  2202. &order_links;
  2203. &prepare_order;
  2204. for ( keys %$form ) {
  2205. $form->{$_} = $form->unquote( $form->{$_} );
  2206. }
  2207. $form->{$ordnumber} = $pt->{reference};
  2208. $form->{transdate} = $pt->{nextdate};
  2209. # calculate reqdate
  2210. $form->{reqdate} =
  2211. $form->add_date( \%myconfig, $form->{transdate},
  2212. $pt->{req}, "days" )
  2213. if $form->{reqdate};
  2214. for (qw(id recurring intnotes printed emailed queued)) {
  2215. delete $form->{$_};
  2216. }
  2217. for ( 1 .. $form->{rowcount} ) {
  2218. delete $form->{"orderitems_id_$_"};
  2219. }
  2220. $form->{$ordnumber} =
  2221. $form->update_defaults( \%myconfig, "$ordfld" )
  2222. unless $form->{$ordnumber};
  2223. $form->{reference} = $form->{$ordnumber};
  2224. for ( "$ordnumber", "reference" ) {
  2225. $form->{$_} = $form->unquote( $form->{$_} );
  2226. }
  2227. $form->{closed} = 0;
  2228. $form->info(
  2229. "\n"
  2230. . $locale->text(
  2231. 'Saving [_1] [_2]',
  2232. $flabel, $form->{$ordnumber}
  2233. )
  2234. );
  2235. if ( $ok = OE->save( \%myconfig, \%$form ) ) {
  2236. $form->info( " ..... " . $locale->text('done') );
  2237. }
  2238. else {
  2239. $form->info( " ..... " . $locale->text('failed') );
  2240. }
  2241. # print form
  2242. if ( ${LedgerSMB::Sysconfig::latex} && $ok ) {
  2243. &print_recurring( \%$pt, $defaultprinter );
  2244. }
  2245. &email_recurring( \%$pt );
  2246. }
  2247. }
  2248. else {
  2249. # GL transaction
  2250. GL->transaction( \%myconfig, \%$form );
  2251. $form->{reference} = $pt->{reference};
  2252. $form->{transdate} = $pt->{nextdate};
  2253. $j = 1;
  2254. foreach $ref ( @{ $form->{GL} } ) {
  2255. $form->{"accno_$j"} = "$ref->{accno}--$ref->{description}";
  2256. $form->{"projectnumber_$j"} =
  2257. "$ref->{projectnumber}--$ref->{project_id}"
  2258. if $ref->{project_id};
  2259. $form->{"fx_transaction_$j"} = $ref->{fx_transaction};
  2260. if ( $ref->{amount} < 0 ) {
  2261. $form->{"debit_$j"} = $ref->{amount} * -1;
  2262. }
  2263. else {
  2264. $form->{"credit_$j"} = $ref->{amount};
  2265. }
  2266. $j++;
  2267. }
  2268. $form->{rowcount} = $j;
  2269. for (qw(id recurring)) { delete $form->{$_} }
  2270. $form->info(
  2271. "\n"
  2272. . $locale->text(
  2273. 'Posting GL Transaction [_1]',
  2274. $form->{reference}
  2275. )
  2276. );
  2277. $ok = GL->post_transaction( \%myconfig, \%$form );
  2278. $form->info( " ..... " . $locale->text('done') );
  2279. }
  2280. AM->update_recurring( \%myconfig, \%$pt, $id ) if $ok;
  2281. }
  2282. }
  2283. $form->{callback} =
  2284. "am.pl?action=recurring_transactions&path=$form->{path}&login=$form->{login}&sessionid=$form->{sessionid}&header=$form->{header}";
  2285. $form->redirect;
  2286. }
  2287. sub print_recurring {
  2288. my ( $pt, $defaultprinter ) = @_;
  2289. use List::Util qw(first);
  2290. my %f = &formnames;
  2291. my $ok = 1;
  2292. if ( $pt->{recurringprint} ) {
  2293. @f = split /:/, $pt->{recurringprint};
  2294. for ( $j = 0 ; $j <= $#f ; $j += 3 ) {
  2295. $media = $f[ $j + 2 ];
  2296. $media ||= $myconfig->{printer}
  2297. if ${LedgerSMB::Sysconfig::printer}{ $myconfig->{printer} };
  2298. $media ||= $defaultprinter;
  2299. $form->info( "\n"
  2300. . $locale->text('Printing') . " "
  2301. . $locale->text( $f{ $f[$j] } )
  2302. . " $form->{reference}" );
  2303. @a = (
  2304. "perl", "$form->{script}",
  2305. "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}"
  2306. );
  2307. $form->error( $locale->text('Invalid redirect') )
  2308. unless first { $_ eq $form->{script} }
  2309. @{LedgerSMB::Sysconfig::scripts};
  2310. $ok = !( system(@a) );
  2311. if ($ok) {
  2312. $form->info( " ..... " . $locale->text('done') );
  2313. }
  2314. else {
  2315. $form->info( " ..... " . $locale->text('failed') );
  2316. last;
  2317. }
  2318. }
  2319. }
  2320. $ok;
  2321. }
  2322. sub email_recurring {
  2323. my ($pt) = @_;
  2324. use List::Util qw(first);
  2325. my %f = &formnames;
  2326. my $ok = 1;
  2327. if ( $pt->{recurringemail} ) {
  2328. @f = split /:/, $pt->{recurringemail};
  2329. for ( $j = 0 ; $j <= $#f ; $j += 2 ) {
  2330. $form->info( "\n"
  2331. . $locale->text('Sending') . " "
  2332. . $locale->text( $f{ $f[$j] } )
  2333. . " $form->{reference}" );
  2334. # no email, bail out
  2335. if ( !$form->{email} ) {
  2336. $form->info(
  2337. " ..... " . $locale->text('E-mail address missing!') );
  2338. last;
  2339. }
  2340. $message = $form->escape( $pt->{message}, 1 );
  2341. @a = (
  2342. "perl", "$form->{script}",
  2343. "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"
  2344. );
  2345. $form->error( $locale->text('Invalid redirect') )
  2346. unless first { $_ eq $form->{script} }
  2347. @{LedgerSMB::Sysconfig::scripts};
  2348. $ok = !( system(@a) );
  2349. if ($ok) {
  2350. $form->info( " ..... " . $locale->text('done') );
  2351. }
  2352. else {
  2353. $form->info( " ..... " . $locale->text('failed') );
  2354. last;
  2355. }
  2356. }
  2357. }
  2358. $ok;
  2359. }
  2360. sub formnames {
  2361. # $locale->text('Transaction')
  2362. # $locale->text('Invoice')
  2363. # $locale->text('Credit Invoice')
  2364. # $locale->text('Debit Invoice')
  2365. # $locale->text('Packing List')
  2366. # $locale->text('Pick List')
  2367. # $locale->text('Sales Order')
  2368. # $locale->text('Work Order')
  2369. # $locale->text('Purchase Order')
  2370. # $locale->text('Bin List')
  2371. my %f = (
  2372. transaction => 'Transaction',
  2373. invoice => 'Invoice',
  2374. credit_invoice => 'Credit Invoice',
  2375. debit_invoice => 'Debit Invoice',
  2376. packing_list => 'Packing List',
  2377. pick_list => 'Pick List',
  2378. sales_order => 'Sales Order',
  2379. work_order => 'Work Order',
  2380. purchase_order => 'Purchase Order',
  2381. bin_list => 'Bin List',
  2382. );
  2383. %f;
  2384. }
  2385. sub continue { &{ $form->{nextsub} } }