From 808af354d318cf437e75c14d89adca8e1d198b29 Mon Sep 17 00:00:00 2001
From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com>
Date: Mon, 20 Oct 2025 16:57:52 +0200
Subject: [PATCH 1/4] Accept request on the fulfillment service before syncing
shipments
---
.../ShpfyGQLAcceptFFRequest.Codeunit.al | 29 +++++
.../ShpfyGQLAssignedFFOrders.Codeunit.al | 29 +++++
.../ShpfyGQLFFOrdersFromOrder.Codeunit.al | 2 +-
.../ShpfyGQLNextAssignedFFOrders.Codeunit.al | 29 +++++
.../ShpfyGQLNextFFOrdersFromOrd.Codeunit.al | 2 +-
.../GraphQL/Enums/ShpfyGraphQLType.Enum.al | 15 +++
.../ShpfyFulfillmentOrdersAPI.Codeunit.al | 80 ++++++++++++
.../Enums/ShpfyFFRequestStatus.Enum.al | 52 ++++++++
.../ShpfyFulFillmentOrderHeader.Table.al | 6 +
.../ShpfyExportShipments.Codeunit.al | 30 ++++-
.../Reports/ShpfySyncShipmToShopify.Report.al | 8 +-
.../FulfillmentOrderAcceptResponse.txt | 1 +
.../ShpfySkippedRecordLogTest.Codeunit.al | 6 +-
.../Shipping/ShpfyShippingHelper.Codeunit.al | 4 +-
.../Shipping/ShpfyShippingTest.Codeunit.al | 121 ++++++++++++++++--
15 files changed, 392 insertions(+), 22 deletions(-)
create mode 100644 src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAcceptFFRequest.Codeunit.al
create mode 100644 src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAssignedFFOrders.Codeunit.al
create mode 100644 src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLNextAssignedFFOrders.Codeunit.al
create mode 100644 src/Apps/W1/Shopify/App/src/Order Fulfillments/Enums/ShpfyFFRequestStatus.Enum.al
create mode 100644 src/Apps/W1/Shopify/Test/.resources/Shipping/FulfillmentOrderAcceptResponse.txt
diff --git a/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAcceptFFRequest.Codeunit.al b/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAcceptFFRequest.Codeunit.al
new file mode 100644
index 0000000000..557fd3df75
--- /dev/null
+++ b/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAcceptFFRequest.Codeunit.al
@@ -0,0 +1,29 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+
+namespace Microsoft.Integration.Shopify;
+
+codeunit 30412 "Shpfy GQL AcceptFFRequest" implements "Shpfy IGraphQL"
+{
+ Access = Internal;
+
+ ///
+ /// GetGraphQL.
+ ///
+ /// Return value of type Text.
+ internal procedure GetGraphQL(): Text
+ begin
+ exit('{"query":"mutation { fulfillmentOrderAcceptFulfillmentRequest(id: \"gid://shopify/FulfillmentOrder/{{FulfillmentOrderId}}\") { fulfillmentOrder { id requestStatus } userErrors { field message }}}"}');
+ end;
+
+ ///
+ /// GetExpectedCost.
+ ///
+ /// Return value of type Integer.
+ internal procedure GetExpectedCost(): Integer
+ begin
+ exit(10);
+ end;
+}
diff --git a/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAssignedFFOrders.Codeunit.al b/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAssignedFFOrders.Codeunit.al
new file mode 100644
index 0000000000..0496461c27
--- /dev/null
+++ b/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAssignedFFOrders.Codeunit.al
@@ -0,0 +1,29 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+
+namespace Microsoft.Integration.Shopify;
+
+codeunit 30410 "Shpfy GQL AssignedFFOrders" implements "Shpfy IGraphQL"
+{
+ Access = Internal;
+
+ ///
+ /// GetGraphQL.
+ ///
+ /// Return value of type Text.
+ internal procedure GetGraphQL(): Text
+ begin
+ exit('{"query":"{ assignedFulfillmentOrders(assignmentStatus: FULFILLMENT_REQUESTED, first: 25) { pageInfo { hasNextPage } edges { cursor node { id status requestStatus }}}}"}');
+ end;
+
+ ///
+ /// GetExpectedCost.
+ ///
+ /// Return value of type Integer.
+ internal procedure GetExpectedCost(): Integer
+ begin
+ exit(12);
+ end;
+}
diff --git a/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLFFOrdersFromOrder.Codeunit.al b/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLFFOrdersFromOrder.Codeunit.al
index 910b2fec6d..7e7e927062 100644
--- a/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLFFOrdersFromOrder.Codeunit.al
+++ b/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLFFOrdersFromOrder.Codeunit.al
@@ -15,7 +15,7 @@ codeunit 30267 "Shpfy GQL FFOrdersFromOrder" implements "Shpfy IGraphQL"
/// Return value of type Text.
internal procedure GetGraphQL(): Text
begin
- exit('{"query":"{order(id: \"gid:\/\/shopify\/Order\/{{OrderId}}\") { legacyResourceId fulfillmentOrders(first: 25) { pageInfo { hasNextPage } edges { cursor node { id updatedAt status assignedLocation {location {legacyResourceId}} order {legacyResourceId} deliveryMethod {methodType}}}}}}"}');
+ exit('{"query":"{order(id: \"gid:\/\/shopify\/Order\/{{OrderId}}\") { legacyResourceId fulfillmentOrders(first: 25) { pageInfo { hasNextPage } edges { cursor node { id updatedAt status requestStatus assignedLocation {location {legacyResourceId}} order {legacyResourceId} deliveryMethod {methodType}}}}}}"}');
end;
///
diff --git a/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLNextAssignedFFOrders.Codeunit.al b/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLNextAssignedFFOrders.Codeunit.al
new file mode 100644
index 0000000000..e08da47a0d
--- /dev/null
+++ b/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLNextAssignedFFOrders.Codeunit.al
@@ -0,0 +1,29 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+
+namespace Microsoft.Integration.Shopify;
+
+codeunit 30411 "Shpfy GQL NextAssignedFFOrders" implements "Shpfy IGraphQL"
+{
+ Access = Internal;
+
+ ///
+ /// GetGraphQL.
+ ///
+ /// Return value of type Text.
+ internal procedure GetGraphQL(): Text
+ begin
+ exit('{"query":"{ assignedFulfillmentOrders(assignmentStatus: FULFILLMENT_REQUESTED, first: 25, after: \"{{After}}\") { pageInfo { hasNextPage } edges { cursor node { id status requestStatus }}}}"}');
+ end;
+
+ ///
+ /// GetExpectedCost.
+ ///
+ /// Return value of type Integer.
+ internal procedure GetExpectedCost(): Integer
+ begin
+ exit(12);
+ end;
+}
diff --git a/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLNextFFOrdersFromOrd.Codeunit.al b/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLNextFFOrdersFromOrd.Codeunit.al
index 7ac6b02287..92701e8d34 100644
--- a/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLNextFFOrdersFromOrd.Codeunit.al
+++ b/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLNextFFOrdersFromOrd.Codeunit.al
@@ -15,7 +15,7 @@ codeunit 30268 "Shpfy GQL NextFFOrdersFromOrd" implements "Shpfy IGraphQL"
/// Return value of type Text.
internal procedure GetGraphQL(): Text
begin
- exit('{"query":"{order(id: \"gid:\/\/shopify\/Order\/{{OrderId}}\") { legacyResourceId fulfillmentOrders(first: 25, after:\"{{After}}\") { pageInfo { hasNextPage } edges { cursor node { id updatedAt status assignedLocation {location {legacyResourceId}} order {legacyResourceId} deliveryMethod {methodType}}}}}}"}');
+ exit('{"query":"{order(id: \"gid:\/\/shopify\/Order\/{{OrderId}}\") { legacyResourceId fulfillmentOrders(first: 25, after:\"{{After}}\") { pageInfo { hasNextPage } edges { cursor node { id updatedAt status requestStatus assignedLocation {location {legacyResourceId}} order {legacyResourceId} deliveryMethod {methodType}}}}}}"}');
end;
///
diff --git a/src/Apps/W1/Shopify/App/src/GraphQL/Enums/ShpfyGraphQLType.Enum.al b/src/Apps/W1/Shopify/App/src/GraphQL/Enums/ShpfyGraphQLType.Enum.al
index f14e14c3c6..575b9c62f3 100644
--- a/src/Apps/W1/Shopify/App/src/GraphQL/Enums/ShpfyGraphQLType.Enum.al
+++ b/src/Apps/W1/Shopify/App/src/GraphQL/Enums/ShpfyGraphQLType.Enum.al
@@ -660,4 +660,19 @@ enum 30111 "Shpfy GraphQL Type" implements "Shpfy IGraphQL"
Caption = 'Get Company Location';
Implementation = "Shpfy IGraphQL" = "Shpfy GQL CompLocation";
}
+ value(134; GetAssignedFulfillmentOrders)
+ {
+ Caption = 'Get Assigned Fulfillment Orders';
+ Implementation = "Shpfy IGraphQL" = "Shpfy GQL AssignedFFOrders";
+ }
+ value(135; GetNextAssignedFulfillmentOrders)
+ {
+ Caption = 'Get Next Assigned Fulfillment Orders';
+ Implementation = "Shpfy IGraphQL" = "Shpfy GQL NextAssignedFFOrders";
+ }
+ value(136; AcceptFulfillmentRequest)
+ {
+ Caption = 'Accept Fulfillment Request';
+ Implementation = "Shpfy IGraphQL" = "Shpfy GQL AcceptFFRequest";
+ }
}
diff --git a/src/Apps/W1/Shopify/App/src/Order Fulfillments/Codeunits/ShpfyFulfillmentOrdersAPI.Codeunit.al b/src/Apps/W1/Shopify/App/src/Order Fulfillments/Codeunits/ShpfyFulfillmentOrdersAPI.Codeunit.al
index 6569053a9c..251c7d45d9 100644
--- a/src/Apps/W1/Shopify/App/src/Order Fulfillments/Codeunits/ShpfyFulfillmentOrdersAPI.Codeunit.al
+++ b/src/Apps/W1/Shopify/App/src/Order Fulfillments/Codeunits/ShpfyFulfillmentOrdersAPI.Codeunit.al
@@ -91,6 +91,7 @@ codeunit 30238 "Shpfy Fulfillment Orders API"
FulfillmentOrderHeader."Shopify Location Id" := JsonHelper.GetValueAsBigInteger(JNode, 'assignedLocation.location.legacyResourceId');
FulfillmentOrderHeader."Updated At" := JsonHelper.GetValueAsDateTime(JNode, 'updatedAt');
FulfillmentOrderHeader.Status := CopyStr(JsonHelper.GetValueAsText(JNode, 'status'), 1, MaxStrLen(FulfillmentOrderHeader.Status));
+ FulfillmentOrderHeader."Request Status" := ConvertToRequestStatus(JsonHelper.GetValueAsText(JNode, 'requestStatus'));
FulfillmentOrderHeader."Delivery Method Type" := ConvertToDeliveryMethodType(JsonHelper.GetValueAsText(JNode, 'deliveryMethod.methodType'));
if not FulfillmentOrderHeader.Insert() then
FulfillmentOrderHeader.Modify();
@@ -199,6 +200,76 @@ codeunit 30238 "Shpfy Fulfillment Orders API"
until not JsonHelper.GetValueAsBoolean(JResponse, 'data.order.fulfillmentOrders.pageInfo.hasNextPage');
end;
+ internal procedure GetAssignedFulfillmentOrders(Shop: Record "Shpfy Shop"; var FulfillmentOrderIds: Dictionary of [BigInteger, Code[20]])
+ var
+ Cursor: Text;
+ Parameters: Dictionary of [Text, Text];
+ JResponse: JsonToken;
+ begin
+ if not Shop."Fulfillment Service Activated" then
+ exit;
+
+ CommunicationMgt.SetShop(Shop);
+ GraphQLType := "Shpfy GraphQL Type"::GetAssignedFulfillmentOrders;
+
+ repeat
+ JResponse := CommunicationMgt.ExecuteGraphQL(GraphQLType, Parameters);
+ if JResponse.IsObject() then
+ if ExtractAssignedFulfillmentOrderIds(Shop.Code, JResponse.AsObject(), FulfillmentOrderIds, Cursor) then begin
+ if Parameters.ContainsKey('After') then
+ Parameters.Set('After', Cursor)
+ else
+ Parameters.Add('After', Cursor);
+ GraphQLType := "Shpfy GraphQL Type"::GetNextAssignedFulfillmentOrders;
+ end else
+ break;
+ until not JsonHelper.GetValueAsBoolean(JResponse, 'data.assignedFulfillmentOrders.pageInfo.hasNextPage');
+ end;
+
+ local procedure ExtractAssignedFulfillmentOrderIds(ShopCode: Code[20]; JResponse: JsonObject; var FulfillmentOrderIds: Dictionary of [BigInteger, Code[20]]; var Cursor: Text): Boolean
+ var
+ JEdges: JsonArray;
+ JNode: JsonObject;
+ JItem: JsonToken;
+ Id: BigInteger;
+ begin
+ if JsonHelper.GetJsonArray(JResponse, JEdges, 'data.assignedFulfillmentOrders.edges') then begin
+ foreach JItem in JEdges do begin
+ Cursor := JsonHelper.GetValueAsText(JItem.AsObject(), 'cursor');
+ if JsonHelper.GetJsonObject(JItem.AsObject(), JNode, 'node') then begin
+ Id := CommunicationMgt.GetIdOfGId(JsonHelper.GetValueAsText(JNode, 'id'));
+ if not FulfillmentOrderIds.ContainsKey(Id) then
+ FulfillmentOrderIds.Add(Id, ShopCode);
+ end;
+ end;
+ exit(JEdges.Count() > 0);
+ end;
+ exit(false);
+ end;
+
+ internal procedure AcceptFulfillmentRequest(Shop: Record "Shpfy Shop"; var FulfillmentOrderHeader: Record "Shpfy FulFillment Order Header"): Boolean
+ var
+ Parameters: Dictionary of [Text, Text];
+ JResponse: JsonToken;
+ NewRequestStatus: Enum "Shpfy FF Request Status";
+ begin
+ CommunicationMgt.SetShop(Shop);
+ Parameters.Add('FulfillmentOrderId', Format(FulfillmentOrderHeader."Shopify Fulfillment Order Id"));
+
+ GraphQLType := "Shpfy GraphQL Type"::AcceptFulfillmentRequest;
+ JResponse := CommunicationMgt.ExecuteGraphQL(GraphQLType, Parameters);
+
+ if JResponse.IsObject() then begin
+ NewRequestStatus := ConvertToRequestStatus(JsonHelper.GetValueAsText(JResponse, 'data.fulfillmentOrderAcceptFulfillmentRequest.fulfillmentOrder.requestStatus'));
+ if NewRequestStatus = Enum::"Shpfy FF Request Status"::ACCEPTED then begin
+ FulfillmentOrderHeader."Request Status" := NewRequestStatus;
+ FulfillmentOrderHeader.Modify();
+ exit(true);
+ end;
+ end;
+ exit(false);
+ end;
+
local procedure ConvertToDeliveryMethodType(Value: Text): Enum "Shpfy Delivery Method Type"
begin
Value := CommunicationMgt.ConvertToCleanOptionValue(Value);
@@ -207,4 +278,13 @@ codeunit 30238 "Shpfy Fulfillment Orders API"
else
exit(Enum::"Shpfy Delivery Method Type"::" ");
end;
+
+ local procedure ConvertToRequestStatus(Value: Text): Enum "Shpfy FF Request Status"
+ begin
+ Value := CommunicationMgt.ConvertToCleanOptionValue(Value);
+ if Enum::"Shpfy FF Request Status".Names().Contains(Value) then
+ exit(Enum::"Shpfy FF Request Status".FromInteger(Enum::"Shpfy FF Request Status".Ordinals().Get(Enum::"Shpfy FF Request Status".Names().IndexOf(Value))))
+ else
+ exit(Enum::"Shpfy FF Request Status"::" ");
+ end;
}
\ No newline at end of file
diff --git a/src/Apps/W1/Shopify/App/src/Order Fulfillments/Enums/ShpfyFFRequestStatus.Enum.al b/src/Apps/W1/Shopify/App/src/Order Fulfillments/Enums/ShpfyFFRequestStatus.Enum.al
new file mode 100644
index 0000000000..b5b0d180c8
--- /dev/null
+++ b/src/Apps/W1/Shopify/App/src/Order Fulfillments/Enums/ShpfyFFRequestStatus.Enum.al
@@ -0,0 +1,52 @@
+// ------------------------------------------------------------------------------------------------
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+// ------------------------------------------------------------------------------------------------
+
+namespace Microsoft.Integration.Shopify;
+
+///
+/// Enum Shpfy FF Request Status (ID 30178).
+///
+enum 30178 "Shpfy FF Request Status"
+{
+ Access = Public;
+ Caption = 'Shopify Fulfillment Request Status';
+
+ value(0; " ")
+ {
+ Caption = ' ';
+ }
+ value(1; Accepted)
+ {
+ Caption = 'Accepted';
+ }
+ value(2; "Cancellation Accepted")
+ {
+ Caption = 'Cancellation Accepted';
+ }
+ value(3; "Cancellation Rejected")
+ {
+ Caption = 'Cancellation Rejected';
+ }
+ value(4; "Cancellation Requested")
+ {
+ Caption = 'Cancellation Requested';
+ }
+ value(5; Closed)
+ {
+ Caption = 'Closed';
+ }
+ value(6; Rejected)
+ {
+ Caption = 'Rejected';
+ }
+ value(7; Submitted)
+ {
+ Caption = 'Submitted';
+ }
+ value(8; Unsubmitted)
+ {
+ Caption = 'Unsubmitted';
+ }
+}
diff --git a/src/Apps/W1/Shopify/App/src/Order Fulfillments/Tables/ShpfyFulFillmentOrderHeader.Table.al b/src/Apps/W1/Shopify/App/src/Order Fulfillments/Tables/ShpfyFulFillmentOrderHeader.Table.al
index 8fb9d54282..ceae6b2033 100644
--- a/src/Apps/W1/Shopify/App/src/Order Fulfillments/Tables/ShpfyFulFillmentOrderHeader.Table.al
+++ b/src/Apps/W1/Shopify/App/src/Order Fulfillments/Tables/ShpfyFulFillmentOrderHeader.Table.al
@@ -60,6 +60,12 @@ table 30143 "Shpfy FulFillment Order Header"
DataClassification = SystemMetadata;
Editable = false;
}
+ field(10; "Request Status"; Enum "Shpfy FF Request Status")
+ {
+ Caption = 'Request Status';
+ DataClassification = SystemMetadata;
+ Editable = false;
+ }
}
keys
{
diff --git a/src/Apps/W1/Shopify/App/src/Shipping/Codeunits/ShpfyExportShipments.Codeunit.al b/src/Apps/W1/Shopify/App/src/Shipping/Codeunits/ShpfyExportShipments.Codeunit.al
index 57fc70a903..1f790f98d1 100644
--- a/src/Apps/W1/Shopify/App/src/Shipping/Codeunits/ShpfyExportShipments.Codeunit.al
+++ b/src/Apps/W1/Shopify/App/src/Shipping/Codeunits/ShpfyExportShipments.Codeunit.al
@@ -29,7 +29,8 @@ codeunit 30190 "Shpfy Export Shipments"
/// Create Shopify Fulfillment.
///
/// Parameter of type Record "Sales Shipment Header".
- internal procedure CreateShopifyFulfillment(var SalesShipmentHeader: Record "Sales Shipment Header");
+ /// Parameter of type Dictionary of [BigInteger, Code[20]].
+ internal procedure CreateShopifyFulfillment(var SalesShipmentHeader: Record "Sales Shipment Header"; var AssignedFulfillmentOrderIds: Dictionary of [BigInteger, Code[20]]);
var
ShipmentLocation: Query "Shpfy Shipment Location";
begin
@@ -37,11 +38,11 @@ codeunit 30190 "Shpfy Export Shipments"
ShipmentLocation.SetRange(No, SalesShipmentHeader."No.");
if ShipmentLocation.Open() then
while ShipmentLocation.Read() do
- CreateShopifyFulfillment(SalesShipmentHeader, ShipmentLocation.LocationId, ShipmentLocation.DeliveryMethodType);
+ CreateShopifyFulfillment(SalesShipmentHeader, ShipmentLocation.LocationId, ShipmentLocation.DeliveryMethodType, AssignedFulfillmentOrderIds);
end;
end;
- local procedure CreateShopifyFulfillment(var SalesShipmentHeader: Record "Sales Shipment Header"; LocationId: BigInteger; DeliveryMethodType: Enum "Shpfy Delivery Method Type");
+ local procedure CreateShopifyFulfillment(var SalesShipmentHeader: Record "Sales Shipment Header"; LocationId: BigInteger; DeliveryMethodType: Enum "Shpfy Delivery Method Type"; var AssignedFulfillmentOrderIds: Dictionary of [BigInteger, Code[20]]);
var
Shop: Record "Shpfy Shop";
ShopifyOrderHeader: Record "Shpfy Order Header";
@@ -57,7 +58,7 @@ codeunit 30190 "Shpfy Export Shipments"
if ShopifyOrderHeader.Get(SalesShipmentHeader."Shpfy Order Id") then begin
ShopifyCommunicationMgt.SetShop(ShopifyOrderHeader."Shop Code");
Shop.Get(ShopifyOrderHeader."Shop Code");
- FulfillmentOrderRequests := CreateFulfillmentOrderRequest(SalesShipmentHeader, Shop, LocationId, DeliveryMethodType);
+ FulfillmentOrderRequests := CreateFulfillmentOrderRequest(SalesShipmentHeader, Shop, LocationId, DeliveryMethodType, AssignedFulfillmentOrderIds);
if FulfillmentOrderRequests.Count <> 0 then
foreach FulfillmentOrderRequest in FulfillmentOrderRequests do begin
JResponse := ShopifyCommunicationMgt.ExecuteGraphQL(FulfillmentOrderRequest);
@@ -79,7 +80,7 @@ codeunit 30190 "Shpfy Export Shipments"
end;
end;
- internal procedure CreateFulfillmentOrderRequest(SalesShipmentHeader: Record "Sales Shipment Header"; Shop: Record "Shpfy Shop"; LocationId: BigInteger; DeliveryMethodType: Enum "Shpfy Delivery Method Type") Requests: List of [Text];
+ internal procedure CreateFulfillmentOrderRequest(SalesShipmentHeader: Record "Sales Shipment Header"; Shop: Record "Shpfy Shop"; LocationId: BigInteger; DeliveryMethodType: Enum "Shpfy Delivery Method Type"; var AssignedFulfillmentOrderIds: Dictionary of [BigInteger, Code[20]]) Requests: List of [Text];
var
SalesShipmentLine: Record "Sales Shipment Line";
ShippingAgent: Record "Shipping Agent";
@@ -119,6 +120,8 @@ codeunit 30190 "Shpfy Export Shipments"
TempFulfillmentOrderLine."Quantity to Fulfill" := Round(SalesShipmentLine.Quantity, 1, '=');
TempFulfillmentOrderLine.Insert();
end;
+ // Accept pending fulfillment request before creating fulfillment
+ AcceptPendingFulfillmentRequests(Shop, FulfillmentOrderLine."Shopify Fulfillment Order Id", AssignedFulfillmentOrderIds);
end;
until SalesShipmentLine.Next() = 0;
@@ -163,6 +166,10 @@ codeunit 30190 "Shpfy Export Shipments"
GraphQuery.Append('lineItemsByFulfillmentOrder: [');
GraphQueryStart := GraphQuery.ToText();
repeat
+ // Skip fulfillment orders that are assigned and not accepted
+ if AssignedFulfillmentOrderIds.ContainsKey(TempFulfillmentOrderLine."Shopify Fulfillment Order Id") then
+ continue;
+
if PrevFulfillmentOrderId <> TempFulfillmentOrderLine."Shopify Fulfillment Order Id" then begin
if PrevFulfillmentOrderId <> 0 then
GraphQuery.Append(']},');
@@ -229,4 +236,17 @@ codeunit 30190 "Shpfy Export Shipments"
else
exit(Shop."Send Shipping Confirmation");
end;
+
+ local procedure AcceptPendingFulfillmentRequests(Shop: Record "Shpfy Shop"; FulfillmentOrderId: BigInteger; var AssignedFulfillmentOrderIds: Dictionary of [BigInteger, Code[20]])
+ var
+ FulfillmentOrderHeader: Record "Shpfy FulFillment Order Header";
+ FulfillmentOrdersAPI: Codeunit "Shpfy Fulfillment Orders API";
+ begin
+ // Check if this fulfillment order needs to be accepted and remove from dictionary
+ if AssignedFulfillmentOrderIds.ContainsKey(FulfillmentOrderId) then
+ if FulfillmentOrderHeader.Get(FulfillmentOrderId) then
+ if (FulfillmentOrderHeader.Status = 'OPEN') and (FulfillmentOrderHeader."Request Status" = FulfillmentOrderHeader."Request Status"::SUBMITTED) then
+ if FulfillmentOrdersAPI.AcceptFulfillmentRequest(Shop, FulfillmentOrderHeader) then
+ AssignedFulfillmentOrderIds.Remove(FulfillmentOrderId);
+ end;
}
\ No newline at end of file
diff --git a/src/Apps/W1/Shopify/App/src/Shipping/Reports/ShpfySyncShipmToShopify.Report.al b/src/Apps/W1/Shopify/App/src/Shipping/Reports/ShpfySyncShipmToShopify.Report.al
index dbdba2018d..e457e1dce8 100644
--- a/src/Apps/W1/Shopify/App/src/Shipping/Reports/ShpfySyncShipmToShopify.Report.al
+++ b/src/Apps/W1/Shopify/App/src/Shipping/Reports/ShpfySyncShipmToShopify.Report.al
@@ -48,8 +48,13 @@ report 30109 "Shpfy Sync Shipm. to Shopify"
end else
if ShopifyOrderHeader.Get("Sales Shipment Header"."Shpfy Order Id") then begin
Shop.Get(ShopifyOrderHeader."Shop Code");
+
+ // Get assigned fulfillment orders if not already retrieved for this shop
+ if not AssignedFulfillmentOrderIds.Values.Contains(Shop.Code) then
+ FulfillmentOrdersAPI.GetAssignedFulfillmentOrders(Shop, AssignedFulfillmentOrderIds);
+
FulfillmentOrdersAPI.GetShopifyFulfillmentOrdersFromShopifyOrder(Shop, "Sales Shipment Header"."Shpfy Order Id");
- ExportShipments.CreateShopifyFulfillment("Sales Shipment Header");
+ ExportShipments.CreateShopifyFulfillment("Sales Shipment Header", AssignedFulfillmentOrderIds);
end else
SkippedRecord.LogSkippedRecord("Sales Shipment Header"."Shpfy Order Id", "Sales Shipment Header".RecordId, StrSubstNo(ShopifyOrderNotExistsLbl, "Sales Shipment Header"."Shpfy Order Id"), Shop);
end;
@@ -59,6 +64,7 @@ report 30109 "Shpfy Sync Shipm. to Shopify"
var
ExportShipments: Codeunit "Shpfy Export Shipments";
FulfillmentOrdersAPI: Codeunit "Shpfy Fulfillment Orders API";
+ AssignedFulfillmentOrderIds: Dictionary of [BigInteger, Code[20]];
NoLinesApplicableLbl: Label 'No lines applicable for fulfillment.';
ShopifyOrderNotExistsLbl: Label 'Shopify order %1 does not exist.', Comment = '%1 = Shopify Order Id';
}
\ No newline at end of file
diff --git a/src/Apps/W1/Shopify/Test/.resources/Shipping/FulfillmentOrderAcceptResponse.txt b/src/Apps/W1/Shopify/Test/.resources/Shipping/FulfillmentOrderAcceptResponse.txt
new file mode 100644
index 0000000000..9f6e33c690
--- /dev/null
+++ b/src/Apps/W1/Shopify/Test/.resources/Shipping/FulfillmentOrderAcceptResponse.txt
@@ -0,0 +1 @@
+{"data":{"fulfillmentOrderAcceptFulfillmentRequest":{"fulfillmentOrder":{"id":"gid://shopify/FulfillmentOrder/8683141071148","requestStatus":"ACCEPTED"},"userErrors":[]}}}
\ No newline at end of file
diff --git a/src/Apps/W1/Shopify/Test/Logs/ShpfySkippedRecordLogTest.Codeunit.al b/src/Apps/W1/Shopify/Test/Logs/ShpfySkippedRecordLogTest.Codeunit.al
index cbc1a6b59e..ee0b18a844 100644
--- a/src/Apps/W1/Shopify/Test/Logs/ShpfySkippedRecordLogTest.Codeunit.al
+++ b/src/Apps/W1/Shopify/Test/Logs/ShpfySkippedRecordLogTest.Codeunit.al
@@ -696,6 +696,7 @@ codeunit 139581 "Shpfy Skipped Record Log Test"
SkippedRecord: Record "Shpfy Skipped Record";
ExportShipments: Codeunit "Shpfy Export Shipments";
ShippingHelper: Codeunit "Shpfy Shipping Helper";
+ AssignedFulfillmentOrderIds: Dictionary of [BigInteger, Code[20]];
ShopifyOrderId: BigInteger;
begin
// [SCENARIO] Log skipped record when sales shipment is export is skip because theres no fulfillment lines shopify.
@@ -707,7 +708,7 @@ codeunit 139581 "Shpfy Skipped Record Log Test"
ShippingHelper.CreateRandomSalesShipment(SalesShipmentHeader, ShopifyOrderId);
// [WHEN] Invoke Shopify Sync Shipment to Shopify
- ExportShipments.CreateShopifyFulfillment(SalesShipmentHeader);
+ ExportShipments.CreateShopifyFulfillment(SalesShipmentHeader, AssignedFulfillmentOrderIds);
// [THEN] Related record is created in shopify skipped record table.
SkippedRecord.SetRange("Record ID", SalesShipmentHeader.RecordId);
@@ -723,6 +724,7 @@ codeunit 139581 "Shpfy Skipped Record Log Test"
ExportShipments: Codeunit "Shpfy Export Shipments";
ShippingHelper: Codeunit "Shpfy Shipping Helper";
SkippedRecordLogSub: Codeunit "Shpfy Skipped Record Log Sub.";
+ AssignedFulfillmentOrderIds: Dictionary of [BigInteger, Code[20]];
ShopifyOrderId: BigInteger;
DeliveryMethodType: Enum "Shpfy Delivery Method Type";
begin
@@ -741,7 +743,7 @@ codeunit 139581 "Shpfy Skipped Record Log Test"
// [WHEN] Invoke Shopify Sync Shipment to Shopify
BindSubscription(SkippedRecordLogSub);
- ExportShipments.CreateShopifyFulfillment(SalesShipmentHeader);
+ ExportShipments.CreateShopifyFulfillment(SalesShipmentHeader, AssignedFulfillmentOrderIds);
UnbindSubscription(SkippedRecordLogSub);
// [THEN] Related record is created in shopify skipped record table.
diff --git a/src/Apps/W1/Shopify/Test/Shipping/ShpfyShippingHelper.Codeunit.al b/src/Apps/W1/Shopify/Test/Shipping/ShpfyShippingHelper.Codeunit.al
index 8dbef6a0e1..aa323f00d2 100644
--- a/src/Apps/W1/Shopify/Test/Shipping/ShpfyShippingHelper.Codeunit.al
+++ b/src/Apps/W1/Shopify/Test/Shipping/ShpfyShippingHelper.Codeunit.al
@@ -55,7 +55,7 @@ codeunit 139559 "Shpfy Shipping Helper"
end;
end;
- internal procedure CreateShopifyFulfillmentOrder(ShopifyOrderId: BigInteger; DeliveryMethodType: Enum "Shpfy Delivery Method Type"): BigInteger
+ internal procedure CreateShopifyFulfillmentOrder(ShopifyOrderId: BigInteger; DeliveryMethodType: Enum "Shpfy Delivery Method Type"): Record "Shpfy FulFillment Order Header"
var
OrderLine: Record "Shpfy Order Line";
FulfillmentOrderHeader: Record "Shpfy FulFillment Order Header";
@@ -87,7 +87,7 @@ codeunit 139559 "Shpfy Shipping Helper"
FulfillmentOrderLine.Insert();
until OrderLine.Next() = 0;
- exit(FulfillmentOrderHeader."Shopify Fulfillment Order Id");
+ exit(FulfillmentOrderHeader);
end;
internal procedure CreateRandomSalesShipment(var SalesShipmentHeader: Record "Sales Shipment Header"; ShopifyOrderId: BigInteger)
diff --git a/src/Apps/W1/Shopify/Test/Shipping/ShpfyShippingTest.Codeunit.al b/src/Apps/W1/Shopify/Test/Shipping/ShpfyShippingTest.Codeunit.al
index 3706ce2d65..2bf462fc3b 100644
--- a/src/Apps/W1/Shopify/Test/Shipping/ShpfyShippingTest.Codeunit.al
+++ b/src/Apps/W1/Shopify/Test/Shipping/ShpfyShippingTest.Codeunit.al
@@ -13,10 +13,14 @@ codeunit 139606 "Shpfy Shipping Test"
{
Subtype = Test;
TestPermissions = Disabled;
+ TestHttpRequestPolicy = BlockOutboundRequests;
var
+ Shop: Record "Shpfy Shop";
Any: Codeunit Any;
LibraryAssert: Codeunit "Library Assert";
+ InitializeTest: Codeunit "Shpfy Initialize Test";
+ IsInitialized: Boolean;
[Test]
procedure UnitTestExportShipment()
@@ -24,32 +28,33 @@ codeunit 139606 "Shpfy Shipping Test"
SalesShipmentHeader: Record "Sales Shipment Header";
SalesShipmentLine: Record "Sales Shipment Line";
OrderLine: Record "Shpfy Order Line";
- Shop: Record "Shpfy Shop";
+ FulfillmentOrderHeader: Record "Shpfy FulFillment Order Header";
ExportShipments: Codeunit "Shpfy Export Shipments";
ShippingHelper: Codeunit "Shpfy Shipping Helper";
DeliveryMethodType: Enum "Shpfy Delivery Method Type";
FulfillmentRequest: Text;
FulfillmentRequests: List of [Text];
+ AssignedFulfillmentOrderIds: Dictionary of [BigInteger, Code[20]];
ShopifyOrderId: BigInteger;
- ShopifyFulfillmentOrderId: BigInteger;
LocationId: BigInteger;
QuantityLbl: Label 'quantity: %1', Comment = '%1 - quantity', Locked = true;
begin
// [SCENARIO] Export a Sales Shipment record into a Json token that contains the shipping info
// [GIVEN] A random Sales Shipment, a random LocationId, a random Shop
+ Initialize();
LocationId := Any.IntegerInRange(10000, 99999);
DeliveryMethodType := DeliveryMethodType::Shipping;
ShopifyOrderId := ShippingHelper.CreateRandomShopifyOrder(LocationId, DeliveryMethodType);
- ShopifyFulfillmentOrderId := ShippingHelper.CreateShopifyFulfillmentOrder(ShopifyOrderId, DeliveryMethodType);
+ FulfillmentOrderHeader := ShippingHelper.CreateShopifyFulfillmentOrder(ShopifyOrderId, DeliveryMethodType);
ShippingHelper.CreateRandomSalesShipment(SalesShipmentHeader, ShopifyOrderId);
// [WHEN] Invoke the function CreateFulfillmentRequest()
- FulfillmentRequests := ExportShipments.CreateFulfillmentOrderRequest(SalesShipmentHeader, Shop, LocationId, DeliveryMethodType);
+ FulfillmentRequests := ExportShipments.CreateFulfillmentOrderRequest(SalesShipmentHeader, Shop, LocationId, DeliveryMethodType, AssignedFulfillmentOrderIds);
// [THEN] We must find the correct fulfilment data in the json token
LibraryAssert.AreEqual(1, FulfillmentRequests.Count, 'FulfillmentRequest count check');
FulfillmentRequests.Get(1, FulfillmentRequest);
- LibraryAssert.IsTrue(FulfillmentRequest.Contains(Format(ShopifyFulfillmentOrderId)), 'Fulfillmentorder Id Check');
+ LibraryAssert.IsTrue(FulfillmentRequest.Contains(Format(FulfillmentOrderHeader."Shopify Fulfillment Order Id")), 'Fulfillmentorder Id Check');
LibraryAssert.IsTrue(FulfillmentRequest.Contains(SalesShipmentHeader."Package Tracking No."), 'tracking number check');
// [THEN] We must find the fulfilment lines in the json token
@@ -66,33 +71,129 @@ codeunit 139606 "Shpfy Shipping Test"
procedure UnitTestExportShipment250Lines()
var
SalesShipmentHeader: Record "Sales Shipment Header";
- Shop: Record "Shpfy Shop";
+ FulfillmentOrderHeader: Record "Shpfy FulFillment Order Header";
ExportShipments: Codeunit "Shpfy Export Shipments";
ShippingHelper: Codeunit "Shpfy Shipping Helper";
DeliveryMethodType: Enum "Shpfy Delivery Method Type";
FulfillmentRequest: Text;
FulfillmentRequests: List of [Text];
+ AssignedFulfillmentOrderIds: Dictionary of [BigInteger, Code[20]];
ShopifyOrderId: BigInteger;
- ShopifyFulfillmentOrderId: BigInteger;
LocationId: BigInteger;
begin
// [SCENARIO] Export a Sales Shipment with more than 250 lines creates two fulfillment requests
// [GIVEN] A random Sales Shipment, a random LocationId, a random Shop
+ Initialize();
LocationId := Any.IntegerInRange(10000, 99999);
DeliveryMethodType := DeliveryMethodType::Shipping;
ShopifyOrderId := ShippingHelper.CreateRandomShopifyOrder(LocationId, DeliveryMethodType);
ShippingHelper.CreateOrderLines(ShopifyOrderId, LocationId, DeliveryMethodType, 300);
- ShopifyFulfillmentOrderId := ShippingHelper.CreateShopifyFulfillmentOrder(ShopifyOrderId, DeliveryMethodType);
+ FulfillmentOrderHeader := ShippingHelper.CreateShopifyFulfillmentOrder(ShopifyOrderId, DeliveryMethodType);
ShippingHelper.CreateRandomSalesShipment(SalesShipmentHeader, ShopifyOrderId);
// [WHEN] Invoke the function CreateFulfillmentRequest()
- FulfillmentRequests := ExportShipments.CreateFulfillmentOrderRequest(SalesShipmentHeader, Shop, LocationId, DeliveryMethodType);
+ FulfillmentRequests := ExportShipments.CreateFulfillmentOrderRequest(SalesShipmentHeader, Shop, LocationId, DeliveryMethodType, AssignedFulfillmentOrderIds);
// [THEN] We must find the correct fulfilment data in the json token
LibraryAssert.AreEqual(2, FulfillmentRequests.Count(), 'FulfillmentRequest count check');
foreach FulfillmentRequest in FulfillmentRequests do begin
- LibraryAssert.IsTrue(FulfillmentRequest.Contains(Format(ShopifyFulfillmentOrderId)), 'Fulfillmentorder Id Check');
+ LibraryAssert.IsTrue(FulfillmentRequest.Contains(Format(FulfillmentOrderHeader."Shopify Fulfillment Order Id")), 'Fulfillmentorder Id Check');
LibraryAssert.IsTrue(FulfillmentRequest.Contains(SalesShipmentHeader."Package Tracking No."), 'tracking number check');
end;
end;
+
+ [Test]
+ [HandlerFunctions('HttpSubmitHandler')]
+ procedure UnitTestExportFulfillmentServiceShipment()
+ var
+ SalesShipmentHeader: Record "Sales Shipment Header";
+ SalesShipmentLine: Record "Sales Shipment Line";
+ OrderLine: Record "Shpfy Order Line";
+ FulfillmentOrderHeader: Record "Shpfy FulFillment Order Header";
+ ExportShipments: Codeunit "Shpfy Export Shipments";
+ ShippingHelper: Codeunit "Shpfy Shipping Helper";
+ DeliveryMethodType: Enum "Shpfy Delivery Method Type";
+ FulfillmentRequest: Text;
+ FulfillmentRequests: List of [Text];
+ AssignedFulfillmentOrderIds: Dictionary of [BigInteger, Code[20]];
+ ShopifyOrderId: BigInteger;
+ LocationId: BigInteger;
+ QuantityLbl: Label 'quantity: %1', Comment = '%1 - quantity', Locked = true;
+ begin
+ // [SCENARIO] Export a Sales Shipment record into a Json token that contains the shipping info
+ // [GIVEN] A random Sales Shipment, a random LocationId, a random Shop
+ Initialize();
+ LocationId := Any.IntegerInRange(10000, 99999);
+ DeliveryMethodType := DeliveryMethodType::Shipping;
+ ShopifyOrderId := ShippingHelper.CreateRandomShopifyOrder(LocationId, DeliveryMethodType);
+ FulfillmentOrderHeader := ShippingHelper.CreateShopifyFulfillmentOrder(ShopifyOrderId, DeliveryMethodType);
+ ShippingHelper.CreateRandomSalesShipment(SalesShipmentHeader, ShopifyOrderId);
+ AssignedFulfillmentOrderIds.Add(FulfillmentOrderHeader."Shopify Fulfillment Order Id", Shop.Code);
+ FulfillmentOrderHeader.Status := 'OPEN';
+ FulfillmentOrderHeader."Request Status" := FulfillmentOrderHeader."Request Status"::Submitted;
+ FulfillmentOrderHeader.Modify();
+
+ // [WHEN] Invoke the function CreateFulfillmentRequest()
+ FulfillmentRequests := ExportShipments.CreateFulfillmentOrderRequest(SalesShipmentHeader, Shop, LocationId, DeliveryMethodType, AssignedFulfillmentOrderIds);
+
+ // [THEN] We must find the correct fulfilment data in the json token
+ LibraryAssert.AreEqual(1, FulfillmentRequests.Count, 'FulfillmentRequest count check');
+ FulfillmentRequests.Get(1, FulfillmentRequest);
+ LibraryAssert.IsTrue(FulfillmentRequest.Contains(Format(FulfillmentOrderHeader."Shopify Fulfillment Order Id")), 'Fulfillmentorder Id Check');
+ LibraryAssert.IsTrue(FulfillmentRequest.Contains(SalesShipmentHeader."Package Tracking No."), 'tracking number check');
+ LibraryAssert.IsTrue(AssignedFulfillmentOrderIds.Count() = 0, 'Assigned Fulfillment Order Ids count check');
+
+ // [THEN] We must find the fulfilment lines in the json token
+ OrderLine.SetRange("Shopify Order Id", ShopifyOrderId);
+ OrderLine.FindFirst();
+#pragma warning disable AA0210
+ SalesShipmentLine.SetRange("Shpfy Order Line Id", OrderLine."Line Id");
+#pragma warning restore AA0210
+ SalesShipmentLine.FindFirst();
+ LibraryAssert.IsTrue(FulfillmentRequest.Contains(StrSubstNo(QuantityLbl, SalesShipmentLine.Quantity)), 'quantity check');
+ end;
+
+ local procedure Initialize()
+ var
+ CommunicationMgt: Codeunit "Shpfy Communication Mgt.";
+ LibraryTestInitialize: Codeunit "Library - Test Initialize";
+ LibraryRandom: Codeunit "Library - Random";
+ AccessToken: SecretText;
+ begin
+ LibraryTestInitialize.OnTestInitialize(Codeunit::"Shpfy Shipping Test");
+ ClearLastError();
+
+ if IsInitialized then
+ exit;
+
+ LibraryTestInitialize.OnBeforeTestSuiteInitialize(Codeunit::"Shpfy Shipping Test");
+
+ LibraryRandom.Init();
+
+ Any.SetDefaultSeed();
+
+ IsInitialized := true;
+ Commit();
+
+ // Creating Shopify Shop
+ Shop := InitializeTest.CreateShop();
+
+ CommunicationMgt.SetTestInProgress(false);
+
+ //Register Shopify Access Token
+ AccessToken := LibraryRandom.RandText(20);
+ InitializeTest.RegisterAccessTokenForShop(Shop.GetStoreName(), AccessToken);
+
+ LibraryTestInitialize.OnAfterTestSuiteInitialize(Codeunit::"Shpfy Shipping Test");
+ end;
+
+ [HttpClientHandler]
+ internal procedure HttpSubmitHandler(Request: TestHttpRequestMessage; var Response: TestHttpResponseMessage): Boolean
+ begin
+ if not InitializeTest.VerifyRequestUrl(Request.Path, Shop."Shopify URL") then
+ exit(true);
+
+ Response.Content.WriteFrom(NavApp.GetResourceAsText('Shipping/FulfillmentOrderAcceptResponse.txt', TextEncoding::UTF8));
+ exit(false); // Prevents actual HTTP call
+ end;
}
\ No newline at end of file
From decbb9f3dd7d4ece5391bc1a4e5f2ace98f94959 Mon Sep 17 00:00:00 2001
From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com>
Date: Mon, 20 Oct 2025 17:01:12 +0200
Subject: [PATCH 2/4] Permissions
---
.../App/src/PermissionSets/ShpfyObjects.PermissionSet.al | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/Apps/W1/Shopify/App/src/PermissionSets/ShpfyObjects.PermissionSet.al b/src/Apps/W1/Shopify/App/src/PermissionSets/ShpfyObjects.PermissionSet.al
index f145465716..39baa906a1 100644
--- a/src/Apps/W1/Shopify/App/src/PermissionSets/ShpfyObjects.PermissionSet.al
+++ b/src/Apps/W1/Shopify/App/src/PermissionSets/ShpfyObjects.PermissionSet.al
@@ -149,9 +149,11 @@ permissionset 30104 "Shpfy - Objects"
codeunit "Shpfy Fulfillment API" = X,
codeunit "Shpfy Fulfillment Orders API" = X,
codeunit "Shpfy Gift Cards" = X,
+ codeunit "Shpfy GQL AcceptFFRequest" = X,
codeunit "Shpfy GQL AddProductImage" = X,
codeunit "Shpfy GQL AllCustomerIds" = X,
codeunit "Shpfy GQL ApiKey" = X,
+ codeunit "Shpfy GQL AssignedFFOrders" = X,
codeunit "Shpfy GQL BulkOperation" = X,
codeunit "Shpfy GQL BulkOperations" = X,
codeunit "Shpfy GQL BulkOpMutation" = X,
@@ -208,6 +210,7 @@ permissionset 30104 "Shpfy - Objects"
codeunit "Shpfy GQL Modify Inventory" = X,
codeunit "Shpfy GQL Next Locations" = X,
codeunit "Shpfy GQL NextAllCustomerIds" = X,
+ codeunit "Shpfy GQL NextAssignedFFOrders" = X,
codeunit "Shpfy GQL NextCatalogMarkets" = X,
codeunit "Shpfy GQL NextCatalogPrices" = X,
codeunit "Shpfy GQL NextCatalogProducts" = X,
From 8c7dea9bd4fb3d8593fcbd5222e40a26f608a42d Mon Sep 17 00:00:00 2001
From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com>
Date: Tue, 21 Oct 2025 12:27:47 +0200
Subject: [PATCH 3/4] Update
---
.../src/GraphQL/Codeunits/ShpfyGQLAcceptFFRequest.Codeunit.al | 4 ++++
.../GraphQL/Codeunits/ShpfyGQLAssignedFFOrders.Codeunit.al | 4 ++++
.../Codeunits/ShpfyGQLNextAssignedFFOrders.Codeunit.al | 4 ++++
3 files changed, 12 insertions(+)
diff --git a/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAcceptFFRequest.Codeunit.al b/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAcceptFFRequest.Codeunit.al
index 557fd3df75..ea5e1cd602 100644
--- a/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAcceptFFRequest.Codeunit.al
+++ b/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAcceptFFRequest.Codeunit.al
@@ -5,6 +5,10 @@
namespace Microsoft.Integration.Shopify;
+///
+/// Codeunit Shpfy GQL AcceptFFRequest (ID 30412).
+/// Implements the IGraphQL interface for accepting Shopify fulfillment requests using GraphQL.
+///
codeunit 30412 "Shpfy GQL AcceptFFRequest" implements "Shpfy IGraphQL"
{
Access = Internal;
diff --git a/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAssignedFFOrders.Codeunit.al b/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAssignedFFOrders.Codeunit.al
index 0496461c27..959e990b42 100644
--- a/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAssignedFFOrders.Codeunit.al
+++ b/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAssignedFFOrders.Codeunit.al
@@ -5,6 +5,10 @@
namespace Microsoft.Integration.Shopify;
+///
+/// Codeunit Shpfy GQL AssignedFFOrders (ID 30410).
+/// Implements the IGraphQL interface for retrieving assigned fulfillment orders using GraphQL.
+///
codeunit 30410 "Shpfy GQL AssignedFFOrders" implements "Shpfy IGraphQL"
{
Access = Internal;
diff --git a/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLNextAssignedFFOrders.Codeunit.al b/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLNextAssignedFFOrders.Codeunit.al
index e08da47a0d..7f42a0285f 100644
--- a/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLNextAssignedFFOrders.Codeunit.al
+++ b/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLNextAssignedFFOrders.Codeunit.al
@@ -5,6 +5,10 @@
namespace Microsoft.Integration.Shopify;
+///
+/// Codeunit Shpfy GQL NextAssignedFFOrders (ID 30411).
+/// Implements the IGraphQL interface for retrieving the next page of assigned fulfillment orders using GraphQL.
+///
codeunit 30411 "Shpfy GQL NextAssignedFFOrders" implements "Shpfy IGraphQL"
{
Access = Internal;
From acc4dde00a33655e9d7881999215684f1ecaadec Mon Sep 17 00:00:00 2001
From: Onat Buyukakkus <55088871+onbuyuka@users.noreply.github.com>
Date: Wed, 22 Oct 2025 17:12:07 +0200
Subject: [PATCH 4/4] Merge
---
.../src/GraphQL/Codeunits/ShpfyGQLAcceptFFRequest.Codeunit.al | 2 +-
.../src/GraphQL/Codeunits/ShpfyGQLAssignedFFOrders.Codeunit.al | 2 +-
.../GraphQL/Codeunits/ShpfyGQLNextAssignedFFOrders.Codeunit.al | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAcceptFFRequest.Codeunit.al b/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAcceptFFRequest.Codeunit.al
index ea5e1cd602..47c22e85bb 100644
--- a/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAcceptFFRequest.Codeunit.al
+++ b/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAcceptFFRequest.Codeunit.al
@@ -9,7 +9,7 @@ namespace Microsoft.Integration.Shopify;
/// Codeunit Shpfy GQL AcceptFFRequest (ID 30412).
/// Implements the IGraphQL interface for accepting Shopify fulfillment requests using GraphQL.
///
-codeunit 30412 "Shpfy GQL AcceptFFRequest" implements "Shpfy IGraphQL"
+codeunit 30414 "Shpfy GQL AcceptFFRequest" implements "Shpfy IGraphQL"
{
Access = Internal;
diff --git a/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAssignedFFOrders.Codeunit.al b/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAssignedFFOrders.Codeunit.al
index 959e990b42..1115a17fac 100644
--- a/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAssignedFFOrders.Codeunit.al
+++ b/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLAssignedFFOrders.Codeunit.al
@@ -9,7 +9,7 @@ namespace Microsoft.Integration.Shopify;
/// Codeunit Shpfy GQL AssignedFFOrders (ID 30410).
/// Implements the IGraphQL interface for retrieving assigned fulfillment orders using GraphQL.
///
-codeunit 30410 "Shpfy GQL AssignedFFOrders" implements "Shpfy IGraphQL"
+codeunit 30412 "Shpfy GQL AssignedFFOrders" implements "Shpfy IGraphQL"
{
Access = Internal;
diff --git a/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLNextAssignedFFOrders.Codeunit.al b/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLNextAssignedFFOrders.Codeunit.al
index 7f42a0285f..8d83f592c1 100644
--- a/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLNextAssignedFFOrders.Codeunit.al
+++ b/src/Apps/W1/Shopify/App/src/GraphQL/Codeunits/ShpfyGQLNextAssignedFFOrders.Codeunit.al
@@ -9,7 +9,7 @@ namespace Microsoft.Integration.Shopify;
/// Codeunit Shpfy GQL NextAssignedFFOrders (ID 30411).
/// Implements the IGraphQL interface for retrieving the next page of assigned fulfillment orders using GraphQL.
///
-codeunit 30411 "Shpfy GQL NextAssignedFFOrders" implements "Shpfy IGraphQL"
+codeunit 30413 "Shpfy GQL NextAssignedFFOrders" implements "Shpfy IGraphQL"
{
Access = Internal;