diff --git a/src/Apps/W1/Quality Management/app/src/API/QltyCreateInspectionAPI.Page.al b/src/Apps/W1/Quality Management/app/src/API/QltyCreateInspectionAPI.Page.al
new file mode 100644
index 0000000000..10fa00fc58
--- /dev/null
+++ b/src/Apps/W1/Quality Management/app/src/API/QltyCreateInspectionAPI.Page.al
@@ -0,0 +1,144 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+namespace Microsoft.QualityManagement.API;
+using Microsoft.QualityManagement.Document;
+using Microsoft.QualityManagement.Utilities;
+using Microsoft.Utilities;
+
+///
+/// Power automate friendly web service for quality inspections.
+/// This web service is used to help create quality inspections.
+///
+page 20415 "Qlty. Create Inspection API"
+{
+ APIVersion = 'v1.0';
+ APIGroup = 'qualityManagement';
+ APIPublisher = 'microsoft';
+ Editable = false;
+ EntityName = 'createQualityInspection';
+ EntitySetName = 'createQualityInspections';
+ EntityCaption = 'Create Quality Inspection';
+ EntitySetCaption = 'Create Quality Inspections';
+ PageType = API;
+ SourceTable = "Name/Value Buffer";
+ SourceTableTemporary = true;
+ ODataKeyFields = SystemId;
+
+ layout
+ {
+ area(Content)
+ {
+ repeater(SourceDocument)
+ {
+ ShowCaption = false;
+
+ field(systemIDOfAnyRecord; Rec.SystemId)
+ {
+ Caption = 'System ID of any record';
+ ToolTip = 'Specifies the System ID of the record to create an inspection for.';
+ }
+ }
+ }
+ }
+
+ var
+ SystemRecord: Guid;
+ CurrentTable: Integer;
+ NoSystemIDRecordErr: Label 'Business Central cannot find a record for the System ID of %1', Comment = '%1=the system ID that was not found';
+ OnlyOneRecordForTableAndFilterErr: Label 'Exactly one record must match the filter, but %1 were found for table %2 with filter %3.', Comment = '%1=count, %2=table, %3=filter';
+
+ trigger OnFindRecord(Which: Text): Boolean
+ var
+ FilterGroupIterator: Integer;
+ begin
+ FilterGroupIterator := 4;
+ repeat
+ Rec.FilterGroup(FilterGroupIterator);
+ if Rec.GetFilter(SystemId) <> '' then
+ SystemRecord := Rec.GetRangeMin(SystemId);
+ if Rec.GetFilter(ID) <> '' then
+ CurrentTable := Rec.GetRangeMin(ID);
+
+ FilterGroupIterator -= 1;
+ until (FilterGroupIterator < 0);
+ Rec.FilterGroup(0);
+
+ Rec.ID := CurrentTable;
+ Rec.SystemId := SystemRecord;
+ if Rec.Insert(false, true) then;
+ exit(Rec.Find(Which));
+ end;
+
+ ///
+ /// Creates an inspection from a known table.
+ ///
+ /// The table ID or table name to create an inspection for.
+ ///
+ [ServiceEnabled]
+ procedure CreateInspectionFromRecordID(var ActionContext: WebServiceActionContext; tableName: Text)
+ var
+ CreatedInspection: Record "Qlty. Inspection Header";
+ QltyInspectionCreate: Codeunit "Qlty. Inspection - Create";
+ QltyFilterHelpers: Codeunit "Qlty. Filter Helpers";
+ AnyInputRecord: RecordRef;
+ begin
+ Rec.ID := QltyFilterHelpers.IdentifyTableIDFromText(tableName);
+
+ AnyInputRecord.Open(Rec.ID);
+
+ if not AnyInputRecord.GetBySystemId(Rec.SystemId) then
+ Error(NoSystemIDRecordErr, Rec.SystemId);
+
+ if QltyInspectionCreate.CreateInspection(AnyInputRecord, true) then begin
+ QltyInspectionCreate.GetCreatedInspection(CreatedInspection);
+ ActionContext.SetObjectType(ObjectType::Table);
+ ActionContext.SetObjectId(Database::"Name/Value Buffer");
+ ActionContext.AddEntityKey(CreatedInspection.FieldNo(SystemId), CreatedInspection.SystemId);
+ ActionContext.SetResultCode(WebServiceActionResultCode::Created);
+ if Rec.IsTemporary() then
+ Rec.DeleteAll();
+ Rec.SystemId := CreatedInspection.SystemId;
+ if Rec.Insert(false, true) then;
+ end else
+ ActionContext.SetResultCode(WebServiceActionResultCode::None);
+ end;
+
+ ///
+ /// Creates an inspection with a table and table filter to identify a record.
+ ///
+ /// VAR WebServiceActionContext.
+ /// Text. The table ID, or table name, or table caption.
+ /// The table filter that can identify a specific record.
+ [ServiceEnabled]
+ procedure CreateInspectionFromTableIDAndFilter(var ActionContext: WebServiceActionContext; tableName: Text; tableNameFilter: Text)
+ var
+ CreatedInspection: Record "Qlty. Inspection Header";
+ QltyInspectionCreate: Codeunit "Qlty. Inspection - Create";
+ QltyFilterHelpers: Codeunit "Qlty. Filter Helpers";
+ AnyInputRecord: RecordRef;
+ begin
+ Rec.ID := QltyFilterHelpers.IdentifyTableIDFromText(tableName);
+ AnyInputRecord.Open(Rec.ID);
+ AnyInputRecord.SetView(tableNameFilter);
+ if not AnyInputRecord.FindSet(false) then
+ Error(OnlyOneRecordForTableAndFilterErr, 0, Rec.ID, tableNameFilter);
+
+ if AnyInputRecord.Count() <> 1 then
+ Error(OnlyOneRecordForTableAndFilterErr, AnyInputRecord.Count(), Rec.ID, tableNameFilter);
+
+ if QltyInspectionCreate.CreateInspection(AnyInputRecord, true) then begin
+ QltyInspectionCreate.GetCreatedInspection(CreatedInspection);
+ ActionContext.SetObjectType(ObjectType::Table);
+ ActionContext.SetObjectId(Database::"Name/Value Buffer");
+ ActionContext.AddEntityKey(CreatedInspection.FieldNo(SystemId), CreatedInspection.SystemId);
+ ActionContext.SetResultCode(WebServiceActionResultCode::Created);
+ if Rec.IsTemporary() then
+ Rec.DeleteAll();
+ Rec.SystemId := CreatedInspection.SystemId;
+ if Rec.Insert(false, true) then;
+ end else
+ ActionContext.SetResultCode(WebServiceActionResultCode::None);
+ end;
+}
diff --git a/src/Apps/W1/Quality Management/app/src/API/QltyEventCategory.EnumExt.al b/src/Apps/W1/Quality Management/app/src/API/QltyEventCategory.EnumExt.al
new file mode 100644
index 0000000000..faa66ddfcb
--- /dev/null
+++ b/src/Apps/W1/Quality Management/app/src/API/QltyEventCategory.EnumExt.al
@@ -0,0 +1,18 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+namespace Microsoft.QualityManagement.API;
+
+using System.Integration;
+
+///
+/// Used for external business events, such as power automate integration.
+///
+enumextension 20403 QltyEventCategory extends EventCategory
+{
+ value(20400; QltyEventCategory)
+ {
+ Caption = 'Quality Management';
+ }
+}
diff --git a/src/Apps/W1/Quality Management/app/src/API/QltyInspectionValues.Query.al b/src/Apps/W1/Quality Management/app/src/API/QltyInspectionValues.Query.al
index 9d5ff7be4e..12cc5e6041 100644
--- a/src/Apps/W1/Quality Management/app/src/API/QltyInspectionValues.Query.al
+++ b/src/Apps/W1/Quality Management/app/src/API/QltyInspectionValues.Query.al
@@ -9,14 +9,13 @@ using Microsoft.QualityManagement.Document;
///
/// Do not use this query outside of web services.
/// Power Automate friendly web service for quality inspections.
-/// This web service is used to help list test values.
+/// This web service is used to help list inspection values.
///
query 20401 "Qlty. Inspection Values"
{
QueryType = API;
- Caption = 'Quality Inspection Values', Locked = true;
APIPublisher = 'microsoft';
- APIGroup = 'qualityInspection';
+ APIGroup = 'qualityManagement';
APIVersion = 'v1.0';
EntityName = 'qualityInspectionValue';
EntityCaption = 'Quality Inspection Value';
diff --git a/src/Apps/W1/Quality Management/app/src/API/QltyInspectionsAPI.Page.al b/src/Apps/W1/Quality Management/app/src/API/QltyInspectionsAPI.Page.al
new file mode 100644
index 0000000000..40d41f573e
--- /dev/null
+++ b/src/Apps/W1/Quality Management/app/src/API/QltyInspectionsAPI.Page.al
@@ -0,0 +1,669 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+namespace Microsoft.QualityManagement.API;
+using Microsoft.QualityManagement.Dispositions;
+using Microsoft.QualityManagement.Dispositions.InventoryAdjustment;
+using Microsoft.QualityManagement.Dispositions.ItemTracking;
+using Microsoft.QualityManagement.Dispositions.Move;
+using Microsoft.QualityManagement.Dispositions.PutAway;
+using Microsoft.QualityManagement.Dispositions.Transfer;
+using Microsoft.QualityManagement.Document;
+using Microsoft.QualityManagement.Integration.Inventory;
+using Microsoft.QualityManagement.Utilities;
+
+///
+/// Power automate friendly web service for quality inspections.
+///
+page 20414 "Qlty. Inspections API"
+{
+ APIVersion = 'v1.0';
+ APIGroup = 'qualityManagement';
+ APIPublisher = 'microsoft';
+ DelayedInsert = true;
+ EntityName = 'qualityInspection';
+ EntitySetName = 'qualityInspections';
+ EntityCaption = 'Quality Inspection';
+ EntitySetCaption = 'Quality Inspections';
+ PageType = API;
+ SourceTable = "Qlty. Inspection Header";
+ ODataKeyFields = SystemId;
+
+ layout
+ {
+ area(Content)
+ {
+ repeater(Inspections)
+ {
+ ShowCaption = false;
+ field(systemIDOfInspection; Rec.SystemId)
+ {
+ Caption = 'System ID of inspection';
+ ToolTip = 'Specifies the System ID of the inspection.';
+ }
+ field(inspectionNo; Rec."No.")
+ {
+ Caption = 'Inspection No.';
+ ToolTip = 'Specifies the quality inspection document No.';
+ }
+ field(reInspectionNo; Rec."Re-inspection No.")
+ {
+ Caption = 'Re-inspection No.';
+ ToolTip = 'Specifies the re-inspection counter.';
+ }
+ field(templateCode; Rec."Template Code")
+ {
+ Caption = 'Template';
+ ToolTip = 'Specifies which template this inspection was created from.';
+ }
+ field(description; Rec.Description)
+ {
+ Caption = 'Description';
+ ToolTip = 'Specifies a description of the inspection.';
+ }
+ field(status; Rec.Status)
+ {
+ Caption = 'Inspection status';
+ ToolTip = 'Specifies the status of the inspection. No additional changes can be made to a finished quality inspection.';
+ }
+
+ field(resultCode; Rec."Result Code")
+ {
+ Caption = 'Result code';
+ ToolTip = 'Specifies the result is automatically determined based on the test value and result configuration.';
+ }
+ field(resultDescription; Rec."Result Description")
+ {
+ Caption = 'Result description';
+ ToolTip = 'Specifies the result description for this inspection. The result is automatically determined based on the test value and result configuration.';
+ }
+ field(finishedDate; Rec."Finished Date")
+ {
+ Caption = 'Finished date';
+ ToolTip = 'Specifies the date that the inspection was finished.';
+ }
+ field(evaluationSequence; Rec."Evaluation Sequence")
+ {
+ Caption = 'Evaluation sequence';
+ ToolTip = 'Specifies the associated evaluation sequence for this inspection. The result is automatically determined based on the test value and result configuration.';
+ }
+ field(sourceTableNo; Rec."Source Table No.")
+ {
+ Caption = 'Source table No.';
+ ToolTip = 'Specifies a reference to the table that the quality inspection is for.';
+ }
+ field(sourceDocumentNo; Rec."Source Document No.")
+ {
+ Caption = 'Source document No.';
+ ToolTip = 'Specifies a reference to the source that this quality inspection is referring to.';
+ }
+ field(sourceDocumentLineNo; Rec."Source Document Line No.")
+ {
+ Caption = 'Source document line No.';
+ ToolTip = 'Specifies a reference to the source line No. that this quality inspection is referring to.';
+ }
+
+ field(sourceItemNo; Rec."Source Item No.")
+ {
+ Caption = 'Source item No.';
+ ToolTip = 'Specifies the item that the quality inspection is for.';
+ }
+ field(sourceVariantCode; Rec."Source Variant Code")
+ {
+ Caption = 'Source variant code';
+ ToolTip = 'Specifies the item variant that the quality inspection is for.';
+ }
+
+ field(sourceSerialNo; Rec."Source Serial No.")
+ {
+ Caption = 'Source serial No.';
+ ToolTip = 'Specifies the serial number that the quality inspection is for. This is only used for serial tracked items.';
+ }
+ field(sourceLotNo; Rec."Source Lot No.")
+ {
+ Caption = 'Source lot No.';
+ ToolTip = 'Specifies the lot number that the quality inspection is for. This is only used for lot tracked items.';
+ }
+ field(sourcePackageNo; Rec."Source Package No.")
+ {
+ Caption = 'Source package No.';
+ ToolTip = 'Specifies the package number that the quality inspection is for. This is only used for package tracked items.';
+ }
+ field(sourceQuantity; Rec."Source Quantity (Base)")
+ {
+ Caption = 'Source quantity';
+ ToolTip = 'Specifies the source quantity when configured.';
+ }
+ field(sourceRecordID; Rec."Source RecordId")
+ {
+ Caption = 'Source record ID';
+ ToolTip = 'Specifies the source record ID.';
+ }
+ field(sourceRecordTableNo; Rec."Source Record Table No.")
+ {
+ Caption = 'Source record table No.';
+ ToolTip = 'Specifies the source record table No.';
+ }
+ field(assignedUserID; Rec."Assigned User ID")
+ {
+ Caption = 'Assigned user ID';
+ ToolTip = 'Specifies the user this inspection is assigned to.';
+ }
+ field(systemCreatedAt; Rec.SystemCreatedAt)
+ {
+ Caption = 'System created at';
+ ToolTip = 'Specifies the date the inspection was created.';
+ }
+ field(systemCreatedBy; Rec.SystemCreatedBy)
+ {
+ Caption = 'System created by';
+ ToolTip = 'Specifies which user ID created the inspection.';
+ }
+ field(systemModifiedAt; Rec.SystemModifiedAt)
+ {
+ Caption = 'System modified at';
+ ToolTip = 'Specifies the last modified date of the inspection.';
+ }
+ field(systemModifiedBy; Rec.SystemModifiedBy)
+ {
+ Caption = 'System modified by';
+ ToolTip = 'Specifies the last modified by user ID.';
+ }
+ }
+ }
+ }
+ var
+ QltyBooleanParsing: Codeunit "Qlty. Boolean Parsing";
+ CannotConvertDateErr: Label 'Could not convert date %1. Use the YYYY-MM-DD date format.', Comment = '%1=date';
+
+
+ ///
+ /// Finishes the inspection.
+ ///
+ ///
+ [ServiceEnabled]
+ procedure FinishInspection(var ActionContext: WebServiceActionContext)
+ begin
+ Rec.FinishInspection();
+ ActionContext.SetResultCode(WebServiceActionResultCode::Updated);
+ end;
+
+ ///
+ /// Creates a reinspection.
+ ///
+ ///
+ [ServiceEnabled]
+ procedure CreateReinspection(var ActionContext: WebServiceActionContext)
+ begin
+ Rec.CreateReinspection();
+ ActionContext.SetResultCode(WebServiceActionResultCode::Updated);
+ end;
+
+ ///
+ /// Reopens an inspection.
+ ///
+ ///
+ [ServiceEnabled]
+ procedure ReopenInspection(var ActionContext: WebServiceActionContext)
+ begin
+ Rec.ReopenInspection();
+ ActionContext.SetResultCode(WebServiceActionResultCode::Updated);
+ end;
+
+ ///
+ /// Sets a test value.
+ ///
+ ///
+ /// Text. The field code to set.
+ /// Text. The field value to set.
+ [ServiceEnabled]
+ procedure SetTestValue(var ActionContext: WebServiceActionContext; testCode: Text; testValue: Text)
+ begin
+ Rec.SetTestValue(testCode, testValue);
+ ActionContext.SetResultCode(WebServiceActionResultCode::Updated);
+ end;
+
+ ///
+ /// Assigns the inspection to a user.
+ ///
+ ///
+ /// Text. The user id to assign the inspection to.
+ [ServiceEnabled]
+ procedure AssignTo(var ActionContext: WebServiceActionContext; assignToUser: Text)
+ begin
+ Rec."Assigned User ID" := CopyStr(assignToUser, 1, MaxStrLen(Rec."Assigned User ID"));
+ Rec.Modify(false);
+ ActionContext.SetResultCode(WebServiceActionResultCode::Updated);
+ end;
+
+ ///
+ /// Blocks the lot.
+ ///
+ ///
+ [ServiceEnabled]
+ procedure BlockLot(var ActionContext: WebServiceActionContext)
+ var
+ QltyItemTracking: Codeunit "Qlty. Item Tracking";
+ begin
+ QltyItemTracking.SetLotBlockState(Rec, true);
+ ActionContext.SetResultCode(WebServiceActionResultCode::Updated);
+ end;
+
+ ///
+ /// Unblocks the lot.
+ ///
+ ///
+ [ServiceEnabled]
+ procedure UnBlockLot(var ActionContext: WebServiceActionContext)
+ var
+ QltyItemTracking: Codeunit "Qlty. Item Tracking";
+ begin
+ QltyItemTracking.SetLotBlockState(Rec, false);
+ ActionContext.SetResultCode(WebServiceActionResultCode::Updated);
+ end;
+
+
+ ///
+ /// Blocks the serial number.
+ ///
+ ///
+ [ServiceEnabled]
+ procedure BlockSerial(var ActionContext: WebServiceActionContext)
+ var
+ QltyItemTracking: Codeunit "Qlty. Item Tracking";
+ begin
+ QltyItemTracking.SetSerialBlockState(Rec, true);
+ ActionContext.SetResultCode(WebServiceActionResultCode::Updated);
+ end;
+
+ ///
+ /// Unblocks the serial number.
+ ///
+ ///
+ [ServiceEnabled]
+ procedure UnBlockSerial(var ActionContext: WebServiceActionContext)
+ var
+ QltyItemTracking: Codeunit "Qlty. Item Tracking";
+ begin
+ QltyItemTracking.SetSerialBlockState(Rec, false);
+ ActionContext.SetResultCode(WebServiceActionResultCode::Updated);
+ end;
+
+ ///
+ /// Blocks the package.
+ ///
+ ///
+ [ServiceEnabled]
+ procedure BlockPackage(var ActionContext: WebServiceActionContext)
+ var
+ QltyItemTracking: Codeunit "Qlty. Item Tracking";
+ begin
+ QltyItemTracking.SetPackageBlockState(Rec, true);
+ ActionContext.SetResultCode(WebServiceActionResultCode::Updated);
+ end;
+
+ ///
+ /// Unblocks the package.
+ ///
+ ///
+ [ServiceEnabled]
+ procedure UnBlockPackage(var ActionContext: WebServiceActionContext)
+ var
+ QltyItemTracking: Codeunit "Qlty. Item Tracking";
+ begin
+ QltyItemTracking.SetPackageBlockState(Rec, false);
+ ActionContext.SetResultCode(WebServiceActionResultCode::Updated);
+ end;
+
+ ///
+ /// Moves inventory with an Inventory Movement.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [ServiceEnabled]
+ procedure CreateMovement(var ActionContext: WebServiceActionContext; optionalDestinationLocation: Text; binCode: Text; optionalSpecificQuantity: Text; moveEntireLot: Text; optionalSourceLocationFilter: Text; optionalSourceBinFilter: Text)
+ var
+ TempInstructionQltyDispositionBuffer: Record "Qlty. Disposition Buffer" temporary;
+ QltyDispInternalMove: Codeunit "Qlty. Disp. Internal Move";
+ begin
+ optionalSourceLocationFilter := DelChr(optionalSourceLocationFilter, '<>', ' ');
+ optionalSourceBinFilter := DelChr(optionalSourceBinFilter, '<>', ' ');
+ binCode := DelChr(binCode, '<>', ' ');
+ optionalDestinationLocation := DelChr(optionalDestinationLocation, '<>', ' ');
+
+ if QltyBooleanParsing.GetBooleanFor(moveEntireLot) then
+ TempInstructionQltyDispositionBuffer."Quantity Behavior" := TempInstructionQltyDispositionBuffer."Quantity Behavior"::"Item Tracked Quantity";
+
+ TempInstructionQltyDispositionBuffer."Disposition Action" := TempInstructionQltyDispositionBuffer."Disposition Action"::"Move with Internal Movement";
+
+ if optionalSpecificQuantity <> '' then
+ Evaluate(TempInstructionQltyDispositionBuffer."Qty. To Handle (Base)", optionalSpecificQuantity);
+
+ TempInstructionQltyDispositionBuffer."Location Filter" := CopyStr(optionalSourceLocationFilter, 1, MaxStrLen(TempInstructionQltyDispositionBuffer."Location Filter"));
+ TempInstructionQltyDispositionBuffer."Bin Filter" := CopyStr(optionalSourceBinFilter, 1, MaxStrLen(TempInstructionQltyDispositionBuffer."Bin Filter"));
+ TempInstructionQltyDispositionBuffer."New Location Code" := CopyStr(optionalDestinationLocation, 1, 10);
+ TempInstructionQltyDispositionBuffer."New Bin Code" := CopyStr(binCode, 1, 20);
+
+ if QltyDispInternalMove.PerformDisposition(
+ Rec,
+ TempInstructionQltyDispositionBuffer
+ ) then
+ ActionContext.SetResultCode(WebServiceActionResultCode::Updated)
+ else
+ ActionContext.SetResultCode(WebServiceActionResultCode::None);
+ end;
+
+ local procedure ConvertTextToQuantityBehaviorEnum(TextToConvert: Text) QltyQuantityBehavior: Enum "Qlty. Quantity Behavior"
+ var
+ IndexOfText: Integer;
+ OrdinalOfEnum: Integer;
+ begin
+ IndexOfText := QltyQuantityBehavior.Names.IndexOf(TextToConvert);
+ if IndexOfText = 0 then
+ QltyQuantityBehavior := QltyQuantityBehavior::"Specific Quantity"
+ else begin
+ OrdinalOfEnum := QltyQuantityBehavior.Ordinals.Get(IndexOfText);
+ QltyQuantityBehavior := Enum::"Qlty. Quantity Behavior".FromInteger(OrdinalOfEnum);
+ end;
+ end;
+
+ ///
+ /// Creates a Warehouse Internal Put-away document.
+ /// This feature can be used with directed pick and put locations with lot warehouse tracked items.
+ ///
+ ///
+ /// When non zero this indicates the quantity to move.
+ /// When set to TRUE, will release the internal put-away
+ /// Optionally restrict the locations to move from.
+ /// Optionally restrict the specific bins to move from.
+ /// Valid options are: SpecificQuantity (quantity defined in optionalSpecificQuantity), TrackedQuantity (quantity of lot/package/serial), SampleQuantity (sample size), FailQuantity (number of failed samples), PassQuantity (number of passed samples)
+ [ServiceEnabled]
+ procedure CreateWarehouseInternalPutaway(var ActionContext: WebServiceActionContext; optionalSpecificQuantity: Text; releaseImmediately: Text; optionalSourceLocationFilter: Text; optionalSourceBinFilter: Text; moveBehavior: Text)
+ var
+ QltyDispInternalPutAway: Codeunit "Qlty. Disp. Internal Put-away";
+ OverrideQuantity: Decimal;
+ ShouldReleaseImmediately: Boolean;
+ QuantityBehavior: Enum "Qlty. Quantity Behavior";
+ begin
+ optionalSourceLocationFilter := DelChr(optionalSourceLocationFilter, '<>', ' ');
+ optionalSourceBinFilter := DelChr(optionalSourceBinFilter, '<>', ' ');
+
+ if optionalSpecificQuantity <> '' then
+ Evaluate(OverrideQuantity, optionalSpecificQuantity);
+
+ ShouldReleaseImmediately := QltyBooleanParsing.GetBooleanFor(releaseImmediately);
+ QuantityBehavior := ConvertTextToQuantityBehaviorEnum(moveBehavior);
+
+ if QltyDispInternalPutAway.PerformDisposition(
+ Rec,
+ OverrideQuantity,
+ optionalSourceLocationFilter,
+ optionalSourceBinFilter,
+ ShouldReleaseImmediately,
+ QuantityBehavior
+ ) then
+ ActionContext.SetResultCode(WebServiceActionResultCode::Updated)
+ else
+ ActionContext.SetResultCode(WebServiceActionResultCode::None);
+ end;
+
+ ///
+ /// Creates a Warehouse Put-away document.
+ /// This feature can be used with directed pick and put locations with lot warehouse tracked items.
+ ///
+ ///
+ /// Quantity to move, if updating a specific quantity
+ /// Optionally restrict the locations to move from.
+ /// Optionally restrict the specific bins to move from.
+ /// valid options are KEEPOPEN (create internal put-away), RELEASE (create and release internal put-away), or CREATEPUTAWAY (create and release internal put-away and create warehouse put-away)
+ /// Valid options are: SpecificQuantity (quantity defined in optionalSpecificQuantity), TrackedQuantity (quantity of lot/package/serial), SampleQuantity (sample size), FailQuantity (number of failed samples), PassQuantity (number of passed samples)
+ [ServiceEnabled]
+ procedure CreateWarehousePutAway(var ActionContext: WebServiceActionContext; optionalSpecificQuantity: Text; optionalSourceLocationFilter: Text; optionalSourceBinFilter: Text; putAwayBehavior: Text; moveBehavior: Text)
+ var
+ QltyDispInternalPutAway: Codeunit "Qlty. Disp. Internal Put-away";
+ QltyDispWarehousePutAway: Codeunit "Qlty. Disp. Warehouse Put-away";
+ OverrideQuantity: Decimal;
+ QuantityBehavior: Enum "Qlty. Quantity Behavior";
+ Success: Boolean;
+ begin
+ optionalSourceLocationFilter := DelChr(optionalSourceLocationFilter, '<>', ' ');
+ optionalSourceBinFilter := DelChr(optionalSourceBinFilter, '<>', ' ');
+ putAwayBehavior := DelChr(putAwayBehavior, '<>', ' ').ToUpper();
+
+ if optionalSpecificQuantity <> '' then
+ Evaluate(OverrideQuantity, optionalSpecificQuantity);
+
+ QuantityBehavior := ConvertTextToQuantityBehaviorEnum(moveBehavior);
+
+ if putAwayBehavior.Contains('CREATEPUTAWAY') then
+ Success := QltyDispWarehousePutAway.PerformDisposition(
+ Rec,
+ OverrideQuantity,
+ optionalSourceLocationFilter,
+ optionalSourceBinFilter,
+ QuantityBehavior)
+ else
+ Success := QltyDispInternalPutAway.PerformDisposition(
+ Rec,
+ OverrideQuantity,
+ optionalSourceLocationFilter,
+ optionalSourceBinFilter,
+ putAwayBehavior.Contains('RELEASE'),
+ QuantityBehavior);
+
+ if Success then
+ ActionContext.SetResultCode(WebServiceActionResultCode::Updated)
+ else
+ ActionContext.SetResultCode(WebServiceActionResultCode::None);
+ end;
+
+ ///
+ /// Uses an item/warehouse reclassification journal or movement worksheet to move the inventory.
+ ///
+ ///
+ /// When left blank this assumes the same location as the from location.
+ /// The target bin to move to.
+ /// Quantity to move, if updating a specific quantity
+ /// When set to TRUE this will post journals immediately or create the warehouse movement. Verify you have sufficient licensing to use this flag.
+ /// Optionally restrict the locations to move from.
+ /// Optionally restrict the specific bins to move from.
+ /// When set to TRUE, will use the Movement Worksheet instead of a reclassification journal.
+ /// Valid options are: SpecificQuantity (quantity defined in optionalSpecificQuantity), TrackedQuantity (quantity of lot/package/serial) SampleQuantity (sample size), FailQuantity (number of failed samples), PassQuantity (number of passed samples)
+ [ServiceEnabled]
+ procedure MoveInventory(var ActionContext: WebServiceActionContext; optionalDestinationLocation: Text; optionalDestinationBin: Text; optionalSpecificQuantity: Text; postImmediately: Text; optionalSourceLocationFilter: Text; optionalSourceBinFilter: Text; useMoveSheet: Text; moveBehavior: Text)
+ var
+ TempInstructionQltyDispositionBuffer: Record "Qlty. Disposition Buffer" temporary;
+ InventoryQltyDispMoveAutoChoose: Codeunit "Qlty. Disp. Move Auto Choose";
+ UseMovement: Boolean;
+ begin
+
+ optionalDestinationBin := DelChr(optionalDestinationBin, '<>', ' ');
+ optionalDestinationLocation := DelChr(optionalDestinationLocation, '<>', ' ');
+ optionalSourceLocationFilter := DelChr(optionalSourceLocationFilter, '<>', ' ');
+ optionalSourceBinFilter := DelChr(optionalSourceBinFilter, '<>', ' ');
+
+
+ TempInstructionQltyDispositionBuffer."Quantity Behavior" := ConvertTextToQuantityBehaviorEnum(moveBehavior);
+
+ TempInstructionQltyDispositionBuffer."Disposition Action" := TempInstructionQltyDispositionBuffer."Disposition Action"::"Move with automatic choice";
+
+ if optionalSpecificQuantity <> '' then
+ Evaluate(TempInstructionQltyDispositionBuffer."Qty. To Handle (Base)", optionalSpecificQuantity);
+
+ TempInstructionQltyDispositionBuffer."Location Filter" := CopyStr(optionalSourceLocationFilter, 1, MaxStrLen(TempInstructionQltyDispositionBuffer."Location Filter"));
+ TempInstructionQltyDispositionBuffer."Bin Filter" := CopyStr(optionalSourceBinFilter, 1, MaxStrLen(TempInstructionQltyDispositionBuffer."Bin Filter"));
+ if QltyBooleanParsing.GetBooleanFor(postImmediately) then
+ TempInstructionQltyDispositionBuffer."Entry Behavior" := TempInstructionQltyDispositionBuffer."Entry Behavior"::Post;
+
+ TempInstructionQltyDispositionBuffer."New Location Code" := CopyStr(optionalDestinationLocation, 1, 10);
+ TempInstructionQltyDispositionBuffer."New Bin Code" := CopyStr(optionalDestinationBin, 1, 20);
+
+
+ if InventoryQltyDispMoveAutoChoose.MoveInventory(
+ Rec,
+ TempInstructionQltyDispositionBuffer,
+ UseMovement
+ ) then
+ ActionContext.SetResultCode(WebServiceActionResultCode::Updated)
+ else
+ ActionContext.SetResultCode(WebServiceActionResultCode::None);
+
+ end;
+
+ ///
+ /// Creates a negative inventory adjustment.
+ ///
+ ///
+ /// Optional additional location filter for item on test
+ /// Optional additional bin filter for item on test
+ /// Quantity to remove, if moving a specific quantity
+ /// Optional Reason Code
+ /// Remove a specific quantity, tracked quantity, sample size, or sample pass/fail quantity
+ /// Whether to create journal entries, register a warehouse item journal, or post an item journal
+ [ServiceEnabled]
+ procedure CreateNegativeAdjustment(var ActionContext: WebServiceActionContext; optionalSourceLocationFilter: Text; optionalSourceBinFilter: Text; optionalSpecificQuantity: Text; optionalReasonCode: Text; adjustmentBehavior: Text; postingBehavior: Text)
+ var
+ QltyDispNegAdjustInv: Codeunit "Qlty. Disp. Neg. Adjust Inv.";
+ SpecificQuantity: Decimal;
+ begin
+ optionalSourceLocationFilter := DelChr(optionalSourceLocationFilter, '<>', ' ');
+ optionalSourceBinFilter := DelChr(optionalSourceBinFilter, '<>', ' ');
+
+ if optionalSpecificQuantity <> '' then
+ Evaluate(SpecificQuantity, optionalSpecificQuantity);
+
+ if QltyDispNegAdjustInv.PerformDisposition(
+ Rec,
+ SpecificQuantity,
+ ConvertTextToQuantityBehaviorEnum(adjustmentBehavior),
+ optionalSourceLocationFilter,
+ optionalSourceBinFilter,
+ ConvertTextToItemAdjPostBehaviorEnum(postingBehavior),
+ CopyStr(optionalReasonCode, 1, 10))
+ then
+ ActionContext.SetResultCode(WebServiceActionResultCode::Created)
+ else
+ ActionContext.SetResultCode(WebServiceActionResultCode::None);
+
+ end;
+
+ local procedure ConvertTextToItemAdjPostBehaviorEnum(InputText: Text) QltyItemAdjPostBehavior: Enum "Qlty. Item Adj. Post Behavior"
+ var
+ IndexOfText: Integer;
+ OrdinalOfEnum: Integer;
+ begin
+ IndexOfText := QltyItemAdjPostBehavior.Names.IndexOf(InputText);
+ if IndexOfText = 0 then
+ QltyItemAdjPostBehavior := QltyItemAdjPostBehavior::"Prepare only"
+ else begin
+ OrdinalOfEnum := QltyItemAdjPostBehavior.Ordinals.Get(IndexOfText);
+ QltyItemAdjPostBehavior := Enum::"Qlty. Item Adj. Post Behavior".FromInteger(OrdinalOfEnum);
+ end;
+ end;
+
+ ///
+ /// Updates item tracking information.
+ ///
+ ///
+ /// Optional additional location filter for item on test
+ /// Optional additional bin filter for item on test
+ /// Quantity to update, if updating a specific quantity
+ /// Valid options are: SpecificQuantity (quantity defined in optionalSpecificQuantity), TrackedQuantity (quantity of lot/package/serial)
+ /// SampleQuantity (sample size), FailQuantity (number of failed samples), PassQuantity (number of passed samples)
+ /// Boolean value signifying whether to create the journal entry or create and post the journal
+ /// New lot no.
+ /// New serial no.
+ /// New package no.
+ /// New expiration date
+ [ServiceEnabled]
+ procedure ChangeItemTracking(var ActionContext: WebServiceActionContext; optionalSourceLocationFilter: Text; optionalSourceBinFilter: Text; optionalSpecificQuantity: Text; quantityChoice: Text; postImmediately: Text;
+ newLotNo: Text; newSerialNo: Text; newPackageNo: Text; newExpirationDate: Text)
+ var
+ TempInstructionQltyDispositionBuffer: Record "Qlty. Disposition Buffer" temporary;
+ QltyDispChangeTracking: Codeunit "Qlty. Disp. Change Tracking";
+ SpecificQuantity: Decimal;
+ DesiredExpirationDate: Date;
+ begin
+ optionalSourceLocationFilter := DelChr(optionalSourceLocationFilter, '<>', ' ');
+ optionalSourceBinFilter := DelChr(optionalSourceBinFilter, '<>', ' ');
+ newExpirationDate := DelChr(newExpirationDate, '<>', ' ');
+
+ if optionalSpecificQuantity <> '' then
+ Evaluate(SpecificQuantity, optionalSpecificQuantity);
+ TempInstructionQltyDispositionBuffer."Qty. To Handle (Base)" := SpecificQuantity;
+ TempInstructionQltyDispositionBuffer."Quantity Behavior" := ConvertTextToQuantityBehaviorEnum(quantityChoice);
+ if QltyBooleanParsing.GetBooleanFor(postImmediately) then
+ TempInstructionQltyDispositionBuffer."Entry Behavior" := TempInstructionQltyDispositionBuffer."Entry Behavior"::Post;
+
+ TempInstructionQltyDispositionBuffer."New Lot No." := CopyStr(DelChr(newLotNo, '<>', ' '), 1, MaxStrLen(TempInstructionQltyDispositionBuffer."New Lot No."));
+ TempInstructionQltyDispositionBuffer."New Serial No." := CopyStr(DelChr(newSerialNo, '<>', ' '), 1, MaxStrLen(TempInstructionQltyDispositionBuffer."New Serial No."));
+ TempInstructionQltyDispositionBuffer."New Package No." := CopyStr(DelChr(newPackageNo, '<>', ' '), 1, MaxStrLen(TempInstructionQltyDispositionBuffer."New Package No."));
+ if newExpirationDate <> '' then
+ if not Evaluate(DesiredExpirationDate, Format(newExpirationDate, 0, 9)) then
+ Error(CannotConvertDateErr, newExpirationDate);
+
+ TempInstructionQltyDispositionBuffer."New Expiration Date" := DesiredExpirationDate;
+ if QltyDispChangeTracking.PerformDisposition(Rec, TempInstructionQltyDispositionBuffer) then
+ ActionContext.SetResultCode(WebServiceActionResultCode::Updated)
+ else
+ ActionContext.SetResultCode(WebServiceActionResultCode::None);
+
+ end;
+
+ ///
+ /// Creates a transfer order to move the inventory.
+ ///
+ ///
+ /// Optional additional location filter for item on test
+ /// Optional additional bin filter for item on test
+ /// Destination location for the transfer
+ /// Quantity to transfer, if using the specific quantity choice
+ /// Transfer a specific quantity (SpecificQuantity), item tracked quantity (TrackedQuantity), sample size (SampleQuantity), or sample pass/fail quantity (PassQuantity or FailQuantity)
+ /// Boolean defining whether the transfer is direct
+ /// The in-transit location to use
+ [ServiceEnabled]
+ procedure CreateTransferOrder(var ActionContext: WebServiceActionContext; optionalSourceLocationFilter: Text; optionalSourceBinFilter: Text; destinationLocation: Text; optionalSpecificQuantity: Text; quantityChoice: Text;
+ directTransfer: Text; inTransitLocation: Text)
+ var
+ QltyDispTransfer: Codeunit "Qlty. Disp. Transfer";
+ SpecificQuantity: Decimal;
+ QuantityBehavior: Enum "Qlty. Quantity Behavior";
+ IsDirectTransfer: Boolean;
+ DestinationLocationCode: Code[10];
+ InTransitLocationCode: Code[10];
+ begin
+ optionalSourceLocationFilter := DelChr(optionalSourceLocationFilter, '<>', ' ');
+ optionalSourceBinFilter := DelChr(optionalSourceBinFilter, '<>', ' ');
+
+ if optionalSpecificQuantity <> '' then
+ Evaluate(SpecificQuantity, optionalSpecificQuantity);
+ QuantityBehavior := ConvertTextToQuantityBehaviorEnum(quantityChoice);
+ IsDirectTransfer := QltyBooleanParsing.GetBooleanFor(directTransfer);
+ DestinationLocationCode := CopyStr(destinationLocation, 1, MaxStrLen(DestinationLocationCode));
+ InTransitLocationCode := CopyStr(inTransitLocation, 1, MaxStrLen(InTransitLocationCode));
+ if IsDirectTransfer then
+ InTransitLocationCode := '';
+
+ if QltyDispTransfer.PerformDisposition(
+ Rec,
+ SpecificQuantity,
+ QuantityBehavior,
+ optionalSourceLocationFilter,
+ optionalSourceBinFilter,
+ DestinationLocationCode,
+ InTransitLocationCode
+ )
+ then
+ ActionContext.SetResultCode(WebServiceActionResultCode::Updated)
+ else
+ ActionContext.SetResultCode(WebServiceActionResultCode::None);
+
+ end;
+
+}
diff --git a/src/Apps/W1/Quality Management/app/src/Workflow/QltyStartWorkflow.Codeunit.al b/src/Apps/W1/Quality Management/app/src/Workflow/QltyStartWorkflow.Codeunit.al
index 1df9ca00d7..14e451d42e 100644
--- a/src/Apps/W1/Quality Management/app/src/Workflow/QltyStartWorkflow.Codeunit.al
+++ b/src/Apps/W1/Quality Management/app/src/Workflow/QltyStartWorkflow.Codeunit.al
@@ -11,6 +11,7 @@ using Microsoft.QualityManagement.Setup;
using Microsoft.QualityManagement.Utilities;
using System.Automation;
using System.Environment.Configuration;
+using System.Integration;
using System.Security.User;
///
@@ -37,16 +38,46 @@ codeunit 20426 "Qlty. Start Workflow"
internal procedure StartWorkflowInspectionCreated(var QltyInspectionHeader: Record "Qlty. Inspection Header")
begin
WorkflowManagement.HandleEvent(QltyWorkflowSetup.GetInspectionCreatedEvent(), QltyInspectionHeader);
+ OnInspectionCreated(
+ QltyInspectionHeader.SystemId,
+ QltyInspectionHeader."No.",
+ QltyInspectionHeader.GetReferenceRecordId(),
+ QltyInspectionHeader."Source Document No.",
+ QltyInspectionHeader."Source Item No.",
+ QltyInspectionHeader."Source Variant Code",
+ QltyInspectionHeader."Source Lot No.",
+ QltyInspectionHeader."Source Serial No.",
+ QltyInspectionHeader."Result Code");
end;
internal procedure StartWorkflowInspectionFinished(var QltyInspectionHeader: Record "Qlty. Inspection Header")
begin
WorkflowManagement.HandleEvent(QltyWorkflowSetup.GetInspectionFinishedEvent(), QltyInspectionHeader);
+ OnInspectionFinished(
+ QltyInspectionHeader.SystemId,
+ QltyInspectionHeader."No.",
+ QltyInspectionHeader.GetReferenceRecordId(),
+ QltyInspectionHeader."Source Document No.",
+ QltyInspectionHeader."Source Item No.",
+ QltyInspectionHeader."Source Variant Code",
+ QltyInspectionHeader."Source Lot No.",
+ QltyInspectionHeader."Source Serial No.",
+ QltyInspectionHeader."Result Code");
end;
internal procedure StartWorkflowInspectionReopens(var QltyInspectionHeader: Record "Qlty. Inspection Header")
begin
WorkflowManagement.HandleEvent(QltyWorkflowSetup.GetInspectionReopenedEvent(), QltyInspectionHeader);
+ OnInspectionReOpened(
+ QltyInspectionHeader.SystemId,
+ QltyInspectionHeader."No.",
+ QltyInspectionHeader.GetReferenceRecordId(),
+ QltyInspectionHeader."Source Document No.",
+ QltyInspectionHeader."Source Item No.",
+ QltyInspectionHeader."Source Variant Code",
+ QltyInspectionHeader."Source Lot No.",
+ QltyInspectionHeader."Source Serial No.",
+ QltyInspectionHeader."Result Code");
end;
internal procedure StartWorkflowInspectionChanged(var QltyInspectionHeader: Record "Qlty. Inspection Header"; xQltyInspectionHeader: Record "Qlty. Inspection Header")
@@ -77,10 +108,93 @@ codeunit 20426 "Qlty. Start Workflow"
WorkflowManagement.HandleEventWithxRec(CopyStr(QltyWorkflowSetup.GetInspectionHasChangedEvent(), 1, 128), QltyInspectionHeader, xQltyInspectionHeader);
RecursionDetectionQltySessionHelper.SetSessionValue('StartWorkflowInspectionChanged-Time', '');
RecursionDetectionQltySessionHelper.SetSessionValue('StartWorkflowInspectionChanged-Record', '');
+
+ OnInspectionChanged(
+ QltyInspectionHeader.SystemId,
+ QltyInspectionHeader."No.",
+ QltyInspectionHeader.GetReferenceRecordId(),
+ QltyInspectionHeader."Source Document No.",
+ QltyInspectionHeader."Source Item No.",
+ QltyInspectionHeader."Source Variant Code",
+ QltyInspectionHeader."Source Lot No.",
+ QltyInspectionHeader."Source Serial No.",
+ QltyInspectionHeader."Result Code");
end;
local procedure RecursionThrottleMilliseconds(): Integer
begin
exit(5000);
end;
+
+ ///
+ /// This action will occur when a new Quality Inspection has been created.
+ /// This is exposed with ExternalBusinessEvent and intended to be used in PowerAutomate
+ ///
+ /// The system record id of the newly created test
+ /// The test document no.
+ /// The source record id of the record that triggered the test
+ /// The source document no.
+ /// The source item no.
+ /// The source variant code.
+ /// The source lot number.
+ /// The source serial number.
+ /// The current grade of the test
+ [ExternalBusinessEvent('QualityInspectionCreated', 'Quality Inspection Created', 'This action will occur when a new Quality Inspection has been created.', EventCategory::QltyEventCategory, '1.0')]
+ procedure OnInspectionCreated(InspectionIdentifier: Guid; InspectionNo: Code[20]; SourceRecordIdentifier: Guid; SourceDocumentNo: Code[20]; SourceItemNo: Code[20]; SourceVariantCode: Code[10]; SourceLotNo: Code[50]; SourceSerialNo: Code[50]; ResultCode: Code[20])
+ begin
+ end;
+
+ ///
+ /// This action will occur when a Quality Inspection has changed to the finished state.
+ /// This is exposed with ExternalBusinessEvent and intended to be used in PowerAutomate
+ ///
+ /// The system ID of the quality inspection test
+ /// The quality inspection test no.
+ /// The system ID of the source record
+ /// The source document no. from the test
+ /// The source item no. associated with the test
+ /// If variants are used then the source variant on the test
+ /// The lot number associated with the test
+ /// The serial number associated with the test
+ /// The current grade of the test
+ [ExternalBusinessEvent('QualityInspectionFinished', 'Quality Inspection Finished', 'This action will occur when a Quality Inspection has changed to the finished state.', EventCategory::QltyEventCategory, '1.0')]
+ procedure OnInspectionFinished(InspectionIdentifier: Guid; InspectionNo: Code[20]; SourceRecordIdentifier: Guid; SourceDocumentNo: Code[20]; SourceItemNo: Code[20]; SourceVariantCode: Code[10]; SourceLotNo: Code[50]; SourceSerialNo: Code[50]; ResultCode: Code[20])
+ begin
+ end;
+
+ ///
+ /// This action will occur when a Quality Inspection has been re-opened.
+ /// This is exposed with ExternalBusinessEvent and intended to be used in PowerAutomate
+ ///
+ /// The system ID of the quality inspection test
+ /// The quality inspection test no.
+ /// The system ID of the source record
+ /// The source document no. from the test
+ /// The source item no. associated with the test
+ /// If variants are used then the source variant on the test
+ /// The lot number associated with the test
+ /// The serial number associated with the test
+ /// The current grade of the test
+ [ExternalBusinessEvent('QualityInspectionReOpened', 'Quality Inspection Re-Opened', 'This action will occur when a Quality Inspection has been re-opened.', EventCategory::QltyEventCategory, '1.0')]
+ procedure OnInspectionReOpened(InspectionIdentifier: Guid; InspectionNo: Code[20]; SourceRecordIdentifier: Guid; SourceDocumentNo: Code[20]; SourceItemNo: Code[20]; SourceVariantCode: Code[10]; SourceLotNo: Code[50]; SourceSerialNo: Code[50]; ResultCode: Code[20])
+ begin
+ end;
+
+ ///
+ /// This action will occur when a Quality Inspection has changed.
+ /// This is exposed with ExternalBusinessEvent and intended to be used in PowerAutomate
+ ///
+ /// The system ID of the quality inspection test
+ /// The quality inspection test no.
+ /// The system ID of the source record
+ /// The source document no. from the test
+ /// The source item no. associated with the test
+ /// If variants are used then the source variant on the test
+ /// The lot number associated with the test
+ /// The serial number associated with the test
+ /// The current grade of the test
+ [ExternalBusinessEvent('QualityInspectionChanged', 'Quality Inspection Changed', 'This action will occur when a Quality Inspection has changed.', EventCategory::QltyEventCategory, '1.0')]
+ procedure OnInspectionChanged(InspectionIdentifier: Guid; InspectionNo: Code[20]; SourceRecordIdentifier: Guid; SourceDocumentNo: Code[20]; SourceItemNo: Code[20]; SourceVariantCode: Code[10]; SourceLotNo: Code[50]; SourceSerialNo: Code[50]; ResultCode: Code[20])
+ begin
+ end;
}
diff --git a/src/Apps/W1/Quality Management/test/DisabledTests/QltyTestsResultCondition.DisabledTest.json b/src/Apps/W1/Quality Management/test/DisabledTests/QltyTestsResultCondition.DisabledTest.json
index 35c9c9f0b0..7bd4400aa2 100644
--- a/src/Apps/W1/Quality Management/test/DisabledTests/QltyTestsResultCondition.DisabledTest.json
+++ b/src/Apps/W1/Quality Management/test/DisabledTests/QltyTestsResultCondition.DisabledTest.json
@@ -10,5 +10,11 @@
"codeunitId": 139956,
"codeunitName": "Qlty. Tests - Result Condition",
"method": "PromptUpdateTestsFromResult_UpdateTextCondition_ShouldNotUpdate"
+ },
+ {
+ "bug": "Not Provided",
+ "codeunitId": 139972,
+ "codeunitName": "Qlty. Tests - Inspections API",
+ "method": "*"
}
]
\ No newline at end of file
diff --git a/src/Apps/W1/Quality Management/test/src/QltyTestsInspectionsAPI.Codeunit.al b/src/Apps/W1/Quality Management/test/src/QltyTestsInspectionsAPI.Codeunit.al
new file mode 100644
index 0000000000..b2a38ac3f7
--- /dev/null
+++ b/src/Apps/W1/Quality Management/test/src/QltyTestsInspectionsAPI.Codeunit.al
@@ -0,0 +1,622 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+namespace Microsoft.Test.QualityManagement;
+
+using Microsoft.Inventory.Item;
+using Microsoft.Purchases.Document;
+using Microsoft.QualityManagement.API;
+using Microsoft.QualityManagement.Configuration.GenerationRule;
+using Microsoft.QualityManagement.Configuration.Template;
+using Microsoft.QualityManagement.Document;
+using Microsoft.Test.QualityManagement.TestLibraries;
+using System.TestLibraries.Utilities;
+
+codeunit 139972 "Qlty. Tests - Inspections API"
+{
+ Subtype = Test;
+ TestType = IntegrationTest;
+ RequiredTestIsolation = Disabled;
+ TestPermissions = Disabled;
+
+ trigger OnRun()
+ begin
+ // [FEATURE] [Quality Management] [API]
+ end;
+
+ var
+ LibraryAssert: Codeunit "Library Assert";
+ LibraryGraphMgt: Codeunit "Library - Graph Mgt";
+ LibraryERMCountryData: Codeunit "Library - ERM Country Data";
+ LibraryPurchase: Codeunit "Library - Purchase";
+ LibraryInventory: Codeunit "Library - Inventory";
+ QltyInspectionUtility: Codeunit "Qlty. Inspection Utility";
+ IsInitialized: Boolean;
+ InspectionsServiceNameTxt: Label 'qualityInspections', Locked = true;
+ CreateInspectionsServiceNameTxt: Label 'createQualityInspections', Locked = true;
+ ActionFinishInspectionTxt: Label 'Microsoft.NAV.FinishInspection', Locked = true;
+ ActionReopenInspectionTxt: Label 'Microsoft.NAV.ReopenInspection', Locked = true;
+ ActionCreateReinspectionTxt: Label 'Microsoft.NAV.CreateReinspection', Locked = true;
+ ActionSetTestValueTxt: Label 'Microsoft.NAV.SetTestValue', Locked = true;
+ ActionAssignToTxt: Label 'Microsoft.NAV.AssignTo', Locked = true;
+ ActionCreateFromRecordIDTxt: Label 'Microsoft.NAV.CreateInspectionFromRecordID', Locked = true;
+ ActionCreateFromTableFilterTxt: Label 'Microsoft.NAV.CreateInspectionFromTableIDAndFilter', Locked = true;
+ PurchaseLineTableFilterTxt: Label 'WHERE(Document Type=CONST(Order),Document No.=FILTER(%1),Line No.=FILTER(%2))', Comment = '%1 = Document No., %2 = Line No.', Locked = true;
+ EmptyResponseErr: Label 'Response should not be empty.';
+
+ local procedure Initialize()
+ begin
+ if IsInitialized then
+ exit;
+
+ LibraryERMCountryData.CreateVATData();
+ IsInitialized := true;
+ Commit();
+ end;
+
+ // region Qlty. Inspections API (page 20414) - GET Tests
+
+ [Test]
+ procedure GetInspection()
+ var
+ QltyInspectionHeader: Record "Qlty. Inspection Header";
+ QltyInspectionTemplateHdr: Record "Qlty. Inspection Template Hdr.";
+ ResponseText: Text;
+ TargetURL: Text;
+ begin
+ // [SCENARIO] Retrieve a single quality inspection via GET request
+ Initialize();
+
+ // [GIVEN] A quality inspection exists
+ CreatePurchaseOrderAndInspection(QltyInspectionHeader, QltyInspectionTemplateHdr);
+ Commit();
+
+ // [WHEN] A GET request is made for the specific inspection
+ TargetURL := LibraryGraphMgt.CreateTargetURL(QltyInspectionHeader.SystemId, Page::"Qlty. Inspections API", InspectionsServiceNameTxt);
+ LibraryGraphMgt.GetFromWebService(ResponseText, TargetURL);
+
+ // [THEN] The response contains the inspection information
+ LibraryAssert.AreNotEqual('', ResponseText, EmptyResponseErr);
+ LibraryGraphMgt.VerifyPropertyInJSON(ResponseText, 'inspectionNo', QltyInspectionHeader."No.");
+ end;
+
+ [Test]
+ procedure GetInspectionVerifiesKeyFields()
+ var
+ QltyInspectionHeader: Record "Qlty. Inspection Header";
+ QltyInspectionTemplateHdr: Record "Qlty. Inspection Template Hdr.";
+ ResponseText: Text;
+ TargetURL: Text;
+ begin
+ // [SCENARIO] Verify key fields (No., Template Code) are returned correctly via GET
+ Initialize();
+
+ // [GIVEN] A quality inspection exists with a known template code
+ CreatePurchaseOrderAndInspection(QltyInspectionHeader, QltyInspectionTemplateHdr);
+ Commit();
+
+ // [WHEN] A GET request is made for the inspection
+ TargetURL := LibraryGraphMgt.CreateTargetURL(QltyInspectionHeader.SystemId, PAGE::"Qlty. Inspections API", InspectionsServiceNameTxt);
+ LibraryGraphMgt.GetFromWebService(ResponseText, TargetURL);
+
+ // [THEN] The response contains the correct No. and template code
+ LibraryAssert.AreNotEqual('', ResponseText, EmptyResponseErr);
+ LibraryGraphMgt.VerifyPropertyInJSON(ResponseText, 'inspectionNo', QltyInspectionHeader."No.");
+ LibraryGraphMgt.VerifyPropertyInJSON(ResponseText, 'templateCode', QltyInspectionHeader."Template Code");
+ end;
+
+ [Test]
+ procedure GetInspectionVerifiesSourceFields()
+ var
+ QltyInspectionHeader: Record "Qlty. Inspection Header";
+ QltyInspectionTemplateHdr: Record "Qlty. Inspection Template Hdr.";
+ ResponseText: Text;
+ TargetURL: Text;
+ begin
+ // [SCENARIO] Verify source fields are returned correctly via GET
+ Initialize();
+
+ // [GIVEN] A quality inspection exists with source information
+ CreatePurchaseOrderAndInspection(QltyInspectionHeader, QltyInspectionTemplateHdr);
+ Commit();
+
+ // [WHEN] A GET request is made for the inspection
+ TargetURL := LibraryGraphMgt.CreateTargetURL(QltyInspectionHeader.SystemId, PAGE::"Qlty. Inspections API", InspectionsServiceNameTxt);
+ LibraryGraphMgt.GetFromWebService(ResponseText, TargetURL);
+
+ // [THEN] The response contains source information fields
+ LibraryAssert.AreNotEqual('', ResponseText, EmptyResponseErr);
+ LibraryGraphMgt.VerifyPropertyInJSON(ResponseText, 'sourceDocumentNo', QltyInspectionHeader."Source Document No.");
+ LibraryGraphMgt.VerifyPropertyInJSON(ResponseText, 'sourceItemNo', QltyInspectionHeader."Source Item No.");
+ end;
+
+ [Test]
+ procedure GetInspectionVerifiesStatusField()
+ var
+ QltyInspectionHeader: Record "Qlty. Inspection Header";
+ QltyInspectionTemplateHdr: Record "Qlty. Inspection Template Hdr.";
+ ResponseText: Text;
+ TargetURL: Text;
+ begin
+ // [SCENARIO] Verify the inspection status field is returned correctly via GET
+ Initialize();
+
+ // [GIVEN] A new quality inspection exists with Open status
+ CreatePurchaseOrderAndInspection(QltyInspectionHeader, QltyInspectionTemplateHdr);
+ Commit();
+
+ // [WHEN] A GET request is made for the inspection
+ TargetURL := LibraryGraphMgt.CreateTargetURL(QltyInspectionHeader.SystemId, PAGE::"Qlty. Inspections API", InspectionsServiceNameTxt);
+ LibraryGraphMgt.GetFromWebService(ResponseText, TargetURL);
+
+ // [THEN] The response contains the status field showing Open
+ LibraryAssert.AreNotEqual('', ResponseText, EmptyResponseErr);
+ LibraryGraphMgt.VerifyPropertyInJSON(ResponseText, 'status', Format(QltyInspectionHeader.Status::Open));
+ end;
+
+ [Test]
+ procedure GetMultipleInspections()
+ var
+ QltyInspectionHeader1: Record "Qlty. Inspection Header";
+ QltyInspectionHeader2: Record "Qlty. Inspection Header";
+ QltyInspectionTemplateHdr1: Record "Qlty. Inspection Template Hdr.";
+ QltyInspectionTemplateHdr2: Record "Qlty. Inspection Template Hdr.";
+ ResponseText: Text;
+ TargetURL: Text;
+ begin
+ // [SCENARIO] Retrieve multiple quality inspections via GET collection request
+ Initialize();
+
+ // [GIVEN] Two quality inspections exist
+ CreatePurchaseOrderAndInspection(QltyInspectionHeader1, QltyInspectionTemplateHdr1);
+ CreatePurchaseOrderAndInspection(QltyInspectionHeader2, QltyInspectionTemplateHdr2);
+ Commit();
+
+ // [WHEN] A GET request is made for the inspections collection
+ TargetURL := LibraryGraphMgt.CreateTargetURL('', PAGE::"Qlty. Inspections API", InspectionsServiceNameTxt);
+ LibraryGraphMgt.GetFromWebService(ResponseText, TargetURL);
+
+ // [THEN] The response contains inspection data
+ LibraryAssert.AreNotEqual('', ResponseText, EmptyResponseErr);
+ end;
+
+ // endregion
+
+ // region Qlty. Inspections API (page 20414) - Action Tests
+
+ [Test]
+ procedure FinishInspection()
+ var
+ QltyInspectionHeader: Record "Qlty. Inspection Header";
+ QltyInspectionTemplateHdr: Record "Qlty. Inspection Template Hdr.";
+ ResponseText: Text;
+ TargetURL: Text;
+ begin
+ // [SCENARIO] Finish a quality inspection via the FinishInspection API action
+ Initialize();
+
+ // [GIVEN] An open quality inspection exists
+ CreatePurchaseOrderAndInspection(QltyInspectionHeader, QltyInspectionTemplateHdr);
+ Commit();
+
+ // [WHEN] The FinishInspection action is called
+ TargetURL := LibraryGraphMgt.CreateTargetURLWithSubpage(
+ QltyInspectionHeader.SystemId, PAGE::"Qlty. Inspections API", InspectionsServiceNameTxt, ActionFinishInspectionTxt);
+ LibraryGraphMgt.PostToWebServiceAndCheckResponseCode(TargetURL, '', ResponseText, 204);
+
+ // [THEN] The inspection status is updated to Finished
+ QltyInspectionHeader.Get(QltyInspectionHeader."No.");
+ LibraryAssert.AreEqual(
+ QltyInspectionHeader.Status::Finished, QltyInspectionHeader.Status,
+ 'Inspection should be finished.');
+ end;
+
+ [Test]
+ procedure FinishInspectionSetsFinishedDate()
+ var
+ QltyInspectionHeader: Record "Qlty. Inspection Header";
+ QltyInspectionTemplateHdr: Record "Qlty. Inspection Template Hdr.";
+ ResponseText: Text;
+ TargetURL: Text;
+ begin
+ // [SCENARIO] Finishing an inspection sets the Finished Date
+ Initialize();
+
+ // [GIVEN] An open quality inspection exists with no finished date
+ CreatePurchaseOrderAndInspection(QltyInspectionHeader, QltyInspectionTemplateHdr);
+ LibraryAssert.AreEqual(0D, DT2Date(QltyInspectionHeader."Finished Date"), 'Finished date should initially be blank.');
+ Commit();
+
+ // [WHEN] The FinishInspection action is called
+ TargetURL := LibraryGraphMgt.CreateTargetURLWithSubpage(
+ QltyInspectionHeader.SystemId, PAGE::"Qlty. Inspections API", InspectionsServiceNameTxt, ActionFinishInspectionTxt);
+ LibraryGraphMgt.PostToWebServiceAndCheckResponseCode(TargetURL, '', ResponseText, 204);
+
+ // [THEN] The finished date is set to today
+ QltyInspectionHeader.Get(QltyInspectionHeader."No.");
+ LibraryAssert.AreEqual(Today(), DT2Date(QltyInspectionHeader."Finished Date"), 'Finished date should be set to today.');
+ end;
+
+ [Test]
+ procedure ReopenFinishedInspection()
+ var
+ QltyInspectionHeader: Record "Qlty. Inspection Header";
+ QltyInspectionTemplateHdr: Record "Qlty. Inspection Template Hdr.";
+ ResponseText: Text;
+ TargetURL: Text;
+ begin
+ // [SCENARIO] Reopen a finished quality inspection via the ReopenInspection API action
+ Initialize();
+
+ // [GIVEN] A finished quality inspection exists
+ CreatePurchaseOrderAndInspection(QltyInspectionHeader, QltyInspectionTemplateHdr);
+ Commit();
+ TargetURL := LibraryGraphMgt.CreateTargetURLWithSubpage(
+ QltyInspectionHeader.SystemId, PAGE::"Qlty. Inspections API", InspectionsServiceNameTxt, ActionFinishInspectionTxt);
+ LibraryGraphMgt.PostToWebServiceAndCheckResponseCode(TargetURL, '', ResponseText, 204);
+
+ // [WHEN] The ReopenInspection action is called
+ TargetURL := LibraryGraphMgt.CreateTargetURLWithSubpage(
+ QltyInspectionHeader.SystemId, PAGE::"Qlty. Inspections API", InspectionsServiceNameTxt, ActionReopenInspectionTxt);
+ LibraryGraphMgt.PostToWebServiceAndCheckResponseCode(TargetURL, '', ResponseText, 204);
+
+ // [THEN] The inspection status is updated back to Open
+ QltyInspectionHeader.Get(QltyInspectionHeader."No.");
+ LibraryAssert.AreEqual(
+ QltyInspectionHeader.Status::Open, QltyInspectionHeader.Status,
+ 'Inspection should be reopened.');
+ end;
+
+ [Test]
+ procedure CreateReinspection()
+ var
+ QltyInspectionHeader: Record "Qlty. Inspection Header";
+ QltyInspectionTemplateHdr: Record "Qlty. Inspection Template Hdr.";
+ AllInspections: Record "Qlty. Inspection Header";
+ ResponseText: Text;
+ TargetURL: Text;
+ BeforeCount: Integer;
+ AfterCount: Integer;
+ begin
+ // [SCENARIO] Create a reinspection from a finished inspection via CreateReinspection API action
+ Initialize();
+
+ // [GIVEN] A finished quality inspection exists
+ CreatePurchaseOrderAndInspection(QltyInspectionHeader, QltyInspectionTemplateHdr);
+ Commit();
+ TargetURL := LibraryGraphMgt.CreateTargetURLWithSubpage(
+ QltyInspectionHeader.SystemId, PAGE::"Qlty. Inspections API", InspectionsServiceNameTxt, ActionFinishInspectionTxt);
+ LibraryGraphMgt.PostToWebServiceAndCheckResponseCode(TargetURL, '', ResponseText, 204);
+
+ AllInspections.Reset();
+ BeforeCount := AllInspections.Count();
+
+ // [WHEN] The CreateReinspection action is called
+ TargetURL := LibraryGraphMgt.CreateTargetURLWithSubpage(
+ QltyInspectionHeader.SystemId, PAGE::"Qlty. Inspections API", InspectionsServiceNameTxt, ActionCreateReinspectionTxt);
+ LibraryGraphMgt.PostToWebServiceAndCheckResponseCode(TargetURL, '', ResponseText, 204);
+
+ // [THEN] A new inspection record is created
+ AllInspections.Reset();
+ AfterCount := AllInspections.Count();
+ LibraryAssert.AreEqual(BeforeCount + 1, AfterCount, 'A reinspection should have been created.');
+ end;
+
+ [Test]
+ procedure SetTestValue()
+ var
+ QltyInspectionHeader: Record "Qlty. Inspection Header";
+ QltyInspectionTemplateHdr: Record "Qlty. Inspection Template Hdr.";
+ QltyInspectionLine: Record "Qlty. Inspection Line";
+ ActionBody: Text;
+ ResponseText: Text;
+ TargetURL: Text;
+ TestCodeToSet: Code[20];
+ TestValueToSet: Text[250];
+ begin
+ // [SCENARIO] Set a test value on an inspection line via the SetTestValue API action
+ Initialize();
+
+ // [GIVEN] An open quality inspection exists with test lines
+ CreatePurchaseOrderAndInspection(QltyInspectionHeader, QltyInspectionTemplateHdr);
+
+ // [GIVEN] A test code from the first inspection line
+ QltyInspectionLine.SetRange("Inspection No.", QltyInspectionHeader."No.");
+ QltyInspectionLine.FindFirst();
+ TestCodeToSet := QltyInspectionLine."Test Code";
+ TestValueToSet := 'API_TEST_VALUE';
+ Commit();
+
+ // [WHEN] The SetTestValue action is called with the test code and a value
+ ActionBody := LibraryGraphMgt.AddPropertytoJSON('', 'testCode', TestCodeToSet);
+ ActionBody := LibraryGraphMgt.AddPropertytoJSON(ActionBody, 'testValue', TestValueToSet);
+ TargetURL := LibraryGraphMgt.CreateTargetURLWithSubpage(
+ QltyInspectionHeader.SystemId, PAGE::"Qlty. Inspections API", InspectionsServiceNameTxt, ActionSetTestValueTxt);
+ LibraryGraphMgt.PostToWebServiceAndCheckResponseCode(TargetURL, ActionBody, ResponseText, 204);
+
+ // [THEN] The inspection line test value is updated
+ QltyInspectionLine.Get(QltyInspectionLine."Inspection No.", QltyInspectionLine."Re-inspection No.", QltyInspectionLine."Line No.");
+ LibraryAssert.AreEqual(TestValueToSet, QltyInspectionLine."Test Value", 'Test value should be updated.');
+ end;
+
+ [Test]
+ procedure AssignToUser()
+ var
+ QltyInspectionHeader: Record "Qlty. Inspection Header";
+ QltyInspectionTemplateHdr: Record "Qlty. Inspection Template Hdr.";
+ ActionBody: Text;
+ ResponseText: Text;
+ TargetURL: Text;
+ AssignedUser: Text;
+ begin
+ // [SCENARIO] Assign a quality inspection to a user via the AssignTo API action
+ Initialize();
+
+ // [GIVEN] An open quality inspection exists
+ CreatePurchaseOrderAndInspection(QltyInspectionHeader, QltyInspectionTemplateHdr);
+ AssignedUser := CopyStr(UserId(), 1, 50);
+ Commit();
+
+ // [WHEN] The AssignTo action is called with a user ID
+ ActionBody := LibraryGraphMgt.AddPropertytoJSON('', 'assignToUser', AssignedUser);
+ TargetURL := LibraryGraphMgt.CreateTargetURLWithSubpage(
+ QltyInspectionHeader.SystemId, PAGE::"Qlty. Inspections API", InspectionsServiceNameTxt, ActionAssignToTxt);
+ LibraryGraphMgt.PostToWebServiceAndCheckResponseCode(TargetURL, ActionBody, ResponseText, 204);
+
+ // [THEN] The inspection is assigned to the specified user
+ QltyInspectionHeader.Get(QltyInspectionHeader."No.");
+ LibraryAssert.AreEqual(
+ CopyStr(AssignedUser, 1, MaxStrLen(QltyInspectionHeader."Assigned User ID")),
+ QltyInspectionHeader."Assigned User ID",
+ 'Inspection should be assigned to the specified user.');
+ end;
+
+ [Test]
+ procedure SetTestValueAndFinishInspection()
+ var
+ QltyInspectionHeader: Record "Qlty. Inspection Header";
+ QltyInspectionTemplateHdr: Record "Qlty. Inspection Template Hdr.";
+ QltyInspectionLine: Record "Qlty. Inspection Line";
+ ActionBody: Text;
+ ResponseText: Text;
+ TargetURL: Text;
+ begin
+ // [SCENARIO] Set test values on all lines and then finish the inspection via API
+ Initialize();
+
+ // [GIVEN] An open quality inspection exists with test lines
+ CreatePurchaseOrderAndInspection(QltyInspectionHeader, QltyInspectionTemplateHdr);
+ Commit();
+
+ // [GIVEN] All test values are set via the API
+ QltyInspectionLine.SetRange("Inspection No.", QltyInspectionHeader."No.");
+ if QltyInspectionLine.FindSet() then
+ repeat
+ ActionBody := LibraryGraphMgt.AddPropertytoJSON('', 'testCode', QltyInspectionLine."Test Code");
+ ActionBody := LibraryGraphMgt.AddPropertytoJSON(ActionBody, 'testValue', 'PASS_VALUE');
+ TargetURL := LibraryGraphMgt.CreateTargetURLWithSubpage(
+ QltyInspectionHeader.SystemId, PAGE::"Qlty. Inspections API", InspectionsServiceNameTxt, ActionSetTestValueTxt);
+ LibraryGraphMgt.PostToWebServiceAndCheckResponseCode(TargetURL, ActionBody, ResponseText, 204);
+ until QltyInspectionLine.Next() = 0;
+
+ // [WHEN] The FinishInspection action is called
+ TargetURL := LibraryGraphMgt.CreateTargetURLWithSubpage(
+ QltyInspectionHeader.SystemId, PAGE::"Qlty. Inspections API", InspectionsServiceNameTxt, ActionFinishInspectionTxt);
+ LibraryGraphMgt.PostToWebServiceAndCheckResponseCode(TargetURL, '', ResponseText, 204);
+
+ // [THEN] The inspection is finished
+ QltyInspectionHeader.Get(QltyInspectionHeader."No.");
+ LibraryAssert.AreEqual(
+ QltyInspectionHeader.Status::Finished, QltyInspectionHeader.Status,
+ 'Inspection should be finished after setting all test values.');
+ end;
+
+ [Test]
+ procedure GetInspectionAfterFinish()
+ var
+ QltyInspectionHeader: Record "Qlty. Inspection Header";
+ QltyInspectionTemplateHdr: Record "Qlty. Inspection Template Hdr.";
+ ResponseText: Text;
+ TargetURL: Text;
+ begin
+ // [SCENARIO] Verify finished inspection fields are correct when retrieved via GET
+ Initialize();
+
+ // [GIVEN] A finished quality inspection exists
+ CreatePurchaseOrderAndInspection(QltyInspectionHeader, QltyInspectionTemplateHdr);
+ Commit();
+ TargetURL := LibraryGraphMgt.CreateTargetURLWithSubpage(
+ QltyInspectionHeader.SystemId, PAGE::"Qlty. Inspections API", InspectionsServiceNameTxt, ActionFinishInspectionTxt);
+ LibraryGraphMgt.PostToWebServiceAndCheckResponseCode(TargetURL, '', ResponseText, 204);
+
+ // [WHEN] A GET request is made for the finished inspection
+ TargetURL := LibraryGraphMgt.CreateTargetURL(QltyInspectionHeader.SystemId, PAGE::"Qlty. Inspections API", InspectionsServiceNameTxt);
+ LibraryGraphMgt.GetFromWebService(ResponseText, TargetURL);
+
+ // [THEN] The response shows the Finished status
+ LibraryAssert.AreNotEqual('', ResponseText, EmptyResponseErr);
+ LibraryGraphMgt.VerifyPropertyInJSON(ResponseText, 'status', Format(QltyInspectionHeader.Status::Finished));
+ end;
+
+ // endregion
+
+ // region Qlty. Create Inspection API (page 20415) - Action Tests
+
+ [Test]
+ procedure CreateInspectionFromRecordIDWithTableNumber()
+ var
+ QltyInspectionTemplateHdr: Record "Qlty. Inspection Template Hdr.";
+ QltyInspectionHeader: Record "Qlty. Inspection Header";
+ PurchaseLine: Record "Purchase Line";
+ ActionBody: Text;
+ ResponseText: Text;
+ TargetURL: Text;
+ BeforeCount: Integer;
+ AfterCount: Integer;
+ begin
+ // [SCENARIO] Create a quality inspection from a record ID using the table number as tableName
+ Initialize();
+
+ // [GIVEN] A purchase order line exists with a matching generation rule
+ SetupPurchaseOrderForCreateInspection(QltyInspectionTemplateHdr, PurchaseLine);
+
+ QltyInspectionHeader.Reset();
+ BeforeCount := QltyInspectionHeader.Count();
+ Commit();
+
+ // [WHEN] The CreateInspectionFromRecordID action is called with the table number
+ ActionBody := LibraryGraphMgt.AddPropertytoJSON('', 'tableName', Format(Database::"Purchase Line"));
+ TargetURL := LibraryGraphMgt.CreateTargetURLWithSubpage(
+ PurchaseLine.SystemId, PAGE::"Qlty. Create Inspection API", CreateInspectionsServiceNameTxt, ActionCreateFromRecordIDTxt);
+ LibraryGraphMgt.PostToWebServiceAndCheckResponseCode(TargetURL, ActionBody, ResponseText, 204);
+
+ // [THEN] A new quality inspection is created
+ QltyInspectionHeader.Reset();
+ AfterCount := QltyInspectionHeader.Count();
+ LibraryAssert.AreEqual(BeforeCount + 1, AfterCount, 'A quality inspection should have been created.');
+
+ // [THEN] The created inspection uses the correct template
+ QltyInspectionHeader.SetRange("Template Code", QltyInspectionTemplateHdr.Code);
+ LibraryAssert.RecordIsNotEmpty(QltyInspectionHeader);
+ end;
+
+ [Test]
+ procedure CreateInspectionFromRecordIDWithTableName()
+ var
+ QltyInspectionTemplateHdr: Record "Qlty. Inspection Template Hdr.";
+ QltyInspectionHeader: Record "Qlty. Inspection Header";
+ PurchaseLine: Record "Purchase Line";
+ ActionBody: Text;
+ ResponseText: Text;
+ TargetURL: Text;
+ BeforeCount: Integer;
+ AfterCount: Integer;
+ begin
+ // [SCENARIO] Create a quality inspection from a record ID using the table name as tableName
+ Initialize();
+
+ // [GIVEN] A purchase order line exists with a matching generation rule
+ SetupPurchaseOrderForCreateInspection(QltyInspectionTemplateHdr, PurchaseLine);
+
+ QltyInspectionHeader.Reset();
+ BeforeCount := QltyInspectionHeader.Count();
+ Commit();
+
+ // [WHEN] The CreateInspectionFromRecordID action is called with the table name
+ ActionBody := LibraryGraphMgt.AddPropertytoJSON('', 'tableName', 'Purchase Line');
+ TargetURL := LibraryGraphMgt.CreateTargetURLWithSubpage(
+ PurchaseLine.SystemId, PAGE::"Qlty. Create Inspection API", CreateInspectionsServiceNameTxt, ActionCreateFromRecordIDTxt);
+ LibraryGraphMgt.PostToWebServiceAndCheckResponseCode(TargetURL, ActionBody, ResponseText, 204);
+
+ // [THEN] A new quality inspection is created
+ QltyInspectionHeader.Reset();
+ AfterCount := QltyInspectionHeader.Count();
+ LibraryAssert.AreEqual(BeforeCount + 1, AfterCount, 'A quality inspection should have been created.');
+ end;
+
+ [Test]
+ procedure CreateInspectionFromTableIDAndFilter()
+ var
+ QltyInspectionTemplateHdr: Record "Qlty. Inspection Template Hdr.";
+ QltyInspectionHeader: Record "Qlty. Inspection Header";
+ PurchaseLine: Record "Purchase Line";
+ ActionBody: Text;
+ ResponseText: Text;
+ TargetURL: Text;
+ TableFilter: Text;
+ BeforeCount: Integer;
+ AfterCount: Integer;
+ begin
+ // [SCENARIO] Create a quality inspection from a table ID and filter
+ Initialize();
+
+ // [GIVEN] A purchase order line exists with a matching generation rule
+ SetupPurchaseOrderForCreateInspection(QltyInspectionTemplateHdr, PurchaseLine);
+
+ QltyInspectionHeader.Reset();
+ BeforeCount := QltyInspectionHeader.Count();
+
+ // [GIVEN] A table filter that uniquely identifies the purchase line
+ TableFilter := StrSubstNo(PurchaseLineTableFilterTxt,
+ PurchaseLine."Document No.",
+ PurchaseLine."Line No.");
+ Commit();
+
+ // [WHEN] The CreateInspectionFromTableIDAndFilter action is called
+ ActionBody := LibraryGraphMgt.AddPropertytoJSON('', 'tableName', Format(Database::"Purchase Line"));
+ ActionBody := LibraryGraphMgt.AddPropertytoJSON(ActionBody, 'tableNameFilter', TableFilter);
+ TargetURL := LibraryGraphMgt.CreateTargetURLWithSubpage(
+ PurchaseLine.SystemId, PAGE::"Qlty. Create Inspection API", CreateInspectionsServiceNameTxt, ActionCreateFromTableFilterTxt);
+ LibraryGraphMgt.PostToWebServiceAndCheckResponseCode(TargetURL, ActionBody, ResponseText, 204);
+
+ // [THEN] A new quality inspection is created
+ QltyInspectionHeader.Reset();
+ AfterCount := QltyInspectionHeader.Count();
+ LibraryAssert.AreEqual(BeforeCount + 1, AfterCount, 'A quality inspection should have been created from the table filter.');
+ end;
+
+ [Test]
+ procedure CreateInspectionFromRecordIDWithInvalidSystemIdFails()
+ var
+ QltyInspectionTemplateHdr: Record "Qlty. Inspection Template Hdr.";
+ PurchaseLine: Record "Purchase Line";
+ ActionBody: Text;
+ ResponseText: Text;
+ TargetURL: Text;
+ InvalidSystemId: Guid;
+ begin
+ // [SCENARIO] Attempting to create an inspection with an invalid SystemId should fail
+ Initialize();
+
+ // [GIVEN] A generation rule exists but the SystemId does not match any record
+ SetupPurchaseOrderForCreateInspection(QltyInspectionTemplateHdr, PurchaseLine);
+ InvalidSystemId := CreateGuid();
+ Commit();
+
+ // [WHEN] The CreateInspectionFromRecordID action is called with an invalid SystemId
+ ActionBody := LibraryGraphMgt.AddPropertytoJSON('', 'tableName', Format(Database::"Purchase Line"));
+ TargetURL := LibraryGraphMgt.CreateTargetURLWithSubpage(
+ InvalidSystemId, PAGE::"Qlty. Create Inspection API", CreateInspectionsServiceNameTxt, ActionCreateFromRecordIDTxt);
+
+ // [THEN] An error occurs because the record cannot be found
+ asserterror LibraryGraphMgt.PostToWebServiceAndCheckResponseCode(TargetURL, ActionBody, ResponseText, 204);
+ end;
+
+ // endregion
+
+ // region Helper procedures
+
+ local procedure CreatePurchaseOrderAndInspection(var OutQltyInspectionHeader: Record "Qlty. Inspection Header"; var OutQltyInspectionTemplateHdr: Record "Qlty. Inspection Template Hdr.")
+ var
+ PurchaseHeader: Record "Purchase Header";
+ PurchaseLine: Record "Purchase Line";
+ Item: Record Item;
+ begin
+ QltyInspectionUtility.EnsureBasicSetupExists(false);
+ QltyInspectionUtility.CreateTemplate(OutQltyInspectionTemplateHdr, 3);
+
+ LibraryInventory.CreateItem(Item);
+ LibraryPurchase.CreatePurchaseOrder(PurchaseHeader);
+ LibraryPurchase.CreatePurchaseLine(PurchaseLine, PurchaseHeader, PurchaseLine.Type::Item, Item."No.", 10);
+
+ QltyInspectionUtility.CreateInspectionWithPurchaseLine(PurchaseLine, OutQltyInspectionTemplateHdr.Code, OutQltyInspectionHeader);
+ end;
+
+ local procedure SetupPurchaseOrderForCreateInspection(var OutQltyInspectionTemplateHdr: Record "Qlty. Inspection Template Hdr."; var OutPurchaseLine: Record "Purchase Line")
+ var
+ QltyInspectionGenRule: Record "Qlty. Inspection Gen. Rule";
+ PurchaseHeader: Record "Purchase Header";
+ Item: Record Item;
+ begin
+ QltyInspectionUtility.EnsureBasicSetupExists(false);
+ QltyInspectionUtility.CreateTemplate(OutQltyInspectionTemplateHdr, 3);
+ QltyInspectionUtility.CreatePrioritizedRule(OutQltyInspectionTemplateHdr, Database::"Purchase Line", QltyInspectionGenRule);
+
+ LibraryInventory.CreateItem(Item);
+ LibraryPurchase.CreatePurchaseOrder(PurchaseHeader);
+ LibraryPurchase.CreatePurchaseLine(OutPurchaseLine, PurchaseHeader, OutPurchaseLine.Type::Item, Item."No.", 10);
+ end;
+
+ // endregion
+}