Skip to content
Open
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 @@ -4,6 +4,7 @@
// ------------------------------------------------------------------------------------------------
namespace Microsoft.Manufacturing.Subcontracting;

using Microsoft.Purchases.Vendor;
using System.Environment.Configuration;

codeunit 99001506 "Subc. Notification Mgmt."
Expand All @@ -18,6 +19,61 @@ codeunit 99001506 "Subc. Notification Mgmt."
ProdOrdNotificationNameLbl: Label 'Show Created Production Orders';
SubcOrdNotificationDescriptionTxt: Label 'Show a notification if Subcontracting Orders were created for Subcontracting.';
SubcOrdNotificationNameLbl: Label 'Show Created Subcontracting Orders';
MissingSubcontractingLocationMsg: Label 'Vendor %1 has no subcontracting location. This location is used to track components and work-in-process (WIP) items at the subcontractor. Choose a Subcontracting Location Code on the vendor before using this work center for subcontracting.', Comment = '%1 = Vendor No.';
OpenVendorCardLbl: Label 'Open Vendor Card';
VendorNoTok: Label 'VendorNo', Locked = true;

internal procedure ShowMissingSubcontractingLocationNotification(VendorNo: Code[20])
var
Vendor: Record Vendor;
MissingSubcontractingLocationNotification: Notification;
begin
#if not CLEAN29
#pragma warning disable AL0432
if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then
#pragma warning restore AL0432
exit;
#endif
MissingSubcontractingLocationNotification.Id := GetMissingSubcontractingLocationNotificationId();
if MissingSubcontractingLocationNotification.Recall() then;

if VendorNo = '' then
exit;

Vendor.SetLoadFields("Subc. Location Code");
if not Vendor.Get(VendorNo) then
exit;
if Vendor."Subc. Location Code" <> '' then
exit;

MissingSubcontractingLocationNotification.Message := StrSubstNo(MissingSubcontractingLocationMsg, VendorNo);
MissingSubcontractingLocationNotification.Scope := NotificationScope::LocalScope;
MissingSubcontractingLocationNotification.SetData(VendorNoTok, VendorNo);
MissingSubcontractingLocationNotification.AddAction(OpenVendorCardLbl, Codeunit::"Subc. Notification Mgmt.", 'OpenVendorCard');
MissingSubcontractingLocationNotification.Send();
end;

internal procedure OpenVendorCard(MissingSubcontractingLocationNotification: Notification)
var
Vendor: Record Vendor;
VendorNo: Code[20];
begin
#if not CLEAN29
#pragma warning disable AL0432
if not SubcFeatureFlagHandler.IsSubcontractingEnabled() then
#pragma warning restore AL0432
exit;
#endif
if not Evaluate(VendorNo, MissingSubcontractingLocationNotification.GetData(VendorNoTok)) then
exit;
if Vendor.Get(VendorNo) then
Page.Run(Page::"Vendor Card", Vendor);
end;

local procedure GetMissingSubcontractingLocationNotificationId(): Guid
begin
exit('{8A4B9A58-21EC-49DD-A3A5-C7E81F745B6D}');
end;

procedure ShowCreatedProductionOrderConfirmationMessageCode(): Code[50]
begin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pageextension 99001506 "Subc. Work Center Card" extends "Work Center Card"
trigger OnAfterValidate()
begin
CurrPage.Update(false);
SubcNotificationMgmt.ShowMissingSubcontractingLocationNotification(Rec."Subcontractor No.");
end;
}
}
Expand Down Expand Up @@ -83,4 +84,5 @@ pageextension 99001506 "Subc. Work Center Card" extends "Work Center Card"
SubcontractingEnabled: Boolean;
#endif
IsSubcontractingWorkCenter: Boolean;
SubcNotificationMgmt: Codeunit "Subc. Notification Mgmt.";
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Microsoft.Manufacturing.Subcontracting.Test;

using Microsoft.Inventory.Ledger;
using Microsoft.Inventory.Location;
using Microsoft.Inventory.Planning;
using Microsoft.Inventory.Requisition;
using Microsoft.Manufacturing.Capacity;
Expand All @@ -16,6 +17,7 @@ using Microsoft.Purchases.Document;
using Microsoft.Purchases.History;
using Microsoft.Purchases.Vendor;
using System.Reflection;
using System.TestLibraries.Utilities;

