Revision 6e083cb8
Von Bernd Bleßmann vor mehr als 5 Jahren hinzugefügt
SL/AP.pm | ||
---|---|---|
41 | 41 |
use SL::MoreCommon; |
42 | 42 |
use SL::DB::Default; |
43 | 43 |
use SL::DB::Draft; |
44 |
use SL::DB::Order; |
|
45 |
use SL::DB::PurchaseInvoice; |
|
44 | 46 |
use SL::Util qw(trim); |
45 | 47 |
use SL::DB; |
46 | 48 |
use Data::Dumper; |
47 |
|
|
49 |
use List::Util qw(sum0); |
|
48 | 50 |
use strict; |
49 | 51 |
|
50 | 52 |
sub post_transaction { |
... | ... | |
155 | 157 |
|
156 | 158 |
$form->new_lastmtime('ap'); |
157 | 159 |
|
160 |
# Link this record to the record it was created from. |
|
161 |
my $convert_from_oe_id = delete $form->{convert_from_oe_id}; |
|
162 |
if (!$form->{postasnew} && $convert_from_oe_id) { |
|
163 |
RecordLinks->create_links('dbh' => $dbh, |
|
164 |
'mode' => 'ids', |
|
165 |
'from_table' => 'oe', |
|
166 |
'from_ids' => $convert_from_oe_id, |
|
167 |
'to_table' => 'ap', |
|
168 |
'to_id' => $form->{id}, |
|
169 |
); |
|
170 |
|
|
171 |
# Close the record it was created from if the amount of |
|
172 |
# all APs create from this record equals the records amount. |
|
173 |
my @links = RecordLinks->get_links('dbh' => $dbh, |
|
174 |
'from_table' => 'oe', |
|
175 |
'from_id' => $convert_from_oe_id, |
|
176 |
'to_table' => 'ap', |
|
177 |
); |
|
178 |
|
|
179 |
my $amount_sum = sum0 map { SL::DB::PurchaseInvoice->new(id => $_->{to_id})->load->amount } @links; |
|
180 |
my $order = SL::DB::Order->new(id => $convert_from_oe_id)->load; |
|
181 |
|
|
182 |
$order->update_attributes(closed => 1) if ($amount_sum - $order->amount) == 0; |
|
183 |
} |
|
184 |
|
|
158 | 185 |
# add individual transactions |
159 | 186 |
for my $i (1 .. $form->{rowcount}) { |
160 | 187 |
if ($form->{"amount_$i"} != 0) { |
SL/Controller/Order.pm | ||
---|---|---|
48 | 48 |
__PACKAGE__->run_before('check_auth'); |
49 | 49 |
|
50 | 50 |
__PACKAGE__->run_before('recalc', |
51 |
only => [ qw(save save_as_new save_and_delivery_order save_and_invoice print send_email) ]); |
|
51 |
only => [ qw(save save_as_new save_and_delivery_order save_and_invoice save_and_ap_transaction |
|
52 |
print send_email) ]); |
|
52 | 53 |
|
53 | 54 |
__PACKAGE__->run_before('get_unalterable_data', |
54 |
only => [ qw(save save_as_new save_and_delivery_order save_and_invoice print send_email) ]); |
|
55 |
only => [ qw(save save_as_new save_and_delivery_order save_and_invoice save_and_ap_transaction |
|
56 |
print send_email) ]); |
|
55 | 57 |
|
56 | 58 |
# |
57 | 59 |
# actions |
... | ... | |
648 | 650 |
$_[0]->workflow_sales_or_purchase_order(); |
649 | 651 |
} |
650 | 652 |
|
653 |
# workflow from purchase order to ap transaction |
|
654 |
sub action_save_and_ap_transaction { |
|
655 |
my ($self) = @_; |
|
656 |
|
|
657 |
my $errors = $self->save(); |
|
658 |
|
|
659 |
if (scalar @{ $errors }) { |
|
660 |
$self->js->flash('error', $_) foreach @{ $errors }; |
|
661 |
return $self->js->render(); |
|
662 |
} |
|
663 |
|
|
664 |
my $text = $self->type eq sales_order_type() ? $::locale->text('The order has been saved') |
|
665 |
: $self->type eq purchase_order_type() ? $::locale->text('The order has been saved') |
|
666 |
: $self->type eq sales_quotation_type() ? $::locale->text('The quotation has been saved') |
|
667 |
: $self->type eq request_quotation_type() ? $::locale->text('The rfq has been saved') |
|
668 |
: ''; |
|
669 |
flash_later('info', $text); |
|
670 |
|
|
671 |
my @redirect_params = ( |
|
672 |
controller => 'ap.pl', |
|
673 |
action => 'add_from_purchase_order', |
|
674 |
id => $self->order->id, |
|
675 |
); |
|
676 |
|
|
677 |
$self->redirect_to(@redirect_params); |
|
678 |
} |
|
679 |
|
|
651 | 680 |
# set form elements in respect to a changed customer or vendor |
652 | 681 |
# |
653 | 682 |
# This action is called on an change of the customer/vendor picker. |
... | ... | |
1695 | 1724 |
call => [ 'kivi.Order.save', 'save_and_invoice', $::instance_conf->get_order_warn_duplicate_parts ], |
1696 | 1725 |
checks => [ 'kivi.Order.check_save_active_periodic_invoices' ], |
1697 | 1726 |
], |
1727 |
action => [ |
|
1728 |
t8('Save and AP Transaction'), |
|
1729 |
call => [ 'kivi.Order.save', 'save_and_ap_transaction', $::instance_conf->get_order_warn_duplicate_parts ], |
|
1730 |
only_if => (any { $self->type eq $_ } (purchase_order_type())) |
|
1731 |
], |
|
1732 |
|
|
1698 | 1733 |
], # end of combobox "Workflow" |
1699 | 1734 |
|
1700 | 1735 |
combobox => [ |
SL/DB/MetaSetup/Default.pm | ||
---|---|---|
167 | 167 |
webdav => { type => 'boolean', default => 'false' }, |
168 | 168 |
webdav_documents => { type => 'boolean', default => 'false' }, |
169 | 169 |
weightunit => { type => 'varchar', length => 5 }, |
170 |
workflow_po_ap_chart_id => { type => 'integer' }, |
|
170 | 171 |
); |
171 | 172 |
|
172 | 173 |
__PACKAGE__->meta->primary_key_columns([ 'id' ]); |
bin/mozilla/ap.pl | ||
---|---|---|
47 | 47 |
use SL::DB::Chart; |
48 | 48 |
use SL::DB::Currency; |
49 | 49 |
use SL::DB::Default; |
50 |
use SL::DB::Order; |
|
50 | 51 |
use SL::DB::PurchaseInvoice; |
51 | 52 |
use SL::DB::RecordTemplate; |
52 | 53 |
use SL::DB::Tax; |
... | ... | |
649 | 650 |
# calculate tax exactly the same way as AP in post_transaction via form->calculate_tax |
650 | 651 |
my $tmpnetamount; |
651 | 652 |
($tmpnetamount,$form->{"tax_$i"}) = $form->calculate_tax($form->{"amount_$i"},$rate,$form->{taxincluded},2); |
652 |
|
|
653 | 653 |
$totaltax += $form->{"tax_$i"}; |
654 | 654 |
map { $a[$j]->{$_} = $form->{"${_}_$i"} } @flds; |
655 | 655 |
$count++; |
... | ... | |
899 | 899 |
|
900 | 900 |
$main::auth->assert('ap_transactions'); |
901 | 901 |
|
902 |
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); |
|
902 |
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);
|
|
903 | 903 |
$form->{paidaccounts} = 1; |
904 | 904 |
$form->{rowcount}--; |
905 | 905 |
|
... | ... | |
1183 | 1183 |
$main::lxdebug->leave_sub(); |
1184 | 1184 |
} |
1185 | 1185 |
|
1186 |
sub add_from_purchase_order { |
|
1187 |
$main::auth->assert('ap_transactions'); |
|
1188 |
|
|
1189 |
return if !$::form->{id}; |
|
1190 |
|
|
1191 |
my $order_id = delete $::form->{id}; |
|
1192 |
my $order = SL::DB::Order->new(id => $order_id)->load; |
|
1193 |
|
|
1194 |
return if $order->type ne 'purchase_order'; |
|
1195 |
|
|
1196 |
my $today = DateTime->today_local; |
|
1197 |
$::form->{title} = "Add"; |
|
1198 |
$::form->{vc} = 'vendor'; |
|
1199 |
$::form->{vendor_id} = $order->customervendor->id; |
|
1200 |
$::form->{vendor} = $order->vendor->name; |
|
1201 |
$::form->{convert_from_oe_id} = $order->id; |
|
1202 |
$::form->{globalproject_id} = $order->globalproject_id; |
|
1203 |
$::form->{ordnumber} = $order->number; |
|
1204 |
$::form->{department_id} = $order->department_id; |
|
1205 |
$::form->{currency} = $order->currency->name; |
|
1206 |
$::form->{taxincluded} = 1; # we use amount below, so tax is included |
|
1207 |
$::form->{transdate} = $today->to_kivitendo; |
|
1208 |
$::form->{duedate} = $today->to_kivitendo; |
|
1209 |
$::form->{duedate} = $order->vendor->payment->calc_date(reference_date => $today)->to_kivitendo if $order->vendor->payment; |
|
1210 |
|
|
1211 |
create_links(); |
|
1212 |
|
|
1213 |
my $config_po_ap_workflow_chart_id = $::instance_conf->get_workflow_po_ap_chart_id; |
|
1214 |
|
|
1215 |
my ($first_taxchart, $default_taxchart, $taxchart_to_use); |
|
1216 |
my @taxcharts = (); |
|
1217 |
@taxcharts = GL->get_active_taxes_for_chart($config_po_ap_workflow_chart_id, $::form->{transdate}) if (defined $config_po_ap_workflow_chart_id); |
|
1218 |
foreach my $item (@taxcharts) { |
|
1219 |
$first_taxchart //= $item; |
|
1220 |
$default_taxchart = $item if $item->{is_default}; |
|
1221 |
} |
|
1222 |
$taxchart_to_use = $default_taxchart // $first_taxchart; |
|
1223 |
|
|
1224 |
my %pat = $order->calculate_prices_and_taxes; |
|
1225 |
my $row = 1; |
|
1226 |
foreach my $amount_chart (keys %{$pat{amounts}}) { |
|
1227 |
my $tax = SL::DB::Manager::Tax->find_by(id => $pat{amounts}->{$amount_chart}->{tax_id}); |
|
1228 |
# If tax chart from order for this amount is active, use it. Use default or first tax chart for selected chart else. |
|
1229 |
if (defined $config_po_ap_workflow_chart_id) { |
|
1230 |
$taxchart_to_use = (first {$_->{id} == $tax->id} @taxcharts) // $taxchart_to_use; |
|
1231 |
} else { |
|
1232 |
$taxchart_to_use = $tax; |
|
1233 |
} |
|
1234 |
|
|
1235 |
$::form->{"AP_amount_chart_id_$row"} = $config_po_ap_workflow_chart_id // $amount_chart; |
|
1236 |
$::form->{"previous_AP_amount_chart_id_$row"} = $::form->{"AP_amount_chart_id_$row"}; |
|
1237 |
$::form->{"amount_$row"} = $::form->format_amount(\%::myconfig, $pat{amounts}->{$amount_chart}->{amount} * (1 + $tax->rate), 2); |
|
1238 |
$::form->{"taxchart_$row"} = $taxchart_to_use->id . '--' . $taxchart_to_use->rate; |
|
1239 |
$::form->{"project_id_$row"} = $order->globalproject_id; |
|
1240 |
|
|
1241 |
$row++; |
|
1242 |
} |
|
1243 |
|
|
1244 |
my $last_used_ap_chart = SL::DB::Vendor->load_cached($::form->{vendor_id})->last_used_ap_chart; |
|
1245 |
$::form->{"AP_amount_chart_id_$row"} = $last_used_ap_chart->id if $last_used_ap_chart; |
|
1246 |
$::form->{rowcount} = $row; |
|
1247 |
|
|
1248 |
update( |
|
1249 |
keep_rows_without_amount => 1, |
|
1250 |
dont_add_new_row => 1, |
|
1251 |
); |
|
1252 |
} |
|
1253 |
|
|
1186 | 1254 |
sub setup_ap_search_action_bar { |
1187 | 1255 |
my %params = @_; |
1188 | 1256 |
|
doc/changelog | ||
---|---|---|
14 | 14 |
|
15 | 15 |
- Part Controller - neuer Tab mit Lagerinformationen - was ist wo gelagert |
16 | 16 |
|
17 |
- Neuer Workflow Lieferantenauftrag->Kreditorenbuchung: Für jedes Aufwandskonto |
|
18 |
der Positionen im Lieferantenauftrag wird eine Zeile in der Kreditorenbuchung |
|
19 |
erstellt. Gebucht wird standardmäßig auf des entsprechende Aufwandskonto. In |
|
20 |
der Mandantenkonfiguration kann unter Standardkonten ein Konto ausgewählt |
|
21 |
werden, auf das dann alle Zeilen gebucht werden. |
|
22 |
Die Steuern werden übernommen, sofern diese für das ausgewählte Aufwandskonto |
|
23 |
gültig sind. Ansonsten wird die Default-Steuer für das Aufwandskonto gesetzt. |
|
24 |
Der Quellauftrag wird geschlossen, wenn der Betrag aller Kreditorenbuchungen, |
|
25 |
die aus Workflows aus dem Quellauftrag entstanden sind, gleich dem Betrag |
|
26 |
des Quellauftrags ist. |
|
27 |
|
|
17 | 28 |
Kleinere neue Features und Detailverbesserungen: |
18 | 29 |
|
19 | 30 |
- Mahnungen nach Abteilung filtern |
locale/de/all | ||
---|---|---|
137 | 137 |
'Account deleted!' => 'Konto gelöscht!', |
138 | 138 |
'Account for fees' => 'Konto für Gebühren', |
139 | 139 |
'Account for interest' => 'Konto für Zinsen', |
140 |
'Account for workflow from purchase order to ap transaction' => 'Konto für den Workflow von Lieferantenauftrag nach Kreditorenbuchung', |
|
140 | 141 |
'Account number' => 'Kontonummer', |
141 | 142 |
'Account number not unique!' => 'Kontonummer bereits vorhanden!', |
142 | 143 |
'Account number of the goal/source' => 'Ziel- oder Quellkonto', |
locale/en/all | ||
---|---|---|
137 | 137 |
'Account deleted!' => '', |
138 | 138 |
'Account for fees' => '', |
139 | 139 |
'Account for interest' => '', |
140 |
'Account for workflow from purchase order to ap transaction' => '', |
|
140 | 141 |
'Account number' => '', |
141 | 142 |
'Account number not unique!' => '', |
142 | 143 |
'Account number of the goal/source' => '', |
sql/Pg-upgrade2/defaults_workflow_po_ap_chart_id.sql | ||
---|---|---|
1 |
-- @tag: defaults_workflow_po_ap_chart_id |
|
2 |
-- @description: Voreingestelltes Konto für Workflow Lieferantenauftrag -> Kreditorenbuchung |
|
3 |
-- @depends: release_3_5_4 |
|
4 |
|
|
5 |
ALTER TABLE defaults ADD COLUMN workflow_po_ap_chart_id INTEGER; |
templates/webpages/ap/form_header.html | ||
---|---|---|
42 | 42 |
|
43 | 43 |
<input type="hidden" name="paidaccounts" value="[% paidaccounts | html %]"> |
44 | 44 |
|
45 |
[%- P.hidden_tag('convert_from_oe_id', convert_from_oe_id) -%] |
|
46 |
|
|
45 | 47 |
[% FOREACH i IN [1..paidaccounts] %] |
46 | 48 |
[% temp = "acc_trans_id_"_ i %] |
47 | 49 |
<input type="hidden" name="[% temp %]" value="[% $temp | html %]"> |
templates/webpages/client_config/_default_accounts.html | ||
---|---|---|
55 | 55 |
<td>[% P.chart.picker('defaults.ar_chart_id', SELF.defaults.ar_chart_id, type='AR', choose=1, style=style) %]<td> |
56 | 56 |
</tr> |
57 | 57 |
|
58 |
</table> |
|
58 |
<tr> |
|
59 |
<td align="right">[% LxERP.t8("Account for workflow from purchase order to ap transaction") %]</td> |
|
60 |
<td>[% P.chart.picker('defaults.workflow_po_ap_chart_id', SELF.defaults.workflow_po_ap_chart_id, type='AP_amount', choose=1, style=style) %]<td> |
|
61 |
</tr> |
|
62 |
|
|
63 |
</table> |
|
59 | 64 |
</div> |
Auch abrufbar als: Unified diff
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.