From 6e083cb8df993623e4810599ba9d50b035ccb250 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bernd=20Ble=C3=9Fmann?= Date: Fri, 2 Aug 2019 18:00:21 +0200 Subject: [PATCH] Neuer Workflow Lieferantenauftrag->Kreditorenbuchung MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Für jedes Aufwandskonto der Positionen im Lieferantenauftrag wird eine Zeile in der Kreditorenbuchung erstellt. Gebucht wird standardmäßig auf des entsprechende Aufwandskonto. In der Mandantenkonfiguration kann unter Standardkonten ein Konto ausgewählt werden, auf das dann alle Zeilen gebucht werden. Die Steuern werden übernommen, sofern diese für das ausgewählte Aufwandskonto gültig sind. Ansonsten wird die Default-Steuer für das Aufwandskonto gesetzt. Der Quellauftrag wird geschlossen, wenn der Betrag aller Kreditorenbuchungen, die aus Workflows aus dem Quellauftrag entstanden sind, gleich dem Betrag des Quellauftrags ist. --- SL/AP.pm | 29 +++++++- SL/Controller/Order.pm | 39 +++++++++- SL/DB/MetaSetup/Default.pm | 1 + bin/mozilla/ap.pl | 72 ++++++++++++++++++- doc/changelog | 11 +++ locale/de/all | 1 + locale/en/all | 1 + .../defaults_workflow_po_ap_chart_id.sql | 5 ++ templates/webpages/ap/form_header.html | 2 + .../client_config/_default_accounts.html | 7 +- 10 files changed, 162 insertions(+), 6 deletions(-) create mode 100644 sql/Pg-upgrade2/defaults_workflow_po_ap_chart_id.sql diff --git a/SL/AP.pm b/SL/AP.pm index caae2bb73..b1608020b 100644 --- a/SL/AP.pm +++ b/SL/AP.pm @@ -41,10 +41,12 @@ use SL::IO; use SL::MoreCommon; use SL::DB::Default; use SL::DB::Draft; +use SL::DB::Order; +use SL::DB::PurchaseInvoice; use SL::Util qw(trim); use SL::DB; use Data::Dumper; - +use List::Util qw(sum0); use strict; sub post_transaction { @@ -155,6 +157,31 @@ sub _post_transaction { $form->new_lastmtime('ap'); + # Link this record to the record it was created from. + my $convert_from_oe_id = delete $form->{convert_from_oe_id}; + if (!$form->{postasnew} && $convert_from_oe_id) { + RecordLinks->create_links('dbh' => $dbh, + 'mode' => 'ids', + 'from_table' => 'oe', + 'from_ids' => $convert_from_oe_id, + 'to_table' => 'ap', + 'to_id' => $form->{id}, + ); + + # Close the record it was created from if the amount of + # all APs create from this record equals the records amount. + my @links = RecordLinks->get_links('dbh' => $dbh, + 'from_table' => 'oe', + 'from_id' => $convert_from_oe_id, + 'to_table' => 'ap', + ); + + my $amount_sum = sum0 map { SL::DB::PurchaseInvoice->new(id => $_->{to_id})->load->amount } @links; + my $order = SL::DB::Order->new(id => $convert_from_oe_id)->load; + + $order->update_attributes(closed => 1) if ($amount_sum - $order->amount) == 0; + } + # add individual transactions for my $i (1 .. $form->{rowcount}) { if ($form->{"amount_$i"} != 0) { diff --git a/SL/Controller/Order.pm b/SL/Controller/Order.pm index 7a7841d3c..47ab4e7de 100644 --- a/SL/Controller/Order.pm +++ b/SL/Controller/Order.pm @@ -48,10 +48,12 @@ use Rose::Object::MakeMethods::Generic __PACKAGE__->run_before('check_auth'); __PACKAGE__->run_before('recalc', - only => [ qw(save save_as_new save_and_delivery_order save_and_invoice print send_email) ]); + only => [ qw(save save_as_new save_and_delivery_order save_and_invoice save_and_ap_transaction + print send_email) ]); __PACKAGE__->run_before('get_unalterable_data', - only => [ qw(save save_as_new save_and_delivery_order save_and_invoice print send_email) ]); + only => [ qw(save save_as_new save_and_delivery_order save_and_invoice save_and_ap_transaction + print send_email) ]); # # actions @@ -648,6 +650,33 @@ sub action_purchase_order { $_[0]->workflow_sales_or_purchase_order(); } +# workflow from purchase order to ap transaction +sub action_save_and_ap_transaction { + my ($self) = @_; + + my $errors = $self->save(); + + if (scalar @{ $errors }) { + $self->js->flash('error', $_) foreach @{ $errors }; + return $self->js->render(); + } + + my $text = $self->type eq sales_order_type() ? $::locale->text('The order has been saved') + : $self->type eq purchase_order_type() ? $::locale->text('The order has been saved') + : $self->type eq sales_quotation_type() ? $::locale->text('The quotation has been saved') + : $self->type eq request_quotation_type() ? $::locale->text('The rfq has been saved') + : ''; + flash_later('info', $text); + + my @redirect_params = ( + controller => 'ap.pl', + action => 'add_from_purchase_order', + id => $self->order->id, + ); + + $self->redirect_to(@redirect_params); +} + # set form elements in respect to a changed customer or vendor # # This action is called on an change of the customer/vendor picker. @@ -1695,6 +1724,12 @@ sub setup_edit_action_bar { call => [ 'kivi.Order.save', 'save_and_invoice', $::instance_conf->get_order_warn_duplicate_parts ], checks => [ 'kivi.Order.check_save_active_periodic_invoices' ], ], + action => [ + t8('Save and AP Transaction'), + call => [ 'kivi.Order.save', 'save_and_ap_transaction', $::instance_conf->get_order_warn_duplicate_parts ], + only_if => (any { $self->type eq $_ } (purchase_order_type())) + ], + ], # end of combobox "Workflow" combobox => [ diff --git a/SL/DB/MetaSetup/Default.pm b/SL/DB/MetaSetup/Default.pm index c0f6a4411..e588b3aeb 100644 --- a/SL/DB/MetaSetup/Default.pm +++ b/SL/DB/MetaSetup/Default.pm @@ -167,6 +167,7 @@ __PACKAGE__->meta->columns( webdav => { type => 'boolean', default => 'false' }, webdav_documents => { type => 'boolean', default => 'false' }, weightunit => { type => 'varchar', length => 5 }, + workflow_po_ap_chart_id => { type => 'integer' }, ); __PACKAGE__->meta->primary_key_columns([ 'id' ]); diff --git a/bin/mozilla/ap.pl b/bin/mozilla/ap.pl index 49f6f7a63..a5d20da87 100644 --- a/bin/mozilla/ap.pl +++ b/bin/mozilla/ap.pl @@ -47,6 +47,7 @@ use SL::DB::BankTransactionAccTrans; use SL::DB::Chart; use SL::DB::Currency; use SL::DB::Default; +use SL::DB::Order; use SL::DB::PurchaseInvoice; use SL::DB::RecordTemplate; use SL::DB::Tax; @@ -649,7 +650,6 @@ sub update { # calculate tax exactly the same way as AP in post_transaction via form->calculate_tax my $tmpnetamount; ($tmpnetamount,$form->{"tax_$i"}) = $form->calculate_tax($form->{"amount_$i"},$rate,$form->{taxincluded},2); - $totaltax += $form->{"tax_$i"}; map { $a[$j]->{$_} = $form->{"${_}_$i"} } @flds; $count++; @@ -899,7 +899,7 @@ sub use_as_new { $main::auth->assert('ap_transactions'); - map { delete $form->{$_} } qw(printed emailed queued invnumber deliverydate id datepaid_1 gldate_1 acc_trans_id_1 source_1 memo_1 paid_1 exchangerate_1 AP_paid_1 storno); + map { delete $form->{$_} } qw(printed emailed queued invnumber deliverydate id datepaid_1 gldate_1 acc_trans_id_1 source_1 memo_1 paid_1 exchangerate_1 AP_paid_1 storno convert_from_oe_id); $form->{paidaccounts} = 1; $form->{rowcount}--; @@ -1183,6 +1183,74 @@ sub storno { $main::lxdebug->leave_sub(); } +sub add_from_purchase_order { + $main::auth->assert('ap_transactions'); + + return if !$::form->{id}; + + my $order_id = delete $::form->{id}; + my $order = SL::DB::Order->new(id => $order_id)->load; + + return if $order->type ne 'purchase_order'; + + my $today = DateTime->today_local; + $::form->{title} = "Add"; + $::form->{vc} = 'vendor'; + $::form->{vendor_id} = $order->customervendor->id; + $::form->{vendor} = $order->vendor->name; + $::form->{convert_from_oe_id} = $order->id; + $::form->{globalproject_id} = $order->globalproject_id; + $::form->{ordnumber} = $order->number; + $::form->{department_id} = $order->department_id; + $::form->{currency} = $order->currency->name; + $::form->{taxincluded} = 1; # we use amount below, so tax is included + $::form->{transdate} = $today->to_kivitendo; + $::form->{duedate} = $today->to_kivitendo; + $::form->{duedate} = $order->vendor->payment->calc_date(reference_date => $today)->to_kivitendo if $order->vendor->payment; + + create_links(); + + my $config_po_ap_workflow_chart_id = $::instance_conf->get_workflow_po_ap_chart_id; + + my ($first_taxchart, $default_taxchart, $taxchart_to_use); + my @taxcharts = (); + @taxcharts = GL->get_active_taxes_for_chart($config_po_ap_workflow_chart_id, $::form->{transdate}) if (defined $config_po_ap_workflow_chart_id); + foreach my $item (@taxcharts) { + $first_taxchart //= $item; + $default_taxchart = $item if $item->{is_default}; + } + $taxchart_to_use = $default_taxchart // $first_taxchart; + + my %pat = $order->calculate_prices_and_taxes; + my $row = 1; + foreach my $amount_chart (keys %{$pat{amounts}}) { + my $tax = SL::DB::Manager::Tax->find_by(id => $pat{amounts}->{$amount_chart}->{tax_id}); + # If tax chart from order for this amount is active, use it. Use default or first tax chart for selected chart else. + if (defined $config_po_ap_workflow_chart_id) { + $taxchart_to_use = (first {$_->{id} == $tax->id} @taxcharts) // $taxchart_to_use; + } else { + $taxchart_to_use = $tax; + } + + $::form->{"AP_amount_chart_id_$row"} = $config_po_ap_workflow_chart_id // $amount_chart; + $::form->{"previous_AP_amount_chart_id_$row"} = $::form->{"AP_amount_chart_id_$row"}; + $::form->{"amount_$row"} = $::form->format_amount(\%::myconfig, $pat{amounts}->{$amount_chart}->{amount} * (1 + $tax->rate), 2); + $::form->{"taxchart_$row"} = $taxchart_to_use->id . '--' . $taxchart_to_use->rate; + $::form->{"project_id_$row"} = $order->globalproject_id; + + $row++; + } + + my $last_used_ap_chart = SL::DB::Vendor->load_cached($::form->{vendor_id})->last_used_ap_chart; + $::form->{"AP_amount_chart_id_$row"} = $last_used_ap_chart->id if $last_used_ap_chart; + $::form->{rowcount} = $row; + + update( + keep_rows_without_amount => 1, + dont_add_new_row => 1, + ); +} + sub setup_ap_search_action_bar { my %params = @_; diff --git a/doc/changelog b/doc/changelog index 507ef71d6..6013a4f0a 100644 --- a/doc/changelog +++ b/doc/changelog @@ -14,6 +14,17 @@ Mittelgroße neue Features: - Part Controller - neuer Tab mit Lagerinformationen - was ist wo gelagert +- Neuer Workflow Lieferantenauftrag->Kreditorenbuchung: Für jedes Aufwandskonto + der Positionen im Lieferantenauftrag wird eine Zeile in der Kreditorenbuchung + erstellt. Gebucht wird standardmäßig auf des entsprechende Aufwandskonto. In + der Mandantenkonfiguration kann unter Standardkonten ein Konto ausgewählt + werden, auf das dann alle Zeilen gebucht werden. + Die Steuern werden übernommen, sofern diese für das ausgewählte Aufwandskonto + gültig sind. Ansonsten wird die Default-Steuer für das Aufwandskonto gesetzt. + Der Quellauftrag wird geschlossen, wenn der Betrag aller Kreditorenbuchungen, + die aus Workflows aus dem Quellauftrag entstanden sind, gleich dem Betrag + des Quellauftrags ist. + Kleinere neue Features und Detailverbesserungen: - Mahnungen nach Abteilung filtern diff --git a/locale/de/all b/locale/de/all index 470757567..66255b544 100755 --- a/locale/de/all +++ b/locale/de/all @@ -137,6 +137,7 @@ $self->{texts} = { 'Account deleted!' => 'Konto gelöscht!', 'Account for fees' => 'Konto für Gebühren', 'Account for interest' => 'Konto für Zinsen', + 'Account for workflow from purchase order to ap transaction' => 'Konto für den Workflow von Lieferantenauftrag nach Kreditorenbuchung', 'Account number' => 'Kontonummer', 'Account number not unique!' => 'Kontonummer bereits vorhanden!', 'Account number of the goal/source' => 'Ziel- oder Quellkonto', diff --git a/locale/en/all b/locale/en/all index 1c0fc7712..a1d4ee490 100644 --- a/locale/en/all +++ b/locale/en/all @@ -137,6 +137,7 @@ $self->{texts} = { 'Account deleted!' => '', 'Account for fees' => '', 'Account for interest' => '', + 'Account for workflow from purchase order to ap transaction' => '', 'Account number' => '', 'Account number not unique!' => '', 'Account number of the goal/source' => '', diff --git a/sql/Pg-upgrade2/defaults_workflow_po_ap_chart_id.sql b/sql/Pg-upgrade2/defaults_workflow_po_ap_chart_id.sql new file mode 100644 index 000000000..93ae0d025 --- /dev/null +++ b/sql/Pg-upgrade2/defaults_workflow_po_ap_chart_id.sql @@ -0,0 +1,5 @@ +-- @tag: defaults_workflow_po_ap_chart_id +-- @description: Voreingestelltes Konto für Workflow Lieferantenauftrag -> Kreditorenbuchung +-- @depends: release_3_5_4 + +ALTER TABLE defaults ADD COLUMN workflow_po_ap_chart_id INTEGER; diff --git a/templates/webpages/ap/form_header.html b/templates/webpages/ap/form_header.html index fd8c91e54..bd52a5189 100644 --- a/templates/webpages/ap/form_header.html +++ b/templates/webpages/ap/form_header.html @@ -42,6 +42,8 @@ +[%- P.hidden_tag('convert_from_oe_id', convert_from_oe_id) -%] + [% FOREACH i IN [1..paidaccounts] %] [% temp = "acc_trans_id_"_ i %] diff --git a/templates/webpages/client_config/_default_accounts.html b/templates/webpages/client_config/_default_accounts.html index ee9669c77..16666782c 100644 --- a/templates/webpages/client_config/_default_accounts.html +++ b/templates/webpages/client_config/_default_accounts.html @@ -55,5 +55,10 @@ [% P.chart.picker('defaults.ar_chart_id', SELF.defaults.ar_chart_id, type='AR', choose=1, style=style) %] - + + [% LxERP.t8("Account for workflow from purchase order to ap transaction") %] + [% P.chart.picker('defaults.workflow_po_ap_chart_id', SELF.defaults.workflow_po_ap_chart_id, type='AP_amount', choose=1, style=style) %] + + + -- 2.20.1