3 use Data::Dumper; # maybe in Tests available?
 
   4 use Test::Deep qw(cmp_deeply superhashof ignore);
 
  10 use SL::Dev::Part qw(new_part new_assembly new_service);
 
  11 use SL::Dev::Inventory qw(create_warehouse_and_bins set_stock);
 
  13 use_ok 'Support::TestSetup';
 
  14 use_ok 'SL::Controller::CsvImport';
 
  16 use_ok 'SL::DB::Part';
 
  17 use_ok 'SL::DB::Warehouse';
 
  18 use_ok 'SL::DB::Inventory';
 
  20 use_ok 'SL::Helper::Inventory';
 
  22 Support::TestSetup::login();
 
  24 my ($wh, $bin1, $bin2, $assembly1, $assembly_service, $part1, $part2, $wh_moon, $bin_moon, $service1);
 
  30   create_standard_stock();
 
  37   my ($file,$settings) = @_;
 
  39   my $controller = SL::Controller::CsvImport->new(
 
  42   $controller->load_default_profile;
 
  43   $controller->profile->set(
 
  47     numberformat => $::myconfig{numberformat},
 
  49   my $csv_inventory_import = SL::Controller::CsvImport::Inventory->new(
 
  50     settings   => $settings,
 
  51     controller => $controller,
 
  54   #print "profile param type=".$csv_part_import->settings->{parts_type}."\n";
 
  56   $csv_inventory_import->run(test => 0);
 
  58   # don't try and save objects that have errors
 
  59   $csv_inventory_import->save_objects unless scalar @{$csv_inventory_import->controller->data->[0]->{errors}};
 
  61   return $csv_inventory_import->controller->data;
 
  64 $::myconfig{numberformat} = '1000.00';
 
  65 my $old_locale = $::locale;
 
  66 # set locale to en so we can match errors
 
  67 $::locale = Locale->new('en');
 
  70 my ($entries, $entry, $file);
 
  72 # different settings for tests
 
  76                   apply_comment => 'missing',
 
  77                   comment       => 'Lager Inventur Standard',
 
  81 # starting test of csv imports
 
  82 # to debug errors in certain tests, run after test_import:
 
  83 #   die Dumper($entry->{errors});
 
  86 ##### create complete bullshit
 
  88 bin,chargenumber,comment,employee_id,partnumber,qty,shippingdate,target_qty,warehouse
 
  89 P1000;100.10;90.20;95.30;kg;111.11;122.22;133.33
 
  91 $entries = test_import($file, $settings1);
 
  92 $entry = $entries->[0];
 
  93 is scalar @{ $entry->{errors} }, 3, "Three errors occurred";
 
  95 cmp_deeply(\@{ $entry->{errors} }, [
 
  96                                     'Error: Warehouse not found',
 
  97                                     'Error: Bin not found',
 
  98                                     'Error: Part not found'
 
 100           "Errors for bullshit import are ok"
 
 103 ##### create minor bullshit
 
 105 warehouse,bin,partnumber,qty,chargenumber,comment,employee_id,qty,shippingdate,target_qty
 
 106 Warehouse,"Bin 1","ap 1",3.4
 
 109 $entries = test_import($file, $settings1);
 
 110 $entry = $entries->[0];
 
 111 is scalar @{ $entry->{errors} }, 1, "One error for minor bullshit occurred";
 
 113 cmp_deeply(\@{ $entry->{errors} }, [
 
 114                                     'Error: A quantity and a target quantity could not be given both.'
 
 116           "Error for minor bullshit import are ok"
 
 120 ##### add some qty on earth, but we have something already stocked
 
 127 is(SL::Helper::Inventory::get_stock(part => $part1), "25.00000", 'simple get_stock works');
 
 128 is(SL::Helper::Inventory::get_onhand(part => $part1), "25.00000", 'simple get_onhand works');
 
 130 my ($trans_id, $inv_obj, $tt);
 
 134 warehouse,bin,partnumber,qty,chargenumber,comment,employee_id,shippingdate
 
 135 Warehouse,"Bin 1","ap 1",3.4
 
 137 $entries = test_import($file, $settings1);
 
 138 $entry = $entries->[0];
 
 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');
 
 144 # now check the real Inventory entry
 
 145 $trans_id = $entry->{object}->trans_id;
 
 146 $inv_obj = SL::DB::Manager::Inventory->find_by(trans_id => $trans_id);
 
 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";
 
 156 $tt = SL::DB::Manager::TransferType->find_by(id => $inv_obj->trans_type_id);
 
 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";
 
 165 warehouse,bin,partnumber,qty,chargenumber,comment,employee_id,shippingdate
 
 166 Warehouse,"Bin 1","ap 1",-13.4
 
 168 $entries = test_import($file, $settings1);
 
 169 $entry = $entries->[0];
 
 170 is scalar @{ $entry->{errors} }, 0, "No error for valid data occurred";
 
 171 is $entry->{object}->qty, "-13.4", "Valid qty accepted";  # evals to text
 
 172 is(SL::Helper::Inventory::get_stock(part => $part1),  "15.00000",  'simple add (stock) qty works');
 
 173 is(SL::Helper::Inventory::get_onhand(part => $part1), "15.00000", 'simple add (onhand) qty works');
 
 175 # now check the real Inventory entry
 
 176 $trans_id = $entry->{object}->trans_id;
 
 177 $inv_obj = SL::DB::Manager::Inventory->find_by(trans_id => $trans_id);
 
 179 # we expect one entry for one trans_id
 
 180 is ref $inv_obj, "SL::DB::Inventory",             "One inventory object, no array or undef";
 
 181 is $inv_obj->qty == -13.4, 1,                       "Valid qty accepted";  # evals to text
 
 182 is $inv_obj->comment, 'Lager Inventur Standard',  "Valid comment accepted";  # evals to text
 
 183 is $inv_obj->employee_id, 1,                      "Employee valid";  # evals to text
 
 184 is ref $inv_obj->shippingdate, 'DateTime',        "Valid DateTime for shippingdate";
 
 185 is $inv_obj->shippingdate, DateTime->today_local, "Default shippingdate set";
 
 187 $tt = SL::DB::Manager::TransferType->find_by(id => $inv_obj->trans_type_id);
 
 189 is ref $tt, 'SL::DB::TransferType',       "Valid TransferType, no undef";
 
 190 is $tt->direction, 'out',                  "Transfer direction correct";
 
 191 is $tt->description, 'correction',        "Transfer description correct";
 
 193 # repeat both test cases but with target qty instead of qty (should throw an error for neg. case)
 
 194 # and customise comment
 
 198 warehouse,bin,partnumber,target_qty,comment
 
 199 Warehouse,"Bin 1","ap 1",3.4,"Alter, wir haben uns voll verhauen bei der aktuellen Zielmenge!"
 
 201 $entries = test_import($file, $settings1);
 
 202 $entry = $entries->[0];
 
 203 is scalar @{ $entry->{errors} }, 0, "No error for valid data occurred";
 
 204 is $entry->{object}->qty, "-11.6", "Valid qty accepted";  # evals to text qty = target_qty - actual_qty
 
 205 is(SL::Helper::Inventory::get_stock(part => $part1),  "3.40000",  'simple add (stock) qty works');
 
 206 is(SL::Helper::Inventory::get_onhand(part => $part1), "3.40000", 'simple add (onhand) qty works');
 
 208 # now check the real Inventory entry
 
 209 $trans_id = $entry->{object}->trans_id;
 
 210 $inv_obj = SL::DB::Manager::Inventory->find_by(trans_id => $trans_id);
 
 212 # we expect one entry for one trans_id
 
 213 is ref $inv_obj, "SL::DB::Inventory",             "One inventory object, no array or undef";
 
 214 is $inv_obj->qty == -11.6, 1,                       "Valid qty accepted";
 
 215 is $inv_obj->comment,
 
 216   "Alter, wir haben uns voll verhauen bei der aktuellen Zielmenge!",  "Valid comment accepted";
 
 217 is $inv_obj->employee_id, 1,                      "Employee valid";
 
 218 is ref $inv_obj->shippingdate, 'DateTime',        "Valid DateTime for shippingdate";
 
 219 is $inv_obj->shippingdate, DateTime->today_local, "Default shippingdate set";
 
 221 $tt = SL::DB::Manager::TransferType->find_by(id => $inv_obj->trans_type_id);
 
 223 is ref $tt, 'SL::DB::TransferType',       "Valid TransferType, no undef";
 
 224 is $tt->direction, 'out',                  "Transfer direction correct";
 
 225 is $tt->description, 'correction',        "Transfer description correct";
 
 227 # remove some stuff, but too much
 
 230 warehouse,bin,partnumber,target_qty,comment
 
 231 Warehouse,"Bin 1","ap 1",-13.4,"Jetzt stimmt aber alles"
 
 233 $entries = test_import($file, $settings1);
 
 234 $entry = $entries->[0];
 
 235 is scalar @{ $entry->{errors} }, 1, "One error for invalid data occurred";
 
 236 is $entry->{object}->qty, undef, "No data accepted";  # evals to text
 
 237 is(SL::Helper::Inventory::get_stock(part => $part1),  "3.40000",  'simple add (stock) qty works');
 
 238 is(SL::Helper::Inventory::get_onhand(part => $part1), "3.40000", 'simple add (onhand) qty works');
 
 240 # now check the real Inventory entry
 
 241 $trans_id = $entry->{object}->trans_id;
 
 242 $inv_obj = SL::DB::Manager::Inventory->find_by(trans_id => $trans_id);
 
 244 is ref $trans_id, '',         "No trans_id -> undef";
 
 245 is ref $inv_obj,  '',         "No inventory object -> undef";
 
 247 # add some stuff, but realistic value
 
 250 warehouse,bin,partnumber,target_qty,comment
 
 251 Warehouse,"Bin 1","ap 1",33.75,"Jetzt wirklich"
 
 253 $entries = test_import($file, $settings1);
 
 254 $entry = $entries->[0];
 
 255 is scalar @{ $entry->{errors} }, 0, "No error for valid data occurred";
 
 256 is $entry->{object}->qty, "30.35", "Valid qty accepted";  # evals to text qty = target_qty - actual_qty
 
 257 is(SL::Helper::Inventory::get_stock(part => $part1),  "33.75000",  'simple add (stock) qty works');
 
 258 is(SL::Helper::Inventory::get_onhand(part => $part1), "33.75000", 'simple add (onhand) qty works');
 
 260 # now check the real Inventory entry
 
 261 $trans_id = $entry->{object}->trans_id;
 
 262 $inv_obj = SL::DB::Manager::Inventory->find_by(trans_id => $trans_id);
 
 264 # we expect one entry for one trans_id
 
 265 is ref $inv_obj, "SL::DB::Inventory",             "One inventory object, no array or undef";
 
 266 is $inv_obj->qty == 30.35, 1,                     "Valid qty accepted";
 
 267 is $inv_obj->comment, "Jetzt wirklich",           "Valid comment accepted";
 
 268 is $inv_obj->employee_id, 1,                      "Employee valid";
 
 269 is ref $inv_obj->shippingdate, 'DateTime',        "Valid DateTime for shippingdate";
 
 270 is $inv_obj->shippingdate, DateTime->today_local, "Default shippingdate set";
 
 272 $tt = SL::DB::Manager::TransferType->find_by(id => $inv_obj->trans_type_id);
 
 274 is ref $tt, 'SL::DB::TransferType',       "Valid TransferType, no undef";
 
 275 is $tt->direction, 'in',                  "Transfer direction correct";
 
 276 is $tt->description, 'correction',        "Transfer description correct";
 
 281 warehouse,bin,partnumber,target_qty,comment
 
 282 Warehouse,"Bin 1","ap 1",0,"Jetzt wirklich"
 
 284 $entries = test_import($file, $settings1);
 
 285 $entry = $entries->[0];
 
 286 is scalar @{ $entry->{errors} }, 0, "No error for valid data occurred";
 
 287 is $entry->{object}->qty, "-33.75", "Valid qty accepted";  # evals to text qty = target_qty - actual_qty
 
 288 is(SL::Helper::Inventory::get_stock(part => $part1),  "0.00000",  'simple add (stock) qty works');
 
 289 is(SL::Helper::Inventory::get_onhand(part => $part1), undef, 'simple add (onhand) qty works'); # hmm good return?
 
 291 # now check the real Inventory entry
 
 292 $trans_id = $entry->{object}->trans_id;
 
 293 $inv_obj = SL::DB::Manager::Inventory->find_by(trans_id => $trans_id);
 
 295 # we expect one entry for one trans_id
 
 296 is ref $inv_obj, "SL::DB::Inventory",             "One inventory object, no array or undef";
 
 297 is $inv_obj->qty == -33.75000, 1,                       "Valid qty accepted";
 
 298 is $inv_obj->comment,
 
 299   "Jetzt wirklich",  "Valid comment accepted";
 
 300 is $inv_obj->employee_id, 1,                      "Employee valid";
 
 301 is ref $inv_obj->shippingdate, 'DateTime',        "Valid DateTime for shippingdate";
 
 302 is $inv_obj->shippingdate, DateTime->today_local, "Default shippingdate set";
 
 304 $tt = SL::DB::Manager::TransferType->find_by(id => $inv_obj->trans_type_id);
 
 306 is ref $tt, 'SL::DB::TransferType',       "Valid TransferType, no undef";
 
 307 is $tt->direction, 'out',                  "Transfer direction correct";
 
 308 is $tt->description, 'correction',        "Transfer description correct";
 
 310 # add some stuff with a different numberformat
 
 312 $::myconfig{numberformat} = '1.000,00';
 
 314 warehouse,bin,partnumber,target_qty,comment
 
 315 Warehouse,"Bin 1","ap 1","31,2","Jetzt wirklich"
 
 317 $entries = test_import($file, $settings1);
 
 318 $entry = $entries->[0];
 
 319 is scalar @{ $entry->{errors} }, 0, "No error for valid data occurred";
 
 320 is $entry->{object}->qty, "31.2",  "Valid qty accepted";  # evals to text qty = target_qty - actual_qty
 
 321 is(SL::Helper::Inventory::get_stock(part => $part1),  "31.20000",  'simple add (stock) qty works');
 
 322 is(SL::Helper::Inventory::get_onhand(part => $part1), "31.20000", 'simple add (onhand) qty works');
 
 324 # now check the real Inventory entry
 
 325 $trans_id = $entry->{object}->trans_id;
 
 326 $inv_obj = SL::DB::Manager::Inventory->find_by(trans_id => $trans_id);
 
 328 # we expect one entry for one trans_id
 
 329 is ref $inv_obj, "SL::DB::Inventory",             "One inventory object, no array or undef";
 
 330 is $inv_obj->qty == 31.2, 1,                     "Valid qty calculated";
 
 334 clear_up(); # remove all data at end of tests
 
 341   SL::DB::Manager::Inventory->delete_all(all => 1);
 
 342   SL::DB::Manager::Assembly->delete_all(all => 1);
 
 343   SL::DB::Manager::Part->delete_all(all => 1);
 
 344   SL::DB::Manager::Bin->delete_all(all => 1);
 
 345   SL::DB::Manager::Warehouse->delete_all(all => 1);
 
 348 sub create_standard_stock {
 
 349   ($wh, $bin1)          = create_warehouse_and_bins();
 
 350   ($wh_moon, $bin_moon) = create_warehouse_and_bins(
 
 351       warehouse_description => 'Our warehouse location at the moon',
 
 352       bin_description       => 'Lunar crater',
 
 354   $bin2 = SL::DB::Bin->new(description => "Bin 2", warehouse => $wh)->save;
 
 357   $assembly1  =  new_assembly(number_of_parts => 2)->save;
 
 358   ($part1, $part2) = map { $_->part } $assembly1->assemblies;
 
 360   $service1 = new_service(partnumber  => "service number 1",
 
 361                           description => "We really need this service",
 
 364   push( @{$assembly_items}, SL::DB::Assembly->new(parts_id => $part1->id,
 
 368   push( @{$assembly_items}, SL::DB::Assembly->new(parts_id => $part2->id,
 
 372   push( @{$assembly_items}, SL::DB::Assembly->new(parts_id => $service1->id,
 
 376   $assembly_service  =  new_assembly(description    => 'Ein Erzeugnis mit Dienstleistungen',
 
 377                                      assembly_items => $assembly_items