Revision fd945718
Von Jan Büren vor fast 2 Jahren hinzugefügt
SL/DB/Helper/Payment.pm | ||
---|---|---|
90 | 90 |
croak t8('Cannot post transaction above the maximum future booking date!') if $transdate_obj > DateTime->now->add( days => $::instance_conf->get_max_future_booking_interval ); |
91 | 91 |
}; |
92 | 92 |
|
93 |
# currency is either passed or use the invoice currency if it differs from the default currency |
|
94 |
# TODO remove |
|
95 |
my ($exchangerate, $currency, $return_bank_amount); |
|
96 |
$return_bank_amount = 0; |
|
97 |
if ($params{currency} || $params{currency_id}) { |
|
98 |
if ($params{currency} || $params{currency_id} ) { # currency was specified |
|
99 |
$currency = SL::DB::Manager::Currency->find_by(name => $params{currency}) || SL::DB::Manager::Currency->find_by(id => $params{currency_id}); |
|
100 |
} else { # use invoice currency |
|
101 |
$currency = SL::DB::Manager::Currency->find_by(id => $self->currency_id); |
|
102 |
}; |
|
103 |
die "no currency" unless $currency; |
|
104 |
if ($currency->id == $::instance_conf->get_currency_id) { |
|
105 |
$exchangerate = 1; |
|
106 |
} else { |
|
107 |
my $rate = SL::DB::Manager::Exchangerate->find_by(currency_id => $currency->id, |
|
108 |
transdate => $transdate_obj, |
|
109 |
); |
|
110 |
if ($rate) { |
|
111 |
$exchangerate = $is_sales ? $rate->buy : $rate->sell; |
|
112 |
} else { |
|
113 |
die "No exchange rate for " . $transdate_obj->to_kivitendo; |
|
114 |
}; |
|
115 |
}; |
|
116 |
} else { # no currency param given or currency is the same as default_currency |
|
93 |
# currency has to be passed and caller has to be sure to assign it for a forex invoice |
|
94 |
# dies if called for a invoice with the default currency (TODO: Params::Validate before) |
|
95 |
my ($exchangerate, $currency, $fx_gain_loss_amount, $return_bank_amount); |
|
96 |
if ($params{currency} || $params{currency_id} && $self->forex) { # currency was specified |
|
97 |
$currency = SL::DB::Manager::Currency->find_by(name => $params{currency}) || SL::DB::Manager::Currency->find_by(id => $params{currency_id}); |
|
98 |
# set exchangerate - no fallback |
|
99 |
# die "No exchange rate" unless $params{exchangerate} > 0; |
|
100 |
$exchangerate = $params{exchangerate}; |
|
101 |
# hook for gl_bookings $book_fx_bank_fees; |
|
102 |
# and calculus fidibus total fx |
|
103 |
# self->amount - paid / self->exchangerate * banktransaction.exchangerate = total new amount EUR |
|
104 |
my $new_open_amount = ( $self->open_amount / $self->get_exchangerate ) * $exchangerate; |
|
105 |
# VORHER |
|
106 |
# my $gain_loss_amount = _round($amount * ($exchangerate - $self->get_exchangerate ) * -1,2); |
|
107 |
$fx_gain_loss_amount = _round( $self->open_amount - $new_open_amount); |
|
108 |
# works for ap, but change sign for ar (todo credit notes and negative ap transactions |
|
109 |
$fx_gain_loss_amount *= -1 if $self->is_sales; |
|
110 |
$main::lxdebug->message(0, 'h 1 ' . $new_open_amount . ' h 3 ' . $params{amount} . ' und fx ' . $fx_gain_loss_amount ); |
|
111 |
if ($params{fx_book} && $new_open_amount < $params{amount}) { |
|
112 |
die "Bank Fees can only be added for AP transactions" if $self->is_sales; |
|
113 |
$self->_add_bank_fx_fees(fee => _round($params{amount} - $new_open_amount), |
|
114 |
bt_id => $params{bt_id}, |
|
115 |
bank_chart_id => $params{chart_id}, |
|
116 |
memo => $params{memo}, |
|
117 |
source => $params{source}, |
|
118 |
transdate_obj => $transdate_obj ); |
|
119 |
# invoice_amount |
|
120 |
$return_bank_amount += _round($params{amount} - $new_open_amount); |
|
121 |
} else { } |
|
122 |
# always use new open amount for payment booking and add this value to arap.paid |
|
123 |
$params{amount} = $new_open_amount; |
|
124 |
# $paid_amount = $new_open_amount; |
|
125 |
} elsif (!$self->forex) { # invoices uses default currency. no exchangerate |
|
117 | 126 |
$exchangerate = 1; |
118 |
}; |
|
127 |
} else { |
|
128 |
die "Cannot calculate exchange rate, if invoices uses the default currency"; |
|
129 |
} |
|
119 | 130 |
|
120 | 131 |
# absolute skonto amount for invoice, use as reference sum to see if the |
121 | 132 |
# calculated skontos add up |
... | ... | |
135 | 146 |
my $source = $params{source} // ''; |
136 | 147 |
|
137 | 148 |
my $rounded_params_amount = _round( $params{amount} ); # / $exchangerate); |
138 |
my $fx_gain_loss_amount = 0; # for fx_gain and fx_loss |
|
139 |
|
|
140 |
my $return_bank_amount; # will be returned for invoice_amount |
|
141 | 149 |
my $db = $self->db; |
142 | 150 |
$db->with_transaction(sub { |
143 | 151 |
my $new_acc_trans; |
... | ... | |
157 | 165 |
$pay_amount = $self->amount_less_skonto if $params{payment_type} eq 'with_skonto_pt'; |
158 | 166 |
|
159 | 167 |
# bank account and AR/AP |
160 |
$paid_amount += $pay_amount * $exchangerate;
|
|
168 |
$paid_amount += $pay_amount; |
|
161 | 169 |
|
162 | 170 |
my $amount = (-1 * $pay_amount) * $mult; |
163 | 171 |
|
... | ... | |
177 | 185 |
$new_acc_trans->save; |
178 | 186 |
$return_bank_amount = $amount; |
179 | 187 |
push @new_acc_ids, $new_acc_trans->acc_trans_id; |
180 |
# deal with fxtransaction |
|
181 |
if ( $self->currency_id != $::instance_conf->get_currency_id && $exchangerate != 1) { |
|
182 |
my $fxamount = _round($amount - ($amount * $exchangerate)); |
|
188 |
# deal with fxtransaction ... |
|
189 |
# if invoice exchangerate differs from exchangerate of payment |
|
190 |
# add fxloss or fxgain |
|
191 |
if ($fx_gain_loss_amount && $exchangerate != 1 && $self->get_exchangerate and $self->get_exchangerate != 1 and $self->get_exchangerate != $exchangerate) { |
|
192 |
# (self->amount - self->paid) / $self->exchangerate |
|
193 |
my $fxgain_chart = SL::DB::Manager::Chart->find_by(id => $::instance_conf->get_fxgain_accno_id) || die "Can't determine fxgain chart"; |
|
194 |
my $fxloss_chart = SL::DB::Manager::Chart->find_by(id => $::instance_conf->get_fxloss_accno_id) || die "Can't determine fxloss chart"; |
|
195 |
$main::lxdebug->message(0, 'was sagt gain loss' . $fx_gain_loss_amount); |
|
196 |
my $gain_loss_chart = $fx_gain_loss_amount > 0 ? $fxgain_chart : $fxloss_chart; |
|
197 |
$paid_amount += $fx_gain_loss_amount if $fx_gain_loss_amount < 0; # only add if we have fx_loss |
|
198 |
$main::lxdebug->message(0, 'paid2 ' . $paid_amount); |
|
199 |
$main::lxdebug->message(0, 'paid2chart ' . $fx_gain_loss_amount); |
|
200 |
# $fx_gain_loss_amount = $gain_loss_amount; |
|
201 |
|
|
183 | 202 |
$new_acc_trans = SL::DB::AccTransaction->new(trans_id => $self->id, |
184 |
chart_id => $account_bank->id,
|
|
185 |
chart_link => $account_bank->link,
|
|
186 |
amount => $fxamount * -1,
|
|
203 |
chart_id => $gain_loss_chart->id,
|
|
204 |
chart_link => $gain_loss_chart->link,
|
|
205 |
amount => $fx_gain_loss_amount,
|
|
187 | 206 |
transdate => $transdate_obj, |
188 | 207 |
source => $source, |
189 | 208 |
memo => $memo, |
190 | 209 |
taxkey => 0, |
191 |
fx_transaction => 1,
|
|
210 |
fx_transaction => 0, # probably indicates a real bank account in foreign currency
|
|
192 | 211 |
tax_id => SL::DB::Manager::Tax->find_by(taxkey => 0)->id); |
193 | 212 |
$new_acc_trans->save; |
194 | 213 |
push @new_acc_ids, $new_acc_trans->acc_trans_id; |
195 |
# if invoice exchangerate differs from exchangerate of payment |
|
196 |
# deal with fxloss and fxamount |
|
197 |
if ($self->exchangerate and $self->exchangerate != 1 and $self->exchangerate != $exchangerate) { |
|
198 |
my $fxgain_chart = SL::DB::Manager::Chart->find_by(id => $::instance_conf->get_fxgain_accno_id) || die "Can't determine fxgain chart"; |
|
199 |
my $fxloss_chart = SL::DB::Manager::Chart->find_by(id => $::instance_conf->get_fxloss_accno_id) || die "Can't determine fxloss chart"; |
|
200 |
# would nearly work if $amount is in foreign currency. Old code in AP.pm |
|
201 |
# and old code says USD * ( rate invoice - rate payment ) |
|
202 |
my $gain_loss_amount = _round($amount * ($exchangerate - $self->exchangerate ) * -1,2); |
|
203 |
# EUR / rate payment * ( rate invoice - rate bank transaction) |
|
204 |
my $gain_loss_chart = $gain_loss_amount > 0 ? $fxgain_chart : $fxloss_chart; |
|
205 |
$fx_gain_loss_amount = $gain_loss_amount; |
|
206 |
|
|
207 |
$new_acc_trans = SL::DB::AccTransaction->new(trans_id => $self->id, |
|
208 |
chart_id => $gain_loss_chart->id, |
|
209 |
chart_link => $gain_loss_chart->link, |
|
210 |
amount => $gain_loss_amount, |
|
211 |
transdate => $transdate_obj, |
|
212 |
source => $source, |
|
213 |
memo => $memo, |
|
214 |
taxkey => 0, |
|
215 |
fx_transaction => 0, |
|
216 |
tax_id => SL::DB::Manager::Tax->find_by(taxkey => 0)->id); |
|
217 |
$new_acc_trans->save; |
|
218 |
push @new_acc_ids, $new_acc_trans->acc_trans_id; |
|
219 |
|
|
220 |
} |
|
221 | 214 |
} |
222 | 215 |
} |
223 | 216 |
# skonto cases |
... | ... | |
253 | 246 |
push @new_acc_ids, $new_acc_trans->acc_trans_id; |
254 | 247 |
|
255 | 248 |
$reference_amount -= abs($amount); |
256 |
$paid_amount += -1 * $amount * $exchangerate;
|
|
249 |
$paid_amount += -1 * $amount; |
|
257 | 250 |
$skonto_amount_check -= $skonto_booking->{'skonto_amount'}; |
258 | 251 |
} |
259 | 252 |
} |
... | ... | |
273 | 266 |
} |
274 | 267 |
|
275 | 268 |
# regardless of payment_type there is always only exactly one arap booking |
276 |
# TODO: compare $arap_amount to running total |
|
269 |
# TODO: compare $arap_amount to running total and/or use this as running total for ar.paid|ap.paid
|
|
277 | 270 |
my $arap_booking= SL::DB::AccTransaction->new(trans_id => $self->id, |
278 | 271 |
chart_id => $reference_account->id, |
279 | 272 |
chart_link => $reference_account->link, |
280 |
amount => _round($arap_amount * $mult * $exchangerate - $fx_gain_loss_amount),
|
|
273 |
amount => _round($arap_amount * $mult - $fx_gain_loss_amount), |
|
281 | 274 |
transdate => $transdate_obj, |
282 | 275 |
source => '', #$params{source}, |
283 | 276 |
taxkey => 0, |
... | ... | |
346 | 339 |
push @new_acc_ids, $tax_booking->acc_trans_id; |
347 | 340 |
} |
348 | 341 |
} |
349 |
$fx_gain_loss_amount *= -1 if $self->is_sales; |
|
350 |
$self->paid($self->paid + _round($paid_amount) + $fx_gain_loss_amount) if $paid_amount;
|
|
342 |
# $fx_gain_loss_amount *= -1 if $self->is_sales;
|
|
343 |
$self->paid($self->paid + _round($paid_amount)) if $paid_amount; |
|
351 | 344 |
$self->datepaid($transdate_obj); |
352 | 345 |
$self->save; |
353 | 346 |
|
... | ... | |
656 | 649 |
return @skonto_charts; |
657 | 650 |
} |
658 | 651 |
|
659 |
|
|
660 | 652 |
sub within_skonto_period { |
661 | 653 |
my $self = shift; |
662 | 654 |
validate( |
Auch abrufbar als: Unified diff
wip: REMOVE Wechselkursberechungen geändert in Payment-Helper