codeunit 139990 "Subc. Subcontracting UI Test"
{
Expand All @@ -36,6 +38,7 @@ codeunit 139990 "Subc. Subcontracting UI Test"

SubcontractingMgmtLibrary.Initialize();
LibraryMfgManagement.Initialize();
LibraryVariableStorage.Clear();

if IsInitialized then
exit;
Expand Down Expand Up @@ -321,6 +324,133 @@ codeunit 139990 "Subc. Subcontracting UI Test"
WorkCenterCard.Close();
end;

[Test]
[HandlerFunctions('SubcontractorLocationNotificationHandler,SubcontractorLocationRecallHandler')]
Comment thread
6CRIPT marked this conversation as resolved.
procedure WorkCenterCardNotifiesWhenSubcontractorHasNoLocation()
var
Vendor: Record Vendor;
WorkCenter: Record "Work Center";
WorkCenterCard: TestPage "Work Center Card";
begin
// [SCENARIO 642229] A notification identifies a subcontractor vendor that has no subcontracting location.
Initialize();

// [GIVEN] A Work Center and a vendor without a Subcontracting Location Code
LibraryMfgManagement.CreateWorkCenterWithCalendar(WorkCenter, 0);
Vendor.Get(LibraryMfgManagement.CreateSubcontractorWithCurrency(''));

// [WHEN] The vendor is selected as the subcontractor on the Work Center Card
WorkCenterCard.OpenEdit();
WorkCenterCard.GoToRecord(WorkCenter);
WorkCenterCard."Subcontractor No.".SetValue(Vendor."No.");

// [THEN] Any previous notification is recalled before one notification is sent for that vendor
VerifySubcontractorLocationNotification(Vendor."No.");
WorkCenterCard.Close();
LibraryVariableStorage.AssertEmpty();
end;

[Test]
[HandlerFunctions('SubcontractorLocationNotificationHandler,SubcontractorLocationRecallHandler')]
procedure WorkCenterCardDoesNotStackSubcontractorLocationNotifications()
var
Vendor: Record Vendor;
WorkCenter: Record "Work Center";
WorkCenterCard: TestPage "Work Center Card";
begin
// [SCENARIO 642229] Revalidating an unconfigured subcontractor replaces the existing notification.
Initialize();

// [GIVEN] A Work Center Card showing a notification for a vendor without a subcontracting location
LibraryMfgManagement.CreateWorkCenterWithCalendar(WorkCenter, 0);
Vendor.Get(LibraryMfgManagement.CreateSubcontractorWithCurrency(''));
WorkCenterCard.OpenEdit();
WorkCenterCard.GoToRecord(WorkCenter);
WorkCenterCard."Subcontractor No.".SetValue(Vendor."No.");
VerifySubcontractorLocationNotification(Vendor."No.");

// [WHEN] The same vendor is validated again
WorkCenterCard."Subcontractor No.".SetValue(Vendor."No.");

// [THEN] The previous notification is recalled before its replacement is sent with the same notification ID
VerifySubcontractorLocationNotification(Vendor."No.");
WorkCenterCard.Close();
LibraryVariableStorage.AssertEmpty();
end;

[Test]
[HandlerFunctions('SubcontractorLocationNotificationHandler,SubcontractorLocationRecallHandler')]
procedure WorkCenterCardRecallsSubcontractorLocationNotificationWhenNoLongerNeeded()
var
Location: Record Location;
ConfiguredVendor: Record Vendor;
UnconfiguredVendor: Record Vendor;
WorkCenter: Record "Work Center";
WorkCenterCard: TestPage "Work Center Card";
begin
// [SCENARIO 642229] A previous notification is removed when the subcontractor is configured or cleared.
Initialize();

// [GIVEN] An unconfigured vendor, a configured vendor, and a Work Center Card showing the notification
LibraryMfgManagement.CreateWorkCenterWithCalendar(WorkCenter, 0);
UnconfiguredVendor.Get(LibraryMfgManagement.CreateSubcontractorWithCurrency(''));
ConfiguredVendor.Get(LibraryMfgManagement.CreateSubcontractorWithCurrency(''));
LibraryWarehouse.CreateLocationWithInventoryPostingSetup(Location);
ConfiguredVendor.Validate("Subc. Location Code", Location.Code);
ConfiguredVendor.Modify(true);
WorkCenterCard.OpenEdit();
WorkCenterCard.GoToRecord(WorkCenter);
WorkCenterCard."Subcontractor No.".SetValue(UnconfiguredVendor."No.");
VerifySubcontractorLocationNotification(UnconfiguredVendor."No.");

// [WHEN] The configured vendor is selected
WorkCenterCard."Subcontractor No.".SetValue(ConfiguredVendor."No.");

// [THEN] The previous notification is recalled and no notification is sent for the configured vendor
VerifySubcontractorLocationNotification('');

// [WHEN] The unconfigured vendor is selected again
WorkCenterCard."Subcontractor No.".SetValue(UnconfiguredVendor."No.");

// [THEN] The previous notification is recalled before a new notification is sent
VerifySubcontractorLocationNotification(UnconfiguredVendor."No.");

// [WHEN] The subcontractor is cleared
WorkCenterCard."Subcontractor No.".SetValue('');

// [THEN] The notification is recalled without sending another one
VerifySubcontractorLocationNotification('');
WorkCenterCard.Close();
LibraryVariableStorage.AssertEmpty();
end;

[Test]
[HandlerFunctions('SubcontractorLocationNotificationActionHandler,SubcontractorLocationRecallHandler,VendorCardHandler')]
procedure WorkCenterCardSubcontractorLocationNotificationActionOpensVendorCard()
var
Vendor: Record Vendor;
WorkCenter: Record "Work Center";
WorkCenterCard: TestPage "Work Center Card";
begin
// [SCENARIO 642229] The notification action opens the selected subcontractor vendor.
Initialize();

// [GIVEN] A Work Center and a vendor without a Subcontracting Location Code
LibraryMfgManagement.CreateWorkCenterWithCalendar(WorkCenter, 0);
Vendor.Get(LibraryMfgManagement.CreateSubcontractorWithCurrency(''));

// [WHEN] The vendor is selected as the subcontractor and the notification action is invoked
WorkCenterCard.OpenEdit();
WorkCenterCard.GoToRecord(WorkCenter);
WorkCenterCard."Subcontractor No.".SetValue(Vendor."No.");

// [THEN] The notification is sent for the vendor and the Vendor Card opens for that vendor
VerifySubcontractorLocationNotification(Vendor."No.");
Assert.AreEqual(Vendor."No.", LibraryVariableStorage.DequeueText(), VendorCardNoErr);
WorkCenterCard.Close();
LibraryVariableStorage.AssertEmpty();
end;

[Test]
procedure WorkCenterListSubcontractingActionsDisabledWhenNotSubcontracting()
var
Expand Down Expand Up @@ -526,6 +656,73 @@ codeunit 139990 "Subc. Subcontracting UI Test"
exit(1);
end;

local procedure VerifySubcontractorLocationNotification(VendorNo: Code[20])
begin
Assert.AreEqual(RecallNotificationTok, LibraryVariableStorage.DequeueText(), NotificationOrderErr);
Assert.AreEqual(Format(GetMissingSubcontractingLocationNotificationId()), LibraryVariableStorage.DequeueText(), NotificationIdErr);
if VendorNo <> '' then begin
Assert.AreEqual(SendNotificationTok, LibraryVariableStorage.DequeueText(), NotificationOrderErr);
Assert.AreEqual(Format(GetMissingSubcontractingLocationNotificationId()), LibraryVariableStorage.DequeueText(), NotificationIdErr);
Assert.AreEqual(StrSubstNo(MissingSubcontractingLocationMsg, VendorNo), LibraryVariableStorage.DequeueText(), NotificationMessageErr);
Assert.AreEqual(VendorNo, LibraryVariableStorage.DequeueText(), NotificationVendorErr);
end;
end;

local procedure GetMissingSubcontractingLocationNotificationId(): Guid
Comment thread
6CRIPT marked this conversation as resolved.
Comment thread
6CRIPT marked this conversation as resolved.
begin
exit('{8A4B9A58-21EC-49DD-A3A5-C7E81F745B6D}');
end;

[SendNotificationHandler]
procedure SubcontractorLocationNotificationHandler(var SubcontractorLocationNotification: Notification): Boolean
Comment thread
6CRIPT marked this conversation as resolved.
begin
if SubcontractorLocationNotification.Id <> GetMissingSubcontractingLocationNotificationId() then
exit(false);

CaptureSubcontractorLocationNotification(SubcontractorLocationNotification);
exit(true);
end;

[SendNotificationHandler]
procedure SubcontractorLocationNotificationActionHandler(var SubcontractorLocationNotification: Notification): Boolean
var
SubcNotificationMgmt: Codeunit "Subc. Notification Mgmt.";
begin
if SubcontractorLocationNotification.Id <> GetMissingSubcontractingLocationNotificationId() then
exit(false);

CaptureSubcontractorLocationNotification(SubcontractorLocationNotification);
// Simulate choosing the Open Vendor Card notification action.
SubcNotificationMgmt.OpenVendorCard(SubcontractorLocationNotification);
exit(true);
end;

local procedure CaptureSubcontractorLocationNotification(SubcontractorLocationNotification: Notification)
begin
LibraryVariableStorage.Enqueue(SendNotificationTok);
LibraryVariableStorage.Enqueue(Format(SubcontractorLocationNotification.Id));
LibraryVariableStorage.Enqueue(SubcontractorLocationNotification.Message);
LibraryVariableStorage.Enqueue(SubcontractorLocationNotification.GetData(VendorNoTok));
end;

[RecallNotificationHandler]
procedure SubcontractorLocationRecallHandler(var SubcontractorLocationNotification: Notification): Boolean
begin
if SubcontractorLocationNotification.Id <> GetMissingSubcontractingLocationNotificationId() then
exit(false);

LibraryVariableStorage.Enqueue(RecallNotificationTok);
LibraryVariableStorage.Enqueue(Format(SubcontractorLocationNotification.Id));
exit(true);
end;

[PageHandler]
procedure VendorCardHandler(var VendorCard: TestPage "Vendor Card")
begin
LibraryVariableStorage.Enqueue(VendorCard."No.".Value());
VendorCard.Close();
end;

[PageHandler]
procedure HandlePostedPurchaseReceiptPage(var PostedPurchaseReceipt: TestPage "Posted Purchase Receipt")
begin
Expand Down Expand Up @@ -675,6 +872,8 @@ codeunit 139990 "Subc. Subcontracting UI Test"
LibraryERMCountryData: Codeunit "Library - ERM Country Data";
LibrarySetupStorage: Codeunit "Library - Setup Storage";
LibraryTestInitialize: Codeunit "Library - Test Initialize";
LibraryVariableStorage: Codeunit "Library - Variable Storage";
LibraryWarehouse: Codeunit "Library - Warehouse";
LibraryMfgManagement: Codeunit "Subc. Library Mfg. Management";
SubcontractingMgmtLibrary: Codeunit "Subc. Management Library";
SubSetupLibrary: Codeunit "Subc. Setup Library";
Expand All @@ -688,4 +887,13 @@ codeunit 139990 "Subc. Subcontracting UI Test"
ILEProdActionsNotEnabledErr: Label 'Production actions should be enabled for a subcontracting Item Ledger Entry.';
ILEPurchActionsEnabledErr: Label 'Purchase Order action should not be enabled for a non-subcontracting Item Ledger Entry.';
ILEPurchActionsNotEnabledErr: Label 'Purchase Order action should be enabled for a subcontracting Item Ledger Entry.';
}
MissingSubcontractingLocationMsg: Label 'Vendor %1 has no subcontracting location. This location is used to track components and work-in-process (WIP) items at the subcontractor. Choose a Subcontracting Location Code on the vendor before using this work center for subcontracting.', Comment = '%1 = Vendor No.';
NotificationIdErr: Label 'The subcontractor location notification ID is unexpected.';
NotificationMessageErr: Label 'The subcontractor location notification message is unexpected.';
NotificationOrderErr: Label 'The subcontractor location notification interactions occurred in an unexpected order.';
NotificationVendorErr: Label 'The vendor in the subcontractor location notification is unexpected.';
RecallNotificationTok: Label 'Recall', Locked = true;
SendNotificationTok: Label 'Send', Locked = true;
VendorCardNoErr: Label 'The Vendor Card opened for an unexpected vendor.';
VendorNoTok: Label 'VendorNo', Locked = true;
}
Loading