kivitendo/t/ar/ar.t @ d56bda45
4f43ec85 | Geoffrey Richardson | use strict;
|
||
df183815 | Geoffrey Richardson | use Test::More tests => 7;
|
||
4f43ec85 | Geoffrey Richardson | |||
use lib 't';
|
||||
use Support::TestSetup;
|
||||
use Carp;
|
||||
use Test::Exception;
|
||||
use SL::DB::Customer;
|
||||
use SL::DB::Employee;
|
||||
use SL::DB::Invoice;
|
||||
use SL::DATEV qw(:CONSTANTS);
|
||||
2d1f1f89 | Geoffrey Richardson | use SL::Dev::CustomerVendor qw(new_customer);
|
||
4f43ec85 | Geoffrey Richardson | use Data::Dumper;
|
||
2d1f1f89 | Geoffrey Richardson | my ($customer, $employee, $ar_tax_19, $ar_tax_7, $ar_tax_0);
|
||
my ($ar_chart, $bank, $ar_amount_chart);
|
||||
4f43ec85 | Geoffrey Richardson | my $config = {};
|
||
$config->{numberformat} = '1.000,00';
|
||||
sub reset_state {
|
||||
my %params = @_;
|
||||
2d1f1f89 | Geoffrey Richardson | $params{$_} ||= {} for qw(buchungsgruppe customer);
|
||
4f43ec85 | Geoffrey Richardson | |||
clear_up();
|
||||
2d1f1f89 | Geoffrey Richardson | $employee = SL::DB::Manager::Employee->current || croak "No employee";
|
||
$ar_tax_19 = SL::DB::Manager::Tax->find_by(taxkey => 3, rate => 0.19) || croak "No 19% tax";
|
||||
$ar_tax_7 = SL::DB::Manager::Tax->find_by(taxkey => 2, rate => 0.07) || croak "No 7% tax";
|
||||
$ar_tax_0 = SL::DB::Manager::Tax->find_by(taxkey => 0, rate => 0.00) || croak "No 0% tax";
|
||||
4f43ec85 | Geoffrey Richardson | |||
2d1f1f89 | Geoffrey Richardson | $customer = new_customer()->save; # new customer with default name "Testkunde"
|
||
4f43ec85 | Geoffrey Richardson | |||
2d1f1f89 | Geoffrey Richardson | $ar_chart = SL::DB::Manager::Chart->find_by(accno => '1400') || croak "Can't find Forderungen";
|
||
$bank = SL::DB::Manager::Chart->find_by(accno => '1200') || croak "Can't find Bank";
|
||||
$ar_amount_chart = SL::DB::Manager::Chart->find_by(accno => '8590') || croak "Can't find verrechn., eigentlich Anzahlungen";
|
||||
4f43ec85 | Geoffrey Richardson | |||
};
|
||||
2d1f1f89 | Geoffrey Richardson | Support::TestSetup::login();
|
||
4f43ec85 | Geoffrey Richardson | |||
2d1f1f89 | Geoffrey Richardson | reset_state();
|
||
4f43ec85 | Geoffrey Richardson | |||
2d1f1f89 | Geoffrey Richardson | # check ar without tax
|
||
my $invoice = _ar(customer => $customer,
|
||||
amount => 100,
|
||||
with_payment => 1,
|
||||
notes => 'ar without tax',
|
||||
);
|
||||
# for testing load a fresh instance of the invoice from the database
|
||||
my $inv = SL::DB::Invoice->new(id => $invoice->id)->load;
|
||||
if ( $inv ) {
|
||||
my $number_of_acc_trans = scalar @{ $inv->transactions };
|
||||
is($::form->round_amount($inv->amount) , 100 , "invoice_amount = 100");
|
||||
is($number_of_acc_trans , 5 , "number of transactions");
|
||||
is($inv->datepaid->to_kivitendo , DateTime->today->to_kivitendo , "datepaid");
|
||||
is($inv->amount - $inv->paid , 0 , "paid = amount ");
|
||||
df183815 | Geoffrey Richardson | is($inv->gldate->to_kivitendo, $inv->transactions->[0]->gldate->to_kivitendo, "gldate matches in ar and acc_trans");
|
||
2d1f1f89 | Geoffrey Richardson | } else {
|
||
ok 0, "couldn't find first invoice";
|
||||
}
|
||||
4f43ec85 | Geoffrey Richardson | |||
2d1f1f89 | Geoffrey Richardson | # check ar with tax
|
||
my $invoice2 = _ar_with_tax(customer => $customer,
|
||||
amount => 200,
|
||||
with_payment => 1,
|
||||
notes => 'ar with taxincluded',
|
||||
);
|
||||
my $inv_with_tax = SL::DB::Invoice->new(id => $invoice2->id)->load;
|
||||
if ( $inv_with_tax ) {
|
||||
is(scalar @{ $inv_with_tax->transactions }, 7, "number of transactions for inv_with_tax");
|
||||
} else {
|
||||
ok 0, "couldn't find second invoice";
|
||||
}
|
||||
4f43ec85 | Geoffrey Richardson | |||
2d1f1f89 | Geoffrey Richardson | # general checks
|
||
is(SL::DB::Manager::Invoice->get_all_count(), 2, "total number of invoices created is 2");
|
||||
4f43ec85 | Geoffrey Richardson | |||
2d1f1f89 | Geoffrey Richardson | done_testing;
|
||
clear_up();
|
||||
4f43ec85 | Geoffrey Richardson | |||
2d1f1f89 | Geoffrey Richardson | 1;
|
||
96670fe8 | Moritz Bunkus | |||
2d1f1f89 | Geoffrey Richardson | sub clear_up {
|
||
SL::DB::Manager::AccTransaction->delete_all(all => 1);
|
||||
SL::DB::Manager::Invoice->delete_all( all => 1);
|
||||
SL::DB::Manager::Customer->delete_all( all => 1);
|
||||
4f43ec85 | Geoffrey Richardson | };
|
||
2d1f1f89 | Geoffrey Richardson | sub _ar {
|
||
4f43ec85 | Geoffrey Richardson | my %params = @_;
|
||
2d1f1f89 | Geoffrey Richardson | my $amount = $params{amount} || croak "ar needs param amount";
|
||
my $customer = $params{customer} || croak "ar needs param customer";
|
||||
df183815 | Geoffrey Richardson | my $transdate = $params{transdate} || DateTime->today;
|
||
my $gldate = $params{gldate} || DateTime->today->add(days => 1);
|
||||
4f43ec85 | Geoffrey Richardson | my $with_payment = $params{with_payment} || 0;
|
||
2d1f1f89 | Geoffrey Richardson | # SL::DB::Invoice has a _before_save_set_invnumber hook, so we don't need to pass invnumber
|
||
4f43ec85 | Geoffrey Richardson | my $invoice = SL::DB::Invoice->new(
|
||
invoice => 0,
|
||||
amount => $amount,
|
||||
netamount => $amount,
|
||||
df183815 | Geoffrey Richardson | transdate => $transdate,
|
||
gldate => $gldate,
|
||||
4f43ec85 | Geoffrey Richardson | taxincluded => 'f',
|
||
customer_id => $customer->id,
|
||||
taxzone_id => $customer->taxzone_id,
|
||||
currency_id => $customer->currency_id,
|
||||
globalproject_id => $params{project},
|
||||
notes => $params{notes},
|
||||
transactions => [],
|
||||
);
|
||||
my $db = $invoice->db;
|
||||
96670fe8 | Moritz Bunkus | $db->with_transaction( sub {
|
||
4f43ec85 | Geoffrey Richardson | |||
2d1f1f89 | Geoffrey Richardson | $invoice->add_ar_amount_row(
|
||
amount => $amount / 2,
|
||||
chart => $ar_amount_chart,
|
||||
tax_id => $ar_tax_0->id,
|
||||
);
|
||||
$invoice->add_ar_amount_row(
|
||||
amount => $amount / 2,
|
||||
chart => $ar_amount_chart,
|
||||
tax_id => $ar_tax_0->id,
|
||||
);
|
||||
4f43ec85 | Geoffrey Richardson | |||
2d1f1f89 | Geoffrey Richardson | $invoice->create_ar_row( chart => $ar_chart );
|
||
4f43ec85 | Geoffrey Richardson | |||
2d1f1f89 | Geoffrey Richardson | _save_and_pay_and_check(invoice => $invoice,
|
||
bank => $bank,
|
||||
pay => $with_payment,
|
||||
datev_check => 1,
|
||||
);
|
||||
4f43ec85 | Geoffrey Richardson | |||
2d1f1f89 | Geoffrey Richardson | 1;
|
||
4f43ec85 | Geoffrey Richardson | |||
}) || die "something went wrong: " . $db->error;
|
||||
2d1f1f89 | Geoffrey Richardson | return $invoice;
|
||
4f43ec85 | Geoffrey Richardson | };
|
||
2d1f1f89 | Geoffrey Richardson | sub _ar_with_tax {
|
||
my %params = @_;
|
||||
4f43ec85 | Geoffrey Richardson | |||
2d1f1f89 | Geoffrey Richardson | my $amount = $params{amount} || croak "ar needs param amount";
|
||
my $customer = $params{customer} || croak "ar needs param customer";
|
||||
df183815 | Geoffrey Richardson | my $transdate = $params{transdate} || DateTime->today;
|
||
my $gldate = $params{gldate} || DateTime->today->add(days => 1);
|
||||
2d1f1f89 | Geoffrey Richardson | my $with_payment = $params{with_payment} || 0;
|
||
4f43ec85 | Geoffrey Richardson | |||
2d1f1f89 | Geoffrey Richardson | my $invoice = SL::DB::Invoice->new(
|
||
invoice => 0,
|
||||
amount => $amount,
|
||||
netamount => $amount,
|
||||
df183815 | Geoffrey Richardson | transdate => $transdate,
|
||
gldate => $gldate,
|
||||
2d1f1f89 | Geoffrey Richardson | taxincluded => 'f',
|
||
customer_id => $customer->id,
|
||||
taxzone_id => $customer->taxzone_id,
|
||||
currency_id => $customer->currency_id,
|
||||
globalproject_id => $params{project},
|
||||
notes => $params{notes},
|
||||
transactions => [],
|
||||
);
|
||||
4f43ec85 | Geoffrey Richardson | |||
2d1f1f89 | Geoffrey Richardson | my $db = $invoice->db;
|
||
4f43ec85 | Geoffrey Richardson | |||
2d1f1f89 | Geoffrey Richardson | $db->with_transaction( sub {
|
||
4f43ec85 | Geoffrey Richardson | |||
2d1f1f89 | Geoffrey Richardson | # TODO: check for currency and exchange rate
|
||
4f43ec85 | Geoffrey Richardson | |||
2d1f1f89 | Geoffrey Richardson | $invoice->add_ar_amount_row(
|
||
amount => $amount / 2,
|
||||
chart => $ar_amount_chart,
|
||||
tax_id => $ar_tax_19->id,
|
||||
);
|
||||
$invoice->add_ar_amount_row(
|
||||
amount => $amount / 2,
|
||||
chart => $ar_amount_chart,
|
||||
tax_id => $ar_tax_19->id,
|
||||
);
|
||||
4f43ec85 | Geoffrey Richardson | |||
2d1f1f89 | Geoffrey Richardson | $invoice->create_ar_row( chart => $ar_chart );
|
||
_save_and_pay_and_check(invoice => $invoice,
|
||||
bank => $bank,
|
||||
pay => $with_payment,
|
||||
datev_check => 1,
|
||||
);
|
||||
1;
|
||||
}) || die "something went wrong: " . $db->error;
|
||||
return $invoice;
|
||||
4f43ec85 | Geoffrey Richardson | };
|
||
sub _save_and_pay_and_check {
|
||||
my %params = @_;
|
||||
2d1f1f89 | Geoffrey Richardson | my $invoice = $params{invoice} // croak "invoice missing";
|
||
my $datev_check = $params{datev_check} // 1; # do datev check by default
|
||||
croak "no bank" unless ref $params{bank} eq 'SL::DB::Chart';
|
||||
4f43ec85 | Geoffrey Richardson | |||
2d1f1f89 | Geoffrey Richardson | # make sure invoice is saved before making payments
|
||
4f43ec85 | Geoffrey Richardson | my $return = $invoice->save;
|
||
$invoice->pay_invoice(chart_id => $params{bank}->id,
|
||||
amount => $invoice->amount,
|
||||
transdate => $invoice->transdate->to_kivitendo,
|
||||
payment_type => 'without_skonto', # default if not specified
|
||||
) if $params{pay};
|
||||
if ($datev_check) {
|
||||
my $datev = SL::DATEV->new(
|
||||
dbh => $invoice->db->dbh,
|
||||
trans_id => $invoice->id,
|
||||
);
|
||||
0a64ac3d | Geoffrey Richardson | $datev->generate_datev_data;
|
||
2d1f1f89 | Geoffrey Richardson | # _save_and_pay_and_check should always be called inside a with_transaction block
|
||
4f43ec85 | Geoffrey Richardson | if ($datev->errors) {
|
||
$invoice->db->dbh->rollback;
|
||||
die join "\n", $::locale->text('DATEV check returned errors:'), $datev->errors;
|
||||
}
|
||||
};
|
||||
};
|