7 use SL::Dev::Part qw(new_part new_assembly);
 
   8 use SL::Dev::Inventory qw(create_warehouse_and_bins set_stock);
 
   9 use SL::Dev::Record qw(create_sales_order);
 
  11 use_ok 'Support::TestSetup';
 
  13 use_ok 'SL::DB::Part';
 
  14 use_ok 'SL::DB::Warehouse';
 
  15 use_ok 'SL::DB::Inventory';
 
  17 use_ok 'SL::Helper::Inventory';
 
  19 Support::TestSetup::login();
 
  21 my ($wh, $bin1, $bin2, $assembly1, $part1, $part2);
 
  24 create_standard_stock();
 
  27 # simple stock in, get_stock, get_onhand
 
  34 is(SL::Helper::Inventory::get_stock(part => $part1), "25.00000", 'simple get_stock works');
 
  35 is(SL::Helper::Inventory::get_onhand(part => $part1), "25.00000", 'simple get_onhand works');
 
  37 # stock on some more, get_stock, get_onhand
 
  40   parts_id          => $part1->id,
 
  42   transfer_type     => 'stock',
 
  43   dst_warehouse_id  => $bin1->warehouse_id,
 
  44   dst_bin_id        => $bin1->id,
 
  49   parts_id          => $part1->id,
 
  51   transfer_type     => 'stock',
 
  52   chargenumber      => '298345',
 
  53   dst_warehouse_id  => $bin1->warehouse_id,
 
  54   dst_bin_id        => $bin1->id,
 
  58 is(SL::Helper::Inventory::get_stock(part => $part1), "60.00000", 'normal get_stock works');
 
  59 is(SL::Helper::Inventory::get_onhand(part => $part1), "60.00000", 'normal get_onhand works');
 
  63 my @allocations = SL::Helper::Inventory::allocate(
 
  68 is_deeply(\%{ $allocations[0] }, {
 
  72    parts_id          => $part1->id,
 
  74    warehouse_id      => $wh->id,
 
  75    comment           => undef, # comment is not a partition so is not set by allocate
 
  76    for_object_id     => undef,
 
  77  }, 'allocation works');
 
  79 # allocate something where more than one result will match
 
  81 @allocations = SL::Helper::Inventory::allocate(
 
  86 is_deeply(\@allocations, [
 
  91     parts_id          => $part1->id,
 
  93     warehouse_id      => $wh->id,
 
  95     for_object_id     => undef,
 
 100     chargenumber      => '298345',
 
 101     parts_id          => $part1->id,
 
 103     warehouse_id      => $wh->id,
 
 105     for_object_id     => undef,
 
 107 ], 'complex allocation works');
 
 109 # try to allocate too much
 
 112   SL::Helper::Inventory::allocate(part => $part1, qty => 100)
 
 114 "allocate too much dies");
 
 119 create_standard_stock();
 
 133 my @alloc1 = SL::Helper::Inventory::allocate(part => $part1, qty => 3);
 
 134 my @alloc2 = SL::Helper::Inventory::allocate(part => $part2, qty => 3);
 
 136 SL::Helper::Inventory::produce_assembly(
 
 139   allocations => [ @alloc1, @alloc2 ],
 
 143   chargenumber => "537",
 
 146 is(SL::Helper::Inventory::get_stock(part => $assembly1), "3.00000", 'produce works');
 
 147 is(SL::Helper::Inventory::get_stock(part => $part1), "2.00000", 'and consumes...');
 
 148 is(SL::Helper::Inventory::get_stock(part => $part2), "7.00000", '..the materials');
 
 150 # produce the same using auto_allocation
 
 153 create_standard_stock();
 
 166 SL::Helper::Inventory::produce_assembly(
 
 173   chargenumber => "537",
 
 176 is(SL::Helper::Inventory::get_stock(part => $assembly1), "3.00000", 'produce with auto allocation works');
 
 177 is(SL::Helper::Inventory::get_stock(part => $part1), "2.00000", 'and consumes...');
 
 178 is(SL::Helper::Inventory::get_stock(part => $part2), "7.00000", '..the materials');
 
 180 # try to produce without allocations dies
 
 183 SL::Helper::Inventory::produce_assembly(
 
 189   chargenumber => "537",
 
 191 }, "producing without allocations dies");
 
 193 # try to produce with insufficient allocations dies
 
 195 @alloc1 = SL::Helper::Inventory::allocate(part => $part1, qty => 1);
 
 196 @alloc2 = SL::Helper::Inventory::allocate(part => $part2, qty => 1);
 
 199 SL::Helper::Inventory::produce_assembly(
 
 202   allocations => [ @alloc1, @alloc2 ],
 
 206   chargenumber => "537",
 
 208 }, "producing with insufficient allocations dies");
 
 215 create_standard_stock();
 
 230 SL::Helper::Inventory::produce_assembly(
 
 236   chargenumber      => "537",
 
 237   bestbefore        => DateTime->today->clone->add(days => -14), # expired 2 weeks ago
 
 238   shippingdate      => DateTime->today->clone->add(days => 1),
 
 241 is(SL::Helper::Inventory::get_stock(part => $assembly1), "3.00000", 'produce with bestbefore works');
 
 242 is(SL::Helper::Inventory::get_onhand(part => $assembly1), "3.00000", 'produce with bestbefore works');
 
 243 is(SL::Helper::Inventory::get_stock(
 
 245   bestbefore => DateTime->today,
 
 246 ), undef, 'get_stock with bestbefore date skips expired');
 
 248   local $::instance_conf->data->{show_bestbefore} = 1;
 
 249   is(SL::Helper::Inventory::get_onhand(
 
 251   ), undef, 'get_onhand with bestbefore skips expired as of today');
 
 255   local $::instance_conf->data->{show_bestbefore} = 0;
 
 256   is(SL::Helper::Inventory::get_onhand(
 
 258   ), "3.00000", 'get_onhand without bestbefore finds all');
 
 263   SL::DB::Manager::Order->delete_all(all => 1);
 
 264   SL::DB::Manager::Inventory->delete_all(all => 1);
 
 265   SL::DB::Manager::Assembly->delete_all(all => 1);
 
 266   SL::DB::Manager::Part->delete_all(all => 1);
 
 267   SL::DB::Manager::Bin->delete_all(all => 1);
 
 268   SL::DB::Manager::Warehouse->delete_all(all => 1);
 
 271 sub create_standard_stock {
 
 272   ($wh, $bin1) = create_warehouse_and_bins();
 
 273   $bin2 = SL::DB::Bin->new(description => "Bin 2", warehouse => $wh)->save;
 
 276   $assembly1  =  new_assembly(number_of_parts => 2)->save;
 
 277   ($part1, $part2) = map { $_->part } $assembly1->assemblies;