Revision b17ed7c1
Von Jan Büren vor fast 3 Jahren hinzugefügt
SL/DB/Helper/Payment.pm | ||
---|---|---|
4 | 4 |
|
5 | 5 |
use parent qw(Exporter); |
6 | 6 |
our @EXPORT = qw(pay_invoice); |
7 |
our @EXPORT_OK = qw(skonto_date skonto_charts amount_less_skonto within_skonto_period percent_skonto reference_account reference_amount open_amount open_percent remaining_skonto_days skonto_amount check_skonto_configuration valid_skonto_amount get_payment_suggestions validate_payment_type open_sepa_transfer_amount get_payment_select_options_for_bank_transaction exchangerate forex _skonto_charts_and_tax_correction);
|
|
7 |
our @EXPORT_OK = qw(skonto_date amount_less_skonto within_skonto_period percent_skonto reference_account reference_amount open_amount open_percent remaining_skonto_days skonto_amount check_skonto_configuration valid_skonto_amount get_payment_suggestions validate_payment_type open_sepa_transfer_amount get_payment_select_options_for_bank_transaction exchangerate forex _skonto_charts_and_tax_correction); |
|
8 | 8 |
our %EXPORT_TAGS = ( |
9 | 9 |
"ALL" => [@EXPORT, @EXPORT_OK], |
10 | 10 |
); |
... | ... | |
711 | 711 |
return @skonto_charts; |
712 | 712 |
} |
713 | 713 |
|
714 |
sub skonto_charts { |
|
715 |
my $self = shift; |
|
716 |
|
|
717 |
# TODO: use param for amount, may also want to calculate skonto_amounts by |
|
718 |
# passing percentage in the future |
|
719 |
|
|
720 |
my $amount = shift || $self->skonto_amount; |
|
721 |
|
|
722 |
croak "no amount passed to skonto_charts" unless abs(_round($amount)) >= 0.01; |
|
723 |
|
|
724 |
# TODO: check whether there are negative values in invoice / acc_trans ... credited items |
|
725 |
|
|
726 |
# don't check whether skonto applies, because user may want to override this |
|
727 |
# return undef unless $self->percent_skonto; |
|
728 |
|
|
729 |
my $is_sales = ref($self) eq 'SL::DB::Invoice'; |
|
730 |
|
|
731 |
my $mult = $is_sales ? 1 : -1; # multiplier for getting the right sign |
|
732 |
|
|
733 |
my @skonto_charts; # resulting array with all income/expense accounts that have to be corrected |
|
734 |
|
|
735 |
# calculate effective skonto (percentage) in difference_as_skonto mode |
|
736 |
# only works if there are no negative acc_trans values |
|
737 |
my $effective_skonto_rate = $amount ? $amount / $self->amount : 0; |
|
738 |
|
|
739 |
# checks: |
|
740 |
my $total_skonto_amount = 0; |
|
741 |
my $total_rounding_error = 0; |
|
742 |
|
|
743 |
my $reference_ARAP_amount = 0; |
|
744 |
|
|
745 |
# my $transactions = $self->transactions; |
|
746 |
foreach my $transaction (@{ $self->transactions }) { |
|
747 |
# find all transactions with an AR_amount or AP_amount link |
|
748 |
$transaction->{chartlinks} = { map { $_ => 1 } split(m/:/, $transaction->{chart_link}) }; |
|
749 |
# second condition is that we can determine an automatic Skonto account for each AR_amount entry |
|
750 |
|
|
751 |
if ( ( $is_sales && $transaction->{chartlinks}->{AR_amount} ) or ( !$is_sales && $transaction->{chartlinks}->{AP_amount}) ) { |
|
752 |
# $reference_ARAP_amount += $transaction->{amount} * $mult; |
|
753 |
|
|
754 |
# quick hack that works around problem of non-unique tax keys in SKR04 |
|
755 |
# ? use tax_id in acc_trans |
|
756 |
my $tax = SL::DB::Manager::Tax->get_first( where => [id => $transaction->{tax_id}]); |
|
757 |
croak "no tax for taxkey " . $transaction->{taxkey} unless ref $tax; |
|
758 |
|
|
759 |
if ( $is_sales ) { |
|
760 |
die t8('no skonto_chart configured for taxkey #1 : #2 : #3', $transaction->{taxkey} , $tax->taxdescription , $tax->rate*100) unless ref $tax->skonto_sales_chart; |
|
761 |
} else { |
|
762 |
die t8('no skonto_chart configured for taxkey #1 : #2 : #3', $transaction->{taxkey} , $tax->taxdescription , $tax->rate*100) unless ref $tax->skonto_purchase_chart; |
|
763 |
}; |
|
764 |
|
|
765 |
my $skonto_amount_unrounded; |
|
766 |
|
|
767 |
my $skonto_percent_abs = $self->amount ? abs($transaction->amount * (1 + $tax->rate) * 100 / $self->amount) : 0; |
|
768 |
|
|
769 |
my $transaction_amount = abs($transaction->{amount} * (1 + $tax->rate)); |
|
770 |
my $transaction_skonto_percent = abs($transaction_amount/$self->amount); # abs($transaction->{amount} * (1 + $tax->rate)); |
|
771 |
|
|
772 |
|
|
773 |
$skonto_amount_unrounded = abs($amount * $transaction_skonto_percent); |
|
774 |
my $skonto_amount_rounded = _round($skonto_amount_unrounded); |
|
775 |
my $rounding_error = $skonto_amount_unrounded - $skonto_amount_rounded; |
|
776 |
my $rounded_rounding_error = _round($rounding_error); |
|
777 |
|
|
778 |
$total_rounding_error += $rounding_error; |
|
779 |
$total_skonto_amount += $skonto_amount_rounded; |
|
780 |
|
|
781 |
my $rec = { |
|
782 |
# skonto_percent_abs: relative part of amount + tax to the total invoice amount |
|
783 |
'skonto_percent_abs' => $skonto_percent_abs, |
|
784 |
'chart_id' => $is_sales ? $tax->skonto_sales_chart->id : $tax->skonto_purchase_chart->id, |
|
785 |
'skonto_amount' => $skonto_amount_rounded, |
|
786 |
# 'rounding_error' => $rounding_error, |
|
787 |
# 'rounded_rounding_error' => $rounded_rounding_error, |
|
788 |
}; |
|
789 |
|
|
790 |
push @skonto_charts, $rec; |
|
791 |
} |
|
792 |
} |
|
793 |
|
|
794 |
# if the rounded sum of all rounding_errors reaches 0.01 this sum is |
|
795 |
# subtracted from the largest skonto_amount |
|
796 |
my $rounded_total_rounding_error = abs(_round($total_rounding_error)); |
|
797 |
|
|
798 |
if ( $rounded_total_rounding_error > 0 ) { |
|
799 |
my $highest_amount_pos = 0; |
|
800 |
my $highest_amount = 0; |
|
801 |
my $i = -1; |
|
802 |
foreach my $ref ( @skonto_charts ) { |
|
803 |
$i++; |
|
804 |
if ( $ref->{skonto_amount} > $highest_amount ) { |
|
805 |
$highest_amount = $ref->{skonto_amount}; |
|
806 |
$highest_amount_pos = $i; |
|
807 |
}; |
|
808 |
}; |
|
809 |
$skonto_charts[$i]->{skonto_amount} -= $rounded_total_rounding_error; |
|
810 |
}; |
|
811 |
|
|
812 |
return @skonto_charts; |
|
813 |
}; |
|
814 |
|
|
815 |
|
|
816 | 714 |
sub within_skonto_period { |
817 | 715 |
my $self = shift; |
818 | 716 |
my $dateref = shift || DateTime->now->truncate( to => 'day' ); |
Auch abrufbar als: Unified diff
Payment-Helper: skonto_charts entfernt