+local $::locale = Locale->new('en');
+reset_db();
+create_standard_stock();
+
+set_stock(
+ part => $part1,
+ qty => 5,
+ bin => $bin1,
+);
+set_stock(
+ part => $part2,
+ qty => 10,
+ bin => $bin1,
+);
+
+SL::Helper::Inventory::produce_assembly(
+ part => $assembly1,
+ qty => 3,
+ auto_allocate => 1,
+
+ # where to put it
+ bin => $bin1,
+ chargenumber => "537",
+);
+
+is(SL::Helper::Inventory::get_stock(part => $assembly1), "3.00000", 'produce with auto allocation works');
+is(SL::Helper::Inventory::get_stock(part => $part1), "2.00000", 'and consumes...');
+is(SL::Helper::Inventory::get_stock(part => $part2), "7.00000", '..the materials');
+
+# check comments and warehouses
+$::form->{l_comment} = 'Y';
+$::form->{l_warehouse_from} = 'Y';
+$::form->{l_warehouse_to} = 'Y';
+local $::instance_conf->data->{produce_assembly_same_warehouse} = 1;
+
+@contents = WH->get_warehouse_journal(sort => 'date');
+
+cmp_deeply(\@contents,
+ [ ignore(), ignore(),
+ superhashof({
+ 'comment' => 'Used for assembly '. $assembly1->partnumber .' Test Assembly',
+ 'warehouse_from' => 'Warehouse'
+ }),
+ superhashof({
+ 'comment' => 'Used for assembly '. $assembly1->partnumber .' Test Assembly',
+ 'warehouse_from' => 'Warehouse'
+ }),
+ superhashof({
+ 'part_type' => 'assembly',
+ 'warehouse_to' => 'Warehouse'
+ }),
+ ],
+ "Comments for assembly productions are ok"
+);
+
+# try to produce something for our lunar warehouse, but parts are only available on earth
+dies_ok(sub {
+SL::Helper::Inventory::produce_assembly(
+ part => $assembly1,
+ qty => 1,
+ auto_allocate => 1,
+ # where to put it
+ bin => $bin_moon,
+ chargenumber => "Lunar Dust inside",
+);
+}, "producing for wrong warehouse dies");
+
+# same test, but check exception class
+throws_ok{
+SL::Helper::Inventory::produce_assembly(
+ part => $assembly1,
+ qty => 1,
+ auto_allocate => 1,
+ # where to put it
+ bin => $bin_moon,
+ chargenumber => "Lunar Dust inside",
+);
+ } "SL::X::Inventory::Allocation", "producing for wrong warehouse throws correct error class";
+
+# same test, but check user feedback for the error message
+throws_ok{
+SL::Helper::Inventory::produce_assembly(
+ part => $assembly1,
+ qty => 1,
+ auto_allocate => 1,
+ # where to put it
+ bin => $bin_moon,
+ chargenumber => "Lunar Dust inside",
+);
+ } qr/Part ap (1|2) Testpart (1|2) exists in warehouse Warehouse, but not in warehouse Our warehouse location at the moon/, "producing for wrong warehouse throws correct error message";
+
+# try to produce without allocations dies
+
+dies_ok(sub {
+SL::Helper::Inventory::produce_assembly(
+ part => $assembly1,
+ qty => 3,
+
+ # where to put it
+ bin => $bin1,
+ chargenumber => "537",
+);
+}, "producing without allocations dies");
+
+# try to produce with insufficient allocations dies
+
+@alloc1 = SL::Helper::Inventory::allocate(part => $part1, qty => 1);
+@alloc2 = SL::Helper::Inventory::allocate(part => $part2, qty => 1);
+
+dies_ok(sub {
+SL::Helper::Inventory::produce_assembly(
+ part => $assembly1,
+ qty => 3,
+ allocations => [ @alloc1, @alloc2 ],
+
+ # where to put it
+ bin => $bin1,
+ chargenumber => "537",
+);
+}, "producing with insufficient allocations dies");
+
+
+# assembly with service default tests (services won't be consumed)
+
+local $::locale = Locale->new('en');
+reset_db();
+create_standard_stock();
+
+set_stock(
+ part => $part1,
+ qty => 12,
+ bin => $bin2,
+);
+set_stock(
+ part => $part2,
+ qty => 6.34,
+ bin => $bin2,
+);
+
+SL::Helper::Inventory::produce_assembly(
+ part => $assembly_service,
+ qty => 1,
+ auto_allocate => 1,
+ # where to put it
+ bin => $bin1,
+);
+
+is(SL::Helper::Inventory::get_stock(part => $assembly_service), "1.00000", 'produce with auto allocation works');
+is(SL::Helper::Inventory::get_stock(part => $part1), "0.00000", 'and consumes...');
+is(SL::Helper::Inventory::get_stock(part => $part2), "0.00000", '..the materials');
+
+# check comments and warehouses
+$::form->{l_comment} = 'Y';
+$::form->{l_warehouse_from} = 'Y';
+$::form->{l_warehouse_to} = 'Y';
+local $::instance_conf->data->{produce_assembly_same_warehouse} = 1;
+
+@contents = WH->get_warehouse_journal(sort => 'date');
+
+cmp_deeply(\@contents,
+ [ ignore(), ignore(),
+ superhashof({
+ 'comment' => 'Used for assembly '. $assembly_service->partnumber .' Ein Erzeugnis mit Dienstleistungen',
+ 'warehouse_from' => 'Warehouse'
+ }),
+ superhashof({
+ 'comment' => 'Used for assembly '. $assembly_service->partnumber .' Ein Erzeugnis mit Dienstleistungen',
+ 'warehouse_from' => 'Warehouse'
+ }),
+ superhashof({
+ 'part_type' => 'assembly',
+ 'warehouse_to' => 'Warehouse'
+ }),
+ ],
+ "Comments for assembly with service productions are ok"
+);
+
+# assembly with service non default tests (services will be consumed)
+
+local $::instance_conf->data->{produce_assembly_transfer_service} = 1;
+
+set_stock(
+ part => $part1,
+ qty => 12,
+ bin => $bin2,
+);
+set_stock(
+ part => $part2,
+ qty => 6.34,
+ bin => $bin2,
+);
+
+throws_ok{
+ SL::Helper::Inventory::produce_assembly(
+ part => $assembly_service,
+ qty => 1,
+ auto_allocate => 1,
+ # where to put it
+ bin => $bin1,
+ );
+} qr/can not allocate 1,2 units of service number 1 We really need this service, missing 1,2 units/, "producing assembly with services and unstocked service throws correct error message";
+
+is(SL::Helper::Inventory::get_stock(part => $assembly_service), "1.00000", 'produce without service does not work');
+is(SL::Helper::Inventory::get_stock(part => $part1), "12.00000", 'and does not consume...');
+is(SL::Helper::Inventory::get_stock(part => $part2), "6.34000", '..the materials');
+
+
+# ok, now add the missing service
+is('SL::DB::Part', ref $service1);
+set_stock(
+ part => $service1,
+ qty => 1.2,
+ bin => $bin2,
+);
+
+SL::Helper::Inventory::produce_assembly(
+ part => $assembly_service,
+ qty => 1,
+ auto_allocate => 1,
+ # where to put it
+ bin => $bin1,
+);
+
+is(SL::Helper::Inventory::get_stock(part => $assembly_service), "2.00000", 'produce with service does work if services is needed and stocked');
+is(SL::Helper::Inventory::get_stock(part => $part1), "0.00000", 'and does consume...');
+is(SL::Helper::Inventory::get_stock(part => $part2), "0.00000", '..the materials');
+is(SL::Helper::Inventory::get_stock(part => $service1), "0.00000", '..and service');
+
+# check comments and warehouses for assembly with service
+$::form->{l_comment} = 'Y';
+$::form->{l_warehouse_from} = 'Y';
+$::form->{l_warehouse_to} = 'Y';
+local $::instance_conf->data->{produce_assembly_same_warehouse} = 1;
+
+@contents = WH->get_warehouse_journal(sort => 'date');
+#use Data::Dumper;
+#diag("hier" . Dumper(@contents));
+cmp_deeply(\@contents,
+ [ ignore(), ignore(), ignore(), ignore(), ignore(), ignore(), ignore(), ignore(),
+ superhashof({
+ 'comment' => 'Used for assembly '. $assembly_service->partnumber .' Ein Erzeugnis mit Dienstleistungen',
+ 'warehouse_from' => 'Warehouse'
+ }),
+ superhashof({
+ 'comment' => 'Used for assembly '. $assembly_service->partnumber .' Ein Erzeugnis mit Dienstleistungen',
+ 'warehouse_from' => 'Warehouse'
+ }),
+ superhashof({
+ 'comment' => 'Used for assembly '. $assembly_service->partnumber .' Ein Erzeugnis mit Dienstleistungen',
+ 'warehouse_from' => 'Warehouse',
+ 'part_type' => 'service',
+ 'qty' => '1.20000',
+ }),
+ superhashof({
+ 'part_type' => 'assembly',
+ 'warehouse_to' => 'Warehouse'
+ }),
+ ],
+ "Comments for assembly with service productions are ok"
+);
+
+
+
+# bestbefore tests
+
+reset_db();
+create_standard_stock();
+
+set_stock(
+ part => $part1,
+ qty => 5,
+ bin => $bin1,
+);
+set_stock(
+ part => $part2,
+ qty => 10,
+ bin => $bin1,
+);
+
+
+
+SL::Helper::Inventory::produce_assembly(
+ part => $assembly1,
+ qty => 3,
+ auto_allocate => 1,
+
+ bin => $bin1,
+ chargenumber => "537",
+ bestbefore => DateTime->today->clone->add(days => -14), # expired 2 weeks ago
+ shippingdate => DateTime->today->clone->add(days => 1),
+);
+
+is(SL::Helper::Inventory::get_stock(part => $assembly1), "3.00000", 'produce with bestbefore works');
+is(SL::Helper::Inventory::get_onhand(part => $assembly1), "3.00000", 'produce with bestbefore works');
+is(SL::Helper::Inventory::get_stock(
+ part => $assembly1,
+ bestbefore => DateTime->today,
+), undef, 'get_stock with bestbefore date skips expired');
+{
+ local $::instance_conf->data->{show_bestbefore} = 1;
+ is(SL::Helper::Inventory::get_onhand(
+ part => $assembly1,
+ ), undef, 'get_onhand with bestbefore skips expired as of today');
+}
+
+{
+ local $::instance_conf->data->{show_bestbefore} = 0;
+ is(SL::Helper::Inventory::get_onhand(
+ part => $assembly1,
+ ), "3.00000", 'get_onhand without bestbefore finds all');
+}
+