Revision 2d1f1f89
Von G. Richardson vor mehr als 6 Jahren hinzugefügt
t/ar/ar.t | ||
---|---|---|
1 | 1 |
use strict; |
2 |
use Test::More; |
|
2 |
use Test::More tests => 6;
|
|
3 | 3 |
|
4 | 4 |
use lib 't'; |
5 | 5 |
use Support::TestSetup; |
6 | 6 |
use Carp; |
7 | 7 |
use Test::Exception; |
8 |
use SL::DB::TaxZone; |
|
9 |
use SL::DB::Buchungsgruppe; |
|
10 |
use SL::DB::Currency; |
|
11 | 8 |
use SL::DB::Customer; |
12 | 9 |
use SL::DB::Employee; |
13 | 10 |
use SL::DB::Invoice; |
14 | 11 |
use SL::DATEV qw(:CONSTANTS); |
12 |
use SL::Dev::CustomerVendor qw(new_customer); |
|
15 | 13 |
use Data::Dumper; |
16 | 14 |
|
17 |
|
|
18 |
my ($i, $customer, $vendor, $currency_id, @parts, $buchungsgruppe, $buchungsgruppe7, $unit, $employee, $ar_tax_19, $ar_tax_7,$ar_tax_0, $taxzone); |
|
19 |
my ($ar_chart,$bank,$ar_amount_chart); |
|
15 |
my ($customer, $employee, $ar_tax_19, $ar_tax_7, $ar_tax_0); |
|
16 |
my ($ar_chart, $bank, $ar_amount_chart); |
|
20 | 17 |
my $config = {}; |
21 | 18 |
$config->{numberformat} = '1.000,00'; |
22 | 19 |
|
23 | 20 |
sub reset_state { |
24 | 21 |
my %params = @_; |
25 | 22 |
|
26 |
$params{$_} ||= {} for qw(buchungsgruppe vendor customer ar_tax_19 ar_tax_7 ar_tax_0 );
|
|
23 |
$params{$_} ||= {} for qw(buchungsgruppe customer);
|
|
27 | 24 |
|
28 | 25 |
clear_up(); |
29 | 26 |
|
30 |
$employee = SL::DB::Manager::Employee->current || croak "No employee"; |
|
31 |
$taxzone = SL::DB::Manager::TaxZone->find_by( description => 'Inland') || croak "No taxzone"; # only needed for setting customer/vendor |
|
32 |
$ar_tax_19 = SL::DB::Manager::Tax->find_by(taxkey => 3, rate => 0.19, %{ $params{ar_tax_19} }) || croak "No 19% tax"; |
|
33 |
$ar_tax_7 = SL::DB::Manager::Tax->find_by(taxkey => 2, rate => 0.07, %{ $params{ar_tax_7} }) || croak "No 7% tax"; |
|
34 |
$ar_tax_0 = SL::DB::Manager::Tax->find_by(taxkey => 0, rate => 0.00, %{ $params{ar_tax_0} }) || croak "No 0% tax"; |
|
35 |
$currency_id = $::instance_conf->get_currency_id; |
|
27 |
$employee = SL::DB::Manager::Employee->current || croak "No employee"; |
|
28 |
$ar_tax_19 = SL::DB::Manager::Tax->find_by(taxkey => 3, rate => 0.19) || croak "No 19% tax"; |
|
29 |
$ar_tax_7 = SL::DB::Manager::Tax->find_by(taxkey => 2, rate => 0.07) || croak "No 7% tax"; |
|
30 |
$ar_tax_0 = SL::DB::Manager::Tax->find_by(taxkey => 0, rate => 0.00) || croak "No 0% tax"; |
|
36 | 31 |
|
37 |
$customer = SL::DB::Customer->new( |
|
38 |
name => 'Test Customer foo', |
|
39 |
currency_id => $currency_id, |
|
40 |
taxzone_id => $taxzone->id, |
|
41 |
)->save; |
|
32 |
$customer = new_customer()->save; # new customer with default name "Testkunde" |
|
42 | 33 |
|
43 |
$ar_chart = SL::DB::Manager::Chart->find_by( accno => '1400' ); # Forderungen
|
|
44 |
$bank = SL::DB::Manager::Chart->find_by( accno => '1200' ); # Bank
|
|
45 |
$ar_amount_chart = SL::DB::Manager::Chart->find_by( accno => '8590' ); # verrechn., eigentlich Anzahlungen
|
|
34 |
$ar_chart = SL::DB::Manager::Chart->find_by(accno => '1400') || croak "Can't find Forderungen";
|
|
35 |
$bank = SL::DB::Manager::Chart->find_by(accno => '1200') || croak "Can't find Bank";
|
|
36 |
$ar_amount_chart = SL::DB::Manager::Chart->find_by(accno => '8590') || croak "Can't find verrechn., eigentlich Anzahlungen";
|
|
46 | 37 |
|
47 | 38 |
}; |
48 | 39 |
|
49 |
sub ar { |
|
50 |
reset_state; |
|
51 |
my %params = @_; |
|
52 |
|
|
53 |
my $amount = $params{amount}; |
|
54 |
my $customer = $params{customer}; |
|
55 |
my $date = $params{date} || DateTime->today; |
|
56 |
my $with_payment = $params{with_payment} || 0; |
|
57 |
|
|
58 |
# SL::DB::Invoice has a _before_save_set_invnumber hook, so we don't need to pass invnumber |
|
59 |
my $invoice = SL::DB::Invoice->new( |
|
60 |
invoice => 0, |
|
61 |
amount => $amount, |
|
62 |
netamount => $amount, |
|
63 |
transdate => $date, |
|
64 |
taxincluded => 'f', |
|
65 |
customer_id => $customer->id, |
|
66 |
taxzone_id => $customer->taxzone_id, |
|
67 |
currency_id => $customer->currency_id, |
|
68 |
globalproject_id => $params{project}, |
|
69 |
notes => $params{notes}, |
|
70 |
transactions => [], |
|
71 |
); |
|
72 |
|
|
73 |
my $db = $invoice->db; |
|
40 |
Support::TestSetup::login(); |
|
74 | 41 |
|
75 |
$db->with_transaction( sub {
|
|
42 |
reset_state();
|
|
76 | 43 |
|
77 |
my $tax = SL::DB::Manager::Tax->find_by(taxkey => 0, rate => 0); |
|
44 |
# check ar without tax |
|
45 |
my $invoice = _ar(customer => $customer, |
|
46 |
amount => 100, |
|
47 |
with_payment => 1, |
|
48 |
notes => 'ar without tax', |
|
49 |
); |
|
50 |
|
|
51 |
# for testing load a fresh instance of the invoice from the database |
|
52 |
my $inv = SL::DB::Invoice->new(id => $invoice->id)->load; |
|
53 |
if ( $inv ) { |
|
54 |
my $number_of_acc_trans = scalar @{ $inv->transactions }; |
|
55 |
is($::form->round_amount($inv->amount) , 100 , "invoice_amount = 100"); |
|
56 |
is($number_of_acc_trans , 5 , "number of transactions"); |
|
57 |
is($inv->datepaid->to_kivitendo , DateTime->today->to_kivitendo , "datepaid"); |
|
58 |
is($inv->amount - $inv->paid , 0 , "paid = amount "); |
|
59 |
} else { |
|
60 |
ok 0, "couldn't find first invoice"; |
|
61 |
} |
|
78 | 62 |
|
79 |
$invoice->add_ar_amount_row( |
|
80 |
amount => $amount / 2, |
|
81 |
chart => $ar_amount_chart, |
|
82 |
tax_id => $tax->id, |
|
83 |
); |
|
84 |
$invoice->add_ar_amount_row( |
|
85 |
amount => $amount / 2, |
|
86 |
chart => $ar_amount_chart, |
|
87 |
tax_id => $tax->id, |
|
88 |
); |
|
63 |
# check ar with tax |
|
64 |
my $invoice2 = _ar_with_tax(customer => $customer, |
|
65 |
amount => 200, |
|
66 |
with_payment => 1, |
|
67 |
notes => 'ar with taxincluded', |
|
68 |
); |
|
69 |
my $inv_with_tax = SL::DB::Invoice->new(id => $invoice2->id)->load; |
|
70 |
if ( $inv_with_tax ) { |
|
71 |
is(scalar @{ $inv_with_tax->transactions }, 7, "number of transactions for inv_with_tax"); |
|
72 |
} else { |
|
73 |
ok 0, "couldn't find second invoice"; |
|
74 |
} |
|
89 | 75 |
|
90 |
$invoice->create_ar_row( chart => $ar_chart ); |
|
76 |
# general checks |
|
77 |
is(SL::DB::Manager::Invoice->get_all_count(), 2, "total number of invoices created is 2"); |
|
91 | 78 |
|
92 |
_save_and_pay_and_check(invoice => $invoice, bank => $bank, pay => 1, check => 1); |
|
79 |
done_testing; |
|
80 |
clear_up(); |
|
93 | 81 |
|
94 |
1;
|
|
82 |
1; |
|
95 | 83 |
|
96 |
}) || die "something went wrong: " . $db->error; |
|
97 |
return $invoice->invnumber; |
|
84 |
sub clear_up { |
|
85 |
SL::DB::Manager::AccTransaction->delete_all(all => 1); |
|
86 |
SL::DB::Manager::Invoice->delete_all( all => 1); |
|
87 |
SL::DB::Manager::Customer->delete_all( all => 1); |
|
98 | 88 |
}; |
99 | 89 |
|
100 |
sub ar_with_tax {
|
|
90 |
sub _ar {
|
|
101 | 91 |
my %params = @_; |
102 | 92 |
|
103 |
my $amount = $params{amount}; |
|
104 |
my $customer = $params{customer}; |
|
105 |
my $date = $params{date} || DateTime->today; |
|
93 |
my $amount = $params{amount} || croak "ar needs param amount";
|
|
94 |
my $customer = $params{customer} || croak "ar needs param customer";
|
|
95 |
my $date = $params{date} || DateTime->today;
|
|
106 | 96 |
my $with_payment = $params{with_payment} || 0; |
107 | 97 |
|
98 |
# SL::DB::Invoice has a _before_save_set_invnumber hook, so we don't need to pass invnumber |
|
108 | 99 |
my $invoice = SL::DB::Invoice->new( |
109 | 100 |
invoice => 0, |
110 | 101 |
amount => $amount, |
... | ... | |
123 | 114 |
|
124 | 115 |
$db->with_transaction( sub { |
125 | 116 |
|
126 |
# TODO: check for currency and exchange rate |
|
117 |
$invoice->add_ar_amount_row( |
|
118 |
amount => $amount / 2, |
|
119 |
chart => $ar_amount_chart, |
|
120 |
tax_id => $ar_tax_0->id, |
|
121 |
); |
|
122 |
$invoice->add_ar_amount_row( |
|
123 |
amount => $amount / 2, |
|
124 |
chart => $ar_amount_chart, |
|
125 |
tax_id => $ar_tax_0->id, |
|
126 |
); |
|
127 | 127 |
|
128 |
my $tax = SL::DB::Manager::Tax->find_by(taxkey => 3, rate => 0.19 ); |
|
129 |
my $tax_id = $tax->id or die "can't find tax"; |
|
128 |
$invoice->create_ar_row( chart => $ar_chart ); |
|
130 | 129 |
|
131 |
$invoice->add_ar_amount_row( |
|
132 |
amount => $amount / 2, |
|
133 |
chart => $ar_amount_chart, |
|
134 |
tax_id => $tax_id, |
|
135 |
); |
|
136 |
$invoice->add_ar_amount_row( |
|
137 |
amount => $amount / 2, |
|
138 |
chart => $ar_amount_chart, |
|
139 |
tax_id => $tax_id, |
|
140 |
); |
|
130 |
_save_and_pay_and_check(invoice => $invoice, |
|
131 |
bank => $bank, |
|
132 |
pay => $with_payment, |
|
133 |
datev_check => 1, |
|
134 |
); |
|
141 | 135 |
|
142 |
$invoice->create_ar_row( chart => $ar_chart ); |
|
143 |
_save_and_pay_and_check(invoice => $invoice, bank => $bank, pay => 1, check => 1); |
|
136 |
1; |
|
144 | 137 |
|
145 |
1; |
|
146 | 138 |
}) || die "something went wrong: " . $db->error; |
147 |
return $invoice->invnumber;
|
|
139 |
return $invoice; |
|
148 | 140 |
}; |
149 | 141 |
|
150 |
Support::TestSetup::login(); |
|
142 |
sub _ar_with_tax { |
|
143 |
my %params = @_; |
|
151 | 144 |
|
152 |
reset_state(); |
|
145 |
my $amount = $params{amount} || croak "ar needs param amount"; |
|
146 |
my $customer = $params{customer} || croak "ar needs param customer"; |
|
147 |
my $date = $params{date} || DateTime->today; |
|
148 |
my $with_payment = $params{with_payment} || 0; |
|
153 | 149 |
|
154 |
# check ar without tax |
|
155 |
my $invnumber = ar(customer => $customer, amount => 100, with_payment => 0 , notes => 'ar without tax'); |
|
156 |
my $inv = SL::DB::Manager::Invoice->find_by(invnumber => $invnumber); |
|
157 |
my $number_of_acc_trans = scalar @{ $inv->transactions }; |
|
158 |
is($::form->round_amount($inv->amount), 100, "invoice_amount = 100"); |
|
159 |
is($number_of_acc_trans, 5, "number of transactions"); |
|
160 |
is($inv->datepaid->to_kivitendo, DateTime->today->to_kivitendo, "datepaid"); |
|
161 |
is($inv->amount - $inv->paid, 0 , "paid = amount "); |
|
150 |
my $invoice = SL::DB::Invoice->new( |
|
151 |
invoice => 0, |
|
152 |
amount => $amount, |
|
153 |
netamount => $amount, |
|
154 |
transdate => $date, |
|
155 |
taxincluded => 'f', |
|
156 |
customer_id => $customer->id, |
|
157 |
taxzone_id => $customer->taxzone_id, |
|
158 |
currency_id => $customer->currency_id, |
|
159 |
globalproject_id => $params{project}, |
|
160 |
notes => $params{notes}, |
|
161 |
transactions => [], |
|
162 |
); |
|
162 | 163 |
|
163 |
# check ar with tax |
|
164 |
my $invnumber2 = ar_with_tax(customer => $customer, amount => 200, with_payment => 0, notes => 'ar with taxincluded'); |
|
165 |
my $inv_with_tax = SL::DB::Manager::Invoice->find_by(invnumber => $invnumber2); |
|
166 |
die unless $inv_with_tax; |
|
167 |
is(scalar @{ $inv_with_tax->transactions } , 7, "number of transactions for inv_with_tax"); |
|
164 |
my $db = $invoice->db; |
|
168 | 165 |
|
169 |
# general checks |
|
170 |
is(SL::DB::Manager::Invoice->get_all_count(), 2, "total number of invoices created is 2"); |
|
171 |
done_testing; |
|
166 |
$db->with_transaction( sub { |
|
172 | 167 |
|
173 |
clear_up();
|
|
168 |
# TODO: check for currency and exchange rate
|
|
174 | 169 |
|
175 |
1; |
|
170 |
$invoice->add_ar_amount_row( |
|
171 |
amount => $amount / 2, |
|
172 |
chart => $ar_amount_chart, |
|
173 |
tax_id => $ar_tax_19->id, |
|
174 |
); |
|
175 |
$invoice->add_ar_amount_row( |
|
176 |
amount => $amount / 2, |
|
177 |
chart => $ar_amount_chart, |
|
178 |
tax_id => $ar_tax_19->id, |
|
179 |
); |
|
176 | 180 |
|
177 |
sub clear_up { |
|
178 |
SL::DB::Manager::AccTransaction->delete_all(all => 1); |
|
179 |
SL::DB::Manager::Invoice->delete_all( all => 1); |
|
180 |
SL::DB::Manager::Customer->delete_all( all => 1); |
|
181 |
$invoice->create_ar_row( chart => $ar_chart ); |
|
182 |
_save_and_pay_and_check(invoice => $invoice, |
|
183 |
bank => $bank, |
|
184 |
pay => $with_payment, |
|
185 |
datev_check => 1, |
|
186 |
); |
|
187 |
|
|
188 |
1; |
|
189 |
}) || die "something went wrong: " . $db->error; |
|
190 |
return $invoice; |
|
181 | 191 |
}; |
182 | 192 |
|
183 | 193 |
sub _save_and_pay_and_check { |
184 | 194 |
my %params = @_; |
185 |
my $invoice = $params{invoice}; |
|
186 |
my $datev_check = 1; |
|
195 |
my $invoice = $params{invoice} // croak "invoice missing"; |
|
196 |
my $datev_check = $params{datev_check} // 1; # do datev check by default |
|
197 |
croak "no bank" unless ref $params{bank} eq 'SL::DB::Chart'; |
|
187 | 198 |
|
199 |
# make sure invoice is saved before making payments |
|
188 | 200 |
my $return = $invoice->save; |
189 | 201 |
|
190 | 202 |
$invoice->pay_invoice(chart_id => $params{bank}->id, |
... | ... | |
201 | 213 |
|
202 | 214 |
$datev->generate_datev_data; |
203 | 215 |
|
216 |
# _save_and_pay_and_check should always be called inside a with_transaction block |
|
204 | 217 |
if ($datev->errors) { |
205 | 218 |
$invoice->db->dbh->rollback; |
206 | 219 |
die join "\n", $::locale->text('DATEV check returned errors:'), $datev->errors; |
Auch abrufbar als: Unified diff
t/ar/ar.t aufgeräumt und Refactoring