Merge branch 'test' of ../kivitendo-erp_20220811
[kivitendo-erp.git] / t / controllers / csvimport / delivery_orders.t
1 use Test::More tests => 28;
2
3 use strict;
4
5 use lib 't';
6 use utf8;
7
8 use Support::TestSetup;
9
10 use List::MoreUtils qw(none any);
11
12 use SL::Controller::CsvImport;
13 use_ok 'SL::Controller::CsvImport::DeliveryOrder';
14
15 use SL::Dev::ALL qw(:ALL);
16
17 Support::TestSetup::login();
18
19 #####
20 sub do_import {
21   my ($file, $settings) = @_;
22
23   my $controller = SL::Controller::CsvImport->new(
24     type => 'delivery_orders',
25   );
26   $controller->load_default_profile;
27   $controller->profile->set(
28     charset  => 'utf-8',
29     sep_char => ';',
30     %$settings
31   );
32
33   my $worker = SL::Controller::CsvImport::DeliveryOrder->new(
34     controller => $controller,
35     file       => $file,
36   );
37   $worker->run(test => 0);
38
39   return if $worker->controller->errors;
40
41   # don't try and save objects that have errors
42   $worker->save_objects unless scalar @{$worker->controller->data->[0]->{errors}};
43
44   return $worker->controller->data;
45 }
46
47 sub clear_up {
48   foreach (qw(RecordLink Order DeliveryOrder Customer Part)) {
49     "SL::DB::Manager::${_}"->delete_all(all => 1);
50   }
51   SL::DB::Manager::Employee->delete_all(where => [ '!login' => 'unittests' ]);
52 }
53
54 #####
55
56 # set numberformat and locale (so we can match errors)
57 my $old_numberformat      = $::myconfig{numberformat};
58 $::myconfig{numberformat} = '1.000,00';
59 my $old_locale            = $::locale;
60 $::locale                 = Locale->new('en');
61
62 clear_up;
63
64 #####
65 my @customers;
66 my @parts;
67 my @orders;
68 my $file;
69 my $entries;
70 my $entry;
71
72 # simple import
73 @customers = (new_customer(name => 'TestCustomer1', discount => 0)->save);
74 @parts = (
75   new_part(description => 'TestPart1', ean => '')->save,
76   new_part(description => 'TestPart2', ean => '')->save
77 );
78
79 $file = \<<EOL;
80 datatype;customer
81 datatype;description;qty
82 datatype
83 DeliveryOrder;TestCustomer1
84 OrderItem;TestPart1;5
85 OrderItem;TestPart2;10
86 EOL
87
88 $entries = do_import($file);
89
90 $entry = $entries->[0];
91 is $entry->{object}->customer_id, $customers[0]->id, 'simple import: customer_id';
92
93 $entry = $entries->[1];
94 is $entry->{object}->parts_id,    $parts[0]->id,     'simple import: part 1: parts_id';
95 is $entry->{object}->qty,         5,                 'simple import: part 1: qty';
96
97 $entry = $entries->[2];
98 is $entry->{object}->parts_id,    $parts[1]->id,     'simple import: part 2: parts_id';
99 is $entry->{object}->qty,         10,                'simple import: part 2: qty';
100
101
102 $entries = undef;
103 clear_up;
104
105 #####
106 # with source order
107 @customers = (new_customer(name => 'TestCustomer1', discount => 0)->save);
108 @parts = (
109   new_part(description => 'TestPart1', ean => '')->save,
110   new_part(description => 'TestPart2', ean => '')->save,
111   new_part(description => 'TestPart3', ean => '')->save
112 );
113 @orders = (
114   create_sales_order(
115     save       => 1,
116     customer   => $customers[0],
117     ordnumber  => '1234',
118     orderitems => [ create_order_item(part => $parts[0], qty =>  3, sellprice => 70),
119                     create_order_item(part => $parts[1], qty => 10, sellprice => 50),
120                     create_order_item(part => $parts[2], qty =>  8, sellprice => 80),
121                     create_order_item(part => $parts[2], qty => 11, sellprice => 80)
122     ]
123   )
124 );
125
126 $file = \<<EOL;
127 datatype;customer;ordnumber
128 datatype;description;qty
129 datatype
130 DeliveryOrder;TestCustomer1;1234
131 OrderItem;TestPart1;5
132 OrderItem;TestPart2;10
133 OrderItem;TestPart3;7
134 OrderItem;TestPart3;1
135 OrderItem;TestPart3;11
136 EOL
137
138   1;                            # make emacs happy
139
140 # should be:
141 # delivery oder pos/qty <- order pos/qty
142 #       1/5             <-       -
143 #       2/10            <-      2/10
144 #       3/7             <-      3/7
145 #       4/1             <-      3/1
146 #       5/11            <-      4/11
147
148 $entries = do_import($file);
149 $orders[0]->load;               # reload order to get correct delivered status
150
151 $entry = $entries->[0];
152 is $entry->{object}->ordnumber, '1234', 'with source order: ordnumber';
153
154 my $linked = $orders[0]->linked_records(to => 'DeliveryOrder');
155 ok(scalar @$linked == 1, 'with source order: order linked to one delivery order');
156 ok($linked->[0]->id == $entry->{object}->id, 'with source order: order linked to imported delivery order');
157
158
159 $linked = $entry->{object}->linked_records(from => 'Order');
160 ok(scalar @$linked == 1, 'with source order: delivery order linked from one order');
161 ok($linked->[0]->id == $orders[0]->id, 'with source order: delivery order linked from source order');
162
163 $entry = $entries->[1];
164 $linked = $entry->{object}->linked_records(from => 'OrderItem');
165 ok(scalar @$linked == 0, 'with source order: delivered qty > ordered qty: delivery order item not linked');
166
167 $entry = $entries->[2];
168 $linked = $entry->{object}->linked_records(from => 'OrderItem');
169 ok(scalar @$linked == 1, 'with source order: same qtys: delivery order item linked');
170 ok($linked->[0]->id == $orders[0]->items_sorted->[1]->id, 'with source order: same qtys: delivery order item linked from source order item');
171
172 $entry = $entries->[3];
173 $linked = $entry->{object}->linked_records(from => 'OrderItem');
174 ok(scalar @$linked == 1, 'with source order: delivered qty < ordered qty: delivery order item linked (fill up)');
175 ok($linked->[0]->position == 3, 'with source order: delivered qty < ordered qty: order position ok (fill up)');
176
177 $entry = $entries->[4];
178 $linked = $entry->{object}->linked_records(from => 'OrderItem');
179 ok(scalar @$linked == 1, 'with source order: delivered qty < ordered qty: delivery order item linked (fill up) 2');
180 ok($linked->[0]->position == 3, 'with source order: delivered qty < ordered qty: order position ok (fill up) 2');
181
182 $entry = $entries->[5];
183 $linked = $entry->{object}->linked_records(from => 'OrderItem');
184 ok(scalar @$linked == 1, 'with source order: delivered qty == ordered qty: found exact match after fill up');
185 ok($linked->[0]->position == 4, 'with source order: delivered qty == ordered qty: order position ok after fill up');
186
187 ok(!$orders[0]->delivered, 'with source order: order not completely delivered');
188
189 $entries = undef;
190 clear_up;
191
192 #####
193 @customers = (new_customer(name => 'TestCustomer1', discount => 0)->save);
194 @parts = (
195   new_part(description => 'TestPart1', ean => '')->save,
196   new_part(description => 'TestPart2', ean => '')->save,
197   new_part(description => 'TestPart3', ean => '')->save
198 );
199 @orders = (
200   create_sales_order(
201     save       => 1,
202     customer   => $customers[0],
203     ordnumber  => '1234',
204     orderitems => [ create_order_item(part => $parts[0], qty =>  3, sellprice => 70),
205                     create_order_item(part => $parts[1], qty => 10, sellprice => 50),
206                     create_order_item(part => $parts[2], qty =>  8, sellprice => 80),
207                     create_order_item(part => $parts[2], qty => 11, sellprice => 80)
208     ]
209   )
210 );
211
212 $file = \<<EOL;
213 datatype;customer;ordnumber
214 datatype;description;qty
215 datatype
216 DeliveryOrder;TestCustomer1;1234
217 OrderItem;TestPart1;1
218 OrderItem;TestPart2;10
219 OrderItem;TestPart1;2
220 OrderItem;TestPart3;7
221 OrderItem;TestPart3;11
222 OrderItem;TestPart3;1
223
224 EOL
225
226   1;                            # make emacs happy
227
228 # should be:
229 # delivery oder pos/qty <- order pos/qty
230 #       1/1             <-      1/1
231 #       2/10            <-      2/10
232 #       3/2             <-      1/2
233 #       4/7             <-      3/7
234 #       5/11            <-      4/11
235 #       6/1             <-      3/1
236
237 $entries = do_import($file);
238 $orders[0]->load;               # reload order to get correct delivered status
239
240 $entry = $entries->[1];
241 $linked = $entry->{object}->linked_records(from => 'OrderItem');
242 ok($linked->[0]->position == 1, 'with source order: mixed qtys and fill up: order position ok 1');
243
244 $entry = $entries->[2];
245 $linked = $entry->{object}->linked_records(from => 'OrderItem');
246 ok($linked->[0]->position == 2, 'with source order: mixed qtys and fill up: order position ok 2');
247
248 $entry = $entries->[3];
249 $linked = $entry->{object}->linked_records(from => 'OrderItem');
250 ok($linked->[0]->position == 1, 'with source order: mixed qtys and fill up: order position ok 3');
251
252 $entry = $entries->[4];
253 $linked = $entry->{object}->linked_records(from => 'OrderItem');
254 ok($linked->[0]->position == 3, 'with source order: mixed qtys and fill up: order position ok 4');
255
256 $entry = $entries->[5];
257 $linked = $entry->{object}->linked_records(from => 'OrderItem');
258 ok($linked->[0]->position == 4, 'with source order: mixed qtys and fill up: order position ok 5');
259
260 $entry = $entries->[6];
261 $linked = $entry->{object}->linked_records(from => 'OrderItem');
262 ok($linked->[0]->position == 3, 'with source order: mixed qtys and fill up: order position ok 6');
263
264 ok(!!$orders[0]->delivered, 'with source order: mixed qtys and fill up: order completely delivered');
265
266 #####
267 $entries = undef;
268 clear_up;
269
270 #####
271
272 $::myconfig{numberformat} = $old_numberformat;
273 $::locale                 = $old_locale;
274
275 1;
276
277 #####
278 # vim: ft=perl
279 # set emacs to perl mode
280 # Local Variables:
281 # mode: perl
282 # End: