11 use Support::TestSetup;
13 use List::Util qw(pairs);
15 use SL::DB::PaymentTerm;
16 use SL::DB::DeliveryTerm;
18 use SL::DB::ReclamationReason;
19 use SL::Model::Record;
21 use SL::Dev::ALL qw(:ALL);
23 my ($customer, $vendor, $employee, $payment_term, $delivery_term, @parts, $reclamation_reason);
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);
29 Support::TestSetup::login();
30 $dbh = SL::DB->client->dbh;
32 # set locale to en so we can match errors
33 local $::locale = Locale->new('en');
35 note "testing deletions";
37 reset_basic_sales_records();
38 reset_basic_purchase_records();
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
50 foreach my $record ( ($sales_quotation1,
55 $purchase_reclamation1
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");
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');
74 note "testing workflows";
76 reset_basic_sales_records();
77 reset_basic_purchase_records();
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
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';
89 local $::instance_conf->data->{lock_oe_subversions} = 1;
90 SL::Model::Record->increment_subversion($sales_order1);
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');
98 note "testing new_from_workflow for quotation";
99 foreach my $target_record_type (qw(sales_order sales_delivery_order)) {
101 note " testing from quotation -> $target_record_type";
102 my $new_record = SL::Model::Record->new_from_workflow($sales_quotation1, $target_record_type);
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 ]);
110 cmp_ok($new_record->netamount, '==', 710, "converted $target_record_type netamount ok") if $new_record->can('netamount');
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");
118 # TODO: test whether orders get closed when all items are deliverd
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");
125 note "testing new_from_workflow for order";
126 foreach my $target_record_type (qw(sales_delivery_order sales_reclamation)) {
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 };
133 SL::Model::Record->save($new_record);
135 my $record_history = SL::DB::Manager::History->find_by(trans_id => $new_record->id, what_done => $target_record_type, addition => 'SAVED');
137 ok($record_history->snumbers =~ m/_/, "history snumbers of record " . $record_history->snumbers . " ok");
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");
143 note ('testing multi');
145 reset_basic_sales_records();
146 reset_basic_purchase_records();
148 note('combining several sales orders to one combined order');
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");
156 note "testing get price and discount sources";
158 reset_basic_sales_records();
159 reset_basic_purchase_records();
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);
165 my ($price_source, $discount_source) = SL::Model::Record->get_best_price_and_discount_source($purchase_quotation1,
166 $purchase_quotation1->items_sorted->[0],
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');
173 $purchase_quotation1->items_sorted->[0]->discount(3);
175 ($price_source, $discount_source) = SL::Model::Record->get_best_price_and_discount_source($purchase_quotation1,
176 $purchase_quotation1->items_sorted->[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');
186 sub test_record_links {
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 };
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
199 foreach (qw(InvoiceItem Invoice
200 DeliveryOrderItem DeliveryOrder
201 OrderItem Order OrderVersion
202 Reclamation ReclamationItem ReclamationReason
203 Part Customer Vendor PaymentTerm DeliveryTerm)
205 "SL::DB::Manager::${_}"->delete_all(all => 1);
207 SL::DB::Manager::History->delete_all(all => 1);
208 SL::DB::Manager::Employee->delete_all(where => [ login => 'testuser' ]);
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'");
214 $sales_quotation1 = create_sales_quotation(
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),
222 $sales_order1 = create_sales_order(
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),
230 $sales_delivery_order1 = create_sales_delivery_order(
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),
238 $sales_reclamation1 = create_sales_reclamation(
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),
246 # disabled sales_invoice
247 # $sales_invoice1 = create_sales_invoice(
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),
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'");
259 $purchase_quotation1 = create_purchase_quotation (
262 orderitems => [ create_order_item(part => $parts[0], qty => 3, sellprice => 70),
263 create_order_item(part => $parts[1], qty => 10, sellprice => 50),
267 $purchase_order1 = create_purchase_order (
270 orderitems => [ create_order_item(part => $parts[0], qty => 3, sellprice => 70),
271 create_order_item(part => $parts[1], qty => 10, sellprice => 50),
275 $purchase_delivery_order1 = create_purchase_delivery_order(
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),
283 $purchase_reclamation1 = create_purchase_reclamation(
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),
297 $customer = new_customer()->save;
298 $vendor = new_vendor()->save;
300 $employee = SL::DB::Employee->new(
301 'login' => 'testuser',
302 'name' => 'Test User',
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',
313 $delivery_term = SL::DB::DeliveryTerm->new(
314 'description' => 'Test Delivey Term',
315 'description_long' => 'Test Delivey Term Test Delivey Term',
318 # some parts/services
320 push @parts, new_part(
323 push @parts, new_part(
327 $reclamation_reason = SL::DB::ReclamationReason->new(
328 name => "test_reason",
337 # set emacs to perl mode