1 #=====================================================================
4 # Based on SQL-Ledger Version 2.1.9
5 # Web http://www.lx-office.org
7 #=====================================================================
8 # SQL-Ledger Accounting
9 # Copyright (c) 1998-2002
11 # Author: Dieter Simader
12 # Email: dsimader@sql-ledger.org
13 # Web: http://www.sql-ledger.org
16 # This program is free software; you can redistribute it and/or modify
17 # it under the terms of the GNU General Public License as published by
18 # the Free Software Foundation; either version 2 of the License, or
19 # (at your option) any later version.
21 # This program is distributed in the hope that it will be useful,
22 # but WITHOUT ANY WARRANTY; without even the implied warranty of
23 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 # GNU General Public License for more details.
25 # You should have received a copy of the GNU General Public License
26 # along with this program; if not, write to the Free Software
27 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
29 #======================================================================
33 #======================================================================
37 use List::MoreUtils qw(any);
40 use SL::Auth::PasswordPolicy;
44 use SL::Helper::Flash;
48 use SL::Locale::String qw(t8);
54 use SL::DBUtils qw(selectall_array_query conv_dateq);
57 require "bin/mozilla/common.pl";
65 sub add { call_sub("add_$main::form->{type}"); }
66 sub delete { call_sub("delete_$main::form->{type}"); }
67 sub save { call_sub("save_$main::form->{type}"); }
68 sub edit { call_sub("edit_$main::form->{type}"); }
69 sub continue { call_sub($main::form->{"nextsub"}); }
70 sub save_as_new { call_sub("save_as_new_$main::form->{type}"); }
73 $main::lxdebug->enter_sub();
75 my $form = $main::form;
76 my %myconfig = %main::myconfig;
78 $main::auth->assert('config');
80 $form->{title} = "Add";
81 $form->{charttype} = "A";
82 AM->get_account(\%myconfig, \%$form);
84 $form->{callback} = "am.pl?action=list_account" unless $form->{callback};
88 $main::lxdebug->leave_sub();
92 $main::lxdebug->enter_sub();
94 my $form = $main::form;
95 my %myconfig = %main::myconfig;
96 my $defaults = SL::DB::Default->get;
98 $main::auth->assert('config');
100 $form->{title} = "Edit";
101 $form->{feature_balance} = $defaults->feature_balance;
102 $form->{feature_datev} = $defaults->feature_datev;
103 $form->{feature_erfolgsrechnung} = $defaults->feature_erfolgsrechnung;
104 $form->{feature_eurechnung} = $defaults->feature_eurechnung;
105 $form->{feature_ustva} = $defaults->feature_ustva;
107 AM->get_account(\%myconfig, \%$form);
109 foreach my $item (split(/:/, $form->{link})) {
110 $form->{$item} = "checked";
115 $main::lxdebug->leave_sub();
119 $main::lxdebug->enter_sub();
121 my $form = $main::form;
122 my %myconfig = %main::myconfig;
123 my $locale = $main::locale;
125 $main::auth->assert('config');
127 if ( $form->{action} eq 'edit_account') {
128 $form->{account_exists} = '1';
131 $form->{title} = $locale->text("$form->{title} Account");
133 $form->{"$form->{charttype}_checked"} = "checked";
134 $form->{"$form->{category}_checked"} = "checked";
136 $form->{select_tax} = "";
138 my @tax_report_pos = USTVA->report_variables({
139 myconfig => \%myconfig,
142 attribute => 'position',
146 if (@{ $form->{TAXKEY} }) {
147 foreach my $item (@{ $form->{TAXKEY} }) {
148 $item->{rate} = $item->{rate} * 100 . '%';
151 # Fill in empty row for new Taxkey
152 my $newtaxkey_ref = {
157 taxdescription => '',
161 startdate => $form->{account_exists} ? '' : DateTime->new(year => 1970, month => 1, day => 1)->to_lxoffice,
164 push @{ $form->{ACCOUNT_TAXKEYS} }, $newtaxkey_ref;
167 foreach my $taxkey_used (@{ $form->{ACCOUNT_TAXKEYS} } ) {
169 # Fill in a runningnumber
170 $form->{ACCOUNT_TAXKEYS}[$i]{runningnumber} = $i;
172 # Fill in the Taxkeys as select options
173 foreach my $item (@{ $form->{TAXKEY} }) {
174 if ($item->{id} == $taxkey_used->{tax_id}) {
175 $form->{ACCOUNT_TAXKEYS}[$i]{selecttaxkey} .=
176 qq|<option value="$item->{id}" selected="selected">|
177 . sprintf("%.2d", $item->{taxkey})
178 . qq|. $item->{taxdescription} ($item->{rate}) |
179 . $locale->text('Tax-o-matic Account')
180 . qq|: $item->{chart_accno}\n|;
183 $form->{ACCOUNT_TAXKEYS}[$i]{selecttaxkey} .=
184 qq|<option value="$item->{id}">|
185 . sprintf("%.2d", $item->{taxkey})
186 . qq|. $item->{taxdescription} ($item->{rate}) |
187 . $locale->text('Tax-o-matic Account')
188 . qq|: $item->{chart_accno}\n|;
193 # Fill in the USTVA Numbers as select options
194 foreach my $item ( '', sort({ $a cmp $b } @tax_report_pos) ) {
196 $form->{ACCOUNT_TAXKEYS}[$i]{select_tax} .= qq|<option value="" selected="selected">-\n|;
198 elsif ( $item eq $taxkey_used->{pos_ustva} ) {
199 $form->{ACCOUNT_TAXKEYS}[$i]{select_tax} .= qq|<option value="$item" selected="selected">$item\n|;
202 $form->{ACCOUNT_TAXKEYS}[$i]{select_tax} .= qq|<option value="$item">$item\n|;
211 # Newaccount Folgekonto
212 if (@{ $form->{NEWACCOUNT} || [] }) {
213 if (!$form->{new_chart_valid}) {
214 $form->{selectnewaccount} = qq|<option value=""> |. $locale->text('None') .q|</option>|;
216 foreach my $item (@{ $form->{NEWACCOUNT} }) {
217 if ($item->{id} == $form->{new_chart_id}) {
218 $form->{selectnewaccount} .=
219 qq|<option value="$item->{id}" selected>$item->{accno}--$item->{description}</option>|;
220 } elsif (!$form->{new_chart_valid}) {
221 $form->{selectnewaccount} .=
222 qq|<option value="$item->{id}">$item->{accno}--$item->{description}</option>|;
228 my $select_eur = q|<option value=""> |. $locale->text('None') .q|</option>\n|;
229 my %eur = %{ AM->get_eur_categories(\%myconfig, $form) };
230 foreach my $item (sort({ $a <=> $b } keys(%eur))) {
231 my $text = H($::locale->{iconv_utf8}->convert($eur{$item}));
232 if ($item == $form->{pos_eur}) {
233 $select_eur .= qq|<option value=$item selected>|. sprintf("%.2d", $item) .qq|. $text</option>\n|;
235 $select_eur .= qq|<option value=$item>|. sprintf("%.2d", $item) .qq|. $text</option>\n|;
240 my $select_er = q|<option value=""> |. $locale->text('None') .q|</option>\n|;
244 foreach my $item (sort({ $a <=> $b } keys(%er))) {
245 my $text = H($::locale->{iconv_utf8}->convert($er{$item}));
246 if ($item == $form->{pos_er}) {
247 $select_er .= qq|<option value=$item selected>|. sprintf("%.2d", $item) .qq|. $text</option>\n|;
249 $select_er .= qq|<option value=$item>|. sprintf("%.2d", $item) .qq|. $text</option>\n|;
254 my $select_bwa = q|<option value=""> |. $locale->text('None') .q|</option>\n|;
256 my %bwapos = %{ AM->get_bwa_categories(\%myconfig, $form) };
257 foreach my $item (sort({ $a <=> $b } keys %bwapos)) {
258 my $text = H($::locale->{iconv_utf8}->convert($bwapos{$item}));
259 if ($item == $form->{pos_bwa}) {
260 $select_bwa .= qq|<option value="$item" selected>|. sprintf("%.2d", $item) .qq|. $text\n|;
262 $select_bwa .= qq|<option value="$item">|. sprintf("%.2d", $item) .qq|. $text\n|;
267 # Wieder hinzugefĆ¼gt zu evaluationszwecken (us) 09.03.2007
268 my $select_bilanz = q|<option value=""> |. $locale->text('None') .q|</option>\n|;
269 foreach my $item ((1, 2, 3, 4)) {
270 if ($item == $form->{pos_bilanz}) {
271 $select_bilanz .= qq|<option value=$item selected>|. sprintf("%.2d", $item) .qq|.\n|;
273 $select_bilanz .= qq|<option value=$item>|. sprintf("%.2d", $item) .qq|.\n|;
278 # this is for our parser only! Do not remove.
279 # type=submit $locale->text('Add Account')
280 # type=submit $locale->text('Edit Account')
282 $form->{type} = "account";
284 # preselections category
286 my $select_category = q|<option value=""> |. $locale->text('None') .q|</option>\n|;
289 'A' => $locale->text('Asset'),
290 'L' => $locale->text('Liability'),
291 'Q' => $locale->text('Equity'),
292 'I' => $locale->text('Revenue'),
293 'E' => $locale->text('Expense'),
294 'C' => $locale->text('Costs'),
296 foreach my $item ( sort({ $a <=> $b } keys %category) ) {
297 if ($item eq $form->{category}) {
298 $select_category .= qq|<option value="$item" selected="selected">$category{$item} (|. sprintf("%s", $item) .qq|)\n|;
300 $select_category .= qq|<option value="$item">$category{$item} (|. sprintf("%s", $item) .qq|)\n|;
305 # preselection chart type
306 my @all_charttypes = ({'name' => $locale->text('Account'), 'value' => 'A'},
307 {'name' => $locale->text('Heading'), 'value' => 'H'},
309 my $selected_charttype = $form->{charttype};
312 # account where AR_tax or AP_tax is set are not orphaned if they are used as
313 # tax-o-matic account
314 if ( $form->{id} && $form->{orphaned} && ($form->{link} =~ m/(AP_tax|AR_tax)/) ) {
315 if (SL::DB::Manager::Tax->find_by(chart_id => $form->{id})) {
316 $form->{orphaned} = 0;
320 my $ChartTypeIsAccount = ($form->{charttype} eq "A") ? "1":"";
321 my $AccountIsPosted = ($form->{orphaned} ) ? "":"1";
323 setup_am_edit_account_action_bar();
327 my $parameters_ref = {
328 ChartTypeIsAccount => $ChartTypeIsAccount,
329 AccountIsPosted => $AccountIsPosted,
330 select_category => $select_category,
331 all_charttypes => \@all_charttypes,
332 selected_charttype => $selected_charttype,
333 select_bwa => $select_bwa,
334 select_bilanz => $select_bilanz,
335 select_eur => $select_eur,
336 select_er => $select_er,
339 # Ausgabe des Templates
340 print($form->parse_html_template('am/edit_accounts', $parameters_ref));
343 $main::lxdebug->leave_sub();
347 $main::lxdebug->enter_sub();
349 my $form = $main::form;
350 my %myconfig = %main::myconfig;
351 my $locale = $main::locale;
353 $main::auth->assert('config');
355 $form->isblank("accno", $locale->text('Account Number missing!'));
356 $form->isblank("description", $locale->text('Account Description missing!'));
358 if ($form->{charttype} eq 'A'){
359 $form->isblank("category", $locale->text('Account Type missing!'));
361 my $found_valid_taxkey = 0;
362 foreach my $i (0 .. 10) { # 10 is maximum count of taxkeys in form
363 if ($form->{"taxkey_startdate_$i"} and !$form->{"taxkey_del_$i"}) {
364 $found_valid_taxkey = 1;
368 if ($found_valid_taxkey == 0) {
369 $form->error($locale->text('A valid taxkey is missing!'));
373 $form->redirect($locale->text('Account saved!'))
374 if (AM->save_account(\%myconfig, \%$form));
375 $form->error($locale->text('Cannot save account!'));
377 $main::lxdebug->leave_sub();
380 sub save_as_new_account {
381 $main::lxdebug->enter_sub();
383 my $form = $main::form;
384 my %myconfig = %main::myconfig;
385 my $locale = $main::locale;
387 $main::auth->assert('config');
389 $form->isblank("accno", $locale->text('Account Number missing!'));
390 $form->isblank("description", $locale->text('Account Description missing!'));
392 if ($form->{charttype} eq 'A'){
393 $form->isblank("category", $locale->text('Account Type missing!'));
396 for my $taxkey (0 .. 9) {
397 if ($form->{"taxkey_id_$taxkey"}) {
398 $form->{"taxkey_id_$taxkey"} = "NEW";
403 $form->redirect($locale->text('Account saved!'))
404 if (AM->save_account(\%myconfig, \%$form));
405 $form->error($locale->text('Cannot save account!'));
407 $main::lxdebug->leave_sub();
411 $main::lxdebug->enter_sub();
413 my $form = $main::form;
414 my %myconfig = %main::myconfig;
415 my $locale = $main::locale;
417 $main::auth->assert('config');
419 $form->{callback} = build_std_url('action=list_account');
420 my $link_edit_account = build_std_url('action=edit_account', 'callback');
422 CA->all_accounts(\%myconfig, \%$form);
424 foreach my $ca (@{ $form->{CA} }) {
429 if ($ca->{amount} > 0) {
430 $ca->{credit} = $form->format_amount(\%myconfig, $ca->{amount}, 2);
432 if ($ca->{amount} < 0) {
433 $ca->{debit} = $form->format_amount(\%myconfig, -1 * $ca->{amount}, 2);
435 $ca->{heading} = ( $ca->{charttype} eq 'H' ) ? 1:'';
436 $ca->{link_edit_account} = $link_edit_account . '&id=' . E($ca->{id});
439 $::request->{layout}->use_stylesheet("list_accounts.css");
440 $form->{title} = $locale->text('Chart of Accounts');
445 my $parameters_ref = {
446 # hidden_variables => $_hidden_variables_ref,
449 # Ausgabe des Templates
450 print($form->parse_html_template('am/list_accounts', $parameters_ref));
452 $main::lxdebug->leave_sub();
457 sub list_account_details {
458 # Ajax Funktion aus list_account_details
459 $main::lxdebug->enter_sub();
461 my $form = $main::form;
462 my %myconfig = %main::myconfig;
463 my $locale = $main::locale;
465 $main::auth->assert('config');
467 my $chart_id = $form->{args};
469 CA->all_accounts(\%myconfig, \%$form, $chart_id);
471 foreach my $ca (@{ $form->{CA} }) {
473 $ca->{debit} = " ";
474 $ca->{credit} = " ";
476 if ($ca->{amount} > 0) {
478 $form->format_amount(\%myconfig, $ca->{amount}, 2, " ");
480 if ($ca->{amount} < 0) {
482 $form->format_amount(\%myconfig, -1 * $ca->{amount}, 2, " ");
485 my @links = split( q{:}, $ca->{link});
489 foreach my $link (@links){
490 $link = ( $link eq 'AR') ? $locale->text('Account Link AR')
491 : ( $link eq 'AP') ? $locale->text('Account Link AP')
492 : ( $link eq 'IC') ? $locale->text('Account Link IC')
493 : ( $link eq 'AR_amount' ) ? $locale->text('Account Link AR_amount')
494 : ( $link eq 'AR_paid' ) ? $locale->text('Account Link AR_paid')
495 : ( $link eq 'AR_tax' ) ? $locale->text('Account Link AR_tax')
496 : ( $link eq 'AP_amount' ) ? $locale->text('Account Link AP_amount')
497 : ( $link eq 'AP_paid' ) ? $locale->text('Account Link AP_paid')
498 : ( $link eq 'AP_tax' ) ? $locale->text('Account Link AP_tax')
499 : ( $link eq 'IC_sale' ) ? $locale->text('Account Link IC_sale')
500 : ( $link eq 'IC_cogs' ) ? $locale->text('Account Link IC_cogs')
501 : ( $link eq 'IC_taxpart' ) ? $locale->text('Account Link IC_taxpart')
502 : ( $link eq 'IC_income' ) ? $locale->text('Account Link IC_income')
503 : ( $link eq 'IC_expense' ) ? $locale->text('Account Link IC_expense')
504 : ( $link eq 'IC_taxservice' ) ? $locale->text('Account Link IC_taxservice')
505 : $locale->text('Unknown Link') . ': ' . $link;
506 $ca->{link} .= ($link ne '') ? "[$link] ":'';
509 $ca->{category} = ($ca->{category} eq 'A') ? $locale->text('Account Category A')
510 : ($ca->{category} eq 'E') ? $locale->text('Account Category E')
511 : ($ca->{category} eq 'L') ? $locale->text('Account Category L')
512 : ($ca->{category} eq 'I') ? $locale->text('Account Category I')
513 : ($ca->{category} eq 'Q') ? $locale->text('Account Category Q')
514 : ($ca->{category} eq 'C') ? $locale->text('Account Category C')
515 : ($ca->{category} eq 'G') ? $locale->text('Account Category G')
516 : $locale->text('Unknown Category') . ': ' . $ca->{category};
519 $form->{title} = $locale->text('Chart of Accounts');
521 print $form->ajax_response_header, $form->parse_html_template('am/list_account_details');
523 $main::lxdebug->leave_sub();
528 $main::lxdebug->enter_sub();
530 my $form = $main::form;
531 my %myconfig = %main::myconfig;
532 my $locale = $main::locale;
534 $main::auth->assert('config');
536 $form->{title} = $locale->text('Delete Account');
539 qw(inventory_accno_id income_accno_id expense_accno_id fxgain_accno_id fxloss_accno_id rndgain_accno_id rndloss_accno_id)
541 if ($form->{id} == $form->{$id}) {
542 $form->error($locale->text('Cannot delete default account!'));
546 $form->redirect($locale->text('Account deleted!'))
547 if (AM->delete_account(\%myconfig, \%$form));
548 $form->error($locale->text('Cannot delete account!'));
550 $main::lxdebug->leave_sub();
553 sub _build_cfg_options {
554 my $form = $main::form;
555 my %myconfig = %main::myconfig;
558 my $array = uc($idx) . 'S';
560 $form->{$array} = [];
561 foreach my $item (@_) {
562 push @{ $form->{$array} }, {
565 'selected' => $item eq $myconfig{$idx},
571 $main::lxdebug->enter_sub();
573 my $form = $main::form;
574 my %myconfig = %main::myconfig;
575 my $locale = $main::locale;
577 _build_cfg_options('dateformat', qw(mm/dd/yy dd/mm/yy dd.mm.yy yyyy-mm-dd));
578 _build_cfg_options('timeformat', qw(hh:mm hh:mm:ss));
579 _build_cfg_options('numberformat', ('1,000.00', '1000.00', '1.000,00', '1000,00', "1'000.00"));
582 if ($::lx_office_conf{print_templates}->{opendocument}
583 && $::lx_office_conf{applications}->{openofficeorg_writer} && (-x $::lx_office_conf{applications}->{openofficeorg_writer})
584 && $::lx_office_conf{applications}->{xvfb} && (-x $::lx_office_conf{applications}->{xvfb})) {
585 push(@formats, { "name" => $locale->text("PDF (OpenDocument/OASIS)"),
586 "value" => "opendocument_pdf" });
588 if ($::lx_office_conf{print_templates}->{latex}) {
589 push(@formats, { "name" => $locale->text("PDF"), "value" => "pdf" });
591 push(@formats, { "name" => "HTML", "value" => "html" });
592 if ($::lx_office_conf{print_templates}->{latex}) {
593 push(@formats, { "name" => $locale->text("Postscript"),
594 "value" => "postscript" });
596 if ($::lx_office_conf{print_templates}->{opendocument}) {
597 push(@formats, { "name" => $locale->text("OpenDocument/OASIS"),
598 "value" => "opendocument" });
601 if (!$myconfig{"template_format"}) {
602 $myconfig{"template_format"} = "pdf";
604 $form->{TEMPLATE_FORMATS} = [];
605 foreach my $item (@formats) {
606 push @{ $form->{TEMPLATE_FORMATS} }, {
607 'name' => $item->{name},
608 'value' => $item->{value},
609 'selected' => $item->{value} eq $myconfig{template_format},
613 if (!$myconfig{"default_media"}) {
614 $myconfig{"default_media"} = "screen";
617 my %selected = ($myconfig{"default_media"} => "selected");
619 { 'name' => $locale->text('Screen'), 'value' => 'screen', 'selected' => $selected{screen}, },
620 { 'name' => $locale->text('Printer'), 'value' => 'printer', 'selected' => $selected{printer}, },
621 { 'name' => $locale->text('Queue'), 'value' => 'queue', 'selected' => $selected{queue}, },
624 $form->{PRINTERS} = SL::DB::Manager::Printer->get_all_sorted;
626 my %countrycodes = User->country_codes;
628 $form->{COUNTRYCODES} = [];
629 foreach my $countrycode (sort { $countrycodes{$a} cmp $countrycodes{$b} } keys %countrycodes) {
630 push @{ $form->{COUNTRYCODES} }, {
631 'name' => $countrycodes{$countrycode},
632 'value' => $countrycode,
633 'selected' => $countrycode eq $myconfig{countrycode},
637 $form->{STYLESHEETS} = [];
638 foreach my $item (qw(lx-office-erp.css kivitendo.css)) {
639 push @{ $form->{STYLESHEETS} }, {
642 'selected' => $item eq $myconfig{stylesheet},
646 $myconfig{show_form_details} = 1 unless (defined($myconfig{show_form_details}));
647 $form->{CAN_CHANGE_PASSWORD} = $main::auth->can_change_password();
648 $form->{todo_cfg} = { TODO->get_user_config('login' => $::myconfig{login}) };
650 $form->{title} = $locale->text('Edit Preferences for #1', $::myconfig{login});
652 setup_am_config_action_bar();
656 $form->{full_signature} = $form->create_email_signature();
658 print $form->parse_html_template('am/config');
660 $main::lxdebug->leave_sub();
663 sub save_preferences {
664 $main::lxdebug->enter_sub();
666 my $form = $main::form;
667 my %myconfig = %main::myconfig;
668 my $locale = $main::locale;
670 $form->{stylesheet} = $form->{usestylesheet};
672 TODO->save_user_config('login' => $::myconfig{login}, %{ $form->{todo_cfg} || { } });
674 if (AM->save_preferences($form)) {
675 if ($::auth->can_change_password()
676 && defined $form->{new_password}
677 && ($form->{new_password} ne '********')) {
678 my $verifier = SL::Auth::PasswordPolicy->new;
679 my $result = $verifier->verify($form->{new_password});
681 if ($result != SL::Auth::PasswordPolicy->OK()) {
682 $form->error($::locale->text('The settings were saved, but the password was not changed.') . ' ' . join(' ', $verifier->errors($result)));
685 $::auth->change_password($::myconfig{login}, $form->{new_password});
688 $form->redirect($locale->text('Preferences saved!'));
691 $form->error($locale->text('Cannot save preferences!'));
693 $main::lxdebug->leave_sub();
697 $::lxdebug->enter_sub;
698 $::auth->assert('config');
700 $::form->{title} = $::locale->text('Audit Control');
702 AM->closedto(\%::myconfig, $::form);
704 setup_am_audit_control_action_bar();
707 print $::form->parse_html_template('am/audit_control');
709 $::lxdebug->leave_sub;
713 $main::lxdebug->enter_sub();
715 my $form = $main::form;
716 my %myconfig = %main::myconfig;
717 my $locale = $main::locale;
719 $main::auth->assert('config');
721 AM->closebooks(\%myconfig, \%$form);
723 if ($form->{closedto}) {
725 $locale->text('Books closed up to') . " "
726 . $locale->date(\%myconfig, $form->{closedto}, 1));
728 $form->redirect($locale->text('Books are open'));
731 $main::lxdebug->leave_sub();
735 $::auth->assert('config');
737 # my $units = AM->retrieve_units(\%::myconfig, $::form, "resolved_");
738 # # AM->units_in_use(\%::myconfig, $::form, $units);
740 # $units->{$_}->{BASE_UNIT_DDBOX} = AM->unit_select_data($units, $units->{$_}->{base_unit}, 1) for keys %{$units};
742 my @languages = @{ SL::DB::Manager::Language->get_all_sorted };
744 my $units = AM->retrieve_units(\%::myconfig, $::form);
745 my $ddbox = AM->unit_select_data($units, undef, 1);
747 setup_am_add_unit_action_bar();
749 $::form->{title} = $::locale->text("Add unit");
751 print($::form->parse_html_template("am/add_unit", {
752 NEW_BASE_UNIT_DDBOX => $ddbox,
753 LANGUAGES => \@languages,
758 $main::lxdebug->enter_sub();
760 my $form = $main::form;
761 my %myconfig = %main::myconfig;
762 my $locale = $main::locale;
764 $main::auth->assert('config');
766 my $units = AM->retrieve_units(\%myconfig, $form, "resolved_");
767 AM->units_in_use(\%myconfig, $form, $units);
768 map({ $units->{$_}->{"BASE_UNIT_DDBOX"} = AM->unit_select_data($units, $units->{$_}->{"base_unit"}, 1); } keys(%{$units}));
770 my @languages = @{ SL::DB::Manager::Language->get_all_sorted };
772 my @unit_list = sort({ $a->{"sortkey"} <=> $b->{"sortkey"} } values(%{$units}));
775 foreach (@unit_list) {
776 $_->{"factor"} = $form->format_amount(\%myconfig, $_->{"factor"} * 1) if ($_->{"factor"});
777 $_->{"UNITLANGUAGES"} = [];
778 foreach my $lang (@languages) {
779 push(@{ $_->{"UNITLANGUAGES"} },
781 "unit" => $_->{"name"},
782 "language_id" => $lang->id,
783 "localized" => $_->{"LANGUAGES"}->{$lang->template_code}->{"localized"},
784 "localized_plural" => $_->{"LANGUAGES"}->{$lang->template_code}->{"localized_plural"},
790 $units = AM->retrieve_units(\%myconfig, $form);
791 my $ddbox = AM->unit_select_data($units, undef, 1);
793 setup_am_edit_units_action_bar();
795 $form->{"title"} = $locale->text("Edit units");
797 print($form->parse_html_template("am/edit_units",
798 { "UNITS" => \@unit_list,
799 "NEW_BASE_UNIT_DDBOX" => $ddbox,
800 "LANGUAGES" => \@languages,
803 $main::lxdebug->leave_sub();
807 $main::lxdebug->enter_sub();
809 my $form = $main::form;
810 my %myconfig = %main::myconfig;
811 my $locale = $main::locale;
813 $main::auth->assert('config');
815 $form->isblank("new_name", $locale->text("The name is missing."));
816 my $units = AM->retrieve_units(\%myconfig, $form);
817 my $all_units = AM->retrieve_units(\%myconfig, $form);
818 $form->show_generic_error($locale->text("A unit with this name does already exist.")) if ($all_units->{$form->{"new_name"}});
820 my ($base_unit, $factor);
821 if ($form->{"new_base_unit"}) {
822 $form->show_generic_error($locale->text("The base unit does not exist.")) unless (defined($units->{$form->{"new_base_unit"}}));
824 $form->isblank("new_factor", $locale->text("The factor is missing."));
825 $factor = $form->parse_amount(\%myconfig, $form->{"new_factor"});
826 $form->show_generic_error($locale->text("The factor is missing.")) unless ($factor);
827 $base_unit = $form->{"new_base_unit"};
831 foreach my $lang (@{ SL::DB::Manager::Language->get_all_sorted }) {
832 next unless ($form->{"new_localized_$lang->{id}"} || $form->{"new_localized_plural_$lang->{id}"});
833 push(@languages, { "id" => $lang->id,
834 "localized" => $form->{"new_localized_" . $lang->id},
835 "localized_plural" => $form->{"new_localized_plural_" . $lang->id},
839 AM->add_unit(\%myconfig, $form, $form->{"new_name"}, $base_unit, $factor, \@languages);
841 flash_later('info', $locale->text("The unit has been added."));
843 print $form->redirect_header('am.pl?action=edit_units');
845 $main::lxdebug->leave_sub();
848 sub set_unit_languages {
849 $main::lxdebug->enter_sub();
851 my $form = $main::form;
853 $main::auth->assert('config');
855 my ($unit, $languages, $idx) = @_;
857 $unit->{"LANGUAGES"} = [];
859 foreach my $lang (@{$languages}) {
860 push(@{ $unit->{"LANGUAGES"} },
862 "localized" => $form->{"localized_${idx}_" . $lang->id},
863 "localized_plural" => $form->{"localized_plural_${idx}_" . $lang->id},
867 $main::lxdebug->leave_sub();
871 $main::lxdebug->enter_sub();
873 my $form = $main::form;
874 my %myconfig = %main::myconfig;
875 my $locale = $main::locale;
877 $main::auth->assert('config');
879 my $old_units = AM->retrieve_units(\%myconfig, $form, "resolved_");
880 AM->units_in_use(\%myconfig, $form, $old_units);
882 my @languages = @{ SL::DB::Manager::Language->get_all_sorted };
885 my @delete_units = ();
886 foreach my $i (1..($form->{"rowcount"} * 1)) {
887 my $old_unit = $old_units->{$form->{"old_name_$i"}};
889 $form->show_generic_error(sprintf($locale->text("The unit in row %d has been deleted in the meantime."), $i));
892 if ($form->{"unchangeable_$i"}) {
893 $new_units->{$form->{"old_name_$i"}} = $old_units->{$form->{"old_name_$i"}};
894 $new_units->{$form->{"old_name_$i"}}->{"unchanged_unit"} = 1;
895 set_unit_languages($new_units->{$form->{"old_name_$i"}}, \@languages, $i);
899 if ($old_unit->{"in_use"}) {
900 $form->show_generic_error(sprintf($locale->text("The unit in row %d has been used in the meantime and cannot be changed anymore."), $i));
903 if ($form->{"delete_$i"}) {
904 push(@delete_units, $old_unit->{"name"});
908 $form->isblank("name_$i", sprintf($locale->text("The name is missing in row %d."), $i));
910 $form->show_generic_error(sprintf($locale->text("The name in row %d has already been used before."), $i)) if ($new_units->{$form->{"name_$i"}});
911 my %h = map({ $_ => $form->{"${_}_$i"} } qw(name base_unit factor old_name));
912 $new_units->{$form->{"name_$i"}} = \%h;
913 $new_units->{$form->{"name_$i"}}->{"row"} = $i;
914 set_unit_languages($new_units->{$form->{"old_name_$i"}}, \@languages, $i);
917 foreach my $unit (values(%{$new_units})) {
918 next unless ($unit->{"old_name"});
919 if ($unit->{"base_unit"}) {
920 $form->show_generic_error(sprintf($locale->text("The base unit does not exist or it is about to be deleted in row %d."), $unit->{"row"}))
921 unless (defined($new_units->{$unit->{"base_unit"}}));
922 $unit->{"factor"} = $form->parse_amount(\%myconfig, $unit->{"factor"});
923 $form->show_generic_error(sprintf($locale->text("The factor is missing in row %d."), $unit->{"row"})) unless ($unit->{"factor"} >= 1.0);
925 $unit->{"base_unit"} = undef;
926 $unit->{"factor"} = undef;
930 foreach my $unit (values(%{$new_units})) {
931 next if ($unit->{"unchanged_unit"});
933 map({ $_->{"seen"} = 0; } values(%{$new_units}));
934 my $new_unit = $unit;
935 while ($new_unit->{"base_unit"}) {
936 $new_unit->{"seen"} = 1;
937 $new_unit = $new_units->{$new_unit->{"base_unit"}};
938 if ($new_unit->{"seen"}) {
939 $form->show_generic_error(sprintf($locale->text("The base unit relations must not contain loops (e.g. by saying that unit A's base unit is B, " .
940 "B's base unit is C and C's base unit is A) in row %d."), $unit->{"row"}));
945 AM->save_units(\%myconfig, $form, $new_units, \@delete_units);
947 flash_later('info', $locale->text("The units have been saved."));
949 print $form->redirect_header('am.pl?action=edit_units');
951 $main::lxdebug->leave_sub();
954 sub show_history_search {
955 $main::lxdebug->enter_sub();
957 my $form = $main::form;
958 my $locale = $main::locale;
960 $main::auth->assert('config');
962 setup_am_show_history_search_action_bar();
964 $form->{title} = $locale->text("History Search");
967 print $form->parse_html_template("common/search_history");
969 $main::lxdebug->leave_sub();
972 sub show_am_history {
973 $main::lxdebug->enter_sub();
975 my $form = $main::form;
976 my %myconfig = %main::myconfig;
977 my $locale = $main::locale;
979 $main::auth->assert('config');
981 my $callback = build_std_url(qw(action einschraenkungen fromdate todate mitarbeiter searchid what2search));
982 $form->{order} ||= 'h.itime--1';
984 # my %search = ( "Artikelnummer" => "parts",
985 # "Kundennummer" => "customer",
986 # "Lieferantennummer" => "vendor",
987 # "Projektnummer" => "project",
988 # "Auftragsnummer" => "oe",
989 # "Angebotsnummer" => "oe",
990 # "Eingangsrechnungnummer" => "ap",
991 # "Ausgangsrechnungnummer" => "ar",
992 # "Mahnungsnummer" => "dunning",
993 # "Buchungsnummer" => "gl",
996 my %searchNo = ( "Artikelnummer" => "partnumber",
997 "Kundennummer" => "customernumber",
998 "Lieferantennummer" => "vendornumber",
999 "Projektnummer" => "projectnumber",
1000 "Auftragsnummer" => "ordnumber",
1001 "Angebotsnummer" => "quonumber",
1002 "Eingangsrechnungnummer" => "invnumber",
1003 "Ausgangsrechnungnummer" => "invnumber",
1004 "Mahnungsnummer" => "dunning_id",
1005 "Buchungsnummer" => "gltransaction"
1008 my $dbh = $form->dbconnect(\%myconfig);
1011 $restriction = qq| AND (| . join(' OR ', map { " addition = " . $dbh->quote($_) } split(m/\,/, $form->{einschraenkungen})) . qq|)| if $form->{einschraenkungen};
1012 $restriction .= qq| AND h.itime::date >= | . conv_dateq($form->{fromdate}) if $form->{fromdate};
1013 $restriction .= qq| AND h.itime::date <= | . conv_dateq($form->{todate}) if $form->{todate};
1014 if ($form->{mitarbeiter} =~ m/^\d+$/) {
1015 $restriction .= qq| AND employee_id = | . $form->{mitarbeiter};
1016 } elsif ($form->{mitarbeiter}) {
1017 $restriction .= qq| AND employee_id = (SELECT id FROM employee WHERE name ILIKE | . $dbh->quote('%' . $form->{mitarbeiter} . '%') . qq|)|;
1020 my $snumbers_where = '';
1022 if ($form->{'searchid'}) {
1023 $snumbers_where = ' WHERE snumbers = ?';
1024 $snumbers_value = $searchNo{$form->{'what2search'}} . '_' . $form->{'searchid'};
1026 $snumbers_where = ' WHERE snumbers ~ ?';
1027 $snumbers_value = '^' . $searchNo{$form->{'what2search'}};
1029 my $query = qq|SELECT trans_id AS id FROM history_erp $snumbers_where|;
1031 my @ids = grep { $_ * 1 } selectall_array_query($form, $dbh, $query, $snumbers_value);
1032 my $daten .= shift @ids;
1033 if (scalar(@ids) > 0 ) {
1034 $daten .= ' OR trans_id IN (' . join(',', @ids) . ')';
1036 my ($sort, $sortby) = split(/\-\-/, $form->{order});
1037 $sort =~ s/.*\.(.*)$/$1/;
1039 setup_am_show_am_history_action_bar();
1041 $form->{title} = $locale->text("History Search");
1044 print $form->parse_html_template("common/show_history",
1045 { "DATEN" => $form->get_history($dbh, $daten, $restriction, $form->{order}),
1046 "SUCCESS" => ($form->get_history($dbh, $daten, $restriction, $form->{order}) ne "0"),
1049 uc($sort) . "BY" => $sortby,
1050 'callback' => $callback,
1054 $main::lxdebug->leave_sub();
1058 $main::lxdebug->enter_sub();
1060 my $form = $main::form;
1061 my $locale = $main::locale;
1063 $main::auth->assert('config');
1065 $form->{title} = $locale->text('Add');
1067 $form->{callback} ||= "am.pl?action=add_tax";
1069 _get_taxaccount_selection();
1072 $form->{liability} = 1;
1073 $form->{equity} = 1;
1074 $form->{revenue} = 1;
1075 $form->{expense} = 1;
1078 setup_am_edit_tax_action_bar();
1081 my $parameters_ref = {
1082 LANGUAGES => SL::DB::Manager::Language->get_all_sorted,
1085 # Ausgabe des Templates
1086 print($form->parse_html_template('am/edit_tax', $parameters_ref));
1088 $main::lxdebug->leave_sub();
1092 $main::lxdebug->enter_sub();
1094 my $form = $main::form;
1095 my %myconfig = %main::myconfig;
1096 my $locale = $main::locale;
1098 $main::auth->assert('config');
1100 $form->{title} = $locale->text('Edit');
1102 AM->get_tax(\%myconfig, \%$form);
1104 _get_taxaccount_selection();
1106 $form->{asset} = $form->{chart_categories} =~ 'A' ? 1 : 0;
1107 $form->{liability} = $form->{chart_categories} =~ 'L' ? 1 : 0;
1108 $form->{equity} = $form->{chart_categories} =~ 'Q' ? 1 : 0;
1109 $form->{revenue} = $form->{chart_categories} =~ 'I' ? 1 : 0;
1110 $form->{expense} = $form->{chart_categories} =~ 'E' ? 1 : 0;
1111 $form->{costs} = $form->{chart_categories} =~ 'C' ? 1 : 0;
1113 $form->{rate} = $form->format_amount(\%myconfig, $form->{rate}, 2);
1115 setup_am_edit_tax_action_bar();
1118 my $parameters_ref = {
1119 LANGUAGES => SL::DB::Manager::Language->get_all_sorted,
1120 TAX => SL::DB::Manager::Tax->find_by(id => $form->{id}),
1123 # Ausgabe des Templates
1124 print($form->parse_html_template('am/edit_tax', $parameters_ref));
1126 $main::lxdebug->leave_sub();
1130 $main::lxdebug->enter_sub();
1132 my $form = $main::form;
1133 my %myconfig = %main::myconfig;
1134 my $locale = $main::locale;
1136 $main::auth->assert('config');
1138 AM->taxes(\%myconfig, \%$form);
1140 map { $_->{rate} = $form->format_amount(\%myconfig, $_->{rate}, 2) } @{ $form->{TAX} };
1142 $form->{callback} = build_std_url('action=list_tax');
1144 $form->{title} = $locale->text('Tax-O-Matic');
1146 setup_am_list_tax_action_bar();
1149 # Ausgabe des Templates
1150 print($form->parse_html_template('am/list_tax'));
1152 $main::lxdebug->leave_sub();
1155 sub _get_taxaccount_selection{
1156 $main::lxdebug->enter_sub();
1158 my $form = $main::form;
1159 my %myconfig = %main::myconfig;
1161 $main::auth->assert('config');
1163 AM->get_tax_accounts(\%myconfig, \%$form);
1165 map { $_->{selected} = $form->{chart_id} == $_->{id} } @{ $form->{ACCOUNTS} };
1167 $main::lxdebug->leave_sub();
1171 $main::lxdebug->enter_sub();
1173 my $form = $main::form;
1174 my %myconfig = %main::myconfig;
1175 my $locale = $main::locale;
1177 $main::auth->assert('config');
1179 $form->error($locale->text('Taxkey missing!')) unless length($form->{taxkey}) != 0;
1180 $form->error($locale->text('Taxdescription missing!')) unless length($form->{taxdescription}) != 0;
1181 $form->error($locale->text('Taxrate missing!')) unless length($form->{rate}) != 0;
1183 $form->{rate} = $form->parse_amount(\%myconfig, $form->{rate});
1185 if ($form->{taxkey} == 0 and $form->{rate} > 0) {
1186 $form->error($locale->text('Taxkey 0 is reserved for rate 0'));
1189 if ( $form->{rate} < 0 || $form->{rate} >= 100 ) {
1190 $form->error($locale->text('Tax Percent is a number between 0 and 100'));
1193 if ( $form->{rate} <= 0.99 && $form->{rate} > 0 ) {
1194 $form->error($locale->text('Tax Percent is a number between 0 and 100'));
1197 my @translation_keys = grep { $_ =~ '^translation_\d+' } keys %$form;
1198 $form->{translations} = { map { $_ =~ '^translation_(\d+)'; $1 => $form->{$_} } @translation_keys };
1200 AM->save_tax(\%myconfig, \%$form);
1201 $form->redirect($locale->text('Tax saved!'));
1203 $main::lxdebug->leave_sub();
1207 $main::lxdebug->enter_sub();
1209 my $form = $main::form;
1210 my %myconfig = %main::myconfig;
1211 my $locale = $main::locale;
1213 $main::auth->assert('config');
1215 AM->delete_tax(\%myconfig, \%$form);
1216 $form->redirect($locale->text('Tax deleted!'));
1218 $main::lxdebug->leave_sub();
1222 $main::lxdebug->enter_sub();
1224 my $form = $main::form;
1225 my $locale = $main::locale;
1227 $main::auth->assert('config');
1229 $form->{title} = $locale->text('Add Warehouse');
1230 $form->{callback} ||= build_std_url('action=add_warehouse');
1232 setup_am_edit_warehouse_action_bar();
1235 print $form->parse_html_template('am/edit_warehouse');
1237 $main::lxdebug->leave_sub();
1240 sub edit_warehouse {
1241 $main::lxdebug->enter_sub();
1243 my $form = $main::form;
1244 my %myconfig = %main::myconfig;
1245 my $locale = $main::locale;
1247 $main::auth->assert('config');
1249 AM->get_warehouse(\%myconfig, $form);
1251 $form->get_lists('employees' => 'EMPLOYEES');
1253 $form->{title} = $locale->text('Edit Warehouse');
1254 $form->{callback} ||= build_std_url('action=list_warehouses');
1256 setup_am_edit_warehouse_action_bar(id => $::form->{id}, in_use => any { $_->{in_use} } @{ $::form->{BINS} });
1259 print $form->parse_html_template('am/edit_warehouse');
1261 $main::lxdebug->leave_sub();
1265 $::auth->assert('config');
1267 AM->get_warehouse(\%::myconfig, $::form);
1269 $::form->{title} = $::locale->text('Edit Bins for Warehouse \'#1\'', $::form->{description});
1270 $::form->{callback} ||= build_std_url('action=list_warehouses');
1272 setup_am_edit_bins_action_bar(id => $::form->{id});
1275 print $::form->parse_html_template('am/edit_bins');
1278 sub list_warehouses {
1279 $main::lxdebug->enter_sub();
1281 my $form = $main::form;
1282 my %myconfig = %main::myconfig;
1283 my $locale = $main::locale;
1285 $main::auth->assert('config');
1287 AM->get_all_warehouses(\%myconfig, $form);
1289 $form->{callback} = build_std_url('action=list_warehouses');
1290 $form->{title} = $locale->text('Warehouses');
1291 $form->{url_base} = build_std_url('callback');
1293 setup_am_list_warehouses_action_bar();
1296 print $form->parse_html_template('am/list_warehouses');
1298 $main::lxdebug->leave_sub();
1301 sub save_warehouse {
1302 $main::lxdebug->enter_sub();
1304 my $form = $main::form;
1305 my %myconfig = %main::myconfig;
1306 my $locale = $main::locale;
1308 $main::auth->assert('config');
1310 $form->isblank("description", $locale->text('Description missing!'));
1312 $form->{number_of_new_bins} = $form->parse_amount(\%myconfig, $form->{number_of_new_bins});
1314 AM->save_warehouse(\%myconfig, $form);
1316 $form->{callback} .= '&saved_message=' . E($locale->text('Warehouse saved.')) if ($form->{callback});
1318 $form->redirect($locale->text('Warehouse saved.'));
1320 $main::lxdebug->leave_sub();
1323 sub delete_warehouse {
1324 $main::lxdebug->enter_sub();
1326 my $form = $main::form;
1327 my %myconfig = %main::myconfig;
1328 my $locale = $main::locale;
1330 $main::auth->assert('config');
1332 if (AM->delete_warehouse(\%myconfig, $form)) {
1333 $form->{callback} .= '&saved_message=' . E($locale->text('Warehouse deleted.')) if ($form->{callback});
1334 $form->redirect($locale->text('Warehouse deleted.'));
1337 $form->error($locale->text('The warehouse could not be deleted because it has already been used.'));
1340 $main::lxdebug->leave_sub();
1344 $main::lxdebug->enter_sub();
1346 my $form = $main::form;
1347 my %myconfig = %main::myconfig;
1348 my $locale = $main::locale;
1350 $main::auth->assert('config');
1352 AM->save_bins(\%myconfig, $form);
1354 $form->{callback} .= '&saved_message=' . E($locale->text('Bins saved.')) if ($form->{callback});
1356 $form->redirect($locale->text('Bins saved.'));
1358 $main::lxdebug->leave_sub();
1361 sub setup_am_config_action_bar {
1364 for my $bar ($::request->layout->get('actionbar')) {
1368 submit => [ '#form', { action => "save_preferences" } ],
1369 accesskey => 'enter',
1375 sub setup_am_edit_account_action_bar {
1378 for my $bar ($::request->layout->get('actionbar')) {
1383 submit => [ '#form', { action => "save_account" } ],
1384 accesskey => 'enter',
1389 submit => [ '#form', { action => "save_as_new_account" } ],
1390 disabled => !$::form->{id} ? t8('The object has not been saved yet.') : undef,
1396 submit => [ '#form', { action => "delete_account" } ],
1397 disabled => !$::form->{id} ? t8('The object has not been saved yet.')
1398 : $::form->{id} && !$::form->{orphaned} ? t8('The object is in use and cannot be deleted.')
1400 confirm => t8('Do you really want to delete this object?'),
1406 sub setup_am_list_tax_action_bar {
1409 for my $bar ($::request->layout->get('actionbar')) {
1413 link => 'am.pl?action=add_tax',
1419 sub setup_am_edit_tax_action_bar {
1422 for my $bar ($::request->layout->get('actionbar')) {
1426 submit => [ '#form', { action => "save_tax" } ],
1427 accesskey => 'enter',
1432 submit => [ '#form', { action => "delete_tax" } ],
1433 disabled => !$::form->{id} ? t8('The object has not been saved yet.')
1434 : !$::form->{orphaned} || $::form->{tax_already_used} ? t8('The object is in use and cannot be deleted.')
1436 confirm => t8('Do you really want to delete this object?'),
1442 sub setup_am_add_unit_action_bar {
1445 for my $bar ($::request->layout->get('actionbar')) {
1449 submit => [ '#form', { action => "create_unit" } ],
1450 accesskey => 'enter',
1457 link => 'am.pl?action=edit_units',
1463 sub setup_am_edit_units_action_bar {
1466 for my $bar ($::request->layout->get('actionbar')) {
1470 submit => [ '#form', { action => "save_unit" } ],
1471 accesskey => 'enter',
1478 link => 'am.pl?action=add_unit',
1484 sub setup_am_list_warehouses_action_bar {
1487 for my $bar ($::request->layout->get('actionbar')) {
1491 link => 'am.pl?action=add&type=warehouse&callback=' . E($::form->{callback}),
1492 accesskey => 'enter',
1498 sub setup_am_edit_warehouse_action_bar {
1501 for my $bar ($::request->layout->get('actionbar')) {
1505 submit => [ '#form', { action => 'save_warehouse' } ],
1506 accesskey => 'enter',
1511 submit => [ '#form', { action => 'delete_warehouse' } ],
1512 disabled => !$params{id} ? t8('The object has not been saved yet.')
1513 : $params{in_use} ? t8('The object is in use and cannot be deleted.')
1515 confirm => t8('Do you really want to delete this object?'),
1522 link => 'am.pl?action=edit_bins&id=' . E($params{id}),
1523 only_if => $params{id},
1528 link => $::form->{callback} || 'am.pl?action=list_warehouses',
1534 sub setup_am_edit_bins_action_bar {
1537 for my $bar ($::request->layout->get('actionbar')) {
1541 submit => [ '#form', { action => 'save_bin' } ],
1542 accesskey => 'enter',
1549 link => 'am.pl?action=edit_warehouse&id=' . E($params{id}),
1555 sub setup_am_audit_control_action_bar {
1558 for my $bar ($::request->layout->get('actionbar')) {
1562 submit => [ '#form', { action => 'doclose' } ],
1563 accesskey => 'enter',
1569 sub setup_am_show_history_search_action_bar {
1572 for my $bar ($::request->layout->get('actionbar')) {
1576 submit => [ '#form' ],
1577 accesskey => 'enter',
1583 sub setup_am_show_am_history_action_bar {
1586 for my $bar ($::request->layout->get('actionbar')) {
1590 call => [ 'kivi.history_back' ],