Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ namespace Microsoft.Manufacturing.Subcontracting;
using Microsoft.Foundation.UOM;
using Microsoft.Inventory.Costing;
using Microsoft.Inventory.Item;
using Microsoft.Inventory.Location;
using Microsoft.Inventory.Setup;
using Microsoft.Inventory.Transfer;
using Microsoft.Manufacturing.Document;
using Microsoft.Manufacturing.WorkCenter;
Expand Down Expand Up @@ -83,6 +85,27 @@ report 20501 "Subc. Create Transf. Order"
OrderNoDoesNotExistInProdOrderErr: Label 'Operation %1 in the subcontracting order %2 does not exist in the routing %3 of the production order %4.', Comment = '%1=Operation No., %2=Purchase Order No., %3=Routing No., %4=Production Order No.';
OrderNoIsNotSubcontractorErr: Label 'Order %1 is not a Subcontractor work.', Comment = '%1=Purchase Order No.';
WarningToSpecifyPurchOrderErr: Label 'Warning. Specify a Purchase Order No. for the Subcontractor work.';
CannotCreateTransferErr: Label 'Cannot create a transfer from location %1 to location %2 because location %1 requires warehousing. Set up an in-transit transfer route between the locations, or set Direct Transfer Posting to Direct Transfer in Inventory Setup.', Comment = '%1=Transfer-from location code, %2=Transfer-to location code';

local procedure CheckDirectTransferAllowed(TransferFromLocation: Code[10]; TransferToLocation: Code[10])
var
Location: Record Location;
begin
if IsOneStepDirectTransfer() then
exit;

if Location.RequirePicking(TransferFromLocation) or Location.RequireShipment(TransferFromLocation) then
Error(CannotCreateTransferErr, TransferFromLocation, TransferToLocation);
end;

local procedure IsOneStepDirectTransfer(): Boolean
var
InventorySetup: Record "Inventory Setup";
begin
InventorySetup.SetLoadFields("Direct Transfer Posting");
InventorySetup.GetRecordOnce();
exit(InventorySetup."Direct Transfer Posting" = InventorySetup."Direct Transfer Posting"::"Direct Transfer");
end;

local procedure InsertTransferHeader(TransferFromLocation: Code[10])
var
Expand All @@ -106,8 +129,10 @@ report 20501 "Subc. Create Transf. Order"
TransferHeader.Insert(true);
TransferHeader.Validate("Transfer-from Code", TransferFromLocation);
TransferHeader.Validate("Transfer-to Code", TransferToLocationCode);
if not TransferRoute.Get(TransferFromLocation, TransferToLocationCode) or (TransferRoute."In-Transit Code" = '') then
if not TransferRoute.Get(TransferFromLocation, TransferToLocationCode) or (TransferRoute."In-Transit Code" = '') then begin
CheckDirectTransferAllowed(TransferFromLocation, TransferToLocationCode);
TransferHeader.Validate("Direct Transfer", true);
end;

TransferHeader."Subc. Source Type" := TransferHeader."Subc. Source Type"::Subcontracting;
TransferHeader."Source ID" := "Purchase Header"."Buy-from Vendor No.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ using Microsoft.Foundation.Company;
using Microsoft.Inventory.Item;
using Microsoft.Inventory.Journal;
using Microsoft.Inventory.Location;
using Microsoft.Inventory.Setup;
using Microsoft.Inventory.Transfer;
using Microsoft.Manufacturing.Document;
using Microsoft.Manufacturing.MachineCenter;
Expand Down Expand Up @@ -62,6 +63,8 @@ codeunit 139981 "Subc. Location Handler Test"
LibraryERMCountryData.CreateVATData();
SubSetupLibrary.InitialSetupForGenProdPostingGroup();

LibrarySetupStorage.Save(Database::"Inventory Setup");

IsInitialized := true;
Commit();

Expand Down Expand Up @@ -197,6 +200,99 @@ codeunit 139981 "Subc. Location Handler Test"
Assert.AreEqual(LocationSub.Code, TransferHeader."Transfer-to Code", 'Transfer-to Code should be Subcontractor Location');
end;

[Test]
procedure DirectTransferFromRequireShipmentLocationIsBlocked()
var
Item: Record Item;
LocationOrig: Record Location;
LocationSub: Record Location;
ProdOrder: Record "Production Order";
ProdOrderComp: Record "Prod. Order Component";
ProdOrderLine: Record "Prod. Order Line";
ProdOrderRtngLine: Record "Prod. Order Routing Line";
PurchaseHeader: Record "Purchase Header";
PurchaseLine: Record "Purchase Line";
Vendor: Record Vendor;
CreateSubCTransfOrder: Report "Subc. Create Transf. Order";
begin
// [SCENARIO 640958] Creating a subcontracting transfer with no in-transit route from a location that
// requires a shipment is blocked with a guided error instead of a raw TestField error.
Initialize();

