X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;ds=sidebyside;f=bin%2Fmozilla%2Fgl.pl;h=0d39d47ea65e403c3b1818cec19839d95659c82e;hb=5c8a0b36440e012cd0a54e6b68eb3d1411243b1a;hp=719f2220991dd32a42497e73f401b31943ad17ec;hpb=8a40e3dd0f638557b8c666fe708ccbc1ac709c4e;p=kivitendo-erp.git diff --git a/bin/mozilla/gl.pl b/bin/mozilla/gl.pl index 719f22209..0d39d47ea 100644 --- a/bin/mozilla/gl.pl +++ b/bin/mozilla/gl.pl @@ -24,7 +24,8 @@ # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1335, USA. #====================================================================== # # Genereal Ledger @@ -35,16 +36,23 @@ use utf8; use strict; use POSIX qw(strftime); -use List::Util qw(sum); +use List::Util qw(first sum); +use SL::DB::RecordTemplate; +use SL::DB::BankTransactionAccTrans; +use SL::DB::Tax; use SL::FU; use SL::GL; +use SL::Helper::Flash qw(flash flash_later); use SL::IS; -use SL::PE; use SL::ReportGenerator; - +use SL::DBUtils qw(selectrow_query selectall_hashref_query); +use SL::Webdav; +use SL::Locale::String qw(t8); +use SL::Helper::GlAttachments qw(count_gl_attachments); +use SL::Presenter::Tag; +use SL::Presenter::Chart; require "bin/mozilla/common.pl"; -require "bin/mozilla/drafts.pl"; require "bin/mozilla/reportgenerator.pl"; # this is for our long dates @@ -75,16 +83,142 @@ require "bin/mozilla/reportgenerator.pl"; # $locale->text('Nov') # $locale->text('Dec') +sub load_record_template { + $::auth->assert('gl_transactions'); + + # Load existing template and verify that its one for this module. + my $template = SL::DB::RecordTemplate + ->new(id => $::form->{id}) + ->load( + with_object => [ qw(customer payment currency record_items record_items.chart) ], + ); + + die "invalid template type" unless $template->template_type eq 'gl_transaction'; + + $template->substitute_variables; + my $payment_suggestion = $::form->{form_defaults}->{amount_1}; + + # Clean the current $::form before rebuilding it from the template. + my $form_defaults = delete $::form->{form_defaults}; + delete @{ $::form }{ grep { !m{^(?:script|login)$}i } keys %{ $::form } }; + + my $dummy_form = {}; + GL->transaction(\%::myconfig, $dummy_form); + + # Fill $::form from the template. + my $today = DateTime->today_local; + $::form->{title} = "Add"; + $::form->{transdate} = $today->to_kivitendo; + $::form->{duedate} = $today->to_kivitendo; + $::form->{rowcount} = @{ $template->items }; + $::form->{paidaccounts} = 1; + $::form->{$_} = $template->$_ for qw(department_id taxincluded ob_transaction cb_transaction reference description show_details); + $::form->{$_} = $dummy_form->{$_} for qw(closedto revtrans previous_id previous_gldate); + + my $row = 0; + foreach my $item (@{ $template->items }) { + $row++; + + my $active_taxkey = $item->chart->get_active_taxkey; + my $taxes = SL::DB::Manager::Tax->get_all( + where => [ chart_categories => { like => '%' . $item->chart->category . '%' }], + sort_by => 'taxkey, rate', + ); + + my $tax = first { $item->tax_id == $_->id } @{ $taxes }; + $tax //= first { $active_taxkey->tax_id == $_->id } @{ $taxes }; + $tax //= $taxes->[0]; + + if (!$tax) { + $row--; + next; + } + + $::form->{"accno_id_${row}"} = $item->chart_id; + $::form->{"previous_accno_id_${row}"} = $item->chart_id; + $::form->{"debit_${row}"} = $::form->format_amount(\%::myconfig, ($payment_suggestion ? $payment_suggestion : $item->amount1), 2) if $item->amount1 * 1; + $::form->{"credit_${row}"} = $::form->format_amount(\%::myconfig, ($payment_suggestion ? $payment_suggestion : $item->amount2), 2) if $item->amount2 * 1; + $::form->{"taxchart_${row}"} = $item->tax_id . '--' . $tax->rate; + $::form->{"${_}_${row}"} = $item->$_ for qw(source memo project_id); + } + + $::form->{$_} = $form_defaults->{$_} for keys %{ $form_defaults // {} }; + + flash('info', $::locale->text("The record template '#1' has been loaded.", $template->template_name)); + + update( + keep_rows_without_amount => 1, + dont_add_new_row => 1, + ); +} + +sub save_record_template { + $::auth->assert('gl_transactions'); + + my $template = $::form->{record_template_id} ? SL::DB::RecordTemplate->new(id => $::form->{record_template_id})->load : SL::DB::RecordTemplate->new; + my $js = SL::ClientJS->new(controller => SL::Controller::Base->new); + my $new_name = $template->template_name_to_use($::form->{record_template_new_template_name}); + $js->dialog->close('#record_template_dialog'); + + + # bank transactions need amounts for assignment + my $can_save = 0; + $can_save = 1 if ($::form->{credit_1} > 0 && $::form->{debit_2} > 0 && $::form->{credit_2} == 0 && $::form->{debit_1} == 0); + $can_save = 1 if ($::form->{credit_2} > 0 && $::form->{debit_1} > 0 && $::form->{credit_1} == 0 && $::form->{debit_2} == 0); + return $js->flash('error', t8('Can only save template if amounts,i.e. 1 for debit and credit are set.'))->render unless $can_save; + + my @items = grep { + $_->{chart_id} && (($_->{tax_id} // '') ne '') + } map { + +{ chart_id => $::form->{"accno_id_${_}"}, + amount1 => $::form->parse_amount(\%::myconfig, $::form->{"debit_${_}"}), + amount2 => $::form->parse_amount(\%::myconfig, $::form->{"credit_${_}"}), + tax_id => (split m{--}, $::form->{"taxchart_${_}"})[0], + project_id => $::form->{"project_id_${_}"} || undef, + source => $::form->{"source_${_}"}, + memo => $::form->{"memo_${_}"}, + } + } (1..($::form->{rowcount} || 1)); + + $template->assign_attributes( + template_type => 'gl_transaction', + template_name => $new_name, + + currency_id => $::instance_conf->get_currency_id, + department_id => $::form->{department_id} || undef, + project_id => $::form->{globalproject_id} || undef, + taxincluded => $::form->{taxincluded} ? 1 : 0, + ob_transaction => $::form->{ob_transaction} ? 1 : 0, + cb_transaction => $::form->{cb_transaction} ? 1 : 0, + reference => $::form->{reference}, + description => $::form->{description}, + show_details => $::form->{show_details}, + + items => \@items, + ); + + eval { + $template->save; + 1; + } or do { + return $js + ->flash('error', $::locale->text("Saving the record template '#1' failed.", $new_name)) + ->render; + }; + + return $js + ->flash('info', $::locale->text("The record template '#1' has been saved.", $new_name)) + ->render; +} + sub add { $main::lxdebug->enter_sub(); - $main::auth->assert('general_ledger'); + $main::auth->assert('gl_transactions'); my $form = $main::form; my %myconfig = %main::myconfig; - return $main::lxdebug->leave_sub() if (load_draft_maybe()); - $form->{title} = "Add"; $form->{callback} = "gl.pl?action=add" unless $form->{callback}; @@ -99,16 +233,7 @@ sub add { $form->{credit} = 0; $form->{tax} = 0; - # departments - $form->all_departments(\%myconfig); - if (@{ $form->{all_departments} || [] }) { - $form->{selectdepartment} = "\n"; - - map { - $form->{selectdepartment} .= - "$_->{description}--$_->{id}\n" - } (@{ $form->{all_departments} || [] }); - } + $::form->{ALL_DEPARTMENTS} = SL::DB::Manager::Department->get_all_sorted; $form->{show_details} = $myconfig{show_form_details} unless defined $form->{show_details}; @@ -120,7 +245,7 @@ sub add { sub prepare_transaction { $main::lxdebug->enter_sub(); - $main::auth->assert('general_ledger'); + $main::auth->assert('gl_transactions'); my $form = $main::form; my %myconfig = %main::myconfig; @@ -129,16 +254,7 @@ sub prepare_transaction { $form->{amount} = $form->format_amount(\%myconfig, $form->{amount}, 2); - # departments - $form->all_departments(\%myconfig); - if (@{ $form->{all_departments} || [] }) { - $form->{selectdepartment} = "\n"; - - map { - $form->{selectdepartment} .= - "$_->{description}--$_->{id}\n" - } (@{ $form->{all_departments} || [] }); - } + $::form->{ALL_DEPARTMENTS} = SL::DB::Manager::Department->get_all_sorted; my $i = 1; my $tax = 0; @@ -158,7 +274,7 @@ sub prepare_transaction { $form->{"project_id_$j"} = $ref->{project_id}; } else { - $form->{"accno_$i"} = "$ref->{accno}--$ref->{tax_id}"; + $form->{"accno_id_$i"} = $ref->{chart_id}; for (qw(fx_transaction source memo)) { $form->{"${_}_$i"} = $ref->{$_} } if ($ref->{amount} < 0) { $form->{totaldebit} -= $ref->{amount}; @@ -167,7 +283,7 @@ sub prepare_transaction { $form->{totalcredit} += $ref->{amount}; $form->{"credit_$i"} = $ref->{amount}; } - $form->{"taxchart_$i"} = "0--0.00"; + $form->{"taxchart_$i"} = $ref->{id}."--0.00000"; $form->{"project_id_$i"} = $ref->{project_id}; $i++; } @@ -191,7 +307,7 @@ sub prepare_transaction { sub edit { $main::lxdebug->enter_sub(); - $main::auth->assert('general_ledger'); + $main::auth->assert('gl_transactions'); my $form = $main::form; my %myconfig = %main::myconfig; @@ -202,6 +318,17 @@ sub edit { $form->{show_details} = $myconfig{show_form_details} unless defined $form->{show_details}; + if ($form->{id} && $::instance_conf->get_webdav) { + my $webdav = SL::Webdav->new( + type => 'general_ledger', + number => $form->{id}, + ); + my @all_objects = $webdav->get_all_objects; + @{ $form->{WEBDAV} } = map { { name => $_->filename, + type => t8('File'), + link => File::Spec->catfile($_->full_filedescriptor), + } } @all_objects; + } form_header(); display_rows(); form_footer(); @@ -212,17 +339,18 @@ sub edit { sub search { $::lxdebug->enter_sub; - $::auth->assert('general_ledger'); + $::auth->assert('general_ledger | gl_transactions'); - $::form->all_departments(\%::myconfig); $::form->get_lists( projects => { key => "ALL_PROJECTS", all => 1 }, ); - $::form->{ALL_EMPLOYEES} = SL::DB::Manager::Employee->get_all(query => [ deleted => 0 ]); + $::form->{ALL_EMPLOYEES} = SL::DB::Manager::Employee->get_all_sorted(query => [ deleted => 0 ]); + $::form->{ALL_DEPARTMENTS} = SL::DB::Manager::Department->get_all_sorted; + + setup_gl_search_action_bar(); $::form->header; print $::form->parse_html_template('gl/search', { - department_label => sub { ("$_[0]{description}--$_[0]{id}")x2 }, employee_label => sub { "$_[0]{id}--$_[0]{name}" }, }); @@ -251,22 +379,22 @@ sub create_subtotal_row { sub generate_report { $main::lxdebug->enter_sub(); - $main::auth->assert('general_ledger'); + $main::auth->assert('general_ledger | gl_transactions'); my $form = $main::form; my %myconfig = %main::myconfig; my $locale = $main::locale; - # generate_report wird beim ersten Aufruf per Weiter-Knopf und POST mit der hidden Variablen sort mit Wert "datesort" (früher "transdate" als Defaultsortiervariable) übertragen + # generate_report wird beim ersten Aufruf per Weiter-Knopf und POST mit der hidden Variablen sort mit Wert "datesort" (früher "transdate" als Defaultsortiervariable) übertragen # # # form->{sort} setzen # # anhand von neuer Variable datesort wird jetzt $form->{sort} auf transdate oder gldate gesetzt - # damit ist die Hidden Variable "sort" wahrscheinlich sogar überflüssig + # damit ist die Hidden Variable "sort" wahrscheinlich sogar überflüssig - # ändert man die Sortierreihenfolge per Klick auf eine der Überschriften wird die Variable "sort" per GET übergeben, z.B. id,transdate, gldate, ... + # ändert man die Sortierreihenfolge per Klick auf eine der Ãberschriften wird die Variable "sort" per GET übergeben, z.B. id,transdate, gldate, ... # gl.pl?action=generate_report&employee=18383--Jan%20B%c3%bcren&datesort=transdate&category=X&l_transdate=Y&l_gldate=Y&l_id=Y&l_reference=Y&l_description=Y&l_source=Y&l_debit=Y&l_credit=Y&sort=gldate&sortdir=0 if ( $form->{sort} eq 'datesort' ) { # sollte bei einem Post (Aufruf aus Suchmaske) immer wahr sein @@ -297,18 +425,18 @@ sub generate_report { my $ml = ($form->{ml} =~ /(A|E|Q)/) ? -1 : 1; my @columns = qw( - gldate transdate id reference description - notes source debit debit_accno + transdate gldate id reference description + notes source doccnt debit debit_accno credit credit_accno debit_tax debit_tax_accno - credit_tax credit_tax_accno projectnumbers balance employee + credit_tax credit_tax_accno balance projectnumbers + department employee ); # add employee here, so that variable is still known and passed in url when choosing a different sort order in resulting table - my @hidden_variables = qw(accno source reference department description notes project_id datefrom dateto employee datesort category l_subtotal); + my @hidden_variables = qw(accno source reference description notes project_id datefrom dateto employee_id datesort category l_subtotal department_id); push @hidden_variables, map { "l_${_}" } @columns; - foreach ( @hidden_variables ) { - print URL "$_\n"; - }; + + my $employee = $form->{employee_id} ? SL::DB::Employee->new(id => $form->{employee_id})->load->name : ''; my (@options, @date_options); push @options, $locale->text('Account') . " : $form->{accno} $form->{account_description}" if ($form->{accno}); @@ -316,22 +444,19 @@ sub generate_report { push @options, $locale->text('Reference') . " : $form->{reference}" if ($form->{reference}); push @options, $locale->text('Description') . " : $form->{description}" if ($form->{description}); push @options, $locale->text('Notes') . " : $form->{notes}" if ($form->{notes}); - push @options, $locale->text('Employee') . " : $form->{employee_name}" if ($form->{employee_name}); - my $datesorttext = $form->{datesort} eq 'transdate' ? $locale->text('Invoice Date') : $locale->text('Booking Date'); + push @options, $locale->text('Employee') . " : $employee" if $employee; + my $datesorttext = $form->{datesort} eq 'transdate' ? $locale->text('Transdate') : $locale->text('Gldate'); push @date_options, "$datesorttext" if ($form->{datesort} and ($form->{datefrom} or $form->{dateto})); push @date_options, $locale->text('From'), $locale->date(\%myconfig, $form->{datefrom}, 1) if ($form->{datefrom}); push @date_options, $locale->text('Bis'), $locale->date(\%myconfig, $form->{dateto}, 1) if ($form->{dateto}); push @options, join(' ', @date_options) if (scalar @date_options); - if ($form->{department}) { - my ($department) = split /--/, $form->{department}; - push @options, $locale->text('Department') . " : $department"; + if ($form->{department_id}) { + my $department = SL::DB::Manager::Department->find_by( id => $form->{department_id} ); + push @options, $locale->text('Department') . " : " . $department->description; } - my $callback = build_std_url('action=generate_report', grep { $form->{$_} } @hidden_variables); - print URL $callback; - close URL; $form->{l_credit_accno} = 'Y'; $form->{l_debit_accno} = 'Y'; @@ -342,13 +467,15 @@ sub generate_report { $form->{l_datesort} = 'Y'; $form->{l_debit_tax_accno} = 'Y'; $form->{l_balance} = $form->{accno} ? 'Y' : ''; + $form->{l_doccnt} = $form->{l_source} ? 'Y' : ''; my %column_defs = ( 'id' => { 'text' => $locale->text('ID'), }, - 'transdate' => { 'text' => $locale->text('Invoice Date'), }, - 'gldate' => { 'text' => $locale->text('Booking Date'), }, + 'transdate' => { 'text' => $locale->text('Transdate'), }, + 'gldate' => { 'text' => $locale->text('Gldate'), }, 'reference' => { 'text' => $locale->text('Reference'), }, 'source' => { 'text' => $locale->text('Source'), }, + 'doccnt' => { 'text' => $locale->text('Document Count'), }, 'description' => { 'text' => $locale->text('Description'), }, 'notes' => { 'text' => $locale->text('Notes'), }, 'debit' => { 'text' => $locale->text('Debit'), }, @@ -361,10 +488,11 @@ sub generate_report { 'credit_tax_accno' => { 'text' => $locale->text('Credit Tax Account'), }, 'balance' => { 'text' => $locale->text('Balance'), }, 'projectnumbers' => { 'text' => $locale->text('Project Numbers'), }, + 'department' => { 'text' => $locale->text('Department'), }, 'employee' => { 'text' => $locale->text('Employee'), }, ); - foreach my $name (qw(id transdate gldate reference description debit_accno credit_accno debit_tax_accno credit_tax_accno)) { + foreach my $name (qw(id transdate gldate reference description debit_accno credit_accno debit_tax_accno credit_tax_accno department)) { my $sortname = $name =~ m/accno/ ? 'accno' : $name; my $sortdir = $sortname eq $form->{sort} ? 1 - $form->{sortdir} : $form->{sortdir}; $column_defs{$name}->{link} = $callback . "&sort=$sortname&sortdir=$sortdir"; @@ -384,7 +512,8 @@ sub generate_report { $report->set_columns(%column_defs); $report->set_column_order(@columns); - $report->set_export_options('generate_report', @hidden_variables, qw(sort sortdir)); + $form->{l_attachments} = 'Y'; + $report->set_export_options('generate_report', @hidden_variables, qw(sort sortdir l_attachments)); $report->set_sort_indicator($form->{sort} eq 'accno' ? 'debit_accno' : $form->{sort}, $form->{sortdir}); @@ -433,6 +562,10 @@ sub generate_report { my $row = { }; map { $row->{$_} = { 'data' => '', 'align' => $column_alignment{$_} } } @columns; + if ( $form->{l_doccnt} ) { + $row->{doccnt}->{data} = SL::Helper::GlAttachments->count_gl_pdf_attachments($ref->{id},$ref->{type}); + } + my $sh = ""; if ($form->{balance} < 0) { $sh = " S"; @@ -447,7 +580,7 @@ sub generate_report { $row->{balance}->{data} = $data; $row->{projectnumbers}->{data} = join ", ", sort { lc($a) cmp lc($b) } keys %{ $ref->{projectnumbers} }; - map { $row->{$_}->{data} = $ref->{$_} } qw(id reference description notes gldate employee); + map { $row->{$_}->{data} = $ref->{$_} } qw(id reference description notes gldate employee department); map { $row->{$_}->{data} = \@{ $rows{$_} }; } qw(transdate debit credit debit_accno credit_accno debit_tax_accno credit_tax_accno source); @@ -510,15 +643,25 @@ sub generate_report { $report->set_options('raw_bottom_info_text' => $raw_bottom_info_text); + setup_gl_transactions_action_bar(); + $report->generate_with_headers(); $main::lxdebug->leave_sub(); } +sub show_draft { + $::form->{transdate} = DateTime->today_local->to_kivitendo if !$::form->{transdate}; + $::form->{gldate} = $::form->{transdate} if !$::form->{gldate}; + update(); +} + sub update { + my %params = @_; + $main::lxdebug->enter_sub(); - $main::auth->assert('general_ledger'); + $main::auth->assert('gl_transactions'); my $form = $main::form; my %myconfig = %main::myconfig; @@ -533,77 +676,73 @@ sub update { my $creditcount = 0; my ($debitcredit, $amount); + my $dbh = SL::DB->client->dbh; + my ($notax_id) = selectrow_query($form, $dbh, "SELECT id FROM tax WHERE taxkey = 0 LIMIT 1", ); + my $zerotaxes = selectall_hashref_query($form, $dbh, "SELECT id FROM tax WHERE rate = 0", ); + my @flds = - qw(accno debit credit projectnumber fx_transaction source memo tax taxchart); + qw(accno_id debit credit projectnumber fx_transaction source memo tax taxchart); for my $i (1 .. $form->{rowcount}) { + $form->{"${_}_$i"} = $form->parse_amount(\%myconfig, $form->{"${_}_$i"}) for qw(debit credit tax); - unless (($form->{"debit_$i"} eq "") && ($form->{"credit_$i"} eq "")) { - for (qw(debit credit tax)) { - $form->{"${_}_$i"} = - $form->parse_amount(\%myconfig, $form->{"${_}_$i"}); - } + next if !$form->{"debit_$i"} && !$form->{"credit_$i"} && !$params{keep_rows_without_amount}; - push @a, {}; - $debitcredit = ($form->{"debit_$i"} == 0) ? "0" : "1"; - if ($debitcredit) { - $debitcount++; - } else { - $creditcount++; - } + push @a, {}; + $debitcredit = ($form->{"debit_$i"} == 0) ? "0" : "1"; + if ($debitcredit) { + $debitcount++; + } else { + $creditcount++; + } - if (($debitcount >= 2) && ($creditcount == 2)) { - $form->{"credit_$i"} = 0; - $form->{"tax_$i"} = 0; - $creditcount--; - $form->{creditlock} = 1; - } - if (($creditcount >= 2) && ($debitcount == 2)) { - $form->{"debit_$i"} = 0; - $form->{"tax_$i"} = 0; - $debitcount--; - $form->{debitlock} = 1; - } - if (($creditcount == 1) && ($debitcount == 2)) { - $form->{creditlock} = 1; - } - if (($creditcount == 2) && ($debitcount == 1)) { - $form->{debitlock} = 1; - } - if ($debitcredit && $credittax) { - $form->{"taxchart_$i"} = "0--0.00"; - } - if (!$debitcredit && $debittax) { - $form->{"taxchart_$i"} = "0--0.00"; - } - $amount = - ($form->{"debit_$i"} == 0) - ? $form->{"credit_$i"} - : $form->{"debit_$i"}; - my $j = $#a; - if (($debitcredit && $credittax) || (!$debitcredit && $debittax)) { - $form->{"taxchart_$i"} = "0--0.00"; - $form->{"tax_$i"} = 0; - } - my ($taxkey, $rate) = split(/--/, $form->{"taxchart_$i"}); - if ($taxkey > 1) { - if ($debitcredit) { - $debittax = 1; - } else { - $credittax = 1; - } - if ($form->{taxincluded}) { - $form->{"tax_$i"} = $amount / ($rate + 1) * $rate; - } else { - $form->{"tax_$i"} = $amount * $rate; - } + if (($debitcount >= 2) && ($creditcount == 2)) { + $form->{"credit_$i"} = 0; + $form->{"tax_$i"} = 0; + $creditcount--; + $form->{creditlock} = 1; + } + if (($creditcount >= 2) && ($debitcount == 2)) { + $form->{"debit_$i"} = 0; + $form->{"tax_$i"} = 0; + $debitcount--; + $form->{debitlock} = 1; + } + if (($creditcount == 1) && ($debitcount == 2)) { + $form->{creditlock} = 1; + } + if (($creditcount == 2) && ($debitcount == 1)) { + $form->{debitlock} = 1; + } + if ($debitcredit && $credittax) { + $form->{"taxchart_$i"} = "$notax_id--0.00000"; + } + if (!$debitcredit && $debittax) { + $form->{"taxchart_$i"} = "$notax_id--0.00000"; + } + $amount = + ($form->{"debit_$i"} == 0) + ? $form->{"credit_$i"} + : $form->{"debit_$i"}; + my $j = $#a; + if (($debitcredit && $credittax) || (!$debitcredit && $debittax)) { + $form->{"taxchart_$i"} = "$notax_id--0.00000"; + $form->{"tax_$i"} = 0; + } + my ($taxkey, $rate) = split(/--/, $form->{"taxchart_$i"}); + my $iswithouttax = grep { $_->{id} == $taxkey } @{ $zerotaxes }; + if (!$iswithouttax) { + if ($debitcredit) { + $debittax = 1; } else { - $form->{"tax_$i"} = 0; + $credittax = 1; } + }; + my ($tmpnetamount,$tmpdiff); + ($tmpnetamount,$form->{"tax_$i"},$tmpdiff) = $form->calculate_tax($amount,$rate,$form->{taxincluded} *= 1,2); - for (@flds) { $a[$j]->{$_} = $form->{"${_}_$i"} } - $count++; - } + for (@flds) { $a[$j]->{$_} = $form->{"${_}_$i"} } + $count++; } for my $i (1 .. $count) { @@ -615,9 +754,9 @@ sub update { for (@flds) { delete $form->{"${_}_$i"} } } - $form->{rowcount} = $count + 1; + $form->{rowcount} = $count + ($params{dont_add_new_row} ? 0 : 1); - &display_form; + display_form(); $main::lxdebug->leave_sub(); } @@ -626,7 +765,7 @@ sub display_form { my ($init) = @_; $main::lxdebug->enter_sub(); - $main::auth->assert('general_ledger'); + $main::auth->assert('gl_transactions'); my $form = $main::form; my %myconfig = %main::myconfig; @@ -649,48 +788,22 @@ sub display_rows { my ($init) = @_; $main::lxdebug->enter_sub(); - $main::auth->assert('general_ledger'); + $main::auth->assert('gl_transactions'); my $form = $main::form; my %myconfig = %main::myconfig; my $cgi = $::request->{cgi}; + my %balances = GL->get_chart_balances(map { $_->{id} } @{ $form->{ALL_CHARTS} }); + $form->{debit_1} = 0 if !$form->{"debit_1"}; $form->{totaldebit} = 0; $form->{totalcredit} = 0; - my %project_labels = (); - my @project_values = (""); - foreach my $item (@{ $form->{"ALL_PROJECTS"} }) { - push(@project_values, $item->{"id"}); - $project_labels{$item->{"id"}} = $item->{"projectnumber"}; - } - - my %chart_labels = (); - my @chart_values = (); - my %charts = (); - my $taxchart_init; - foreach my $item (@{ $form->{ALL_CHARTS} }) { - if ($item->{charttype} eq 'H'){ #falls überschrift - next; #überspringen (Bug 1150) - } - my $key = $item->{accno} . "--" . $item->{tax_id}; - $taxchart_init = $item->{tax_id} unless (@chart_values); - push(@chart_values, $key); - $chart_labels{$key} = $item->{accno} . "--" . $item->{description}; - $charts{$item->{accno}} = $item; - } - - my %taxchart_labels = (); - my @taxchart_values = (); - my %taxcharts = (); - foreach my $item (@{ $form->{ALL_TAXCHARTS} }) { - my $key = $item->{id} . "--" . $item->{rate}; - $taxchart_init = $key if ($taxchart_init == $item->{id}); - push(@taxchart_values, $key); - $taxchart_labels{$key} = $item->{taxdescription} . " " . $item->{rate} * 100 . ' %'; - $taxcharts{$item->{id}} = $item; - } + my %charts_by_id = map { ($_->{id} => $_) } @{ $::form->{ALL_CHARTS} }; + my $default_chart = $::form->{ALL_CHARTS}[0]; + my $transdate = $::form->{transdate} ? DateTime->from_kivitendo($::form->{transdate}) : DateTime->today_local; + my $deliverydate = $::form->{deliverydate} ? DateTime->from_kivitendo($::form->{deliverydate}) : undef; my ($source, $memo, $source_hidden, $memo_hidden); for my $i (1 .. $form->{rowcount}) { @@ -706,43 +819,44 @@ sub display_rows { |; } - my $selected_accno_full; - my ($accno_row) = split(/--/, $form->{"accno_$i"}); - my $item = $charts{$accno_row}; - $selected_accno_full = "$item->{accno}--$item->{tax_id}"; + my %taxchart_labels = (); + my @taxchart_values = (); - my $selected_taxchart = $form->{"taxchart_$i"}; - my ($selected_accno, $selected_tax_id) = split(/--/, $selected_accno_full); - my ($previous_accno, $previous_tax_id) = split(/--/, $form->{"previous_accno_$i"}); + my $accno_id = $::form->{"accno_id_$i"}; + my $chart = $charts_by_id{$accno_id} // $default_chart; + $accno_id = $chart->{id}; + my ($first_taxchart, $default_taxchart, $taxchart_to_use); - if ($previous_accno && - ($previous_accno eq $selected_accno) && - ($previous_tax_id ne $selected_tax_id)) { - my $item = $taxcharts{$selected_tax_id}; - $selected_taxchart = "$item->{id}--$item->{rate}"; + my $used_tax_id; + if ( $form->{"taxchart_$i"} ) { + ($used_tax_id) = split(/--/, $form->{"taxchart_$i"}); } - $selected_accno = '' if ($init); - $selected_taxchart ||= $taxchart_init; + my $taxdate = $deliverydate ? $deliverydate : $transdate; + foreach my $item ( GL->get_active_taxes_for_chart($accno_id, $taxdate, $used_tax_id) ) { + my $key = $item->id . "--" . $item->rate; + $first_taxchart //= $item; + $default_taxchart = $item if $item->{is_default}; + $taxchart_to_use = $item if $key eq $form->{"taxchart_$i"}; + + push(@taxchart_values, $key); + $taxchart_labels{$key} = $item->taxkey . " - " . $item->taxdescription . " " . $item->rate * 100 . ' %'; + } + + $taxchart_to_use //= $default_taxchart // $first_taxchart; + my $selected_taxchart = $taxchart_to_use->id . '--' . $taxchart_to_use->rate; my $accno = qq|| . - NTI($cgi->popup_menu('-name' => "accno_$i", - '-id' => "accno_$i", - '-onChange' => "setTaxkey($i)", - '-style' => 'width:200px', - '-values' => \@chart_values, - '-labels' => \%chart_labels, - '-default' => $selected_accno_full)) - . $cgi->hidden('-name' => "previous_accno_$i", - '-default' => $selected_accno_full) + SL::Presenter::Chart::picker("accno_id_$i", $accno_id, style => "width: 300px") . + SL::Presenter::Tag::hidden_tag("previous_accno_id_$i", $accno_id) . qq||; my $tax_ddbox = qq|| . NTI($cgi->popup_menu('-name' => "taxchart_$i", - '-id' => "taxchart_$i", - '-style' => 'width:200px', - '-values' => \@taxchart_values, - '-labels' => \%taxchart_labels, - '-default' => $selected_taxchart)) + '-id' => "taxchart_$i", + '-style' => 'width:200px', + '-values' => \@taxchart_values, + '-labels' => \%taxchart_labels, + '-default' => $selected_taxchart)) . qq||; my ($fx_transaction, $checked); @@ -801,19 +915,21 @@ sub display_rows { } } - my $projectnumber = - NTI($cgi->popup_menu('-name' => "project_id_$i", - '-values' => \@project_values, - '-labels' => \%project_labels, - '-default' => $form->{"project_id_$i"} )); - my $projectnumber_hidden = qq| - |; + my $projectnumber = SL::Presenter::Project::picker("project_id_$i", $form->{"project_id_$i"}); + my $projectnumber_hidden = SL::Presenter::Tag::hidden_tag("project_id_$i", $form->{"project_id_$i"}); my $copy2credit = $i == 1 ? 'onkeyup="copy_debit_to_credit()"' : ''; + my $balance = $form->format_amount(\%::myconfig, $balances{$accno_id} // 0, 2, 'DRCR'); + + # if we have a bt_chart_id we disallow changing the amount of the bank account + if ($form->{bt_chart_id}) { + $debitreadonly = $creditreadonly = "readonly" if ($form->{"accno_id_$i"} eq $form->{bt_chart_id}); + $copy2credit = '' if $i == 1; # and disallow copy2credit + } print qq| $accno - + ${balance} $fx_transaction @@ -844,22 +960,171 @@ sub display_rows { } +sub _get_radieren { + return ($::instance_conf->get_gl_changeable == 2) ? ($::form->current_date(\%::myconfig) eq $::form->{gldate}) : ($::instance_conf->get_gl_changeable == 1); +} + +sub setup_gl_action_bar { + my %params = @_; + my $form = $::form; + my $change_never = $::instance_conf->get_gl_changeable == 0; + my $change_on_same_day_only = $::instance_conf->get_gl_changeable == 2 && ($form->current_date(\%::myconfig) ne $form->{gldate}); + my $is_linked_bank_transaction; + + if ($form->{id} && SL::DB::Manager::BankTransactionAccTrans->find_by(gl_id => $form->{id})) { + $is_linked_bank_transaction = 1; + } + + my $create_post_action = sub { + # $_[0]: description + # $_[1]: after_action + action => [ + $_[0], + submit => [ '#form', { action => 'post', after_action => $_[1] } ], + disabled => $form->{locked} ? t8('The billing period has already been locked.') + : $form->{storno} ? t8('A canceled general ledger transaction cannot be posted.') + : ($form->{id} && $change_never) ? t8('Changing general ledger transaction has been disabled in the configuration.') + : ($form->{id} && $change_on_same_day_only) ? t8('General ledger transactions can only be changed on the day they are posted.') + : $is_linked_bank_transaction ? t8('This transaction is linked with a bank transaction. Please undo and redo the bank transaction booking if needed.') + : undef, + ], + }; + + my %post_entry; + if ($::instance_conf->get_gl_add_doc && $::instance_conf->get_doc_storage) { + %post_entry = (combobox => [ $create_post_action->(t8('Post'), 'doc-tab'), + $create_post_action->(t8('Post and new booking')) ]); + } elsif ($::instance_conf->get_doc_storage) { + %post_entry = (combobox => [ $create_post_action->(t8('Post')), + $create_post_action->(t8('Post and upload document'), 'doc-tab') ]); + } else { + %post_entry = $create_post_action->(t8('Post')); + } + + for my $bar ($::request->layout->get('actionbar')) { + $bar->add( + action => [ + t8('Update'), + submit => [ '#form', { action => 'update' } ], + id => 'update_button', + accesskey => 'enter', + ], + %post_entry, + combobox => [ + action => [ t8('Storno'), + submit => [ '#form', { action => 'storno' } ], + confirm => t8('Do you really want to cancel this general ledger transaction?'), + disabled => !$form->{id} ? t8('This general ledger transaction has not been posted yet.') + : $form->{storno} ? t8('A canceled general ledger transaction cannot be canceled again.') + : $is_linked_bank_transaction ? t8('This transaction is linked with a bank transaction. Please undo and redo the bank transaction booking if needed.') + : undef, + ], + action => [ t8('Delete'), + submit => [ '#form', { action => 'delete' } ], + confirm => t8('Do you really want to delete this object?'), + disabled => !$form->{id} ? t8('This invoice has not been posted yet.') + : $form->{locked} ? t8('The billing period has already been locked.') + : $change_never ? t8('Changing invoices has been disabled in the configuration.') + : $change_on_same_day_only ? t8('Invoices can only be changed on the day they are posted.') + : $is_linked_bank_transaction ? t8('This transaction is linked with a bank transaction. Please undo and redo the bank transaction booking if needed.') + : $form->{storno} ? t8('A canceled general ledger transaction cannot be deleted.') + : undef, + ], + ], # end of combobox "Storno" + + combobox => [ + action => [ t8('more') ], + action => [ + t8('History'), + call => [ 'set_history_window', $form->{id} * 1, 'glid' ], + disabled => !$form->{id} ? t8('This invoice has not been posted yet.') : undef, + ], + action => [ + t8('Follow-Up'), + call => [ 'follow_up_window' ], + disabled => !$form->{id} ? t8('This invoice has not been posted yet.') : undef, + ], + action => [ + t8('Record templates'), + call => [ 'kivi.RecordTemplate.popup', 'gl_transaction' ], + ], + action => [ + t8('Drafts'), + call => [ 'kivi.Draft.popup', 'gl', 'unknown', $form->{draft_id}, $form->{draft_description} ], + disabled => $form->{id} ? t8('This invoice has already been posted.') + : $form->{locked} ? t8('The billing period has already been locked.') + : undef, + ], + ], # end of combobox "more" + ); + } +} + +sub setup_gl_search_action_bar { + my %params = @_; + + for my $bar ($::request->layout->get('actionbar')) { + $bar->add( + action => [ + t8('Search'), + submit => [ '#form', { action => 'continue', nextsub => 'generate_report' } ], + accesskey => 'enter', + ], + ); + } +} + +sub setup_gl_transactions_action_bar { + my %params = @_; + + for my $bar ($::request->layout->get('actionbar')) { + $bar->add( + combobox => [ + action => [ $::locale->text('Create new') ], + action => [ + $::locale->text('GL Transaction'), + submit => [ '#create_new_form', { action => 'gl_transaction' } ], + ], + action => [ + $::locale->text('AR Transaction'), + submit => [ '#create_new_form', { action => 'ar_transaction' } ], + ], + action => [ + $::locale->text('AP Transaction'), + submit => [ '#create_new_form', { action => 'ap_transaction' } ], + ], + action => [ + $::locale->text('Sales Invoice'), + submit => [ '#create_new_form', { action => 'sales_invoice' } ], + ], + action => [ + $::locale->text('Vendor Invoice'), + submit => [ '#create_new_form', { action => 'vendor_invoice' } ], + ], + ], # end of combobox "Create new" + ); + } +} + sub form_header { $::lxdebug->enter_sub; - $::auth->assert('general_ledger'); + $::auth->assert('gl_transactions'); my ($init) = @_; - my @old_project_ids = grep { $_ } map{ $::form->{"project_id_$_"} } 1..$::form->{rowcount}; + $::request->layout->add_javascripts("autocomplete_chart.js", "autocomplete_project.js", "kivi.File.js", "kivi.GL.js", "kivi.RecordTemplate.js", "kivi.Validator.js", "show_history.js"); - $::form->get_lists("projects" => { "key" => "ALL_PROJECTS", - "all" => 0, - "old_id" => \@old_project_ids }, - "charts" => { "key" => "ALL_CHARTS", - "transdate" => $::form->{transdate} }, - "taxcharts" => "ALL_TAXCHARTS"); + my @old_project_ids = grep { $_ } map{ $::form->{"project_id_$_"} } 1..$::form->{rowcount}; + my @conditions = @old_project_ids ? (id => \@old_project_ids) : (); + $::form->{ALL_PROJECTS} = SL::DB::Manager::Project->get_all_sorted(query => [ or => [ active => 1, @conditions ]]); + + $::form->get_lists( + "charts" => { "key" => "ALL_CHARTS", "transdate" => $::form->{transdate} }, + ); - GL->get_chart_balances('charts' => $::form->{ALL_CHARTS}); + # we cannot book on charttype header + @{ $::form->{ALL_CHARTS} } = grep { $_->{charttype} ne 'H' } @{ $::form->{ALL_CHARTS} }; + $::form->{ALL_DEPARTMENTS} = SL::DB::Manager::Department->get_all_sorted; my $title = $::form->{title}; $::form->{title} = $::locale->text("$title General Ledger Transaction"); @@ -869,23 +1134,22 @@ sub form_header { map { $::form->{$_} =~ s/\"/"/g } qw(chart taxchart); - $::form->{selectdepartment} =~ s/ selected//; - $::form->{selectdepartment} =~ - s/option>\Q$::form->{department}\E/option selected>$::form->{department}/; - if ($init) { $::request->{layout}->focus("#reference"); $::form->{taxincluded} = "1"; } else { - $::request->{layout}->focus("#accno_$::form->{rowcount}"); + $::request->{layout}->focus("#accno_id_$::form->{rowcount}_name"); } $::form->{previous_id} ||= "--"; $::form->{previous_gldate} ||= "--"; + setup_gl_action_bar(); + $::form->header; print $::form->parse_html_template('gl/form_header', { hide_title => $title, + readonly => $::form->{id} && ($::form->{locked} || !_get_radieren()), }); $::lxdebug->leave_sub; @@ -894,21 +1158,17 @@ sub form_header { sub form_footer { $::lxdebug->enter_sub; - $::auth->assert('general_ledger'); + $::auth->assert('gl_transactions'); my ($follow_ups, $follow_ups_due); if ($::form->{id}) { - $follow_ups = FU->follow_ups('trans_id' => $::form->{id}); + $follow_ups = FU->follow_ups('trans_id' => $::form->{id}, 'not_done' => 1); $follow_ups_due = sum map { $_->{due} * 1 } @{ $follow_ups || [] }; } - my $radieren = ($::instance_conf->get_gl_changeable == 2) - ? ($::form->current_date(\%::myconfig) eq $::form->{gldate}) - : ($::instance_conf->get_gl_changeable == 1); - print $::form->parse_html_template('gl/form_footer', { - radieren => $radieren, + radieren => _get_radieren(), follow_ups => $follow_ups, follow_ups_due => $follow_ups_due, }); @@ -919,42 +1179,6 @@ sub form_footer { sub delete { $main::lxdebug->enter_sub(); - my $form = $main::form; - my $locale = $main::locale; - - $form->header; - - print qq| - -|; - - map { $form->{$_} =~ s/\"/"/g } qw(reference description); - - delete $form->{header}; - - foreach my $key (keys %$form) { - next if (($key eq 'login') || ($key eq 'password') || ('' ne ref $form->{$key})); - print qq|\n|; - } - - print qq| -| . $locale->text('Confirm!') . qq| - -| - . $locale->text('Are you sure you want to delete Transaction') - . qq| $form->{reference} - - - -|; - $main::lxdebug->leave_sub(); - -} - -sub yes { - $main::lxdebug->enter_sub(); - my $form = $main::form; my %myconfig = %main::myconfig; my $locale = $main::locale; @@ -962,8 +1186,9 @@ sub yes { if (GL->delete_transaction(\%myconfig, \%$form)){ # saving the history if(!exists $form->{addition} && $form->{id} ne "") { - $form->{snumbers} = qq|ordnumber_| . $form->{ordnumber}; + $form->{snumbers} = qq|gltransaction_| . $form->{id}; $form->{addition} = "DELETED"; + $form->{what_done} = "gl_transaction"; $form->save_history; } # /saving the history @@ -998,7 +1223,11 @@ sub post_transaction { my $debitcredit; my %split_safety = (); - my @flds = qw(accno debit credit projectnumber fx_transaction source memo tax taxchart); + my $dbh = SL::DB->client->dbh; + my ($notax_id) = selectrow_query($form, $dbh, "SELECT id FROM tax WHERE taxkey = 0 LIMIT 1", ); + my $zerotaxes = selectall_hashref_query($form, $dbh, "SELECT id FROM tax WHERE rate = 0", ); + + my @flds = qw(accno_id debit credit projectnumber fx_transaction source memo tax taxchart); for my $i (1 .. $form->{rowcount}) { next if $form->{"debit_$i"} eq "" && $form->{"credit_$i"} eq ""; @@ -1038,36 +1267,36 @@ sub post_transaction { $form->{debitlock} = 1; } if ($debitcredit && $credittax) { - $form->{"taxchart_$i"} = "0--0.00"; + $form->{"taxchart_$i"} = "$notax_id--0.00000"; } if (!$debitcredit && $debittax) { - $form->{"taxchart_$i"} = "0--0.00"; + $form->{"taxchart_$i"} = "$notax_id--0.00000"; } my $amount = ($form->{"debit_$i"} == 0) ? $form->{"credit_$i"} : $form->{"debit_$i"}; my $j = $#a; if (($debitcredit && $credittax) || (!$debitcredit && $debittax)) { - $form->{"taxchart_$i"} = "0--0.00"; + $form->{"taxchart_$i"} = "$notax_id--0.00000"; $form->{"tax_$i"} = 0; } my ($taxkey, $rate) = split(/--/, $form->{"taxchart_$i"}); - if ($taxkey > 1) { + my $iswithouttax = grep { $_->{id} == $taxkey } @{ $zerotaxes }; + if (!$iswithouttax) { if ($debitcredit) { $debittax = 1; } else { $credittax = 1; } - if ($form->{taxincluded}) { - $form->{"tax_$i"} = $amount / ($rate + 1) * $rate; - if ($debitcredit) { - $form->{"debit_$i"} = $form->{"debit_$i"} - $form->{"tax_$i"}; - } else { - $form->{"credit_$i"} = $form->{"credit_$i"} - $form->{"tax_$i"}; - } + + my ($tmpnetamount,$tmpdiff); + ($tmpnetamount,$form->{"tax_$i"},$tmpdiff) = $form->calculate_tax($amount,$rate,$form->{taxincluded} *= 1,2); + if ($debitcredit) { + $form->{"debit_$i"} = $tmpnetamount; } else { - $form->{"tax_$i"} = $amount * $rate; + $form->{"credit_$i"} = $tmpnetamount; } + } else { $form->{"tax_$i"} = 0; } @@ -1077,7 +1306,8 @@ sub post_transaction { } if ($split_safety{-1} > 1 && $split_safety{1} > 1) { - $::form->error($::locale->text("Split entry detected. The values you have entered will result in an entry with more than one position on both debit and credit. Due to known problems involving accounting software Lx-Office does not allow these.")); + $::form->error($::locale->text("Split entry detected. The values you have entered will result in an entry with more than one position on both debit and credit. " . + "Due to known problems involving accounting software kivitendo does not allow these.")); } for my $i (1 .. $count) { @@ -1105,6 +1335,9 @@ sub post_transaction { $form->{taxincluded} = 0 if !$taxtotal; # this is just for the wise guys + + $form->error($locale->text('Cannot post transaction above the maximum future booking date!')) + if ($form->date_max_future($form->{"transdate"}, \%myconfig)); $form->error($locale->text('Cannot post transaction for a closed period!')) if ($form->date_closed($form->{"transdate"}, \%myconfig)); if ($form->round_amount($debit, 2) != $form->round_amount($credit, 2)) { @@ -1115,24 +1348,72 @@ sub post_transaction { $form->error($locale->text('Empty transaction!')); } - if ((my $errno = GL->post_transaction(\%myconfig, \%$form)) <= -1) { - $errno *= -1; - my @err; - $err[1] = $locale->text('Cannot have a value in both Debit and Credit!'); - $err[2] = $locale->text('Debit and credit out of balance!'); - $err[3] = $locale->text('Cannot post a transaction without a value!'); - $form->error($err[$errno]); - } - undef($form->{callback}); - # saving the history - if(!exists $form->{addition} && $form->{id} ne "") { - $form->{snumbers} = qq|ordnumber_| . $form->{ordnumber}; - $form->{addition} = "SAVED"; - $form->{what_done} = $locale->text("Buchungsnummer") . " = " . $form->{id}; - $form->save_history; - } - # /saving the history + # start transaction (post + history + (optional) banktrans) + SL::DB->client->with_transaction(sub { + + if ((my $errno = GL->post_transaction(\%myconfig, \%$form)) <= -1) { + $errno *= -1; + my @err; + $err[1] = $locale->text('Cannot have a value in both Debit and Credit!'); + $err[2] = $locale->text('Debit and credit out of balance!'); + $err[3] = $locale->text('Cannot post a transaction without a value!'); + + die $err[$errno]; + } + # saving the history + if(!exists $form->{addition} && $form->{id} ne "") { + $form->{snumbers} = qq|gltransaction_| . $form->{id}; + $form->{addition} = "POSTED"; + $form->{what_done} = "gl transaction"; + $form->save_history; + } + + # Case BankTransaction: update RecordLink and BankTransaction + if ($form->{callback} =~ /BankTransaction/ && $form->{bt_id}) { + # set invoice_amount - we only rely on bt_id in form, do all other stuff ui independent + # die if we have a unlogic or NYI case and abort the whole transaction + my ($bt, $chart_id, $payment); + require SL::DB::Manager::BankTransaction; + + $bt = SL::DB::Manager::BankTransaction->find_by(id => $::form->{bt_id}); + die "No bank transaction found" unless $bt; + + $chart_id = SL::DB::Manager::BankAccount->find_by(id => $bt->local_bank_account_id)->chart_id; + die "no chart id" unless $chart_id; + + $payment = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $::form->{id}, + chart_link => { like => '%_paid%' }, + chart_id => $chart_id ]); + die "guru meditation error: Can only assign amount to one bank account booking" if scalar @{ $payment } > 1; + + # credit/debit * -1 matches the sign for bt.amount and bt.invoice_amount + + die "Can only assign the full (partial) bank amount to a single general ledger booking: " . $bt->not_assigned_amount . " " . ($payment->[0]->amount * -1) + unless (abs($bt->not_assigned_amount - ($payment->[0]->amount * -1)) < 0.001); + + $bt->update_attributes(invoice_amount => $bt->invoice_amount + ($payment->[0]->amount * -1)); + + # create record_link + my %props = ( + from_table => 'bank_transactions', + from_id => $::form->{bt_id}, + to_table => 'gl', + to_id => $::form->{id}, + ); + SL::DB::RecordLink->new(%props)->save; + # and tighten holy acc_trans_id for this bank_transaction + my %props_acc = ( + acc_trans_id => $payment->[0]->acc_trans_id, + bank_transaction_id => $bt->id, + gl_id => $payment->[0]->trans_id, + ); + my $bta = SL::DB::BankTransactionAccTrans->new(%props_acc); + $bta->save; + + } + 1; + }) or do { die SL::DB->client->error }; $main::lxdebug->leave_sub(); } @@ -1140,26 +1421,43 @@ sub post_transaction { sub post { $main::lxdebug->enter_sub(); - $main::auth->assert('general_ledger'); + $main::auth->assert('gl_transactions'); my $form = $main::form; my $locale = $main::locale; - if ($::myconfig{mandatory_departments} && !$form->{department}) { - $form->{saved_message} = $::locale->text('You have to specify a department.'); - update(); - exit; + if ($::myconfig{mandatory_departments} && !$form->{department_id}) { + $form->error($locale->text('You have to specify a department.')); } $form->{title} = $locale->text("$form->{title} General Ledger Transaction"); $form->{storno} = 0; post_transaction(); + if ($::instance_conf->get_webdav) { + SL::Webdav->new(type => 'general_ledger', + number => $form->{id}, + )->webdav_path; + } - remove_draft() if $form->{remove_draft}; + my $msg = $::locale->text("General ledger transaction '#1' posted (ID: #2)", $form->{reference}, $form->{id}); + if ($form->{callback} =~ /BankTransaction/ && $form->{bt_id}) { + $form->redirect($msg); - $form->{callback} = build_std_url("action=add&DONT_LOAD_DRAFT=1", "show_details"); - $form->redirect($form->{callback}); + } elsif ('doc-tab' eq $form->{after_action}) { + # Redirect with callback containing a fragment does not work (by now) + # because the callback info is stored in the session an parsing the + # callback parameters does not support fragments (see SL::Form::redirect). + # So use flash_later for the message and redirect_headers for redirecting. + my $add_doc_url = build_std_url("script=gl.pl", 'action=edit', 'id=' . E($form->{id}), 'fragment=ui-tabs-docs'); + SL::Helper::Flash::flash_later('info', $msg); + print $form->redirect_header($add_doc_url); + $::dispatcher->end_request; + + } else { + $form->{callback} = build_std_url("action=add", "show_details"); + $form->redirect($msg); + } $main::lxdebug->leave_sub(); } @@ -1167,7 +1465,7 @@ sub post { sub post_as_new { $main::lxdebug->enter_sub(); - $main::auth->assert('general_ledger'); + $main::auth->assert('gl_transactions'); my $form = $main::form; @@ -1180,7 +1478,7 @@ sub post_as_new { sub storno { $main::lxdebug->enter_sub(); - $main::auth->assert('general_ledger'); + $main::auth->assert('gl_transactions'); my $form = $main::form; my %myconfig = %main::myconfig; @@ -1196,8 +1494,9 @@ sub storno { # saving the history if(!exists $form->{addition} && $form->{id} ne "") { - $form->{snumbers} = "ordnumber_$form->{ordnumber}"; + $form->{snumbers} = qq|gltransaction_| . $form->{id}; $form->{addition} = "STORNO"; + $form->{what_done} = "gl_transaction"; $form->save_history; } # /saving the history @@ -1211,4 +1510,20 @@ sub continue { call_sub($main::form->{nextsub}); } +sub get_tax_dropdown { + my $transdate = $::form->{transdate} ? DateTime->from_kivitendo($::form->{transdate}) : DateTime->today_local; + my $deliverydate = $::form->{deliverydate} ? DateTime->from_kivitendo($::form->{deliverydate}) : undef; + my @tax_accounts = GL->get_active_taxes_for_chart($::form->{accno_id}, $deliverydate // $transdate); + my $html = $::form->parse_html_template("gl/update_tax_accounts", { TAX_ACCOUNTS => \@tax_accounts }); + + print $::form->ajax_response_header, $html; +} + +sub get_chart_balance { + my %balances = GL->get_chart_balances($::form->{accno_id}); + my $balance = $::form->format_amount(\%::myconfig, $balances{ $::form->{accno_id} }, 2, 'DRCR'); + + print $::form->ajax_response_header, $balance; +} + 1;