X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=t%2Fdb_helper%2Fpayment.t;h=81fc201509fd9ac942d69e6b61a8c2d2eb4435b7;hb=c6d47254a0c5a7063d5f52341ad5def0d5ae8e52;hp=18da821f2d06bba46b367a80e0f65b473e52d7ee;hpb=15f58ff3dfd79651a95535b53f864ea0e8cb6620;p=kivitendo-erp.git diff --git a/t/db_helper/payment.t b/t/db_helper/payment.t index 18da821f2..81fc20150 100644 --- a/t/db_helper/payment.t +++ b/t/db_helper/payment.t @@ -10,8 +10,12 @@ use Support::TestSetup; use Test::Exception; use List::Util qw(sum); +use SL::Dev::Record; +use SL::Dev::CustomerVendor; +use SL::Dev::Part; use SL::DB::Buchungsgruppe; use SL::DB::Currency; +use SL::DB::Exchangerate; use SL::DB::Customer; use SL::DB::Vendor; use SL::DB::Employee; @@ -21,8 +25,12 @@ use SL::DB::Unit; use SL::DB::TaxZone; use SL::DB::BankAccount; use SL::DB::PaymentTerm; +use SL::DBUtils qw(selectfirst_array_query); +use Data::Dumper; -my ($customer, $vendor, $currency_id, @parts, $buchungsgruppe, $buchungsgruppe7, $unit, $employee, $tax, $tax7, $taxzone, $payment_terms, $bank_account); +my ($customer, $vendor, $currency_id, @parts, $buchungsgruppe, $buchungsgruppe7, $unit, $employee, $tax, $tax7, $tax_9, $taxzone, $payment_terms, $bank_account); +my ($transdate1, $transdate2, $transdate3, $transdate4, $currency, $exchangerate, $exchangerate2, $exchangerate3, $exchangerate4); +my ($ar_chart,$bank,$ar_amount_chart, $ap_chart, $ap_amount_chart, $fxloss_chart, $fxgain_chart); my $ALWAYS_RESET = 1; @@ -39,6 +47,8 @@ sub clear_up { SL::DB::Manager::Vendor->delete_all(all => 1); SL::DB::Manager::BankAccount->delete_all(all => 1); SL::DB::Manager::PaymentTerm->delete_all(all => 1); + SL::DB::Manager::Exchangerate->delete_all(all => 1); + SL::DB::Manager::Currency->delete_all(where => [ name => 'CUR' ]); }; sub reset_state { @@ -50,6 +60,10 @@ sub reset_state { clear_up(); + $transdate1 = DateTime->today; + $transdate2 = DateTime->today->add(days => 1); + $transdate3 = DateTime->today->add(days => 2); + $transdate4 = DateTime->today->add(days => 3); $buchungsgruppe = SL::DB::Manager::Buchungsgruppe->find_by(description => 'Standard 19%', %{ $params{buchungsgruppe} }) || croak "No accounting group"; $buchungsgruppe7 = SL::DB::Manager::Buchungsgruppe->find_by(description => 'Standard 7%') || croak "No accounting group for 7\%"; @@ -58,14 +72,47 @@ sub reset_state { $tax = SL::DB::Manager::Tax->find_by(taxkey => 3, rate => 0.19, %{ $params{tax} }) || croak "No tax"; $tax7 = SL::DB::Manager::Tax->find_by(taxkey => 2, rate => 0.07) || croak "No tax for 7\%"; $taxzone = SL::DB::Manager::TaxZone->find_by( description => 'Inland') || croak "No taxzone"; + $tax_9 = SL::DB::Manager::Tax->find_by(taxkey => 9, rate => 0.19, %{ $params{tax} }) || croak "No tax"; + # $tax7 = SL::DB::Manager::Tax->find_by(taxkey => 2, rate => 0.07) || croak "No tax for 7\%"; $currency_id = $::instance_conf->get_currency_id; - $customer = SL::DB::Customer->new( + $currency = SL::DB::Currency->new(name => 'CUR')->save; + + $fxgain_chart = SL::DB::Manager::Chart->find_by(accno => '2660') or die "Can't find fxgain_chart in test"; + $fxloss_chart = SL::DB::Manager::Chart->find_by(accno => '2150') or die "Can't find fxloss_chart in test"; + + $currency->db->dbh->do('UPDATE defaults SET fxgain_accno_id = ' . $fxgain_chart->id); + $currency->db->dbh->do('UPDATE defaults SET fxloss_accno_id = ' . $fxloss_chart->id); + $::instance_conf->reload->data; + is($fxgain_chart->id, $::instance_conf->get_fxgain_accno_id, "fxgain_chart was updated in defaults"); + is($fxloss_chart->id, $::instance_conf->get_fxloss_accno_id, "fxloss_chart was updated in defaults"); + + $exchangerate = SL::DB::Exchangerate->new(transdate => $transdate1, + buy => '1.33333', + sell => '1.33333', + currency_id => $currency->id, + )->save; + $exchangerate2 = SL::DB::Exchangerate->new(transdate => $transdate2, + buy => '0.8', + sell => '0.8', + currency_id => $currency->id, + )->save; + $exchangerate3 = SL::DB::Exchangerate->new(transdate => $transdate3, + buy => '1.55557', + sell => '1.55557', + currency_id => $currency->id, + )->save; + $exchangerate4 = SL::DB::Exchangerate->new(transdate => $transdate4, + buy => '0.77777', + sell => '0.77777', + currency_id => $currency->id, + )->save; + + $customer = SL::Dev::CustomerVendor::create_customer( name => 'Test Customer', currency_id => $currency_id, taxzone_id => $taxzone->id, - %{ $params{customer} } )->save; $bank_account = SL::DB::BankAccount->new( @@ -83,20 +130,20 @@ sub reset_state { description_long => 'payment', terms_netto => '30', terms_skonto => '5', - percent_skonto => '0.05' + percent_skonto => '0.05', + auto_calculation => 1, )->save; - $vendor = SL::DB::Vendor->new( + $vendor = SL::Dev::CustomerVendor::create_vendor( name => 'Test Vendor', currency_id => $currency_id, taxzone_id => $taxzone->id, payment_id => $payment_terms->id, - %{ $params{vendor} } )->save; @parts = (); - push @parts, SL::DB::Part->new( + push @parts, SL::Dev::Part::create_part( partnumber => 'T4254', description => 'Fourty-two fifty-four', lastcost => 1.93, @@ -106,7 +153,7 @@ sub reset_state { %{ $params{part1} } )->save; - push @parts, SL::DB::Part->new( + push @parts, SL::Dev::Part::create_part( partnumber => 'T0815', description => 'Zero EIGHT fifteeN @ 7%', lastcost => 5.473, @@ -115,7 +162,7 @@ sub reset_state { unit => $unit->name, %{ $params{part2} } )->save; - push @parts, SL::DB::Part->new( + push @parts, SL::Dev::Part::create_part( partnumber => '19%', description => 'Testware 19%', lastcost => 0, @@ -124,7 +171,7 @@ sub reset_state { unit => $unit->name, %{ $params{part3} } )->save; - push @parts, SL::DB::Part->new( + push @parts, SL::Dev::Part::create_part( partnumber => '7%', description => 'Testware 7%', lastcost => 0, @@ -134,25 +181,13 @@ sub reset_state { %{ $params{part4} } )->save; - $reset_state_counter++; -} - -sub new_invoice { - my %params = @_; - - return SL::DB::Invoice->new( - customer_id => $customer->id, - currency_id => $currency_id, - employee_id => $employee->id, - salesman_id => $employee->id, - gldate => DateTime->today_local->to_kivitendo, - taxzone_id => $taxzone->id, - transdate => DateTime->today_local->to_kivitendo, - invoice => 1, - type => 'invoice', - %params, - ); + $ar_chart = SL::DB::Manager::Chart->find_by( accno => '1400' ); # Forderungen + $ap_chart = SL::DB::Manager::Chart->find_by( accno => '1600' ); # Verbindlichkeiten + $bank = SL::DB::Manager::Chart->find_by( accno => '1200' ); # Bank + $ar_amount_chart = SL::DB::Manager::Chart->find_by( accno => '8400' ); # Erlöse + $ap_amount_chart = SL::DB::Manager::Chart->find_by( accno => '3400' ); # Wareneingang 19% + $reset_state_counter++; } sub new_purchase_invoice { @@ -166,9 +201,9 @@ sub new_purchase_invoice { invnumber => 'newap ' . $purchase_invoice_counter , currency_id => $currency_id, employee_id => $employee->id, - gldate => DateTime->today_local->to_kivitendo, + gldate => $transdate1, taxzone_id => $taxzone->id, - transdate => DateTime->today_local->to_kivitendo, + transdate => $transdate1, invoice => 0, type => 'invoice', taxincluded => 0, @@ -178,14 +213,13 @@ sub new_purchase_invoice { # %params, )->save; - my $today = DateTime->today_local->to_kivitendo; my $expense_chart = SL::DB::Manager::Chart->find_by(accno => '3400'); my $expense_chart_booking= SL::DB::AccTransaction->new( trans_id => $purchase_invoice->id, chart_id => $expense_chart->id, chart_link => $expense_chart->link, amount => '-100', - transdate => $today, + transdate => $transdate1, source => '', taxkey => 9, tax_id => SL::DB::Manager::Tax->find_by(taxkey => 9)->id); @@ -197,7 +231,7 @@ sub new_purchase_invoice { chart_id => $tax_chart->id, chart_link => $tax_chart->link, amount => '-19', - transdate => $today, + transdate => $transdate1, source => '', taxkey => 0, tax_id => SL::DB::Manager::Tax->find_by(taxkey => 9)->id); @@ -208,7 +242,7 @@ sub new_purchase_invoice { chart_id => $expense_chart->id, chart_link => $expense_chart->link, amount => '-100', - transdate => $today, + transdate => $transdate1, source => '', taxkey => 8, tax_id => SL::DB::Manager::Tax->find_by(taxkey => 8)->id); @@ -221,7 +255,7 @@ sub new_purchase_invoice { chart_id => $tax_chart->id, chart_link => $tax_chart->link, amount => '-7', - transdate => $today, + transdate => $transdate1, source => '', taxkey => 0, tax_id => SL::DB::Manager::Tax->find_by(taxkey => 8)->id); @@ -231,7 +265,7 @@ sub new_purchase_invoice { chart_id => $arap_chart->id, chart_link => $arap_chart->link, amount => '226', - transdate => $today, + transdate => $transdate1, source => '', taxkey => 0, tax_id => SL::DB::Manager::Tax->find_by(taxkey => 0)->id); @@ -240,27 +274,12 @@ sub new_purchase_invoice { return $purchase_invoice; } -sub new_item { - my (%params) = @_; - - my $part = delete($params{part}) || $parts[0]; - - return SL::DB::InvoiceItem->new( - parts_id => $part->id, - lastcost => $part->lastcost, - sellprice => $part->sellprice, - description => $part->description, - unit => $part->unit, - %params, - ); -} - sub number_of_payments { - my $transactions = shift; + my $invoice = shift; my $number_of_payments; my $paid_amount; - foreach my $transaction ( @$transactions ) { + foreach my $transaction ( @{ $invoice->transactions } ) { if ( $transaction->chart_link =~ /(AR_paid|AP_paid)/ ) { $paid_amount += $transaction->amount ; $number_of_payments++; @@ -270,9 +289,9 @@ sub number_of_payments { }; sub total_amount { - my $transactions = shift; + my $invoice = shift; - my $total = sum map { $_->amount } @$transactions; + my $total = sum map { $_->amount } @{ $invoice->transactions }; return $::form->round_amount($total, 5); @@ -283,17 +302,15 @@ sub total_amount { sub test_default_invoice_one_item_19_without_skonto() { reset_state() if $ALWAYS_RESET; - my $item = new_item(qty => 2.5); - my $invoice = new_invoice( + my $item = SL::Dev::Record::create_invoice_item(part => $parts[0], qty => 2.5); + my $invoice = SL::Dev::Record::create_sales_invoice( taxincluded => 0, invoiceitems => [ $item ], payment_id => $payment_terms->id, ); - $invoice->post; my $purchase_invoice = new_purchase_invoice(); - # default values my %params = ( chart_id => $bank_account->chart_id, transdate => DateTime->today_local->to_kivitendo @@ -304,8 +321,8 @@ sub test_default_invoice_one_item_19_without_skonto() { $invoice->pay_invoice( %params ); - my ($number_of_payments, $paid_amount) = number_of_payments($invoice->transactions); - my $total = total_amount($invoice->transactions); + my ($number_of_payments, $paid_amount) = number_of_payments($invoice); + my $total = total_amount($invoice); my $title = 'default invoice, one item, 19% tax, without_skonto'; @@ -321,13 +338,12 @@ sub test_default_invoice_one_item_19_without_skonto() { sub test_default_invoice_one_item_19_without_skonto_overpaid() { reset_state() if $ALWAYS_RESET; - my $item = new_item(qty => 2.5); - my $invoice = new_invoice( + my $item = SL::Dev::Record::create_invoice_item(part => $parts[0], qty => 2.5); + my $invoice = SL::Dev::Record::create_sales_invoice( taxincluded => 0, invoiceitems => [ $item ], payment_id => $payment_terms->id, ); - $invoice->post; my $purchase_invoice = new_purchase_invoice(); @@ -344,8 +360,8 @@ sub test_default_invoice_one_item_19_without_skonto_overpaid() { $params{amount} = '-10.00'; $invoice->pay_invoice( %params ); - my ($number_of_payments, $paid_amount) = number_of_payments($invoice->transactions); - my $total = total_amount($invoice->transactions); + my ($number_of_payments, $paid_amount) = number_of_payments($invoice); + my $total = total_amount($invoice); my $title = 'default invoice, one item, 19% tax, without_skonto'; @@ -363,14 +379,13 @@ sub test_default_invoice_one_item_19_without_skonto_overpaid() { sub test_default_invoice_two_items_19_7_tax_with_skonto() { reset_state() if $ALWAYS_RESET; - my $item1 = new_item(qty => 2.5); - my $item2 = new_item(qty => 1.2, part => $parts[1]); - my $invoice = new_invoice( + my $item1 = SL::Dev::Record::create_invoice_item(part => $parts[0], qty => 2.5); + my $item2 = SL::Dev::Record::create_invoice_item(part => $parts[1], qty => 1.2); + my $invoice = SL::Dev::Record::create_sales_invoice( taxincluded => 0, invoiceitems => [ $item1, $item2 ], - payment_id => $payment_terms->id, + payment_id => $payment_terms->id, ); - $invoice->post; # default values my %params = ( chart_id => $bank_account->chart_id, @@ -382,8 +397,8 @@ sub test_default_invoice_two_items_19_7_tax_with_skonto() { $invoice->pay_invoice( %params ); - my ($number_of_payments, $paid_amount) = number_of_payments($invoice->transactions); - my $total = total_amount($invoice->transactions); + my ($number_of_payments, $paid_amount) = number_of_payments($invoice); + my $total = total_amount($invoice); my $title = 'default invoice, two items, 19/7% tax with_skonto_pt'; @@ -398,14 +413,13 @@ sub test_default_invoice_two_items_19_7_tax_with_skonto() { sub test_default_invoice_two_items_19_7_tax_with_skonto_tax_included() { reset_state() if $ALWAYS_RESET; - my $item1 = new_item(qty => 2.5); - my $item2 = new_item(qty => 1.2, part => $parts[1]); - my $invoice = new_invoice( + my $item1 = SL::Dev::Record::create_invoice_item(part => $parts[0], qty => 2.5); + my $item2 = SL::Dev::Record::create_invoice_item(part => $parts[1], qty => 1.2); + my $invoice = SL::Dev::Record::create_sales_invoice( taxincluded => 1, invoiceitems => [ $item1, $item2 ], - payment_id => $payment_terms->id, + payment_id => $payment_terms->id, ); - $invoice->post; # default values my %params = ( chart_id => $bank_account->chart_id, @@ -417,8 +431,8 @@ sub test_default_invoice_two_items_19_7_tax_with_skonto_tax_included() { $invoice->pay_invoice( %params ); - my ($number_of_payments, $paid_amount) = number_of_payments($invoice->transactions); - my $total = total_amount($invoice->transactions); + my ($number_of_payments, $paid_amount) = number_of_payments($invoice); + my $total = total_amount($invoice); my $title = 'default invoice, two items, 19/7% tax with_skonto_pt'; @@ -427,21 +441,22 @@ sub test_default_invoice_two_items_19_7_tax_with_skonto_tax_included() { is($paid_amount, -17.51, "${title}: paid amount"); is($invoice->paid, 17.51, "${title}: paid"); is($number_of_payments, 3, "${title}: 3 AR_paid bookings"); + { local $TODO = "currently this test fails because the code writing the invoice is buggy, the calculation of skonto is correct"; is($total, 0, "${title}: even balance"); + } } # test 3 : two items, without skonto sub test_default_invoice_two_items_19_7_without_skonto() { reset_state() if $ALWAYS_RESET; - my $item1 = new_item(qty => 2.5); - my $item2 = new_item(qty => 1.2, part => $parts[1]); - my $invoice = new_invoice( + my $item1 = SL::Dev::Record::create_invoice_item(part => $parts[0], qty => 2.5); + my $item2 = SL::Dev::Record::create_invoice_item(part => $parts[1], qty => 1.2); + my $invoice = SL::Dev::Record::create_sales_invoice( taxincluded => 0, invoiceitems => [ $item1, $item2 ], - payment_id => $payment_terms->id, + payment_id => $payment_terms->id, ); - $invoice->post; # default values my %params = ( chart_id => $bank_account->chart_id, @@ -453,8 +468,8 @@ sub test_default_invoice_two_items_19_7_without_skonto() { $invoice->pay_invoice( %params ); - my ($number_of_payments, $paid_amount) = number_of_payments($invoice->transactions); - my $total = total_amount($invoice->transactions); + my ($number_of_payments, $paid_amount) = number_of_payments($invoice); + my $total = total_amount($invoice); my $title = 'default invoice, two items, 19/7% tax without skonto'; @@ -470,14 +485,13 @@ sub test_default_invoice_two_items_19_7_without_skonto() { sub test_default_invoice_two_items_19_7_without_skonto_incomplete_payment() { reset_state() if $ALWAYS_RESET; - my $item1 = new_item(qty => 2.5); - my $item2 = new_item(qty => 1.2, part => $parts[1]); - my $invoice = new_invoice( + my $item1 = SL::Dev::Record::create_invoice_item(part => $parts[0], qty => 2.5); + my $item2 = SL::Dev::Record::create_invoice_item(part => $parts[1], qty => 1.2); + my $invoice = SL::Dev::Record::create_sales_invoice( taxincluded => 0, invoiceitems => [ $item1, $item2 ], - payment_id => $payment_terms->id, + payment_id => $payment_terms->id, ); - $invoice->post; $invoice->pay_invoice( amount => '9.44', payment_type => 'without_skonto', @@ -485,8 +499,8 @@ sub test_default_invoice_two_items_19_7_without_skonto_incomplete_payment() { transdate => DateTime->today_local->to_kivitendo, ); - my ($number_of_payments, $paid_amount) = number_of_payments($invoice->transactions); - my $total = total_amount($invoice->transactions); + my ($number_of_payments, $paid_amount) = number_of_payments($invoice); + my $total = total_amount($invoice); my $title = 'default invoice, two items, 19/7% tax without skonto incomplete payment'; @@ -502,14 +516,13 @@ sub test_default_invoice_two_items_19_7_without_skonto_incomplete_payment() { sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments() { reset_state() if $ALWAYS_RESET; - my $item1 = new_item(qty => 2.5); - my $item2 = new_item(qty => 1.2, part => $parts[1]); - my $invoice = new_invoice( + my $item1 = SL::Dev::Record::create_invoice_item(part => $parts[0], qty => 2.5); + my $item2 = SL::Dev::Record::create_invoice_item(part => $parts[1], qty => 1.2); + my $invoice = SL::Dev::Record::create_sales_invoice( taxincluded => 0, invoiceitems => [ $item1, $item2 ], - payment_id => $payment_terms->id, + payment_id => $payment_terms->id, ); - $invoice->post; $invoice->pay_invoice( amount => '9.44', payment_type => 'without_skonto', @@ -521,8 +534,8 @@ sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments() { transdate => DateTime->today_local->to_kivitendo ); - my ($number_of_payments, $paid_amount) = number_of_payments($invoice->transactions); - my $total = total_amount($invoice->transactions); + my ($number_of_payments, $paid_amount) = number_of_payments($invoice); + my $total = total_amount($invoice); my $title = 'default invoice, two items, 19/7% tax not included'; @@ -539,14 +552,13 @@ sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments() { sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto() { reset_state() if $ALWAYS_RESET; - my $item1 = new_item(qty => 2.5); - my $item2 = new_item(qty => 1.2, part => $parts[1]); - my $invoice = new_invoice( + my $item1 = SL::Dev::Record::create_invoice_item(part => $parts[0], qty => 2.5); + my $item2 = SL::Dev::Record::create_invoice_item(part => $parts[1], qty => 1.2); + my $invoice = SL::Dev::Record::create_sales_invoice( taxincluded => 0, invoiceitems => [ $item1, $item2 ], - payment_id => $payment_terms->id, + payment_id => $payment_terms->id, ); - $invoice->post; $invoice->pay_invoice( amount => '9.44', payment_type => 'without_skonto', @@ -564,8 +576,8 @@ sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_fin transdate => DateTime->today_local->to_kivitendo ); - my ($number_of_payments, $paid_amount) = number_of_payments($invoice->transactions); - my $total = total_amount($invoice->transactions); + my ($number_of_payments, $paid_amount) = number_of_payments($invoice); + my $total = total_amount($invoice); my $title = 'default invoice, two items, 19/7% tax not included'; @@ -586,14 +598,13 @@ sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_fi # (11.66) rather than the 19% account (5.85). The actual tax amount is # higher for the 19% case, though (1.11 compared to 0.82) - my $item1 = new_item(qty => 2.5); - my $item2 = new_item(qty => 1.2, part => $parts[1]); - my $invoice = new_invoice( + my $item1 = SL::Dev::Record::create_invoice_item(part => $parts[0], qty => 2.5); + my $item2 = SL::Dev::Record::create_invoice_item(part => $parts[1], qty => 1.2); + my $invoice = SL::Dev::Record::create_sales_invoice( taxincluded => 0, invoiceitems => [ $item1, $item2 ], - payment_id => $payment_terms->id, + payment_id => $payment_terms->id, ); - $invoice->post; $invoice->pay_invoice( amount => '19.42', payment_type => 'without_skonto', @@ -606,8 +617,8 @@ sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_fi transdate => DateTime->today_local->to_kivitendo ); - my ($number_of_payments, $paid_amount) = number_of_payments($invoice->transactions); - my $total = total_amount($invoice->transactions); + my ($number_of_payments, $paid_amount) = number_of_payments($invoice); + my $total = total_amount($invoice); my $title = 'default invoice, two items, 19/7% tax not included'; @@ -620,18 +631,17 @@ sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_fi } -sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto_2cent() { +sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto_2cent() { reset_state() if $ALWAYS_RESET; # if there are two cents left there will be two skonto bookings, 1 cent each - my $item1 = new_item(qty => 2.5); - my $item2 = new_item(qty => 1.2, part => $parts[1]); - my $invoice = new_invoice( + my $item1 = SL::Dev::Record::create_invoice_item(part => $parts[0], qty => 2.5); + my $item2 = SL::Dev::Record::create_invoice_item(part => $parts[1], qty => 1.2); + my $invoice = SL::Dev::Record::create_sales_invoice( taxincluded => 0, invoiceitems => [ $item1, $item2 ], - payment_id => $payment_terms->id, + payment_id => $payment_terms->id, ); - $invoice->post; $invoice->pay_invoice( amount => '19.42', payment_type => 'without_skonto', @@ -644,8 +654,8 @@ sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_fi transdate => DateTime->today_local->to_kivitendo ); - my ($number_of_payments, $paid_amount) = number_of_payments($invoice->transactions); - my $total = total_amount($invoice->transactions); + my ($number_of_payments, $paid_amount) = number_of_payments($invoice); + my $total = total_amount($invoice); my $title = 'default invoice, two items, 19/7% tax not included'; @@ -661,13 +671,12 @@ sub test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_fi sub test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto() { reset_state() if $ALWAYS_RESET; - my $item = new_item(qty => 2.5); - my $invoice = new_invoice( + my $item = SL::Dev::Record::create_invoice_item(part => $parts[0], qty => 2.5); + my $invoice = SL::Dev::Record::create_sales_invoice( taxincluded => 0, invoiceitems => [ $item ], payment_id => $payment_terms->id, ); - $invoice->post; # default values my %params = ( chart_id => $bank_account->chart_id, @@ -686,8 +695,8 @@ sub test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto $params{payment_type} = 'difference_as_skonto'; $invoice->pay_invoice( %params ); - my ($number_of_payments, $paid_amount) = number_of_payments($invoice->transactions); - my $total = total_amount($invoice->transactions); + my ($number_of_payments, $paid_amount) = number_of_payments($invoice); + my $total = total_amount($invoice); my $title = 'default invoice, one item, 19% tax, without_skonto'; @@ -703,13 +712,12 @@ sub test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto sub test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto_1cent() { reset_state() if $ALWAYS_RESET; - my $item = new_item(qty => 2.5); - my $invoice = new_invoice( + my $item = SL::Dev::Record::create_invoice_item(part => $parts[0], qty => 2.5); + my $invoice = SL::Dev::Record::create_sales_invoice( taxincluded => 0, invoiceitems => [ $item ], payment_id => $payment_terms->id, ); - $invoice->post; # default values my %params = ( chart_id => $bank_account->chart_id, @@ -724,8 +732,8 @@ sub test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto $params{payment_type} = 'difference_as_skonto'; $invoice->pay_invoice( %params ); - my ($number_of_payments, $paid_amount) = number_of_payments($invoice->transactions); - my $total = total_amount($invoice->transactions); + my ($number_of_payments, $paid_amount) = number_of_payments($invoice); + my $total = total_amount($invoice); my $title = 'default invoice, one item, 19% tax, without_skonto'; @@ -753,8 +761,8 @@ sub test_default_purchase_invoice_two_charts_19_7_without_skonto() { $purchase_invoice->pay_invoice( %params ); - my ($number_of_payments, $paid_amount) = number_of_payments($purchase_invoice->transactions); - my $total = total_amount($purchase_invoice->transactions); + my ($number_of_payments, $paid_amount) = number_of_payments($purchase_invoice); + my $total = total_amount($purchase_invoice); my $title = 'default invoice, two items, 19/7% tax without skonto'; @@ -778,8 +786,8 @@ sub test_default_purchase_invoice_two_charts_19_7_with_skonto() { $purchase_invoice->pay_invoice( %params ); - my ($number_of_payments, $paid_amount) = number_of_payments($purchase_invoice->transactions); - my $total = total_amount($purchase_invoice->transactions); + my ($number_of_payments, $paid_amount) = number_of_payments($purchase_invoice); + my $total = total_amount($purchase_invoice); my $title = 'default invoice, two items, 19/7% tax without skonto'; @@ -799,8 +807,8 @@ sub test_default_purchase_invoice_two_charts_19_7_tax_partial_unrounded_payment_ chart_id => $bank_account->chart_id, transdate => DateTime->today_local->to_kivitendo ); - my ($number_of_payments, $paid_amount) = number_of_payments($purchase_invoice->transactions); - my $total = total_amount($purchase_invoice->transactions); + my ($number_of_payments, $paid_amount) = number_of_payments($purchase_invoice); + my $total = total_amount($purchase_invoice); my $title = 'default purchase_invoice, two charts, 19/7% tax multiple payments with final difference as skonto'; @@ -834,8 +842,8 @@ sub test_default_purchase_invoice_two_charts_19_7_tax_without_skonto_multiple_pa transdate => DateTime->today_local->to_kivitendo ); - my ($number_of_payments, $paid_amount) = number_of_payments($purchase_invoice->transactions); - my $total = total_amount($purchase_invoice->transactions); + my ($number_of_payments, $paid_amount) = number_of_payments($purchase_invoice); + my $total = total_amount($purchase_invoice); my $title = 'default purchase_invoice, two charts, 19/7% tax multiple payments with final difference as skonto'; @@ -849,14 +857,13 @@ sub test_default_purchase_invoice_two_charts_19_7_tax_without_skonto_multiple_pa sub test_default_invoice_two_items_19_7_tax_with_skonto_50_50() { reset_state() if $ALWAYS_RESET; - my $item1 = new_item(qty => 1, part => $parts[2]); - my $item2 = new_item(qty => 1, part => $parts[3]); - my $invoice = new_invoice( + my $item1 = SL::Dev::Record::create_invoice_item(part => $parts[2], qty => 1); + my $item2 = SL::Dev::Record::create_invoice_item(part => $parts[3], qty => 1); + my $invoice = SL::Dev::Record::create_sales_invoice( taxincluded => 0, invoiceitems => [ $item1, $item2 ], - payment_id => $payment_terms->id, + payment_id => $payment_terms->id, ); - $invoice->post; # default values my %params = ( chart_id => $bank_account->chart_id, @@ -868,8 +875,8 @@ sub test_default_invoice_two_items_19_7_tax_with_skonto_50_50() { $invoice->pay_invoice( %params ); - my ($number_of_payments, $paid_amount) = number_of_payments($invoice->transactions); - my $total = total_amount($invoice->transactions); + my ($number_of_payments, $paid_amount) = number_of_payments($invoice); + my $total = total_amount($invoice); my $title = 'default invoice, two items, 19/7% tax with_skonto_pt 50/50'; @@ -885,16 +892,15 @@ sub test_default_invoice_two_items_19_7_tax_with_skonto_50_50() { sub test_default_invoice_four_items_19_7_tax_with_skonto_4x_25() { reset_state() if $ALWAYS_RESET; - my $item1 = new_item(qty => 0.5, part => $parts[2]); - my $item2 = new_item(qty => 0.5, part => $parts[3]); - my $item3 = new_item(qty => 0.5, part => $parts[2]); - my $item4 = new_item(qty => 0.5, part => $parts[3]); - my $invoice = new_invoice( + my $item1 = SL::Dev::Record::create_invoice_item(part => $parts[2], qty => 0.5); + my $item2 = SL::Dev::Record::create_invoice_item(part => $parts[3], qty => 0.5); + my $item3 = SL::Dev::Record::create_invoice_item(part => $parts[2], qty => 0.5); + my $item4 = SL::Dev::Record::create_invoice_item(part => $parts[3], qty => 0.5); + my $invoice = SL::Dev::Record::create_sales_invoice( taxincluded => 0, invoiceitems => [ $item1, $item2, $item3, $item4 ], - payment_id => $payment_terms->id, + payment_id => $payment_terms->id, ); - $invoice->post; # default values my %params = ( chart_id => $bank_account->chart_id, @@ -906,8 +912,8 @@ sub test_default_invoice_four_items_19_7_tax_with_skonto_4x_25() { $invoice->pay_invoice( %params ); - my ($number_of_payments, $paid_amount) = number_of_payments($invoice->transactions); - my $total = total_amount($invoice->transactions); + my ($number_of_payments, $paid_amount) = number_of_payments($invoice); + my $total = total_amount($invoice); my $title = 'default invoice, four items, 19/7% tax with_skonto_pt 4x25'; @@ -922,16 +928,15 @@ sub test_default_invoice_four_items_19_7_tax_with_skonto_4x_25() { sub test_default_invoice_four_items_19_7_tax_with_skonto_4x_25_tax_included() { reset_state() if $ALWAYS_RESET; - my $item1 = new_item(qty => 0.5, part => $parts[2]); - my $item2 = new_item(qty => 0.5, part => $parts[3]); - my $item3 = new_item(qty => 0.5, part => $parts[2]); - my $item4 = new_item(qty => 0.5, part => $parts[3]); - my $invoice = new_invoice( + my $item1 = SL::Dev::Record::create_invoice_item(part => $parts[2], qty => 0.5); + my $item2 = SL::Dev::Record::create_invoice_item(part => $parts[3], qty => 0.5); + my $item3 = SL::Dev::Record::create_invoice_item(part => $parts[2], qty => 0.5); + my $item4 = SL::Dev::Record::create_invoice_item(part => $parts[3], qty => 0.5); + my $invoice = SL::Dev::Record::create_sales_invoice( taxincluded => 1, invoiceitems => [ $item1, $item2, $item3, $item4 ], - payment_id => $payment_terms->id, + payment_id => $payment_terms->id, ); - $invoice->post; # default values my %params = ( chart_id => $bank_account->chart_id, @@ -943,8 +948,8 @@ sub test_default_invoice_four_items_19_7_tax_with_skonto_4x_25_tax_included() { $invoice->pay_invoice( %params ); - my ($number_of_payments, $paid_amount) = number_of_payments($invoice->transactions); - my $total = total_amount($invoice->transactions); + my ($number_of_payments, $paid_amount) = number_of_payments($invoice); + my $total = total_amount($invoice); my $title = 'default invoice, four items, 19/7% tax with_skonto_pt 4x25'; @@ -953,23 +958,23 @@ sub test_default_invoice_four_items_19_7_tax_with_skonto_4x_25_tax_included() { is($paid_amount, -100, "${title}: paid amount"); is($invoice->paid, 100, "${title}: paid"); is($number_of_payments, 3, "${title}: 3 AR_paid bookings"); -# currently this test fails because the code writing the invoice is buggy, the calculation of skonto is correct - is($total, 0, "${title}: even balance: this will fail due to rounding error in invoice post, not the skonto"); + { local $TODO = "currently this test fails because the code writing the invoice is buggy, the calculation of skonto is correct"; + is($total, 0, "${title}: even balance"); + } } sub test_default_invoice_four_items_19_7_tax_with_skonto_4x_25_multiple() { reset_state() if $ALWAYS_RESET; - my $item1 = new_item(qty => 0.5, part => $parts[2]); - my $item2 = new_item(qty => 0.5, part => $parts[3]); - my $item3 = new_item(qty => 0.5, part => $parts[2]); - my $item4 = new_item(qty => 0.5, part => $parts[3]); - my $invoice = new_invoice( + my $item1 = SL::Dev::Record::create_invoice_item(part => $parts[2], qty => 0.5); + my $item2 = SL::Dev::Record::create_invoice_item(part => $parts[3], qty => 0.5); + my $item3 = SL::Dev::Record::create_invoice_item(part => $parts[2], qty => 0.5); + my $item4 = SL::Dev::Record::create_invoice_item(part => $parts[3], qty => 0.5); + my $invoice = SL::Dev::Record::create_sales_invoice( taxincluded => 0, invoiceitems => [ $item1, $item2, $item3, $item4 ], - payment_id => $payment_terms->id, + payment_id => $payment_terms->id, ); - $invoice->post; $invoice->pay_invoice( amount => '90', payment_type => 'without_skonto', @@ -981,8 +986,8 @@ sub test_default_invoice_four_items_19_7_tax_with_skonto_4x_25_multiple() { transdate => DateTime->today_local->to_kivitendo ); - my ($number_of_payments, $paid_amount) = number_of_payments($invoice->transactions); - my $total = total_amount($invoice->transactions); + my ($number_of_payments, $paid_amount) = number_of_payments($invoice); + my $total = total_amount($invoice); my $title = 'default invoice, four items, 19/7% tax with_skonto_pt 4x25'; @@ -994,34 +999,461 @@ sub test_default_invoice_four_items_19_7_tax_with_skonto_4x_25_multiple() { is($total, 0, "${title}: even balance: this will fail due to rounding error in invoice post, not the skonto"); } +sub test_ar_currency_tax_not_included_and_payment { + my $netamount = $::form->round_amount(75 * $exchangerate->sell,2); # 75 in CUR, 100.00 in EUR + my $amount = $::form->round_amount($netamount * 1.19,2); # 100 in CUR, 119.00 in EUR + my $invoice = SL::DB::Invoice->new( + invoice => 0, + amount => $amount, + netamount => $netamount, + transdate => $transdate1, + taxincluded => 0, + customer_id => $customer->id, + taxzone_id => $customer->taxzone_id, + currency_id => $currency->id, + transactions => [], + notes => 'test_ar_currency_tax_not_included_and_payment', + ); + $invoice->add_ar_amount_row( + amount => $invoice->netamount, + chart => $ar_amount_chart, + tax_id => $tax->id, + ); + + $invoice->create_ar_row(chart => $ar_chart); + $invoice->save; + + is(SL::DB::Manager::Invoice->get_all_count(where => [ invoice => 0 ]), 1, 'there is one ar transaction'); + is($invoice->currency_id , $currency->id , 'currency_id has been saved'); + is($invoice->netamount , 100 , 'ar amount has been converted'); + is($invoice->amount , 119 , 'ar amount has been converted'); + is($invoice->taxincluded , 0 , 'ar transaction doesn\'t have taxincluded'); + is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ar_amount_chart->id, trans_id => $invoice->id)->amount, '100.00000', $ar_amount_chart->accno . ': has been converted for currency'); + is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ar_chart->id, trans_id => $invoice->id)->amount, '-119.00000', $ar_chart->accno . ': has been converted for currency'); + + $invoice->pay_invoice(chart_id => $bank->id, + amount => 50, + currency => 'CUR', + transdate => $transdate1->to_kivitendo, + ); + $invoice->pay_invoice(chart_id => $bank->id, + amount => 39.25, + currency => 'CUR', + transdate => $transdate1->to_kivitendo, + ); + # $invoice->pay_invoice(chart_id => $bank->id, + # amount => 30, + # transdate => $transdate2->to_kivitendo, + # ); + is(scalar @{$invoice->transactions}, 9, 'ar transaction has 9 transactions (incl. fxtransactions)'); + is($invoice->paid, $invoice->amount, 'ar transaction paid = amount in default currency'); +}; + +sub test_ar_currency_tax_included { + # we want the acc_trans amount to be 100 + my $amount = $::form->round_amount(75 * $exchangerate->sell * 1.19); + my $netamount = $::form->round_amount($amount / 1.19,2); + my $invoice = SL::DB::Invoice->new( + invoice => 0, + amount => 119, + netamount => 100, + transdate => $transdate1, + taxincluded => 1, + customer_id => $customer->id, + taxzone_id => $customer->taxzone_id, + currency_id => $currency->id, + notes => 'test_ar_currency_tax_included', + transactions => [], + ); + $invoice->add_ar_amount_row( # should take care of taxincluded + amount => $invoice->amount, # tax included in local currency + chart => $ar_amount_chart, + tax_id => $tax->id, + ); + + $invoice->create_ar_row( chart => $ar_chart ); + $invoice->save; + is(SL::DB::Manager::Invoice->get_all_count(where => [ invoice => 0 ]), 2, 'there are now two ar transactions'); + is($invoice->currency_id , $currency->id , 'currency_id has been saved'); + is($invoice->amount , $amount , 'amount ok'); + is($invoice->netamount , $netamount , 'netamount ok'); + is($invoice->taxincluded , 1 , 'ar transaction has taxincluded'); + is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ar_amount_chart->id, trans_id => $invoice->id)->amount, '100.00000', $ar_amount_chart->accno . ': has been converted for currency'); + is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ar_chart->id, trans_id => $invoice->id)->amount, '-119.00000', $ar_chart->accno . ': has been converted for currency'); + $invoice->pay_invoice(chart_id => $bank->id, + amount => 89.25, + currency => 'CUR', + transdate => $transdate1->to_kivitendo, + ); + +}; + +sub test_ap_currency_tax_not_included_and_payment { + my $netamount = $::form->round_amount(75 * $exchangerate->buy,2); # 75 in CUR, 100.00 in EUR + my $amount = $::form->round_amount($netamount * 1.19,2); # 100 in CUR, 119.00 in EUR + my $invoice = SL::DB::PurchaseInvoice->new( + invoice => 0, + invnumber => 'test_ap_currency_tax_not_included_and_payment', + amount => $amount, + netamount => $netamount, + transdate => $transdate1, + taxincluded => 0, + vendor_id => $vendor->id, + taxzone_id => $vendor->taxzone_id, + currency_id => $currency->id, + transactions => [], + notes => 'test_ap_currency_tax_not_included_and_payment', + ); + $invoice->add_ap_amount_row( + amount => $invoice->netamount, + chart => $ap_amount_chart, + tax_id => $tax_9->id, + ); + + $invoice->create_ap_row(chart => $ap_chart); + $invoice->save; + + is($invoice->currency_id, $currency->id, 'currency_id has been saved'); + is($invoice->netamount, 100, 'ap amount has been converted'); + is($invoice->amount, 119, 'ap amount has been converted'); + is($invoice->taxincluded, 0, 'ap transaction doesn\'t have taxincluded'); + is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ap_amount_chart->id, trans_id => $invoice->id)->amount, '-100.00000', $ap_amount_chart->accno . ': has been converted for currency'); + is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ap_chart->id, trans_id => $invoice->id)->amount, '119.00000', $ap_chart->accno . ': has been converted for currency'); + + $invoice->pay_invoice(chart_id => $bank->id, + amount => 50, + currency => 'CUR', + transdate => $transdate1->to_kivitendo, + ); + $invoice->pay_invoice(chart_id => $bank->id, + amount => 39.25, + currency => 'CUR', + transdate => $transdate1->to_kivitendo, + ); + is(scalar @{$invoice->transactions}, 9, 'ap transaction has 9 transactions (incl. fxtransactions)'); + is($invoice->paid, $invoice->amount, 'ap transaction paid = amount in default currency'); +}; + +sub test_ap_currency_tax_included { + # we want the acc_trans amount to be 100 + my $amount = $::form->round_amount(75 * $exchangerate->buy * 1.19); + my $netamount = $::form->round_amount($amount / 1.19,2); + my $invoice = SL::DB::PurchaseInvoice->new( + invoice => 0, + amount => 119, #$amount, + netamount => 100, #$netamount, + transdate => $transdate1, + taxincluded => 1, + vendor_id => $vendor->id, + taxzone_id => $vendor->taxzone_id, + currency_id => $currency->id, + notes => 'test_ap_currency_tax_included', + invnumber => 'test_ap_currency_tax_included', + transactions => [], + ); + $invoice->add_ap_amount_row( # should take care of taxincluded + amount => $invoice->amount, # tax included in local currency + chart => $ap_amount_chart, + tax_id => $tax_9->id, + ); + + $invoice->create_ap_row( chart => $ap_chart ); + $invoice->save; + is($invoice->currency_id , $currency->id , 'currency_id has been saved'); + is($invoice->amount , $amount , 'amount ok'); + is($invoice->netamount , $netamount , 'netamount ok'); + is($invoice->taxincluded , 1 , 'ap transaction has taxincluded'); + is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ap_amount_chart->id, trans_id => $invoice->id)->amount, '-100.00000', $ap_amount_chart->accno . ': has been converted for currency'); + is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ap_chart->id, trans_id => $invoice->id)->amount, '119.00000', $ap_chart->accno . ': has been converted for currency'); + + $invoice->pay_invoice(chart_id => $bank->id, + amount => 89.25, + currency => 'CUR', + transdate => $transdate1->to_kivitendo, + ); + +}; + +sub test_ar_currency_tax_not_included_and_payment_2 { + my $title = 'test_ar_currency_tax_not_included_and_payment_2'; + my $netamount = $::form->round_amount(125 * $exchangerate2->sell,2); # 125.00 in CUR, 100.00 in EUR + my $amount = $::form->round_amount($netamount * 1.19,2); # 148.75 in CUR, 119.00 in EUR + my $invoice = SL::DB::Invoice->new( + invoice => 0, + amount => $amount, + netamount => $netamount, + transdate => $transdate2, + taxincluded => 0, + customer_id => $customer->id, + taxzone_id => $customer->taxzone_id, + currency_id => $currency->id, + transactions => [], + notes => 'test_ar_currency_tax_not_included_and_payment 0.8', + invnumber => 'test_ar_currency_tax_not_included_and_payment 0.8', + ); + $invoice->add_ar_amount_row( + amount => $invoice->netamount, + chart => $ar_amount_chart, + tax_id => $tax->id, + ); + + $invoice->create_ar_row(chart => $ar_chart); + $invoice->save; + + is($invoice->currency_id , $currency->id , "$title: currency_id has been saved"); + is($invoice->netamount , 100 , "$title: ar amount has been converted"); + is($invoice->amount , 119 , "$title: ar amount has been converted"); + is($invoice->taxincluded , 0 , "$title: ar transaction doesn\"t have taxincluded"); + is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ar_amount_chart->id, trans_id => $invoice->id)->amount, '100.00000', $title . " " . $ar_amount_chart->accno . ": has been converted for currency"); + is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ar_chart->id, trans_id => $invoice->id)->amount, '-119.00000', $title . " " . $ar_chart->accno . ': has been converted for currency'); + + $invoice->pay_invoice(chart_id => $bank->id, + amount => 123.45, + currency => 'CUR', + transdate => $transdate2->to_kivitendo, + ); + $invoice->pay_invoice(chart_id => $bank->id, + amount => 15.30, + currency => 'CUR', + transdate => $transdate3->to_kivitendo, + ); + $invoice->pay_invoice(chart_id => $bank->id, + amount => 10.00, + currency => 'CUR', + transdate => $transdate4->to_kivitendo, + ); + # $invoice->pay_invoice(chart_id => $bank->id, + # amount => 30, + # transdate => $transdate2->to_kivitendo, + # ); + my $fx_transactions = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, fx_transaction => 1 ], sort_by => ('acc_trans_id')); + is(scalar @{$fx_transactions}, 3, "$title: ar transaction has 3 fx transactions"); + is($fx_transactions->[0]->amount, '24.69000', "$title fx transactions 1: 123.45-(123.45*0.8) = 24.69"); + + is(scalar @{$invoice->transactions}, 14, "$title ar transaction has 14 transactions (incl. fxtransactions and fx_gain)"); + is($invoice->paid, $invoice->amount, "$title ar transaction paid = amount in default currency"); +}; + +sub test_ar_currency_tax_not_included_and_payment_2_credit_note { + my $netamount = $::form->round_amount(-125 * $exchangerate2->sell,2); # 125.00 in CUR, 100.00 in EUR + my $amount = $::form->round_amount($netamount * 1.19,2); # 148.75 in CUR, 119.00 in EUR + my $invoice = SL::DB::Invoice->new( + invoice => 0, + amount => $amount, + netamount => $netamount, + transdate => $transdate2, + taxincluded => 0, + customer_id => $customer->id, + taxzone_id => $customer->taxzone_id, + currency_id => $currency->id, + transactions => [], + notes => 'test_ar_currency_tax_not_included_and_payment credit note 0.8', + invnumber => 'test_ar_currency_tax_not_included_and_payment credit note 0.8', + ); + $invoice->add_ar_amount_row( + amount => $invoice->netamount, + chart => $ar_amount_chart, + tax_id => $tax->id, + ); + + $invoice->create_ar_row(chart => $ar_chart); + $invoice->save; + + is($invoice->currency_id , $currency->id , 'currency_id has been saved'); + is($invoice->netamount , -100 , 'ar amount has been converted'); + is($invoice->amount , -119 , 'ar amount has been converted'); + is($invoice->taxincluded , 0 , 'ar transaction doesn\'t have taxincluded'); + is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ar_amount_chart->id, trans_id => $invoice->id)->amount, '-100.00000', $ar_amount_chart->accno . ': has been converted for currency'); + is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ar_chart->id, trans_id => $invoice->id)->amount, '119.00000', $ar_chart->accno . ': has been converted for currency'); + + $invoice->pay_invoice(chart_id => $bank->id, + amount => -123.45, + currency => 'CUR', + transdate => $transdate2->to_kivitendo, + ); + $invoice->pay_invoice(chart_id => $bank->id, + amount => -25.30, + currency => 'CUR', + transdate => $transdate2->to_kivitendo, + ); + my $fx_transactions = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, fx_transaction => 1 ], sort_by => ('acc_trans_id')); + is(scalar @{$fx_transactions}, 2, 'ar transaction has 2 fx transactions'); + is($fx_transactions->[0]->amount, '-24.69000', 'fx transactions 1: 123.45-(123.45*0.8) = 24.69'); + + is(scalar @{$invoice->transactions}, 9, 'ar transaction has 9 transactions (incl. fxtransactions)'); + is($invoice->paid, $invoice->amount, 'ar transaction paid = amount in default currency'); +}; + +sub test_ap_currency_tax_not_included_and_payment_2 { + my $title = 'test_ap_currency_tax_not_included_and_payment_2'; + my $netamount = $::form->round_amount(125 * $exchangerate2->sell,2); # 125.00 in CUR, 100.00 in EUR + my $amount = $::form->round_amount($netamount * 1.19,2); # 148.75 in CUR, 119.00 in EUR + my $invoice = SL::DB::PurchaseInvoice->new( + invoice => 0, + amount => $amount, + netamount => $netamount, + transdate => $transdate2, + taxincluded => 0, + vendor_id => $vendor->id, + taxzone_id => $vendor->taxzone_id, + currency_id => $currency->id, + transactions => [], + notes => 'test_ap_currency_tax_not_included_and_payment_2 0.8 + 1.33333', + invnumber => 'test_ap_currency_tax_not_included_and_payment_2 0.8 + 1.33333', + ); + $invoice->add_ap_amount_row( + amount => $invoice->netamount, + chart => $ap_amount_chart, + tax_id => $tax_9->id, + ); + + $invoice->create_ap_row(chart => $ap_chart); + $invoice->save; + + is($invoice->currency_id , $currency->id , "$title: currency_id has been saved"); + is($invoice->netamount , 100 , "$title: ap amount has been converted"); + is($invoice->amount , 119 , "$title: ap amount has been converted"); + is($invoice->taxincluded , 0 , "$title: ap transaction doesn\'t have taxincluded"); + is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ap_amount_chart->id, trans_id => $invoice->id)->amount, '-100.00000', $ap_amount_chart->accno . ': has been converted for currency'); + is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ap_chart->id, trans_id => $invoice->id)->amount, '119.00000', $ap_chart->accno . ': has been converted for currency'); + + $invoice->pay_invoice(chart_id => $bank->id, + amount => 10, + currency => 'CUR', + transdate => $transdate2->to_kivitendo, + ); + $invoice->pay_invoice(chart_id => $bank->id, + amount => 123.45, + currency => 'CUR', + transdate => $transdate3->to_kivitendo, + ); + $invoice->pay_invoice(chart_id => $bank->id, + amount => 15.30, + currency => 'CUR', + transdate => $transdate4->to_kivitendo, + ); + my $fx_transactions = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, fx_transaction => 1 ], sort_by => ('acc_trans_id')); + is(scalar @{$fx_transactions}, 3, "$title: ap transaction has 3 fx transactions"); + is($fx_transactions->[0]->amount, '-2.00000', "$title: fx transaction 1: 10.00-( 10.00*0.80000) = 2.00000"); + is($fx_transactions->[1]->amount, '68.59000', "$title: fx transaction 2: 123.45-(123.45*1.55557) = -68.58511"); + is($fx_transactions->[2]->amount, '-3.40000', "$title: fx transaction 3: 15.30-(15.30 *0.77777) = 3.40012"); + + my $fx_loss_transactions = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, chart_id => $fxloss_chart->id ], sort_by => ('acc_trans_id')); + my $fx_gain_transactions = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, chart_id => $fxgain_chart->id ], sort_by => ('acc_trans_id')); + is($fx_gain_transactions->[0]->amount, '0.34000', "$title: fx gain amount ok"); + is($fx_loss_transactions->[0]->amount, '-93.28000', "$title: fx loss amount ok"); + + is(scalar @{$invoice->transactions}, 14, "$title: ap transaction has 14 transactions (incl. fxtransactions and gain_loss)"); + is($invoice->paid, $invoice->amount, "$title: ap transaction paid = amount in default currency"); + is(total_amount($invoice), 0, "$title: even balance"); +}; + +sub test_ap_currency_tax_not_included_and_payment_2_credit_note { + my $title = 'test_ap_currency_tax_not_included_and_payment_2_credit_note'; + my $netamount = $::form->round_amount(-125 * $exchangerate2->sell,2); # 125.00 in CUR, 100.00 in EUR + my $amount = $::form->round_amount($netamount * 1.19,2); # 148.75 in CUR, 119.00 in EUR + my $invoice = SL::DB::PurchaseInvoice->new( + invoice => 0, + amount => $amount, + netamount => $netamount, + transdate => $transdate2, + taxincluded => 0, + vendor_id => $vendor->id, + taxzone_id => $vendor->taxzone_id, + currency_id => $currency->id, + transactions => [], + notes => 'test_ap_currency_tax_not_included_and_payment credit note 0.8 + 1.33333', + invnumber => 'test_ap_currency_tax_not_included_and_payment credit note 0.8 + 1.33333', + ); + $invoice->add_ap_amount_row( + amount => $invoice->netamount, + chart => $ap_amount_chart, + tax_id => $tax_9->id, + ); + + $invoice->create_ap_row(chart => $ap_chart); + $invoice->save; + + is($invoice->currency_id , $currency->id , "$title: currency_id has been saved"); + is($invoice->netamount , -100 , "$title: ap amount has been converted"); + is($invoice->amount , -119 , "$title: ap amount has been converted"); + is($invoice->taxincluded , 0 , "$title: ap transaction doesn\'t have taxincluded"); + is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ap_amount_chart->id, trans_id => $invoice->id)->amount, '100.00000', $ap_amount_chart->accno . ': has been converted for currency'); + is(SL::DB::Manager::AccTransaction->find_by(chart_id => $ap_chart->id, trans_id => $invoice->id)->amount, '-119.00000', $ap_chart->accno . ': has been converted for currency'); + + $invoice->pay_invoice(chart_id => $bank->id, + amount => -10, + currency => 'CUR', + transdate => $transdate2->to_kivitendo, + ); + $invoice->pay_invoice(chart_id => $bank->id, + amount => -123.45, + currency => 'CUR', + transdate => $transdate3->to_kivitendo, + ); + $invoice->pay_invoice(chart_id => $bank->id, + amount => -15.30, + currency => 'CUR', + transdate => $transdate4->to_kivitendo, + ); + my $fx_transactions = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, fx_transaction => 1 ], sort_by => ('acc_trans_id')); + is(scalar @{$fx_transactions}, 3, "$title: ap transaction has 3 fx transactions"); + is($fx_transactions->[0]->amount, '2.00000', "$title: fx transaction 1: 10.00-( 10.00*0.80000) = 2.00000"); + is($fx_transactions->[1]->amount, '-68.59000', "$title: fx transaction 2: 123.45-(123.45*1.55557) = -68.58511"); + is($fx_transactions->[2]->amount, '3.40000', "$title: fx transaction 3: 15.30-(15.30 *0.77777) = 3.40012"); + + my $fx_gain_loss_transactions = SL::DB::Manager::AccTransaction->get_all(where => [ trans_id => $invoice->id, chart_id => $fxgain_chart->id ], sort_by => ('acc_trans_id')); + is($fx_gain_loss_transactions->[0]->amount, '93.28000', "$title: fx gain loss amount ok"); + + is(scalar @{$invoice->transactions}, 14, "$title: ap transaction has 14 transactions (incl. fxtransactions and gain_loss)"); + is($invoice->paid, $invoice->amount, "$title: ap transaction paid = amount in default currency"); + is(total_amount($invoice), 0, "$title: even balance"); +}; + Support::TestSetup::login(); - # die; # test cases: without_skonto - test_default_invoice_one_item_19_without_skonto(); - test_default_invoice_two_items_19_7_tax_with_skonto(); - test_default_invoice_two_items_19_7_without_skonto(); - test_default_invoice_two_items_19_7_without_skonto_incomplete_payment(); - test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments(); - test_default_purchase_invoice_two_charts_19_7_without_skonto(); - test_default_purchase_invoice_two_charts_19_7_tax_partial_unrounded_payment_without_skonto(); - test_default_invoice_one_item_19_without_skonto_overpaid(); +test_default_invoice_one_item_19_without_skonto(); +test_default_invoice_two_items_19_7_tax_with_skonto(); +test_default_invoice_two_items_19_7_without_skonto(); +test_default_invoice_two_items_19_7_without_skonto_incomplete_payment(); +test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments(); +test_default_purchase_invoice_two_charts_19_7_without_skonto(); +test_default_purchase_invoice_two_charts_19_7_tax_partial_unrounded_payment_without_skonto(); +test_default_invoice_one_item_19_without_skonto_overpaid(); # test cases: difference_as_skonto - test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto(); - test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto_1cent(); - test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto_2cent(); - test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto(); - test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto_1cent(); - test_default_purchase_invoice_two_charts_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto(); +test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto(); +test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto_1cent(); +test_default_invoice_two_items_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto_2cent(); +test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto(); +test_default_invoice_one_item_19_multiple_payment_final_difference_as_skonto_1cent(); +test_default_purchase_invoice_two_charts_19_7_tax_without_skonto_multiple_payments_final_difference_as_skonto(); # test cases: with_skonto_pt - test_default_invoice_two_items_19_7_tax_with_skonto_50_50(); - test_default_invoice_four_items_19_7_tax_with_skonto_4x_25(); - test_default_invoice_four_items_19_7_tax_with_skonto_4x_25_multiple(); - test_default_purchase_invoice_two_charts_19_7_with_skonto(); - test_default_invoice_four_items_19_7_tax_with_skonto_4x_25_tax_included(); - test_default_invoice_two_items_19_7_tax_with_skonto_tax_included(); +test_default_invoice_two_items_19_7_tax_with_skonto_50_50(); +test_default_invoice_four_items_19_7_tax_with_skonto_4x_25(); +test_default_invoice_four_items_19_7_tax_with_skonto_4x_25_multiple(); +test_default_purchase_invoice_two_charts_19_7_with_skonto(); +test_default_invoice_four_items_19_7_tax_with_skonto_4x_25_tax_included(); +test_default_invoice_two_items_19_7_tax_with_skonto_tax_included(); + +# test payment of ar and ap transactions with currency and tax included/not included +# exchangerate = 1.33333 +test_ar_currency_tax_not_included_and_payment(); +test_ar_currency_tax_included(); +test_ap_currency_tax_not_included_and_payment(); +test_ap_currency_tax_included(); + +test_ar_currency_tax_not_included_and_payment_2(); # exchangerate 0.8 +test_ar_currency_tax_not_included_and_payment_2_credit_note(); # exchangerate 0.8 + +test_ap_currency_tax_not_included_and_payment_2(); # two exchangerates, with fx_gain_loss +test_ap_currency_tax_not_included_and_payment_2_credit_note(); # two exchangerates, with fx_gain_loss + +{ local $TODO = "currently this test fails because the code writing the invoice is buggy, the calculation of skonto is correct"; + my ($acc_trans_sum) = selectfirst_array_query($::form, $currency->db->dbh, 'SELECT SUM(amount) FROM acc_trans'); is($acc_trans_sum, '0.00000', "sum of all acc_trans is 0"); +} # remove all created data at end of test clear_up();