7 use SL::Controller::BankTransaction;
8 use SL::DB::AccTransaction;
9 use SL::DB::BankTransaction;
10 use SL::DB::BankTransactionAccTrans;
14 use SL::DB::Exchangerate;
15 use SL::DB::InvoiceItem;
16 use SL::DB::PurchaseInvoice;
18 use SL::DB::ValidityToken;
19 use SL::Dev::CustomerVendor qw(:ALL);
20 use SL::Dev::Part qw(:ALL);
21 use SL::Dev::Payment qw(:ALL);
23 use SL::Helper::Number qw(_format_number);
24 use SL::InstanceConfiguration;
27 use Support::TestSetup;
28 use Support::Integration;
40 SL::DB::Manager::BankTransactionAccTrans->delete_all(all => 1);
41 SL::DB::Manager::BankTransaction->delete_all(all => 1);
42 SL::DB::Manager::AccTransaction->delete_all(all => 1);
43 SL::DB::Manager::InvoiceItem->delete_all(all => 1);
44 SL::DB::Manager::PurchaseInvoice->delete_all(all => 1);
45 SL::DB::Manager::Exchangerate->delete_all(all => 1);
49 $payment_terms->delete;
53 SL::DB::Manager::Exchangerate->delete_all(all => 1);
54 $vendor = new_vendor->save;
55 $part = new_part->save;
56 $usd = SL::DB::Manager::Currency->find_by(name => 'USD') // SL::DB::Currency->new(name => 'USD')->save;
57 $taxzone = SL::DB::Manager::TaxZone->find_by( description => 'Inland');
58 $fxgain = SL::DB::Manager::Chart->find_by(accno => '2660');
59 $fxloss = SL::DB::Manager::Chart->find_by(accno => '2150');
60 $payment_terms = create_payment_terms();
61 $dt = DateTime->new(year => 1999, month => 1, day => 12);
64 SL::DB::Default->get->update_attributes(
65 fxgain_accno_id => $fxgain->id,
66 fxloss_accno_id => $fxloss->id,
69 $::instance_conf = SL::InstanceConfiguration->new;
73 ######## main test code #######
75 Support::TestSetup::login();
76 Support::Integration::setup();
80 my $description = "simple purchase invoice";
84 my $exchangerate = 2.5;
85 my $payment_exchangerate = 1.5;
90 my ($out, $err, @ret) = make_request('ir', 'add', type => 'invoice');
91 is $ret[0], 1, "new purchase invoice";
92 %form = form_from_html($out);
94 # set invnumber and currency
95 $form{invnumber} = $description;
96 $form{currency} = $currency;
99 ($out, $err, @ret) = make_request('ir', 'update', %form);
100 is $ret[0], 1, "update purchase invoice with currency";
101 %form = form_from_html($out);
103 # set part and exchangerate
104 $form{exchangerate} = _format_number($exchangerate, -2);
105 $form{partnumber_1} = $part->partnumber;
108 ($out, $err, @ret) = make_request('ir', 'update', %form);
109 is $ret[0], 1, "update purchase invoice with part and exchangerate";
110 %form = form_from_html($out);
112 # now set par, exchangerate and payments - this will cause the part to be loaded with the lastcost translated into USD
113 $form{paid_1} = _format_number($part->lastcost / $exchangerate, -2); # lastcost = 5€ = 2$
114 $form{exchangerate_1} = _format_number($payment_exchangerate, -2);
116 ($out, $err, @ret) = make_request('ir', 'post', %form);
117 is $ret[0], 1, "posting '$description' does not generate error";
119 ok $out =~ /ir\.pl\?action=edit&id=(\d+)/, "posting '$description' returns redirect to id";
122 ($out, $err, @ret) = make_request('ir', 'edit', id => $id );
123 is $ret[0], 1, "'$description' did not cause an error";
126 my $q = HTML::Query->new(text => $out);
127 is $q->query('input[name=paid_1]')->size, 1, "out '$description' contains paid_1";
128 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€)";
130 is $q->query('#ui-tabs-basic-data tr.invtotal th')->first->as_text, 'Summe', "'$description' - total present";
131 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";
132 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";
136 my $description = "ap transaction from redmine #563";
137 # 20 on 4710 Verpackungsmaterial
138 # 20 payment on 1000 kasse
139 my $currency = 'USD';
140 my $exchangerate = 1.1;
141 my $payment_exchangerate = 1.3;
142 my $chart = SL::DB::Manager::Chart->find_by(accno => '4710');
145 # make new ap transaction
146 my ($out, $err, @ret) = make_request('ap', 'add');
147 is $ret[0], 1, "new ap transaction";
148 %form = form_from_html($out);
150 # set chart, amount, currency, invnumber
151 $form{AP_amount_chart_id_1} = $chart->id;
152 $form{amount_1} = 20;
153 $form{currency} = 'USD';
154 $form{invnumber} = $description;
156 # make new ap transaction
157 ($out, $err, @ret) = make_request('ap', 'update', %form);
158 is $ret[0], 1, "update ap transaction with currency";
159 %form = form_from_html($out);
161 # add exchangerate and payments
163 $form{exchangerate} = _format_number($exchangerate, -2);
164 $form{exchangerate_1} = _format_number($payment_exchangerate, -2);
166 ($out, $err, @ret) = make_request('ap', 'post', %form);
167 is $ret[0], 1, "posting '$description' did not cause an error";
169 my $invoice = SL::DB::Manager::PurchaseInvoice->find_by(invnumber => $description);
170 ok $invoice, "posting '$description' can be found in the database";
172 ($out, $err, @ret) = make_request('ap', 'edit', id => $invoice->id);
173 is $ret[0], 1, "loading '$description' did not cause an error";
176 my $q = HTML::Query->new(text => $out);
177 is $q->query('input[name=paid_1]')->size, 1, "out '$description' contains paid_1";
178 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)";
182 my $testname = 'ap_transaction_fx_gain_fees';
183 my $usd_amount = 83300;
185 my $fx_rate_bank = 1.75;
186 my $eur_amount = $usd_amount * $fx_rate;
188 my $netamount = $eur_amount;
189 my $amount = $eur_amount;
190 my $buysell = 'sell';
191 my $eur_payment = $usd_amount * $fx_rate_bank;
192 my $usd_payment = $eur_payment / $fx_rate_bank; # for rounding issues
194 my $bank = SL::DB::Manager::Chart->find_by(description => 'Bank');
195 my $bank_account = SL::DB::Manager::BankAccount->find_by(chart_id => $bank->id) // SL::DB::BankAccount->new(
196 account_number => '123',
201 chart_id => $bank->id,
202 name => $bank->description,
205 my $ex = SL::DB::Manager::Exchangerate->find_by(currency_id => $usd->id, transdate => $dt)
206 || SL::DB::Exchangerate->new(currency_id => $usd->id, transdate => $dt);
207 $ex->update_attributes($buysell => $fx_rate);
209 my $ap_chart = SL::DB::Manager::Chart->get_first(query => [ link => 'AP' ], sort_by => 'accno');
210 my $ap_amount_chart = SL::DB::Manager::Chart->get_first(query => [ link => 'AP_amount' ], sort_by => 'accno');
211 my $invoice = SL::DB::PurchaseInvoice->new(
213 invnumber => $testname,
215 netamount => $netamount,
218 vendor_id => $vendor->id,
219 taxzone_id => $vendor->taxzone_id,
220 currency_id => $usd->id,
222 notes => 'ap_transaction_fx',
224 $invoice->add_ap_amount_row(
225 amount => $netamount,
226 chart => $ap_amount_chart,
230 $invoice->create_ap_row(chart => $ap_chart);
232 my $ap_transaction_fx = $invoice;
235 is($ap_transaction_fx->currency->name , 'USD' , "$testname: USD currency");
236 is($ap_transaction_fx->get_exchangerate , '2.00000' , "$testname: fx rate record");
237 my $bt = create_bank_transaction(record => $ap_transaction_fx,
238 bank_chart_id => $bank->id,
241 amount => $eur_payment,
242 exchangerate => $fx_rate_bank,
243 ) or die "Couldn't create bank_transaction";
245 local $::form = Form->new;
246 $::form->{invoice_ids} = {
247 $bt->id => [ $ap_transaction_fx->id ]
249 $::form->{"book_fx_bank_fees_" . $bt->id . "_" . $ap_transaction_fx->id} = 1;
250 $::form->{"exchangerate_" . $bt->id . "_" . $ap_transaction_fx->id} = "1,75"; # will be parsed
251 $::form->{"currency_id_" . $bt->id . "_" . $ap_transaction_fx->id} = $usd->id;
253 my ($stdout, $stderr, @result);
255 open(my $out_fh, '>', \$stdout) or die;
256 open(my $err_fh, '>', \$stderr) or die;
258 local *STDOUT = $out_fh;
259 local *STDERR = $err_fh;
260 my $bt_controller = SL::Controller::BankTransaction->new;
261 @result = $bt_controller->action_save_invoices;
263 ok !$stderr, "ap_transaction '$testname' can be booked with BackTransaction controller";
265 $invoice = SL::DB::Manager::PurchaseInvoice->find_by(invnumber => $testname);
267 # now load with old code
268 my ($out, $err, @ret) = make_request('ap', 'edit', id => $invoice->id);
269 is $ret[0], 1, "loading '$testname' did not cause an error";
272 my $q = HTML::Query->new(text => $out);
273 is $q->query('input[name=paid_1]')->size, 1, "out '$testname' contains paid_1";
274 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)";