Skip to content
Draft
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 @@ -20,6 +20,8 @@ codeunit 99001524 "Subc. Prod. Order Comp. Ext."
ExistingPurchLineErr: Label 'You cannot change this field because the component is already assigned to subcontracting purchase order %1.\\Updating the quantity is only allowed through the purchase order.', Comment = '%1=Document No';
ExistingTransferLineQst: Label 'The component has already been assigned to the subcontracting transfer order %1.\\The quantity may only be updated via the purchase order and processing of the stock transfer.', Comment = '%1=Transfer Order No';
ExistingTransferLineErr: Label 'You cannot open Tracking Specification because this component is already specified in Transfer Order %1.', Comment = '%1=Document No.';
CannotModifyCompTransferExistsErr: Label 'You cannot change this component because transfer orders exist for the linked production order %1, purchase order %2.', Comment = '%1=Production Order No., %2=Purchase Order No.';
CannotModifyCompStockAtSubcErr: Label 'You cannot change this component because there are remaining components or WIP items transferred to the subcontractor for production order %1, purchase order %2.', Comment = '%1=Production Order No., %2=Purchase Order No.';

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Prod. Order Comp.-Reserve", OnAfterInitFromProdOrderComp, '', false, false)]
local procedure OnAfterInitFromProdOrderComp(ProdOrderComponent: Record "Prod. Order Component")
Expand Down Expand Up @@ -57,6 +59,47 @@ codeunit 99001524 "Subc. Prod. Order Comp. Ext."
if Rec.IsTemporary then
exit;
CheckExistingSubcontractingTransferOrder(Rec, xRec, CurrFieldNo);

if CurrFieldNo <> 0 then
if Rec."Location Code" <> xRec."Location Code" then
if xRec."Component Supply Method" = Rec."Component Supply Method"::"Transfer to Vendor" then
CheckUncompletedSubcontractingDocumentsExist(xRec);
end;

[EventSubscriber(ObjectType::Table, Database::"Prod. Order Component", OnBeforeValidateEvent, "Bin Code", false, false)]
local procedure OnBeforeValidateBinCode(var Rec: Record "Prod. Order Component"; var xRec: Record "Prod. Order Component"; CurrFieldNo: Integer)
begin
if Rec.IsTemporary then
exit;

if CurrFieldNo <> 0 then
if Rec."Bin Code" <> xRec."Bin Code" then
if xRec."Component Supply Method" = Rec."Component Supply Method"::"Transfer to Vendor" then
CheckUncompletedSubcontractingDocumentsExist(xRec);
end;

[EventSubscriber(ObjectType::Table, Database::"Prod. Order Component", OnBeforeValidateEvent, "Item No.", false, false)]
local procedure OnBeforeValidateItemNo(var Rec: Record "Prod. Order Component"; var xRec: Record "Prod. Order Component"; CurrFieldNo: Integer)
begin
if Rec.IsTemporary then
exit;

if CurrFieldNo <> 0 then
if Rec."Item No." <> xRec."Item No." then
if xRec."Component Supply Method" = Rec."Component Supply Method"::"Transfer to Vendor" then
CheckUncompletedSubcontractingDocumentsExist(xRec);
end;

[EventSubscriber(ObjectType::Table, Database::"Prod. Order Component", OnBeforeValidateEvent, "Variant Code", false, false)]
local procedure OnBeforeValidateVariantCode(var Rec: Record "Prod. Order Component"; var xRec: Record "Prod. Order Component"; CurrFieldNo: Integer)
begin
if Rec.IsTemporary then
exit;

if CurrFieldNo <> 0 then
if Rec."Variant Code" <> xRec."Variant Code" then
if xRec."Component Supply Method" = Rec."Component Supply Method"::"Transfer to Vendor" then
CheckUncompletedSubcontractingDocumentsExist(xRec);
end;

[EventSubscriber(ObjectType::Table, Database::"Prod. Order Component", OnBeforeValidateEvent, "Quantity per", false, false)]
Expand All @@ -65,6 +108,47 @@ codeunit 99001524 "Subc. Prod. Order Comp. Ext."
if Rec.IsTemporary then
exit;
CheckExistingDocumentsForSubcontracting(Rec, xRec, CurrFieldNo);

if CurrFieldNo <> 0 then
if Rec."Quantity per" <> xRec."Quantity per" then
if xRec."Component Supply Method" = Rec."Component Supply Method"::"Transfer to Vendor" then
CheckUncompletedSubcontractingDocumentsExist(xRec);
end;

[EventSubscriber(ObjectType::Table, Database::"Prod. Order Component", OnBeforeValidateEvent, "Expected Quantity", false, false)]
local procedure OnBeforeValidateExpectedQuantity(var Rec: Record "Prod. Order Component"; var xRec: Record "Prod. Order Component"; CurrFieldNo: Integer)
begin
if Rec.IsTemporary then
exit;

if CurrFieldNo <> 0 then
if Rec."Expected Quantity" <> xRec."Expected Quantity" then
if xRec."Component Supply Method" = Rec."Component Supply Method"::"Transfer to Vendor" then
CheckUncompletedSubcontractingDocumentsExist(xRec);
end;

[EventSubscriber(ObjectType::Table, Database::"Prod. Order Component", OnBeforeValidateEvent, "Component Supply Method", false, false)]
local procedure OnBeforeValidateComponentSupplyMethod(var Rec: Record "Prod. Order Component"; var xRec: Record "Prod. Order Component"; CurrFieldNo: Integer)
begin
if Rec.IsTemporary then
exit;

if CurrFieldNo <> 0 then
if Rec."Component Supply Method" <> xRec."Component Supply Method" then
if xRec."Component Supply Method" = Rec."Component Supply Method"::"Transfer to Vendor" then
CheckUncompletedSubcontractingDocumentsExist(xRec);
end;

[EventSubscriber(ObjectType::Table, Database::"Prod. Order Component", OnBeforeDeleteEvent, '', false, false)]
local procedure OnBeforeDeleteProdOrderComponent(var Rec: Record "Prod. Order Component"; RunTrigger: Boolean)
begin
if Rec.IsTemporary then
exit;
if not RunTrigger then
exit;

if Rec."Component Supply Method" = Rec."Component Supply Method"::"Transfer to Vendor" then
CheckUncompletedSubcontractingDocumentsExist(Rec);
end;

local procedure CheckExistingPostedSubcontractingTransferOrder(ProdOrderComponent: Record "Prod. Order Component"): Boolean
Expand Down Expand Up @@ -323,4 +407,66 @@ codeunit 99001524 "Subc. Prod. Order Comp. Ext."
CheckExistingSubcontractingPurchaseOrder(ProdOrderComponent);
end;
end;

local procedure CheckUncompletedSubcontractingDocumentsExist(ProdOrderComponent: Record "Prod. Order Component")
var
ProdOrderLine: Record "Prod. Order Line";
ProdOrderRoutingLine: Record "Prod. Order Routing Line";
PurchaseLine: Record "Purchase Line";
begin
ProdOrderLine.SetLoadFields("Routing Reference No.", "Routing No.");
if not ProdOrderLine.Get(ProdOrderComponent.Status, ProdOrderComponent."Prod. Order No.", ProdOrderComponent."Prod. Order Line No.") then
exit;

PurchaseLine.SetCurrentKey("Document Type", Type, "Prod. Order No.", "Prod. Order Line No.");
PurchaseLine.SetRange("Document Type", PurchaseLine."Document Type"::Order);
PurchaseLine.SetRange("Prod. Order No.", ProdOrderComponent."Prod. Order No.");
PurchaseLine.SetRange("Prod. Order Line No.", ProdOrderComponent."Prod. Order Line No.");

if ProdOrderComponent."Routing Link Code" <> '' then begin
ProdOrderRoutingLine.SetRange(Status, ProdOrderLine.Status);
ProdOrderRoutingLine.SetRange("Prod. Order No.", ProdOrderLine."Prod. Order No.");
ProdOrderRoutingLine.SetRange("Routing Reference No.", ProdOrderLine."Routing Reference No.");
ProdOrderRoutingLine.SetRange("Routing Link Code", ProdOrderComponent."Routing Link Code");
ProdOrderRoutingLine.SetLoadFields("Operation No.");
if ProdOrderRoutingLine.FindFirst() then
PurchaseLine.SetRange("Operation No.", ProdOrderRoutingLine."Operation No.");
end;

if PurchaseLine.FindSet() then
repeat
if HasSubcTransferForPurchLine(PurchaseLine, ProdOrderComponent) then
Error(CannotModifyCompTransferExistsErr, PurchaseLine."Prod. Order No.", PurchaseLine."Document No.");

ProdOrderComponent.SetRange("Subc. Purchase Order Filter", PurchaseLine."Document No.");
if HasStockAtSubcLocationForComponentForPurchLine(ProdOrderComponent) then
Error(CannotModifyCompStockAtSubcErr, PurchaseLine."Prod. Order No.", PurchaseLine."Document No.");
until PurchaseLine.Next() = 0;
end;

local procedure HasSubcTransferForPurchLine(PurchaseLine: Record "Purchase Line"; ProdOrderComponent: Record "Prod. Order Component"): Boolean
var
TransferLine: Record "Transfer Line";
begin
TransferLine.SetCurrentKey("Subc. Purch. Order No.", "Subc. Prod. Order No.", "Subc. Prod. Order Line No.", "Subc. Operation No.");
TransferLine.SetRange("Subc. Purch. Order No.", PurchaseLine."Document No.");
TransferLine.SetRange("Subc. Prod. Order No.", ProdOrderComponent."Prod. Order No.");
TransferLine.SetRange("Subc. Prod. Order Line No.", ProdOrderComponent."Prod. Order Line No.");
TransferLine.SetRange("Subc. Prod. Ord. Comp Line No.", ProdOrderComponent."Line No.");
exit(not TransferLine.IsEmpty());
end;

local procedure HasStockAtSubcLocationForComponentForPurchLine(ProdOrderComponent: Record "Prod. Order Component"): Boolean
var
SubcTransferManagement: Codeunit "Subc. Transfer Management";
NetStockAtSubcLocation: Decimal;
begin
ProdOrderComponent.CalcFields("Subc. Qty. transf. to Subcontr");
if ProdOrderComponent."Subc. Qty. transf. to Subcontr" = 0 then
exit(false);

NetStockAtSubcLocation := ProdOrderComponent."Subc. Qty. transf. to Subcontr";
NetStockAtSubcLocation -= SubcTransferManagement.CalcConsumedQtyAtSubcLocation(ProdOrderComponent);
exit(NetStockAtSubcLocation > 0);
end;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,31 @@
// ------------------------------------------------------------------------------------------------
namespace Microsoft.Manufacturing.Subcontracting;

using Microsoft.Inventory.Transfer;
using Microsoft.Manufacturing.Document;
using Microsoft.Manufacturing.Routing;
using Microsoft.Manufacturing.WorkCenter;
using Microsoft.Purchases.Document;

codeunit 99001520 "Subc. Prod. Order Rtng. Ext."
{
var
CannotModifyRtngLineTransferExistsErr: Label 'You cannot change this routing line because transfer orders exist for the linked production order %1, purchase order %2.', Comment = '%1=Production Order No., %2=Purchase Order No.';
CannotModifyRtngLineStockAtSubcErr: Label 'You cannot change this routing line because there are remaining components or WIP items transferred to the subcontractor for production order %1, purchase order %2.', Comment = '%1=Production Order No., %2=Purchase Order No.';

[EventSubscriber(ObjectType::Table, Database::"Prod. Order Routing Line", OnBeforeDeleteEvent, '', false, false)]
local procedure OnBeforeDeleteProdOrderRtngLine(var Rec: Record "Prod. Order Routing Line"; RunTrigger: Boolean)
begin
if Rec.IsTemporary then
exit;

if not RunTrigger then
exit;

if Rec."Transfer WIP Item" then
CheckSubcRtngLineDocumentsExist(Rec);
end;

[EventSubscriber(ObjectType::Table, Database::"Prod. Order Routing Line", OnAfterDeleteEvent, '', false, false)]
local procedure OnAfterDeleteProdOrderRtngLine(var Rec: Record "Prod. Order Routing Line"; RunTrigger: Boolean)
begin
Expand All @@ -30,10 +49,58 @@ codeunit 99001520 "Subc. Prod. Order Rtng. Ext."
if Rec.IsTemporary then
exit;

if CurrFieldNo <> 0 then
if (xRec."No." <> Rec."No.") and xRec."Transfer WIP Item" then
CheckSubcRtngLineDocumentsExist(xRec);

if (xRec."No." <> Rec."No.") and (Rec."Routing Link Code" <> '') then
SubcontractingManagement.UpdLinkedComponents(Rec, true);
end;

[EventSubscriber(ObjectType::Table, Database::"Prod. Order Routing Line", OnBeforeValidateEvent, "Operation No.", false, false)]
local procedure OnBeforeValidateOperationNo(var Rec: Record "Prod. Order Routing Line"; var xRec: Record "Prod. Order Routing Line"; CurrFieldNo: Integer)
begin
if Rec.IsTemporary then
exit;

if CurrFieldNo <> 0 then
if (xRec."Operation No." <> Rec."Operation No.") and xRec."Transfer WIP Item" then
CheckSubcRtngLineDocumentsExist(xRec);
end;

[EventSubscriber(ObjectType::Table, Database::"Prod. Order Routing Line", OnBeforeValidateEvent, "Routing Link Code", false, false)]
local procedure OnBeforeValidateRoutingLinkCode(var Rec: Record "Prod. Order Routing Line"; var xRec: Record "Prod. Order Routing Line"; CurrFieldNo: Integer)
begin
if Rec.IsTemporary then
exit;

if CurrFieldNo <> 0 then
if (xRec."Routing Link Code" <> Rec."Routing Link Code") and xRec."Transfer WIP Item" then
CheckSubcRtngLineDocumentsExist(xRec);
end;

[EventSubscriber(ObjectType::Table, Database::"Prod. Order Routing Line", OnBeforeValidateEvent, "Type", false, false)]
local procedure OnBeforeValidateType(var Rec: Record "Prod. Order Routing Line"; var xRec: Record "Prod. Order Routing Line"; CurrFieldNo: Integer)
begin
if Rec.IsTemporary then
exit;

if CurrFieldNo <> 0 then
if (xRec.Type <> Rec.Type) and xRec."Transfer WIP Item" then
CheckSubcRtngLineDocumentsExist(xRec);
end;

[EventSubscriber(ObjectType::Table, Database::"Prod. Order Routing Line", OnBeforeValidateEvent, "Transfer WIP Item", false, false)]
local procedure OnBeforeValidateTransferWIPItem(var Rec: Record "Prod. Order Routing Line"; var xRec: Record "Prod. Order Routing Line"; CurrFieldNo: Integer)
begin
if Rec.IsTemporary then
exit;

if CurrFieldNo <> 0 then
if (xRec."Transfer WIP Item" <> Rec."Transfer WIP Item") and xRec."Transfer WIP Item" then
CheckSubcRtngLineDocumentsExist(xRec);
end;

[EventSubscriber(ObjectType::Table, Database::"Prod. Order Routing Line", OnAfterValidateEvent, "Routing Link Code", false, false)]
local procedure OnAfterValidateRoutingLinkCode(var Rec: Record "Prod. Order Routing Line"; var xRec: Record "Prod. Order Routing Line"; CurrFieldNo: Integer)
begin
Expand Down Expand Up @@ -101,4 +168,73 @@ codeunit 99001520 "Subc. Prod. Order Rtng. Ext."
SubcontractingManagement.DelLocationLinkedComponents(ProdOrderRoutingLine, false);
end;
end;

local procedure CheckSubcRtngLineDocumentsExist(ProdOrderRoutingLine: Record "Prod. Order Routing Line")
var
PurchaseLine: Record "Purchase Line";
begin
PurchaseLine.SetCurrentKey("Document Type", Type, "Prod. Order No.", "Prod. Order Line No.");
PurchaseLine.SetRange("Document Type", PurchaseLine."Document Type"::Order);
PurchaseLine.SetRange("Prod. Order No.", ProdOrderRoutingLine."Prod. Order No.");
PurchaseLine.SetRange("Routing No.", ProdOrderRoutingLine."Routing No.");
PurchaseLine.SetRange("Routing Reference No.", ProdOrderRoutingLine."Routing Reference No.");
PurchaseLine.SetRange("Operation No.", ProdOrderRoutingLine."Operation No.");
if PurchaseLine.FindSet() then
repeat
if HasSubcTransferForPurchLine(PurchaseLine) then
Error(CannotModifyRtngLineTransferExistsErr, PurchaseLine."Prod. Order No.", PurchaseLine."Document No.");
if HasStockAtSubcLocation(PurchaseLine, ProdOrderRoutingLine) then
Error(CannotModifyRtngLineStockAtSubcErr, PurchaseLine."Prod. Order No.", PurchaseLine."Document No.");
until PurchaseLine.Next() = 0;
end;

local procedure HasSubcTransferForPurchLine(PurchaseLine: Record "Purchase Line"): Boolean
var
TransferLine: Record "Transfer Line";
begin
TransferLine.SetRange("Subc. Purch. Order No.", PurchaseLine."Document No.");
TransferLine.SetRange("Subc. Purch. Order Line No.", PurchaseLine."Line No.");
TransferLine.SetRange("Subc. Prod. Order No.", PurchaseLine."Prod. Order No.");
exit(not TransferLine.IsEmpty());
end;

local procedure HasStockAtSubcLocation(PurchaseLine: Record "Purchase Line"; ProdOrderRoutingLine: Record "Prod. Order Routing Line"): Boolean
var
ProdOrderComponent: Record "Prod. Order Component";
SubcWIPLedgerEntry: Record "Subcontractor WIP Ledger Entry";
SubcTransferManagement: Codeunit "Subc. Transfer Management";
NetStockAtSubcLocation: Decimal;
begin
ProdOrderComponent.SetCurrentKey(Status, "Prod. Order No.", "Routing Link Code");
ProdOrderComponent.SetRange(Status, "Production Order Status"::Released);
ProdOrderComponent.SetRange("Prod. Order No.", PurchaseLine."Prod. Order No.");
ProdOrderComponent.SetRange("Prod. Order Line No.", PurchaseLine."Prod. Order Line No.");
ProdOrderComponent.SetRange("Component Supply Method", ProdOrderComponent."Component Supply Method"::"Transfer to Vendor");
ProdOrderComponent.SetRange("Subc. Purchase Order Filter", PurchaseLine."Document No.");
ProdOrderComponent.SetRange("Routing Link Code", ProdOrderRoutingLine."Routing Link Code");
ProdOrderComponent.SetAutoCalcFields("Subc. Qty. transf. to Subcontr");
if ProdOrderComponent.FindSet() then
repeat
if ProdOrderComponent."Subc. Qty. transf. to Subcontr" <> 0 then begin
NetStockAtSubcLocation := ProdOrderComponent."Subc. Qty. transf. to Subcontr";
NetStockAtSubcLocation -= SubcTransferManagement.CalcConsumedQtyAtSubcLocation(ProdOrderComponent);
if NetStockAtSubcLocation > 0 then
exit(true);
end;
until ProdOrderComponent.Next() = 0;

SubcWIPLedgerEntry.SetCurrentKey("Prod. Order No.", "Prod. Order Status", "Prod. Order Line No.", "Routing Reference No.", "Routing No.", "Operation No.", "Location Code");
SubcWIPLedgerEntry.SetRange("Prod. Order No.", PurchaseLine."Prod. Order No.");
SubcWIPLedgerEntry.SetRange("Prod. Order Status", "Production Order Status"::Released);
SubcWIPLedgerEntry.SetRange("Prod. Order Line No.", PurchaseLine."Prod. Order Line No.");
SubcWIPLedgerEntry.SetRange("Routing Reference No.", ProdOrderRoutingLine."Routing Reference No.");
SubcWIPLedgerEntry.SetRange("Routing No.", ProdOrderRoutingLine."Routing No.");
SubcWIPLedgerEntry.SetRange("Operation No.", ProdOrderRoutingLine."Operation No.");
SubcWIPLedgerEntry.SetRange("In Transit", false);
SubcWIPLedgerEntry.CalcSums("Quantity (Base)");
if SubcWIPLedgerEntry."Quantity (Base)" <> 0 then
exit(true);

exit(false);
end;
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ codeunit 99001516 "Subc. Req. Wksh. Make Ord."
ProdOrderComponent.SetRange("Prod. Order Line No.", RequisitionLine."Prod. Order Line No.");
ProdOrderComponent.SetRange("Routing Link Code", ProdOrderRoutingLine."Routing Link Code");
ProdOrderComponent.SetRange("Component Supply Method", "Component Supply Method"::"Vendor-Supplied");
ProdOrderComponent.SetLoadFields("Item No.", "Variant Code", "Remaining Quantity");
if ProdOrderComponent.FindSet() then
repeat
PurchaseLineComp.SetRange("Document Type", PurchaseLine."Document Type");
Expand Down
Loading
Loading