// [GIVEN] Subcontractor and Original locations; the Original location requires a shipment; no in-transit transfer route exists.
LibraryWarehouse.CreateLocation(LocationSub);
LibraryWarehouse.CreateLocation(LocationOrig);
LocationOrig."Require Shipment" := true;
LocationOrig.Modify(true);

// [GIVEN] Inventory Setup posts direct transfers via Receipt and Shipment (so warehouse handling is enforced)
SetInventoryDirectTransferPosting(false);

// [GIVEN] Subcontracting Scenario Setup (component at the subcontractor location, original at the require-shipment location)
CreateSubcontractingSetup(
PurchaseHeader, PurchaseLine, ProdOrder, ProdOrderLine, ProdOrderComp, ProdOrderRtngLine, Vendor,
LocationSub, Item, LibraryRandom.RandInt(10), LocationSub.Code, LocationOrig.Code);

// [WHEN] Running the Create Subcontracting Transfer Order report
Commit(); // Report requires commit
PurchaseHeader.SetRecFilter();
CreateSubCTransfOrder.SetTableView(PurchaseHeader);
CreateSubCTransfOrder.UseRequestPage(false);

// [THEN] A guided error is raised instead of a raw TestField error on the location
asserterror CreateSubCTransfOrder.Run();
Assert.ExpectedError('requires warehousing');
end;

[Test]
[HandlerFunctions('HandleTransferOrder')]
procedure DirectTransferFromRequireShipmentLocationAllowedWithDirectTransferPosting()
var
Item: Record Item;
LocationOrig: Record Location;
LocationSub: Record Location;
ProdOrder: Record "Production Order";
ProdOrderComp: Record "Prod. Order Component";
ProdOrderLine: Record "Prod. Order Line";
ProdOrderRtngLine: Record "Prod. Order Routing Line";
PurchaseHeader: Record "Purchase Header";
PurchaseLine: Record "Purchase Line";
TransferHeader: Record "Transfer Header";
Vendor: Record Vendor;
CreateSubCTransfOrder: Report "Subc. Create Transf. Order";
begin
// [SCENARIO 640958] When Inventory Setup posts direct transfers as Direct Transfer, the transfer is created
// from a require-shipment source location instead of being blocked, because the Direct Transfer
// posting type skips the outbound warehouse-handling check.
Initialize();

// [GIVEN] Subcontractor and Original locations; the Original location requires a shipment; no in-transit route exists.
LibraryWarehouse.CreateLocation(LocationSub);
LibraryWarehouse.CreateLocation(LocationOrig);
LocationOrig."Require Shipment" := true;
LocationOrig.Modify(true);

// [GIVEN] Inventory Setup posts direct transfers via Direct Transfer
SetInventoryDirectTransferPosting(true);

// [GIVEN] Subcontracting Scenario Setup
CreateSubcontractingSetup(
PurchaseHeader, PurchaseLine, ProdOrder, ProdOrderLine, ProdOrderComp, ProdOrderRtngLine, Vendor,
LocationSub, Item, LibraryRandom.RandInt(10), LocationSub.Code, LocationOrig.Code);

// [WHEN] Running the Create Subcontracting Transfer Order report
Commit(); // Report requires commit
PurchaseHeader.SetRecFilter();
CreateSubCTransfOrder.SetTableView(PurchaseHeader);
CreateSubCTransfOrder.UseRequestPage(false);
CreateSubCTransfOrder.Run();

// [THEN] A direct transfer order is created (not blocked)
TransferHeader.SetRange("Subcontr. Purch. Order No.", PurchaseHeader."No.");
Assert.IsTrue(TransferHeader.FindFirst(), 'A transfer order should be created when Inventory Setup uses Direct Transfer posting.');
Assert.IsTrue(TransferHeader."Direct Transfer", 'The created transfer order should be a direct transfer.');
end;

[Test]
[HandlerFunctions('HandleTransferOrder')]
procedure TestTransferOrderCreation_PostAndRecreate()
Expand Down Expand Up @@ -624,4 +720,16 @@ codeunit 139981 "Subc. Location Handler Test"
procedure HandleTransferOrder(var TransfOrderPage: TestPage "Transfer Order")
begin
end;

local procedure SetInventoryDirectTransferPosting(UseDirectTransfer: Boolean)
var
InventorySetup: Record "Inventory Setup";
begin
InventorySetup.Get();
if UseDirectTransfer then
InventorySetup.Validate("Direct Transfer Posting", InventorySetup."Direct Transfer Posting"::"Direct Transfer")
else
InventorySetup.Validate("Direct Transfer Posting", InventorySetup."Direct Transfer Posting"::"Receipt and Shipment");
InventorySetup.Modify(true);
end;
}
Loading