kivitendo/t/fxtransaction/ap_transactions.t @ cd4586b8
c7a5335e | Sven Schöling | use strict;
|
||
use lib 't';
|
||||
use Test::More;
|
||||
use SL::Controller::BankTransaction;
|
||||
use SL::DB::AccTransaction;
|
||||
use SL::DB::BankTransaction;
|
||||
use SL::DB::BankTransactionAccTrans;
|
||||
use SL::DB::Chart;
|
||||
use SL::DB::Currency;
|
||||
use SL::DB::Employee;
|
||||
use SL::DB::Exchangerate;
|
||||
use SL::DB::InvoiceItem;
|
||||
use SL::DB::PurchaseInvoice;
|
||||
use SL::DB::TaxZone;
|
||||
use SL::DB::ValidityToken;
|
||||
use SL::Dev::CustomerVendor qw(:ALL);
|
||||
use SL::Dev::Part qw(:ALL);
|
||||
use SL::Dev::Payment qw(:ALL);
|
||||
use SL::Form;
|
||||
use SL::Helper::Number qw(_format_number);
|
||||
use SL::InstanceConfiguration;
|
||||
use HTML::Query;
|
||||
use Support::TestSetup;
|
||||
9866d032 | Sven Schöling | use Support::Integration;
|
||
c7a5335e | Sven Schöling | |||
my $part;
|
||||
my $vendor;
|
||||
my $usd;
|
||||
my $taxzone;
|
||||
my $fxgain;
|
||||
my $fxloss;
|
||||
my $payment_terms;
|
||||
my $dt;
|
||||
sub reset_db {
|
||||
SL::DB::Manager::BankTransactionAccTrans->delete_all(all => 1);
|
||||
SL::DB::Manager::BankTransaction->delete_all(all => 1);
|
||||
SL::DB::Manager::AccTransaction->delete_all(all => 1);
|
||||
SL::DB::Manager::InvoiceItem->delete_all(all => 1);
|
||||
SL::DB::Manager::PurchaseInvoice->delete_all(all => 1);
|
||||
SL::DB::Manager::Exchangerate->delete_all(all => 1);
|
||||
$usd->delete;
|
||||
$vendor->delete;
|
||||
$part->delete;
|
||||
$payment_terms->delete;
|
||||
}
|
||||
sub init_db {
|
||||
SL::DB::Manager::Exchangerate->delete_all(all => 1);
|
||||
$vendor = new_vendor->save;
|
||||
$part = new_part->save;
|
||||
$usd = SL::DB::Manager::Currency->find_by(name => 'USD') // SL::DB::Currency->new(name => 'USD')->save;
|
||||
$taxzone = SL::DB::Manager::TaxZone->find_by( description => 'Inland');
|
||||
$fxgain = SL::DB::Manager::Chart->find_by(accno => '2660');
|
||||
$fxloss = SL::DB::Manager::Chart->find_by(accno => '2150');
|
||||
$payment_terms = create_payment_terms();
|
||||
$dt = DateTime->new(year => 1999, month => 1, day => 12);
|
||||
SL::DB::Default->get->update_attributes(
|
||||
fxgain_accno_id => $fxgain->id,
|
||||
fxloss_accno_id => $fxloss->id,
|
||||
)->load;
|
||||
# reload
|
||||
$::instance_conf = SL::InstanceConfiguration->new;
|
||||
}
|
||||
######## main test code #######
|
||||
Support::TestSetup::login();
|
||||
9866d032 | Sven Schöling | Support::Integration::setup();
|
||
c7a5335e | Sven Schöling | init_db();
|
||
{
|
||||
my $description = "simple purchase invoice";
|
||||
# vendor 1
|
||||
# part 1
|
||||
my $currency = 'USD';
|
||||
my $exchangerate = 2.5;
|
||||
my $payment_exchangerate = 1.5;
|
||||
my %form;
|
||||
# make new invoice
|
||||
9866d032 | Sven Schöling | my ($out, $err, @ret) = make_request('ir', 'add', type => 'invoice');
|
||
c7a5335e | Sven Schöling | is $ret[0], 1, "new purchase invoice";
|
||
%form = form_from_html($out);
|
||||
# set invnumber and currency
|
||||
$form{invnumber} = $description;
|
||||
$form{currency} = $currency;
|
||||
# update
|
||||
9866d032 | Sven Schöling | ($out, $err, @ret) = make_request('ir', 'update', %form);
|
||
c7a5335e | Sven Schöling | is $ret[0], 1, "update purchase invoice with currency";
|
||
%form = form_from_html($out);
|
||||
# set part and exchangerate
|
||||
$form{exchangerate} = _format_number($exchangerate, -2);
|
||||
$form{partnumber_1} = $part->partnumber;
|
||||
# update
|
||||
9866d032 | Sven Schöling | ($out, $err, @ret) = make_request('ir', 'update', %form);
|
||
c7a5335e | Sven Schöling | is $ret[0], 1, "update purchase invoice with part and exchangerate";
|
||
%form = form_from_html($out);
|
||||
# now set par, exchangerate and payments - this will cause the part to be loaded with the lastcost translated into USD
|
||||
$form{paid_1} = _format_number($part->lastcost / $exchangerate, -2); # lastcost = 5€ = 2$
|
||||
$form{exchangerate_1} = _format_number($payment_exchangerate, -2);
|
||||
9866d032 | Sven Schöling | ($out, $err, @ret) = make_request('ir', 'post', %form);
|
||
c7a5335e | Sven Schöling | is $ret[0], 1, "posting '$description' does not generate error";
|
||
warn $err if $err;
|
||||
ok $out =~ /ir\.pl\?action=edit&id=(\d+)/, "posting '$description' returns redirect to id";
|
||||
my $id = $1;
|
||||
9866d032 | Sven Schöling | ($out, $err, @ret) = make_request('ir', 'edit', id => $id );
|
||
c7a5335e | Sven Schöling | is $ret[0], 1, "'$description' did not cause an error";
|
||
warn $err if $err;
|
||||
my $q = HTML::Query->new(text => $out);
|
||||
is $q->query('input[name=paid_1]')->size, 1, "out '$description' contains paid_1";
|
||||
is $q->query('input[name=paid_1]')->first->attr('value'), '2,00', "out '$description' paid_1 is 2,00 (the dollar amount, not the internal 5.00€)";
|
||||
is $q->query('#ui-tabs-basic-data tr.invtotal th')->first->as_text, 'Summe', "'$description' - total present";
|
||||
is $q->query('#ui-tabs-basic-data tr.invtotal td')->first->as_text, '2,38', "'$description' - total should be 2.00 * 1.19 = 2.38";
|
||||
is $q->query('#ui-tabs-basic-data input[name=oldtotalpaid]')->first->attr('value'), '2', "'$description' - totalpaid should be 2,00 in dollar, not the internal value";
|
||||
};
|
||||
{
|
||||
my $description = "ap transaction from redmine #563";
|
||||
# 20 on 4710 Verpackungsmaterial
|
||||
# 20 payment on 1000 kasse
|
||||
my $currency = 'USD';
|
||||
my $exchangerate = 1.1;
|
||||
my $payment_exchangerate = 1.3;
|
||||
my $chart = SL::DB::Manager::Chart->find_by(accno => '4710');
|
||||
my %form;
|
||||
# make new ap transaction
|
||||
9866d032 | Sven Schöling | my ($out, $err, @ret) = make_request('ap', 'add');
|
||
c7a5335e | Sven Schöling | is $ret[0], 1, "new ap transaction";
|
||
%form = form_from_html($out);
|
||||
# set chart, amount, currency, invnumber
|
||||
$form{AP_amount_chart_id_1} = $chart->id;
|
||||
$form{amount_1} = 20;
|
||||
$form{currency} = 'USD';
|
||||
$form{invnumber} = $description;
|
||||
# make new ap transaction
|
||||
9866d032 | Sven Schöling | ($out, $err, @ret) = make_request('ap', 'update', %form);
|
||
c7a5335e | Sven Schöling | is $ret[0], 1, "update ap transaction with currency";
|
||
%form = form_from_html($out);
|
||||
# add exchangerate and payments
|
||||
$form{paid_1} = 20;
|
||||
$form{exchangerate} = _format_number($exchangerate, -2);
|
||||
$form{exchangerate_1} = _format_number($payment_exchangerate, -2);
|
||||
9866d032 | Sven Schöling | ($out, $err, @ret) = make_request('ap', 'post', %form);
|
||
c7a5335e | Sven Schöling | is $ret[0], 1, "posting '$description' did not cause an error";
|
||
my $invoice = SL::DB::Manager::PurchaseInvoice->find_by(invnumber => $description);
|
||||
ok $invoice, "posting '$description' can be found in the database";
|
||||
9866d032 | Sven Schöling | ($out, $err, @ret) = make_request('ap', 'edit', id => $invoice->id);
|
||
c7a5335e | Sven Schöling | is $ret[0], 1, "loading '$description' did not cause an error";
|
||
warn $err if $err;
|
||||
my $q = HTML::Query->new(text => $out);
|
||||
is $q->query('input[name=paid_1]')->size, 1, "out '$description' contains paid_1";
|
||||
is $q->query('input[name=paid_1]')->first->attr('value'), '20,00', "out '$description' paid_1 is 20 (the dollar amount, not the internal amount)";
|
||||
}
|
||||
{
|
||||
my $testname = 'ap_transaction_fx_gain_fees';
|
||||
my $usd_amount = 83300;
|
||||
my $fx_rate = 2;
|
||||
my $fx_rate_bank = 1.75;
|
||||
my $eur_amount = $usd_amount * $fx_rate;
|
||||
my $netamount = $eur_amount;
|
||||
my $amount = $eur_amount;
|
||||
my $buysell = 'sell';
|
||||
my $eur_payment = $usd_amount * $fx_rate_bank;
|
||||
my $usd_payment = $eur_payment / $fx_rate_bank; # for rounding issues
|
||||
my $bank = SL::DB::Manager::Chart->find_by(description => 'Bank');
|
||||
my $bank_account = SL::DB::Manager::BankAccount->find_by(chart_id => $bank->id) // SL::DB::BankAccount->new(
|
||||
account_number => '123',
|
||||
bank_code => '123',
|
||||
iban => '123',
|
||||
bic => '123',
|
||||
bank => '123',
|
||||
chart_id => $bank->id,
|
||||
name => $bank->description,
|
||||
)->save;
|
||||
my $ex = SL::DB::Manager::Exchangerate->find_by(currency_id => $usd->id, transdate => $dt)
|
||||
|| SL::DB::Exchangerate->new(currency_id => $usd->id, transdate => $dt);
|
||||
$ex->update_attributes($buysell => $fx_rate);
|
||||
my $ap_chart = SL::DB::Manager::Chart->get_first(query => [ link => 'AP' ], sort_by => 'accno');
|
||||
my $ap_amount_chart = SL::DB::Manager::Chart->get_first(query => [ link => 'AP_amount' ], sort_by => 'accno');
|
||||
my $invoice = SL::DB::PurchaseInvoice->new(
|
||||
invoice => 0,
|
||||
invnumber => $testname,
|
||||
amount => $amount,
|
||||
netamount => $netamount,
|
||||
transdate => $dt,
|
||||
taxincluded => 0,
|
||||
vendor_id => $vendor->id,
|
||||
taxzone_id => $vendor->taxzone_id,
|
||||
currency_id => $usd->id,
|
||||
transactions => [],
|
||||
notes => 'ap_transaction_fx',
|
||||
);
|
||||
$invoice->add_ap_amount_row(
|
||||
amount => $netamount,
|
||||
chart => $ap_amount_chart,
|
||||
tax_id => 0,
|
||||
);
|
||||
$invoice->create_ap_row(chart => $ap_chart);
|
||||
$invoice->save;
|
||||
my $ap_transaction_fx = $invoice;
|
||||
# check exchangerate
|
||||
is($ap_transaction_fx->currency->name , 'USD' , "$testname: USD currency");
|
||||
is($ap_transaction_fx->get_exchangerate , '2.00000' , "$testname: fx rate record");
|
||||
my $bt = create_bank_transaction(record => $ap_transaction_fx,
|
||||
bank_chart_id => $bank->id,
|
||||
transdate => $dt,
|
||||
valutadate => $dt,
|
||||
amount => $eur_payment,
|
||||
exchangerate => $fx_rate_bank,
|
||||
) or die "Couldn't create bank_transaction";
|
||||
local $::form = Form->new;
|
||||
$::form->{invoice_ids} = {
|
||||
$bt->id => [ $ap_transaction_fx->id ]
|
||||
};
|
||||
$::form->{"book_fx_bank_fees_" . $bt->id . "_" . $ap_transaction_fx->id} = 1;
|
||||
$::form->{"exchangerate_" . $bt->id . "_" . $ap_transaction_fx->id} = "1,75"; # will be parsed
|
||||
$::form->{"currency_id_" . $bt->id . "_" . $ap_transaction_fx->id} = $usd->id;
|
||||
my ($stdout, $stderr, @result);
|
||||
{
|
||||
open(my $out_fh, '>', \$stdout) or die;
|
||||
open(my $err_fh, '>', \$stderr) or die;
|
||||
local *STDOUT = $out_fh;
|
||||
local *STDERR = $err_fh;
|
||||
my $bt_controller = SL::Controller::BankTransaction->new;
|
||||
@result = $bt_controller->action_save_invoices;
|
||||
};
|
||||
ok !$stderr, "ap_transaction '$testname' can be booked with BackTransaction controller";
|
||||
$invoice = SL::DB::Manager::PurchaseInvoice->find_by(invnumber => $testname);
|
||||
# now load with old code
|
||||
9866d032 | Sven Schöling | my ($out, $err, @ret) = make_request('ap', 'edit', id => $invoice->id);
|
||
c7a5335e | Sven Schöling | is $ret[0], 1, "loading '$testname' did not cause an error";
|
||
warn $err if $err;
|
||||
my $q = HTML::Query->new(text => $out);
|
||||
is $q->query('input[name=paid_1]')->size, 1, "out '$testname' contains paid_1";
|
||||
is $q->query('input[name=paid_1]')->first->attr('value'), _format_number($usd_payment, -2), "out '$testname' paid_1 is $usd_payment (the dollar amount, not the internal amount)";
|
||||
}
|
||||
reset_db();
|
||||
done_testing();
|
||||
1;
|