29b28766b57b3d353bdd5f54b10a9f7fccc52ea6
[kivitendo-erp.git] / t / controllers / csvimport / inventory.t
1 use strict;
2
3 use Data::Dumper; # maybe in Tests available?
4 use Test::Deep qw(cmp_deeply superhashof ignore);
5 use Test::More;
6 use Test::Exception;
7
8 use lib 't';
9
10 use SL::Dev::Part qw(new_part new_assembly new_service);
11 use SL::Dev::Inventory qw(create_warehouse_and_bins set_stock);
12
13 use_ok 'Support::TestSetup';
14 use_ok 'SL::Controller::CsvImport';
15 use_ok 'SL::DB::Bin';
16 use_ok 'SL::DB::Part';
17 use_ok 'SL::DB::Warehouse';
18 use_ok 'SL::DB::Inventory';
19 use_ok 'SL::WH';
20 use_ok 'SL::Helper::Inventory';
21
22 Support::TestSetup::login();
23
24 my ($wh, $bin1, $bin2, $assembly1, $assembly_service, $part1, $part2, $wh_moon, $bin_moon, $service1);
25
26 sub reset_state {
27   # Create test data
28
29   clear_up();
30   create_standard_stock();
31
32
33
34 }
35 reset_state();
36
37 #####
38 sub test_import {
39   my ($file,$settings) = @_;
40
41   my $controller = SL::Controller::CsvImport->new(
42     type => 'inventories'
43   );
44   $controller->load_default_profile;
45   $controller->profile->set(
46     charset      => 'utf-8',
47     sep_char     => ',',
48     quote_char   => '"',
49     numberformat => $::myconfig{numberformat},
50   );
51   my $csv_inventory_import = SL::Controller::CsvImport::Inventory->new(
52     settings   => $settings,
53     controller => $controller,
54     file       => $file,
55   );
56   #print "profile param type=".$csv_part_import->settings->{parts_type}."\n";
57
58   $csv_inventory_import->run(test => 0);
59
60   # don't try and save objects that have errors
61   $csv_inventory_import->save_objects unless scalar @{$csv_inventory_import->controller->data->[0]->{errors}};
62
63   return $csv_inventory_import->controller->data;
64 }
65
66 $::myconfig{numberformat} = '1000.00';
67 my $old_locale = $::locale;
68 # set locale to en so we can match errors
69 $::locale = Locale->new('en');
70
71
72 my ($entries, $entry, $file);
73
74 # different settings for tests
75 #
76
77 my $settings1 = {
78                   apply_comment => 'missing',
79                   comment       => 'Lager Inventur Standard',
80                 };
81 #
82 #
83 # starting test of csv imports
84 # to debug errors in certain tests, run after test_import:
85 #   die Dumper($entry->{errors});
86
87
88 ##### create complete bullshit
89 $file = \<<EOL;
90 bin,chargenumber,comment,employee_id,partnumber,qty,shippingdate,target_qty,warehouse
91 P1000;100.10;90.20;95.30;kg;111.11;122.22;133.33
92 EOL
93 $entries = test_import($file, $settings1);
94 $entry = $entries->[0];
95 is scalar @{ $entry->{errors} }, 3, "Three errors occurred";
96
97 cmp_deeply(\@{ $entry->{errors} }, [
98                                     'Error: Warehouse not found',
99                                     'Error: Bin not found',
100                                     'Error: Part not found'
101                                    ],
102           "Errors for bullshit import are ok"
103 );
104
105 ##### create minor bullshit
106 $file = \<<EOL;
107 warehouse,bin,partnumber,qty,chargenumber,comment,employee_id,qty,shippingdate,target_qty
108 Warehouse,"Bin 1","ap 1",3.4
109 EOL
110
111 $entries = test_import($file, $settings1);
112 $entry = $entries->[0];
113 is scalar @{ $entry->{errors} }, 1, "One error for minor bullshit occurred";
114
115 cmp_deeply(\@{ $entry->{errors} }, [
116                                     'Error: A quantity and a target quantity could not be given both.'
117                                    ],
118           "Error for minor bullshit import are ok"
119 );
120
121
122 ##### add some qty on earth, but we have something already stocked
123 set_stock(
124   part => $part1,
125   qty => 25,
126   bin => $bin1,
127 );
128
129 is(SL::Helper::Inventory::get_stock(part => $part1), "25.00000", 'simple get_stock works');
130 is(SL::Helper::Inventory::get_onhand(part => $part1), "25.00000", 'simple get_onhand works');
131
132 $file = \<<EOL;
133 warehouse,bin,partnumber,qty,chargenumber,comment,employee_id,shippingdate
134 Warehouse,"Bin 1","ap 1",3.4
135 EOL
136 $entries = test_import($file, $settings1);
137 $entry = $entries->[0];
138 diag Dumper($entry->{object}->trans_id);
139 is scalar @{ $entry->{errors} }, 0, "No error for valid data occurred";
140 is $entry->{object}->qty, "3.4", "Valid qty accepted";  # evals to text
141 is(SL::Helper::Inventory::get_stock(part => $part1),  "28.40000",  'simple add (stock) qty works');
142 is(SL::Helper::Inventory::get_onhand(part => $part1), "28.40000", 'simple add (onhand) qty works');
143
144 # now check the real Inventory entry
145 my $trans_id = $entry->{object}->trans_id;
146 my $inv_obj = SL::DB::Manager::Inventory->find_by(trans_id => $trans_id);
147
148 # we expect one entry for one trans_id
149 is ref $inv_obj, "SL::DB::Inventory",             "One inventory object, no array or undef";
150 is $inv_obj->qty == 3.4, 1,                       "Valid qty accepted";  # evals to text
151 is $inv_obj->comment, 'Lager Inventur Standard',  "Valid comment accepted";  # evals to text
152 is $inv_obj->employee_id, 1,                      "Employee valid";  # evals to text
153 is ref $inv_obj->shippingdate, 'DateTime',        "Valid DateTime for shippingdate";
154 is $inv_obj->shippingdate, DateTime->today_local, "Default shippingdate set";
155
156 my $tt = SL::DB::Manager::TransferType->find_by(id => $inv_obj->trans_type_id);
157
158 is ref $tt, 'SL::DB::TransferType',       "Valid TransferType, no undef";
159 is $tt->direction, 'in',                  "Transfer direction correct";
160 is $tt->description, 'correction',        "Transfer description correct";
161
162 clear_up(); # remove all data at end of tests
163
164 # end of tests
165
166 done_testing();
167
168 sub clear_up {
169   SL::DB::Manager::Inventory->delete_all(all => 1);
170   SL::DB::Manager::Assembly->delete_all(all => 1);
171   SL::DB::Manager::Part->delete_all(all => 1);
172   SL::DB::Manager::Bin->delete_all(all => 1);
173   SL::DB::Manager::Warehouse->delete_all(all => 1);
174 }
175
176 sub create_standard_stock {
177   ($wh, $bin1)          = create_warehouse_and_bins();
178   ($wh_moon, $bin_moon) = create_warehouse_and_bins(
179       warehouse_description => 'Our warehouse location at the moon',
180       bin_description       => 'Lunar crater',
181     );
182   $bin2 = SL::DB::Bin->new(description => "Bin 2", warehouse => $wh)->save;
183   $wh->load;
184
185   $assembly1  =  new_assembly(number_of_parts => 2)->save;
186   ($part1, $part2) = map { $_->part } $assembly1->assemblies;
187
188   $service1 = new_service(partnumber  => "service number 1",
189                           description => "We really need this service",
190                          )->save;
191   my $assembly_items;
192   push( @{$assembly_items}, SL::DB::Assembly->new(parts_id => $part1->id,
193                                                   qty      => 12,
194                                                   position => 1,
195                                                   ));
196   push( @{$assembly_items}, SL::DB::Assembly->new(parts_id => $part2->id,
197                                                   qty      => 6.34,
198                                                   position => 2,
199                                                   ));
200   push( @{$assembly_items}, SL::DB::Assembly->new(parts_id => $service1->id,
201                                                   qty      => 1.2,
202                                                   position => 3,
203                                                   ));
204   $assembly_service  =  new_assembly(description    => 'Ein Erzeugnis mit Dienstleistungen',
205                                      assembly_items => $assembly_items
206                                     )->save;
207 }
208
209
210
211
212 1;
213
214 #####
215 # vim: ft=perl
216 # set emacs to perl mode
217 # Local Variables:
218 # mode: perl
219 # End: