diff --git a/src/Layers/BE/Tests/SCM-Manufacturing/SCMManufacturing70.Codeunit.al b/src/Layers/BE/Tests/SCM-Manufacturing/SCMManufacturing70.Codeunit.al index 692b0e4564c..e6f8f4a68da 100644 --- a/src/Layers/BE/Tests/SCM-Manufacturing/SCMManufacturing70.Codeunit.al +++ b/src/Layers/BE/Tests/SCM-Manufacturing/SCMManufacturing70.Codeunit.al @@ -33,6 +33,7 @@ using Microsoft.Manufacturing.Routing; using Microsoft.Manufacturing.Setup; using Microsoft.Manufacturing.WorkCenter; using Microsoft.Purchases.Document; +using Microsoft.Purchases.History; using Microsoft.Purchases.Setup; using Microsoft.Purchases.Vendor; using Microsoft.Sales.Document; @@ -3903,6 +3904,69 @@ codeunit 137063 "SCM Manufacturing 7.0" Assert.ExpectedTestFieldError(ProductionOrder.FieldCaption("Variant Code"), ''); end; + [Test] + [HandlerFunctions('PostedPurchaseDocumentLinesPageHandler')] + procedure PostPurchaseReturnOrderForSubcontractingWhenLastOperationIsNotSubcontracted() + var + CapacityUnitOfMeasure: Record "Capacity Unit of Measure"; + Item: Record Item; + ProductionOrder: Record "Production Order"; + PurchaseHeader: Record "Purchase Header"; + PurchaseLine: Record "Purchase Line"; + PurchInvLine: Record "Purch. Inv. Line"; + RequisitionLine: Record "Requisition Line"; + RoutingHeader: Record "Routing Header"; + RoutingLine: Record "Routing Line"; + SubcontractingWorkCenter: Record "Work Center"; + WorkCenter: Record "Work Center"; + OperationNo: Code[10]; + begin + // [FEATURE] [AI test 0.4] + // [SCENARIO 647380] A subcontracting purchase return order can be posted when a later operation is not subcontracted. + Initialize(); + + // [GIVEN] A released production order whose subcontracting operation is followed by a non-subcontracting operation. + OperationNo := Format(10 + LibraryRandom.RandInt(10)); + CreateSubcontractingSetup(SubcontractingWorkCenter, RoutingHeader, OperationNo); + UpdateRoutingStatus(RoutingHeader, RoutingHeader.Status::"Under Development"); + CreateWorkCenterSetup(WorkCenter, CapacityUnitOfMeasure.Type::Minutes, 160000T, 235959T); + CreateRoutingLine(RoutingLine, RoutingHeader, WorkCenter."No."); + UpdateRoutingStatus(RoutingHeader, RoutingHeader.Status::Certified); + CreateProdItem(Item, RoutingHeader."No."); + CreateAndRefreshProdOrder( + ProductionOrder, ProductionOrder.Status::Released, Item."No.", LibraryRandom.RandInt(10), + ProductionOrder."Source Type"::Item, false); + + // [GIVEN] A subcontracting purchase order created from the subcontracting worksheet is received and invoiced. + CalculateSubcontractOrder(RequisitionLine, SubcontractingWorkCenter."No.", ProductionOrder); + LibraryPlanning.CarryOutAMSubcontractWksh(RequisitionLine); + PurchaseLine.SetRange("Document Type", PurchaseLine."Document Type"::Order); + PurchaseLine.SetRange("Prod. Order No.", ProductionOrder."No."); + PurchaseLine.SetRange("Operation No.", OperationNo); + PurchaseLine.FindFirst(); + PurchaseHeader.Get(PurchaseLine."Document Type", PurchaseLine."Document No."); + PurchaseHeader.Validate("Vendor Invoice No.", PurchaseHeader."No."); + PurchaseHeader.Modify(true); + LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, true); + + // [GIVEN] A purchase return order populated from the posted subcontracting invoice. + PurchInvLine.SetRange("Order No.", PurchaseHeader."No."); + PurchInvLine.SetRange("Prod. Order No.", ProductionOrder."No."); + PurchInvLine.SetRange("Operation No.", OperationNo); + PurchInvLine.FindFirst(); + LibraryPurchase.CreatePurchHeader( + PurchaseHeader, PurchaseHeader."Document Type"::"Return Order", SubcontractingWorkCenter."Subcontractor No."); + LibraryVariableStorage.Enqueue(PurchInvLine."Document No."); + PurchaseHeader.GetPstdDocLinesToReverse(); + PurchaseHeader.Validate("Vendor Cr. Memo No.", PurchaseHeader."Buy-from Vendor No."); + PurchaseHeader.Modify(true); + + // [WHEN] The purchase return order is shipped and invoiced. + LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, true); + + // [THEN] Posting succeeds. + end; + local procedure Initialize() var LibraryERMCountryData: Codeunit "Library - ERM Country Data"; @@ -6242,6 +6306,14 @@ codeunit 137063 "SCM Manufacturing 7.0" ProdOrderComponents.OK().Invoke(); end; + [ModalPageHandler] + procedure PostedPurchaseDocumentLinesPageHandler(var PostedPurchaseDocumentLines: TestPage "Posted Purchase Document Lines") + begin + PostedPurchaseDocumentLines.PostedReceiptsBtn.SetValue('Posted Invoices'); + PostedPurchaseDocumentLines.PostedInvoices.Filter.SetFilter("Document No.", LibraryVariableStorage.DequeueText()); + PostedPurchaseDocumentLines.OK().Invoke(); + end; + local procedure GetShopCalendarCodeForProductionOrder(ProductionOrder: Record "Production Order"): Code[10] var ProdOrderRoutingLine: Record "Prod. Order Routing Line"; diff --git a/src/Layers/IT/Tests/SCM-Manufacturing/SCMManufacturing70.Codeunit.al b/src/Layers/IT/Tests/SCM-Manufacturing/SCMManufacturing70.Codeunit.al index 1cbdef4ee8f..d09d8a34f11 100644 --- a/src/Layers/IT/Tests/SCM-Manufacturing/SCMManufacturing70.Codeunit.al +++ b/src/Layers/IT/Tests/SCM-Manufacturing/SCMManufacturing70.Codeunit.al @@ -33,6 +33,7 @@ using Microsoft.Manufacturing.Routing; using Microsoft.Manufacturing.Setup; using Microsoft.Manufacturing.WorkCenter; using Microsoft.Purchases.Document; +using Microsoft.Purchases.History; using Microsoft.Purchases.Setup; using Microsoft.Purchases.Vendor; using Microsoft.Sales.Document; @@ -3897,6 +3898,69 @@ codeunit 137063 "SCM Manufacturing 7.0" Assert.ExpectedTestFieldError(ProductionOrder.FieldCaption("Variant Code"), ''); end; + [Test] + [HandlerFunctions('PostedPurchaseDocumentLinesPageHandler')] + procedure PostPurchaseReturnOrderForSubcontractingWhenLastOperationIsNotSubcontracted() + var + CapacityUnitOfMeasure: Record "Capacity Unit of Measure"; + Item: Record Item; + ProductionOrder: Record "Production Order"; + PurchaseHeader: Record "Purchase Header"; + PurchaseLine: Record "Purchase Line"; + PurchInvLine: Record "Purch. Inv. Line"; + RequisitionLine: Record "Requisition Line"; + RoutingHeader: Record "Routing Header"; + RoutingLine: Record "Routing Line"; + SubcontractingWorkCenter: Record "Work Center"; + WorkCenter: Record "Work Center"; + OperationNo: Code[10]; + begin + // [FEATURE] [AI test 0.4] + // [SCENARIO 647380] A subcontracting purchase return order can be posted when a later operation is not subcontracted. + Initialize(); + + // [GIVEN] A released production order whose subcontracting operation is followed by a non-subcontracting operation. + OperationNo := Format(10 + LibraryRandom.RandInt(10)); + CreateSubcontractingSetup(SubcontractingWorkCenter, RoutingHeader, OperationNo); + UpdateRoutingStatus(RoutingHeader, RoutingHeader.Status::"Under Development"); + CreateWorkCenterSetup(WorkCenter, CapacityUnitOfMeasure.Type::Minutes, 160000T, 235959T); + CreateRoutingLine(RoutingLine, RoutingHeader, WorkCenter."No."); + UpdateRoutingStatus(RoutingHeader, RoutingHeader.Status::Certified); + CreateProdItem(Item, RoutingHeader."No."); + CreateAndRefreshProdOrder( + ProductionOrder, ProductionOrder.Status::Released, Item."No.", LibraryRandom.RandInt(10), + ProductionOrder."Source Type"::Item, false); + + // [GIVEN] A subcontracting purchase order created from the subcontracting worksheet is received and invoiced. + CalculateSubcontractOrder(RequisitionLine, SubcontractingWorkCenter."No.", ProductionOrder); + LibraryPlanning.CarryOutAMSubcontractWksh(RequisitionLine); + PurchaseLine.SetRange("Document Type", PurchaseLine."Document Type"::Order); + PurchaseLine.SetRange("Prod. Order No.", ProductionOrder."No."); + PurchaseLine.SetRange("Operation No.", OperationNo); + PurchaseLine.FindFirst(); + PurchaseHeader.Get(PurchaseLine."Document Type", PurchaseLine."Document No."); + PurchaseHeader.Validate("Vendor Invoice No.", PurchaseHeader."No."); + PurchaseHeader.Modify(true); + LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, true); + + // [GIVEN] A purchase return order populated from the posted subcontracting invoice. + PurchInvLine.SetRange("Order No.", PurchaseHeader."No."); + PurchInvLine.SetRange("Prod. Order No.", ProductionOrder."No."); + PurchInvLine.SetRange("Operation No.", OperationNo); + PurchInvLine.FindFirst(); + LibraryPurchase.CreatePurchHeader( + PurchaseHeader, PurchaseHeader."Document Type"::"Return Order", SubcontractingWorkCenter."Subcontractor No."); + LibraryVariableStorage.Enqueue(PurchInvLine."Document No."); + PurchaseHeader.GetPstdDocLinesToReverse(); + PurchaseHeader.Validate("Vendor Cr. Memo No.", PurchaseHeader."Buy-from Vendor No."); + PurchaseHeader.Modify(true); + + // [WHEN] The purchase return order is shipped and invoiced. + LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, true); + + // [THEN] Posting succeeds. + end; + local procedure Initialize() var LibraryERMCountryData: Codeunit "Library - ERM Country Data"; @@ -6251,6 +6315,14 @@ codeunit 137063 "SCM Manufacturing 7.0" ProdOrderComponents.OK().Invoke(); end; + [ModalPageHandler] + procedure PostedPurchaseDocumentLinesPageHandler(var PostedPurchaseDocumentLines: TestPage "Posted Purchase Document Lines") + begin + PostedPurchaseDocumentLines.PostedReceiptsBtn.SetValue('Posted Invoices'); + PostedPurchaseDocumentLines.PostedInvoices.Filter.SetFilter("Document No.", LibraryVariableStorage.DequeueText()); + PostedPurchaseDocumentLines.OK().Invoke(); + end; + local procedure GetShopCalendarCodeForProductionOrder(ProductionOrder: Record "Production Order"): Code[10] var ProdOrderRoutingLine: Record "Prod. Order Routing Line"; diff --git a/src/Layers/W1/BaseApp/Manufacturing/Purchases/Document/MfgPurchaseDocumentMgt.Codeunit.al b/src/Layers/W1/BaseApp/Manufacturing/Purchases/Document/MfgPurchaseDocumentMgt.Codeunit.al index b5493f166f7..ecd48118eb3 100644 --- a/src/Layers/W1/BaseApp/Manufacturing/Purchases/Document/MfgPurchaseDocumentMgt.Codeunit.al +++ b/src/Layers/W1/BaseApp/Manufacturing/Purchases/Document/MfgPurchaseDocumentMgt.Codeunit.al @@ -74,7 +74,7 @@ codeunit 99000789 "Mfg. Purchase Document Mgt." [EventSubscriber(ObjectType::Table, Database::"Purchase Line", 'OnIsSubcontractingCreditMemo', '', true, false)] local procedure OnIsSubcontractingCreditMemo(var PurchaseLine: Record "Purchase Line"; var Result: Boolean) begin - if (PurchaseLine."Document Type" = PurchaseLine."Document Type"::"Credit Memo") and PurchaseLine.IsProdOrder() and + if PurchaseLine.IsCreditDocType() and PurchaseLine.IsProdOrder() and (PurchaseLine."Operation No." <> '') and (PurchaseLine."Work Center No." <> '') then Result := true else diff --git a/src/Layers/W1/Tests/SCM-Manufacturing/SCMManufacturing70.Codeunit.al b/src/Layers/W1/Tests/SCM-Manufacturing/SCMManufacturing70.Codeunit.al index b9107f48410..084fd111e1d 100644 --- a/src/Layers/W1/Tests/SCM-Manufacturing/SCMManufacturing70.Codeunit.al +++ b/src/Layers/W1/Tests/SCM-Manufacturing/SCMManufacturing70.Codeunit.al @@ -33,6 +33,7 @@ using Microsoft.Manufacturing.Routing; using Microsoft.Manufacturing.Setup; using Microsoft.Manufacturing.WorkCenter; using Microsoft.Purchases.Document; +using Microsoft.Purchases.History; using Microsoft.Purchases.Setup; using Microsoft.Purchases.Vendor; using Microsoft.Sales.Document; @@ -3793,6 +3794,69 @@ codeunit 137063 "SCM Manufacturing 7.0" Assert.AreEqual(SKURoutingHeader."No.", ProdOrderLine."Routing No.", ProductionRoutingErr); end; + [Test] + [HandlerFunctions('PostedPurchaseDocumentLinesPageHandler')] + procedure PostPurchaseReturnOrderForSubcontractingWhenLastOperationIsNotSubcontracted() + var + CapacityUnitOfMeasure: Record "Capacity Unit of Measure"; + Item: Record Item; + ProductionOrder: Record "Production Order"; + PurchaseHeader: Record "Purchase Header"; + PurchaseLine: Record "Purchase Line"; + PurchInvLine: Record "Purch. Inv. Line"; + RequisitionLine: Record "Requisition Line"; + RoutingHeader: Record "Routing Header"; + RoutingLine: Record "Routing Line"; + SubcontractingWorkCenter: Record "Work Center"; + WorkCenter: Record "Work Center"; + OperationNo: Code[10]; + begin + // [FEATURE] [AI test 0.4] + // [SCENARIO 647380] A subcontracting purchase return order can be posted when a later operation is not subcontracted. + Initialize(); + + // [GIVEN] A released production order whose subcontracting operation is followed by a non-subcontracting operation. + OperationNo := Format(10 + LibraryRandom.RandInt(10)); + CreateSubcontractingSetup(SubcontractingWorkCenter, RoutingHeader, OperationNo); + UpdateRoutingStatus(RoutingHeader, RoutingHeader.Status::"Under Development"); + CreateWorkCenterSetup(WorkCenter, CapacityUnitOfMeasure.Type::Minutes, 160000T, 235959T); + CreateRoutingLine(RoutingLine, RoutingHeader, WorkCenter."No."); + UpdateRoutingStatus(RoutingHeader, RoutingHeader.Status::Certified); + CreateProdItem(Item, RoutingHeader."No."); + CreateAndRefreshProdOrder( + ProductionOrder, ProductionOrder.Status::Released, Item."No.", LibraryRandom.RandInt(10), + ProductionOrder."Source Type"::Item, false); + + // [GIVEN] A subcontracting purchase order created from the subcontracting worksheet is received and invoiced. + CalculateSubcontractOrder(RequisitionLine, SubcontractingWorkCenter."No.", ProductionOrder); + LibraryPlanning.CarryOutAMSubcontractWksh(RequisitionLine); + PurchaseLine.SetRange("Document Type", PurchaseLine."Document Type"::Order); + PurchaseLine.SetRange("Prod. Order No.", ProductionOrder."No."); + PurchaseLine.SetRange("Operation No.", OperationNo); + PurchaseLine.FindFirst(); + PurchaseHeader.Get(PurchaseLine."Document Type", PurchaseLine."Document No."); + PurchaseHeader.Validate("Vendor Invoice No.", PurchaseHeader."No."); + PurchaseHeader.Modify(true); + LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, true); + + // [GIVEN] A purchase return order populated from the posted subcontracting invoice. + PurchInvLine.SetRange("Order No.", PurchaseHeader."No."); + PurchInvLine.SetRange("Prod. Order No.", ProductionOrder."No."); + PurchInvLine.SetRange("Operation No.", OperationNo); + PurchInvLine.FindFirst(); + LibraryPurchase.CreatePurchHeader( + PurchaseHeader, PurchaseHeader."Document Type"::"Return Order", SubcontractingWorkCenter."Subcontractor No."); + LibraryVariableStorage.Enqueue(PurchInvLine."Document No."); + PurchaseHeader.GetPstdDocLinesToReverse(); + PurchaseHeader.Validate("Vendor Cr. Memo No.", PurchaseHeader."Buy-from Vendor No."); + PurchaseHeader.Modify(true); + + // [WHEN] The purchase return order is shipped and invoiced. + LibraryPurchase.PostPurchaseDocument(PurchaseHeader, true, true); + + // [THEN] Posting succeeds. + end; + local procedure Initialize() var LibraryERMCountryData: Codeunit "Library - ERM Country Data"; @@ -6132,6 +6196,14 @@ codeunit 137063 "SCM Manufacturing 7.0" ProdOrderComponents.OK().Invoke(); end; + [ModalPageHandler] + procedure PostedPurchaseDocumentLinesPageHandler(var PostedPurchaseDocumentLines: TestPage "Posted Purchase Document Lines") + begin + PostedPurchaseDocumentLines.PostedReceiptsBtn.SetValue('Posted Invoices'); + PostedPurchaseDocumentLines.PostedInvoices.Filter.SetFilter("Document No.", LibraryVariableStorage.DequeueText()); + PostedPurchaseDocumentLines.OK().Invoke(); + end; + local procedure GetShopCalendarCodeForProductionOrder(ProductionOrder: Record "Production Order"): Code[10] var ProdOrderRoutingLine: Record "Prod. Order Routing Line";