Neue Methoden um Debitorenbuchungen zu erstellen
[kivitendo-erp.git] / t / ar / ar.t
1 use strict;
2 use Test::More;
3
4 use lib 't';
5 use Support::TestSetup;
6 use Carp;
7 use Test::Exception;
8 use SL::DB::TaxZone;
9 use SL::DB::Buchungsgruppe;
10 use SL::DB::Currency;
11 use SL::DB::Customer;
12 use SL::DB::Employee;
13 use SL::DB::Invoice;
14 use SL::DATEV qw(:CONSTANTS);
15 use Data::Dumper;
16
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);
20 my $config = {};
21 $config->{numberformat} = '1.000,00';
22
23 sub reset_state {
24   my %params = @_;
25
26   $params{$_} ||= {} for qw(buchungsgruppe vendor customer ar_tax_19 ar_tax_7 ar_tax_0 );
27
28   clear_up();
29
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;
36
37   $customer   = SL::DB::Customer->new(
38     name        => 'Test Customer foo',
39     currency_id => $currency_id,
40     taxzone_id  => $taxzone->id,
41   )->save;
42
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
46
47 };
48
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;
74
75   $db->do_transaction( sub {
76
77   my $tax = SL::DB::Manager::Tax->find_by(taxkey => 0, rate => 0);
78
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   );
89
90   $invoice->create_ar_row( chart => $ar_chart );
91
92   _save_and_pay_and_check(invoice => $invoice, bank => $bank, pay => 1, check => 1);
93
94   }) || die "something went wrong: " . $db->error;
95   return $invoice->invnumber;
96 };
97
98 sub ar_with_tax {
99   my %params = @_;
100
101   my $amount       = $params{amount};
102   my $customer     = $params{customer};
103   my $date         = $params{date} || DateTime->today;
104   my $with_payment = $params{with_payment} || 0;
105
106   my $invoice = SL::DB::Invoice->new(
107       invoice          => 0,
108       amount           => $amount,
109       netamount        => $amount,
110       transdate        => $date,
111       taxincluded      => 'f',
112       customer_id      => $customer->id,
113       taxzone_id       => $customer->taxzone_id,
114       currency_id      => $customer->currency_id,
115       globalproject_id => $params{project},
116       notes            => $params{notes},
117       transactions     => [],
118   );
119
120   my $db = $invoice->db;
121
122   $db->do_transaction( sub {
123
124   # TODO: check for currency and exchange rate
125
126   my $tax = SL::DB::Manager::Tax->find_by(taxkey => 3, rate => 0.19 );
127   my $tax_id = $tax->id or die "can't find tax";
128
129   $invoice->add_ar_amount_row(
130     amount     => $amount / 2,
131     chart      => $ar_amount_chart,
132     tax_id     => $tax_id,
133   );
134   $invoice->add_ar_amount_row(
135     amount     => $amount / 2,
136     chart      => $ar_amount_chart,
137     tax_id     => $tax_id,
138   );
139
140   $invoice->create_ar_row( chart => $ar_chart );
141   _save_and_pay_and_check(invoice => $invoice, bank => $bank, pay => 1, check => 1);
142
143   }) || die "something went wrong: " . $db->error;
144   return $invoice->invnumber;
145 };
146
147 Support::TestSetup::login();
148
149 reset_state();
150
151 # check ar without tax
152 my $invnumber  = ar(customer => $customer, amount => 100, with_payment => 0 , notes => 'ar without tax');
153 my $inv = SL::DB::Manager::Invoice->find_by(invnumber => $invnumber);
154 my $number_of_acc_trans = scalar @{ $inv->transactions };
155 is($::form->round_amount($inv->amount), 100,  "invoice_amount = 100");
156 is($number_of_acc_trans, 5,  "number of transactions");
157 is($inv->datepaid->to_kivitendo, DateTime->today->to_kivitendo,  "datepaid");
158 is($inv->amount - $inv->paid, 0 ,  "paid = amount ");
159
160 # check ar with tax
161 my $invnumber2 = ar_with_tax(customer => $customer, amount => 200, with_payment => 0, notes => 'ar with taxincluded');
162 my $inv_with_tax = SL::DB::Manager::Invoice->find_by(invnumber => $invnumber2);
163 die unless $inv_with_tax;
164 is(scalar @{ $inv_with_tax->transactions } , 7,  "number of transactions for inv_with_tax");
165
166 # general checks
167 is(SL::DB::Manager::Invoice->get_all_count(), 2,  "total number of invoices created is 2");
168 done_testing;
169
170 clear_up();
171
172 1;
173
174 sub clear_up {
175   SL::DB::Manager::AccTransaction->delete_all(all => 1);
176   SL::DB::Manager::Invoice->delete_all(       all => 1);
177   SL::DB::Manager::Customer->delete_all(      all => 1);
178 };
179
180 sub _save_and_pay_and_check {
181   my %params = @_;
182   my $invoice = $params{invoice};
183   my $datev_check = 1;
184
185   my $return = $invoice->save;
186
187   $invoice->pay_invoice(chart_id     => $params{bank}->id,
188                         amount       => $invoice->amount,
189                         transdate    => $invoice->transdate->to_kivitendo,
190                         payment_type => 'without_skonto',  # default if not specified
191                        ) if $params{pay};
192
193   if ($datev_check) {
194     my $datev = SL::DATEV->new(
195       exporttype => DATEV_ET_BUCHUNGEN,
196       format     => DATEV_FORMAT_KNE,
197       dbh        => $invoice->db->dbh,
198       trans_id   => $invoice->id,
199     );
200
201     $datev->export;
202     if ($datev->errors) {
203       $invoice->db->dbh->rollback;
204       die join "\n", $::locale->text('DATEV check returned errors:'), $datev->errors;
205     }
206   };
207 };