]> wagnertech.de Git - mfinanz.git/blob - t/model/records.t
date error in mapping
[mfinanz.git] / t / model / records.t
1 use Test::More;
2 use Test::Exception;
3
4 use strict;
5
6 use lib 't';
7 use utf8;
8
9 use Carp;
10 use Data::Dumper;
11 use Support::TestSetup;
12 use Test::Exception;
13 use List::Util qw(pairs);
14
15 use SL::DB::PaymentTerm;
16 use SL::DB::DeliveryTerm;
17 use SL::DB::Employee;
18 use SL::DB::ReclamationReason;
19 use SL::Model::Record;
20
21 use SL::Dev::ALL qw(:ALL);
22
23 my ($customer, $vendor, $employee, $payment_term, $delivery_term, @parts, $reclamation_reason);
24 my ($dbh);
25
26 my ($sales_quotation1,    $sales_order1,    $sales_invoice1,    $sales_delivery_order1,    $sales_reclamation1);
27 my ($purchase_quotation1, $purchase_order1, $purchase_invoice1, $purchase_delivery_order1, $purchase_reclamation1);
28
29 Support::TestSetup::login();
30 $dbh = SL::DB->client->dbh;
31
32 # set locale to en so we can match errors
33 local $::locale = Locale->new('en');
34
35 note "testing deletions";
36 reset_state();
37 reset_basic_sales_records();
38 reset_basic_purchase_records();
39
40 is(SL::DB::Manager::Order->get_all_count(
41     where => [ or  => ['record_type'  => 'sales_quotation', 'record_type'  => 'request_quotation' ]]),
42   2, 'number of quotations before delete ok');
43 is(SL::DB::Manager::Order->get_all_count(
44     where => [ and => ['!record_type' => 'sales_quotation', '!record_type' => 'request_quotation' ]]),
45   2, 'number of orders before delete ok');
46 is(SL::DB::Manager::DeliveryOrder->get_all_count(), 2, 'number of delivery orders before delete ok');
47 is(SL::DB::Manager::Reclamation->get_all_count(), 2, 'number of reclamations before delete ok');
48 # is(SL::DB::Manager::Invoice->get_all_count(), 1, 'number of invoices before delete ok'); # no purchase_invoice was created
49
50 foreach my $record ( ($sales_quotation1,
51                       $sales_order1,
52                       $sales_reclamation1,
53                       $purchase_quotation1,
54                       $purchase_order1,
55                       $purchase_reclamation1
56                      )
57                    ) {
58
59   my $delete_return  = SL::Model::Record->delete($record);
60   my $record_history = SL::DB::Manager::History->find_by(trans_id => $record->id, addition => 'DELETED');
61   # just test if snumbers contains "_", not whether it actually is correct
62   ok($record_history->snumbers =~ m/_/, "history snumbers of record " . $record_history->snumbers . " ok");
63 };
64
65 is(SL::DB::Manager::Order->get_all_count(
66     where => [ or  => ['record_type'  => 'sales_quotation', 'record_type'  => 'request_quotation' ]]),
67   0, 'number of quotations after delete ok');
68 is(SL::DB::Manager::Order->get_all_count(
69     where => [ and => ['!record_type' => 'sales_quotation', '!record_type' => 'request_quotation' ]]),
70   0, 'number of orders after delete ok');
71 # is(SL::DB::Manager::Invoice->get_all_count(), 0, 'number of invoices after delete ok');
72 is(SL::DB::Manager::Reclamation->get_all_count(), 0, 'number of orders after delete ok');
73
74 note "testing workflows";
75 reset_state();
76 reset_basic_sales_records();
77 reset_basic_purchase_records();
78
79 note "testing subversion of order";
80 # make current version a final version, currently this is handled via frontend/controller
81 is($sales_order1->ordnumber, "ord-01", "ordnumber before increment_subversion ok");
82 SL::DB::OrderVersion->new(oe_id => $sales_order1->id, version => 1, final_version => 1)->save;
83 # feature incrementing subversion disabled throws an error
84 throws_ok {
85   local $::instance_conf->data->{lock_oe_subversions} = 0;
86   SL::Model::Record->increment_subversion($sales_order1);
87 } qr{Subversions are not supported or disabled for this record type.}, 'feature subversion disabled throws error when trying to increment';
88 {
89   local $::instance_conf->data->{lock_oe_subversions} = 1;
90   SL::Model::Record->increment_subversion($sales_order1);
91 }
92 is($sales_order1->ordnumber, "ord-01-2", "ordnumber after increment_subversion ok");
93 is(SL::DB::Manager::Order->get_all_count(
94     where => [ and => ['!record_type' => 'sales_quotation', '!record_type' => 'request_quotation' ]]),
95   2, 'number of orders after incremented subversion ok');
96
97
98 note "testing new_from_workflow for quotation";
99 foreach my $target_record_type (qw(sales_order sales_delivery_order)) {
100   # TODO: invoice
101   note "  testing from quotation -> $target_record_type";
102   my $new_record = SL::Model::Record->new_from_workflow($sales_quotation1, $target_record_type);
103
104   is($new_record->closed, 0, "new quotation is open");
105   # in the future closing sales quotations should probably happen as an after-save hook of orders,
106   # but for now we copy the behaviour of the controller and pass the sales quotations as an argument
107   SL::Model::Record->save($new_record, objects_to_close => [ $sales_quotation1 ]);
108
109   $new_record->load;
110   cmp_ok($new_record->netamount, '==', 710, "converted $target_record_type netamount ok") if $new_record->can('netamount');
111
112   # test whether quotations get closed when sales_order is created
113   if ( $target_record_type eq 'sales_order' ) {
114     $sales_quotation1->load;
115     is($sales_quotation1->closed, 1, "quotation is closed after creating an order");
116   }
117
118   # TODO: test whether orders get closed when all items are deliverd
119
120   my $record_history = SL::DB::Manager::History->find_by(trans_id => $new_record->id, addition => 'SAVED');
121   ok($record_history->snumbers =~ m/_/, "history snumbers of record " . $record_history->snumbers . " ok");
122   test_record_links($new_record, "converted $target_record_type");
123 };
124
125 note "testing new_from_workflow for order";
126 foreach my $target_record_type (qw(sales_delivery_order sales_reclamation)) {
127   # TODO: invoice
128   note "  testing from quotation -> $target_record_type";
129   my $new_record = SL::Model::Record->new_from_workflow($sales_order1, $target_record_type);
130   if ( 'SL::DB::Reclamation' eq ref($new_record) ) {
131     $_->reason($reclamation_reason) foreach @{ $new_record->items };
132   };
133   SL::Model::Record->save($new_record);
134   $new_record->load;
135   my $record_history = SL::DB::Manager::History->find_by(trans_id => $new_record->id, what_done => $target_record_type, addition => 'SAVED');
136
137   ok($record_history->snumbers =~ m/_/, "history snumbers of record " . $record_history->snumbers . " ok");
138
139   cmp_ok($new_record->netamount, '==', 710, "converted $target_record_type netamount ok") if $new_record->can('netamount');
140   test_record_links($new_record, "converted $target_record_type");
141 };
142
143 note ('testing multi');
144 reset_state();
145 reset_basic_sales_records();
146 reset_basic_purchase_records();
147
148 note('combining several sales orders to one combined order');
149 my @sales_orders;
150 push(@sales_orders, SL::Model::Record->new_from_workflow($sales_quotation1, 'sales_order')->save->load) for 1 .. 3;
151 my $combined_order = SL::Model::Record->new_from_workflow_multi(\@sales_orders, 'sales_order', sort_sources_by => 'transdate');
152 SL::Model::Record->save($combined_order);
153 cmp_ok($combined_order->netamount, '==', 3*710, "netamount of combined order ok");
154
155
156 note "testing get price and discount sources";
157 reset_state();
158 reset_basic_sales_records();
159 reset_basic_purchase_records();
160
161 $purchase_quotation1->items_sorted->[0]->part->sellprice(500);
162 $purchase_quotation1->items_sorted->[0]->part->lastcost(300);
163 $purchase_quotation1->vendor->discount(5.0);
164
165 my ($price_source, $discount_source) = SL::Model::Record->get_best_price_and_discount_source($purchase_quotation1,
166                                                                                              $purchase_quotation1->items_sorted->[0],
167                                                                                              ignore_given => 1);
168 is($price_source->source_description, 'Master Data', 'get price source right with ignore_given');
169 is($price_source->price, 300, 'get price source purchase price right with ignore_given');
170 is($discount_source->source_description, 'Vendor Discount', 'get discount source right with ignore_given');
171 is($discount_source->discount, 5, 'get discount source purchase discount right with ignore_given');
172
173 $purchase_quotation1->items_sorted->[0]->discount(3);
174
175 ($price_source, $discount_source)    = SL::Model::Record->get_best_price_and_discount_source($purchase_quotation1,
176                                                                                              $purchase_quotation1->items_sorted->[0],
177                                                                                              ignore_given => 0);
178 is($price_source->source_description, 'None (PriceSource)', 'get price source right with given price');
179 is($price_source->price, 70, 'get price source purchase price right with given price');
180 is($discount_source->source_description, 'None (PriceSource Discount)', 'get price source right with given price');
181 is($discount_source->discount, 3, 'get discount source purchase discount right with given price');
182
183 clear_up();
184 done_testing;
185
186 sub test_record_links {
187   my $record = shift;
188   my $text = shift;
189
190   is(@{ $record->linked_records }, 1, "1 record link for $text created ok"); # just check if one exists, not if it is actually correct
191   my $number_of_item_record_links;
192   foreach my $item ( @{ $record->items } ) {
193     $number_of_item_record_links += scalar @{ $item->linked_records };
194   };
195   is($number_of_item_record_links, 2, "2 record links for $text items created ok"); # just check if they exist, not if they are actually correct
196 }
197
198 sub clear_up {
199   foreach (qw(InvoiceItem Invoice
200               DeliveryOrderItem DeliveryOrder
201               OrderItem Order OrderVersion
202               Reclamation ReclamationItem ReclamationReason
203               Part Customer Vendor PaymentTerm DeliveryTerm)
204           ) {
205     "SL::DB::Manager::${_}"->delete_all(all => 1);
206   }
207   SL::DB::Manager::History->delete_all(all => 1);
208   SL::DB::Manager::Employee->delete_all(where => [ login => 'testuser' ]);
209 };
210
211 sub reset_basic_sales_records {
212   $dbh->do("UPDATE defaults SET sonumber = 'ord-00', sqnumber = 'quo-00', sdonumber = 'do-00', s_reclamation_record_number = 'srecl-00'");
213
214   $sales_quotation1 = create_sales_quotation(
215     save       => 1,
216     customer   => $customer,
217     orderitems => [ create_order_item(part => $parts[0], qty =>  3, sellprice => 70),
218                     create_order_item(part => $parts[1], qty => 10, sellprice => 50),
219                   ]
220   );
221
222   $sales_order1 = create_sales_order(
223     save       => 1,
224     customer   => $customer,
225     orderitems => [ create_order_item(part => $parts[0], qty =>  3, sellprice => 70),
226                     create_order_item(part => $parts[1], qty => 10, sellprice => 50),
227                   ]
228   );
229
230   $sales_delivery_order1 = create_sales_delivery_order(
231     save       => 1,
232     customer   => $customer,
233     orderitems => [ create_delivery_order_item(part => $parts[0], qty =>  3, sellprice => 70),
234                     create_delivery_order_item(part => $parts[1], qty => 10, sellprice => 50),
235                   ]
236   );
237
238   $sales_reclamation1 = create_sales_reclamation(
239     save              => 1,
240     employee          => $employee,
241     reclamation_items => [ create_reclamation_item(part => $parts[0], qty =>  3, sellprice => 70, reason => $reclamation_reason),
242                            create_reclamation_item(part => $parts[1], qty => 10, sellprice => 50, reason => $reclamation_reason),
243                          ]
244   );
245
246   # disabled sales_invoice
247   # $sales_invoice1 = create_sales_invoice(
248   #   save        => 1,
249   #   customer    => $customer,
250   #   invoiceitems => [ create_invoice_item(part => $parts[0], qty =>  3, sellprice => 70),
251   #                     create_invoice_item(part => $parts[1], qty => 10, sellprice => 50),
252   #                   ]
253   # );
254 }
255
256 sub reset_basic_purchase_records {
257   $dbh->do("UPDATE defaults SET rfqnumber = 'rfq-00', ponumber = 'po-00', pdonumber = 'pdo-00', p_reclamation_record_number = 'precl-00'");
258
259   $purchase_quotation1 = create_purchase_quotation (
260     save        => 1,
261     vendor      => $vendor,
262     orderitems  => [ create_order_item(part => $parts[0], qty =>  3, sellprice => 70),
263                      create_order_item(part => $parts[1], qty => 10, sellprice => 50),
264                    ]
265   );
266
267   $purchase_order1 = create_purchase_order (
268     save        => 1,
269     vendor      => $vendor,
270     orderitems  => [ create_order_item(part => $parts[0], qty =>  3, sellprice => 70),
271                      create_order_item(part => $parts[1], qty => 10, sellprice => 50),
272                    ]
273   );
274
275   $purchase_delivery_order1 = create_purchase_delivery_order(
276     save       => 1,
277     vendor     => $vendor,
278     orderitems => [ create_delivery_order_item(part => $parts[0], qty =>  3, sellprice => 70),
279                     create_delivery_order_item(part => $parts[1], qty => 10, sellprice => 50),
280                   ]
281   );
282
283   $purchase_reclamation1 = create_purchase_reclamation(
284     save              => 1,
285     employee          => $employee,
286     reclamation_items => [ create_reclamation_item(part => $parts[0], qty =>  3, sellprice => 70, reason => $reclamation_reason),
287                            create_reclamation_item(part => $parts[1], qty => 10, sellprice => 50, reason => $reclamation_reason),
288                          ]
289   );
290 }
291
292 sub reset_state {
293   my %params = @_;
294
295   clear_up();
296
297   $customer = new_customer()->save;
298   $vendor   = new_vendor()->save;
299
300   $employee = SL::DB::Employee->new(
301     'login' => 'testuser',
302     'name'  => 'Test User',
303   )->save;
304
305   $payment_term = create_payment_terms(
306      'description'      => '14Tage 2%Skonto, 30Tage netto',
307      'description_long' => "Innerhalb von 14 Tagen abzüglich 2 % Skonto, innerhalb von 30 Tagen rein netto.|Bei einer Zahlung bis zum <%skonto_date%> gewähren wir 2 % Skonto (EUR <%skonto_amount%>) entspricht EUR <%total_wo_skonto%>.Bei einer Zahlung bis zum <%netto_date%> ist der fällige Betrag in Höhe von <%total%> <%currency%> zu überweisen.",
308      'percent_skonto'   => '0.02',
309      'terms_netto'      => 30,
310      'terms_skonto'     => 14
311   );
312
313   $delivery_term = SL::DB::DeliveryTerm->new(
314     'description'      => 'Test Delivey Term',
315     'description_long' => 'Test Delivey Term Test Delivey Term',
316   )->save;
317
318   # some parts/services
319   @parts = ();
320   push @parts, new_part(
321     partnumber => 'a',
322   )->save;
323   push @parts, new_part(
324     partnumber => 'b',
325   )->save;
326
327   $reclamation_reason = SL::DB::ReclamationReason->new(
328     name        => "test_reason",
329     description => "",
330     position    => 1,
331   );
332
333 }
334
335 1;
336
337 # set emacs to perl mode
338 # Local Variables:
339 # mode: perl
340 # End: