diff --git a/Apps/W1/Shopify/app/src/Base/Enums/ShpfyReturnLocationPriority.Enum.al b/Apps/W1/Shopify/app/src/Base/Enums/ShpfyReturnLocationPriority.Enum.al new file mode 100644 index 0000000000..06e112299d --- /dev/null +++ b/Apps/W1/Shopify/app/src/Base/Enums/ShpfyReturnLocationPriority.Enum.al @@ -0,0 +1,16 @@ +namespace Microsoft.Integration.Shopify; + +enum 30162 "Shpfy Return Location Priority" +{ + Access = Public; + Extensible = false; + + value(0; "Default Return Location") + { + Caption = 'Default Return Location'; + } + value(1; "Original -> Default Location") + { + Caption = 'Original -> Default Location'; + } +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Base/Pages/ShpfyShopCard.Page.al b/Apps/W1/Shopify/app/src/Base/Pages/ShpfyShopCard.Page.al index 18fa93e076..3c71c716ed 100644 --- a/Apps/W1/Shopify/app/src/Base/Pages/ShpfyShopCard.Page.al +++ b/Apps/W1/Shopify/app/src/Base/Pages/ShpfyShopCard.Page.al @@ -540,6 +540,12 @@ page 30101 "Shpfy Shop Card" ShowCaption = false; Visible = IsReturnRefundsVisible; + field("Return Location Priority"; Rec."Return Location Priority") + { + ApplicationArea = All; + Caption = 'Return Location Priority'; + ToolTip = 'Specifies the priority of the return location.'; + } field("Location Code of Returns"; Rec."Return Location") { ApplicationArea = All; diff --git a/Apps/W1/Shopify/app/src/Base/Tables/ShpfyShop.Table.al b/Apps/W1/Shopify/app/src/Base/Tables/ShpfyShop.Table.al index d521572415..05bf12e5ad 100644 --- a/Apps/W1/Shopify/app/src/Base/Tables/ShpfyShop.Table.al +++ b/Apps/W1/Shopify/app/src/Base/Tables/ShpfyShop.Table.al @@ -233,8 +233,8 @@ table 30102 "Shpfy Shop" ObsoleteState = Pending; ObsoleteTag = '24.0'; #else - ObsoleteState = Removed; - ObsoleteTag = '27.0'; + ObsoleteState = Removed; + ObsoleteTag = '27.0'; #endif } field(30; "Shopify Can Update Customer"; Boolean) @@ -511,7 +511,7 @@ table 30102 "Shpfy Shop" } field(73; "Return Location"; Code[10]) { - Caption = 'Return Location'; + Caption = 'Default Return Location'; DataClassification = CustomerContent; TableRelation = Location where("Use As In-Transit" = const(false)); } @@ -778,6 +778,11 @@ table 30102 "Shpfy Shop" end; #endif } + field(128; "Return Location Priority"; Enum "Shpfy Return Location Priority") + { + Caption = 'Return Location Priority'; + DataClassification = CustomerContent; + } field(200; "Shop Id"; Integer) { DataClassification = SystemMetadata; diff --git a/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLNextRefundLines.Codeunit.al b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLNextRefundLines.Codeunit.al index 69a0ca1fd1..426d81629f 100644 --- a/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLNextRefundLines.Codeunit.al +++ b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLNextRefundLines.Codeunit.al @@ -5,7 +5,7 @@ codeunit 30232 "Shpfy GQL NextRefundLines" implements "Shpfy IGraphQL" internal procedure GetGraphQL(): Text begin - exit('{"query":"{ refund(id: \"gid://shopify/Refund/{{RefundId}}\") { refundLineItems(first: 10, after:\"{{After}}\") { pageInfo { endCursor hasNextPage } nodes { lineItem { id } quantity restockType restocked priceSet { presentmentMoney { amount } shopMoney { amount }} subtotalSet { presentmentMoney { amount } shopMoney { amount }} totalTaxSet { presentmentMoney { amount } shopMoney { amount }}}}}}"}'); + exit('{"query":"{ refund(id: \"gid://shopify/Refund/{{RefundId}}\") { refundLineItems(first: 10, after:\"{{After}}\") { pageInfo { endCursor hasNextPage } nodes { lineItem { id } quantity restockType location { legacyResourceId } restocked priceSet { presentmentMoney { amount } shopMoney { amount }} subtotalSet { presentmentMoney { amount } shopMoney { amount }} totalTaxSet { presentmentMoney { amount } shopMoney { amount }}}}}}"}'); end; internal procedure GetExpectedCost(): Integer diff --git a/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLNextRevFulfillOrdLns.Codeunit.al b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLNextRevFulfillOrdLns.Codeunit.al new file mode 100644 index 0000000000..a5e508b6a2 --- /dev/null +++ b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLNextRevFulfillOrdLns.Codeunit.al @@ -0,0 +1,27 @@ +namespace Microsoft.Integration.Shopify; + +/// +/// Codeunit Shpfy GQL NextRevFulfillOrdLns (ID 30349) implements Interface Shpfy IGraphQL. +/// +codeunit 30349 "Shpfy GQL NextRevFulfillOrdLns" implements "Shpfy IGraphQL" +{ + Access = Internal; + + /// + /// GetGraphQL. + /// + /// Return value of type Text. + internal procedure GetGraphQL(): Text + begin + exit('{"query":"{ reverseFulfillmentOrder(id: \"{{FulfillOrderId}}\") { lineItems(first: 10, after:\"{{After}}\") { pageInfo { endCursor hasNextPage } nodes { id fulfillmentLineItem { id lineItem { id name } } dispositions { id quantity type location { id legacyResourceId } } } } } }"}'); + end; + + /// + /// GetExpectedCost. + /// + /// Return value of type Integer. + internal procedure GetExpectedCost(): Integer + begin + exit(15); + end; +} diff --git a/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLNextRevFulfillOrders.Codeunit.al b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLNextRevFulfillOrders.Codeunit.al new file mode 100644 index 0000000000..126f0ffab7 --- /dev/null +++ b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLNextRevFulfillOrders.Codeunit.al @@ -0,0 +1,28 @@ +namespace Microsoft.Integration.Shopify; + +/// +/// Codeunit Shpfy GQL NextRevFulfillOrders (ID 30347) implements Interface Shpfy IGraphQL. +/// +codeunit 30347 "Shpfy GQL NextRevFulfillOrders" implements "Shpfy IGraphQL" +{ + Access = Internal; + + /// + /// GetGraphQL. + /// + /// Return value of type Text. + internal procedure GetGraphQL(): Text + begin + exit('{"query":"{ return(id: \"gid://shopify/Return/{{ReturnId}}\") { reverseFulfillmentOrders(first: 10, after:\"{{After}}\") { pageInfo { endCursor hasNextPage } nodes { id } } } }"}'); + + end; + + /// + /// GetExpectedCost. + /// + /// Return value of type Integer. + internal procedure GetExpectedCost(): Integer + begin + exit(7); + end; +} diff --git a/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLRefundLines.Codeunit.al b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLRefundLines.Codeunit.al index bb11635ff8..29649cb17f 100644 --- a/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLRefundLines.Codeunit.al +++ b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLRefundLines.Codeunit.al @@ -5,7 +5,7 @@ codeunit 30230 "Shpfy GQL RefundLines" implements "Shpfy IGraphQL" internal procedure GetGraphQL(): Text begin - exit('{"query":"{ refund(id: \"gid://shopify/Refund/{{RefundId}}\") { refundLineItems(first: 10) { pageInfo { endCursor hasNextPage } nodes { lineItem { id } quantity restockType restocked priceSet { presentmentMoney { amount } shopMoney { amount }} subtotalSet { presentmentMoney { amount } shopMoney { amount }} totalTaxSet { presentmentMoney { amount } shopMoney { amount }}}}}}"}'); + exit('{"query":"{ refund(id: \"gid://shopify/Refund/{{RefundId}}\") { refundLineItems(first: 10) { pageInfo { endCursor hasNextPage } nodes { lineItem { id } quantity restockType location { legacyResourceId } restocked priceSet { presentmentMoney { amount } shopMoney { amount }} subtotalSet { presentmentMoney { amount } shopMoney { amount }} totalTaxSet { presentmentMoney { amount } shopMoney { amount }}}}}}"}'); end; internal procedure GetExpectedCost(): Integer diff --git a/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLRevFulfillOrderLines.Codeunit.al b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLRevFulfillOrderLines.Codeunit.al new file mode 100644 index 0000000000..f4e6ac63e5 --- /dev/null +++ b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLRevFulfillOrderLines.Codeunit.al @@ -0,0 +1,27 @@ +namespace Microsoft.Integration.Shopify; + +/// +/// Codeunit Shpfy GQL RevFulfillOrderLines (ID 30348) implements Interface Shpfy IGraphQL. +/// +codeunit 30348 "Shpfy GQL RevFulfillOrderLines" implements "Shpfy IGraphQL" +{ + Access = Internal; + + /// + /// GetGraphQL. + /// + /// Return value of type Text. + internal procedure GetGraphQL(): Text + begin + exit('{"query":"{ reverseFulfillmentOrder(id: \"{{FulfillOrderId}}\") { id lineItems(first: 10) { nodes { id fulfillmentLineItem { id lineItem { id name } } dispositions { id quantity type location { id legacyResourceId } } } } } }"}'); + end; + + /// + /// GetExpectedCost. + /// + /// Return value of type Integer. + internal procedure GetExpectedCost(): Integer + begin + exit(15); + end; +} diff --git a/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLRevFulfillOrders.Codeunit.al b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLRevFulfillOrders.Codeunit.al new file mode 100644 index 0000000000..29dd45361e --- /dev/null +++ b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLRevFulfillOrders.Codeunit.al @@ -0,0 +1,28 @@ +namespace Microsoft.Integration.Shopify; + +/// +/// Codeunit Shpfy GQL RevFulfillOrders (ID 30346) implements Interface Shpfy IGraphQL. +/// +codeunit 30346 "Shpfy GQL RevFulfillOrders" implements "Shpfy IGraphQL" +{ + Access = Internal; + + /// + /// GetGraphQL. + /// + /// Return value of type Text. + internal procedure GetGraphQL(): Text + begin + exit('{"query":"{ return(id: \"gid://shopify/Return/{{ReturnId}}\") { reverseFulfillmentOrders(first: 10) { pageInfo { endCursor hasNextPage } nodes { id } } } }"}'); + + end; + + /// + /// GetExpectedCost. + /// + /// Return value of type Integer. + internal procedure GetExpectedCost(): Integer + begin + exit(7); + end; +} diff --git a/Apps/W1/Shopify/app/src/GraphQL/Enums/ShpfyGraphQLType.Enum.al b/Apps/W1/Shopify/app/src/GraphQL/Enums/ShpfyGraphQLType.Enum.al index d6d2c8d75a..031d9283ae 100644 --- a/Apps/W1/Shopify/app/src/GraphQL/Enums/ShpfyGraphQLType.Enum.al +++ b/Apps/W1/Shopify/app/src/GraphQL/Enums/ShpfyGraphQLType.Enum.al @@ -405,4 +405,24 @@ enum 30111 "Shpfy GraphQL Type" implements "Shpfy IGraphQL" Caption = 'Get Order Transactions'; Implementation = "Shpfy IGraphQL" = "Shpfy GQL OrderTransactions"; } + value(87; GetReverseFulfillmentOrders) + { + Caption = 'Get Reverse Fulfillment Orders'; + Implementation = "Shpfy IGraphQL" = "Shpfy GQL RevFulfillOrders"; + } + value(88; GetNextReverseFulfillmentOrders) + { + Caption = 'Get Next Reverse Fulfillment Orders'; + Implementation = "Shpfy IGraphQL" = "Shpfy GQL NextRevFulfillOrders"; + } + value(89; GetReverseFulfillmentOrderLines) + { + Caption = 'Get Reverse Fulfillment Order Lines'; + Implementation = "Shpfy IGraphQL" = "Shpfy GQL RevFulfillOrderLines"; + } + value(90; GetNextReverseFulfillmentOrderLines) + { + Caption = 'Get Next Reverse Fulfillment Order Lines'; + Implementation = "Shpfy IGraphQL" = "Shpfy GQL NextRevFulfillOrdLns"; + } } diff --git a/Apps/W1/Shopify/app/src/Order Refunds/Codeunits/ShpfyRefundsAPI.Codeunit.al b/Apps/W1/Shopify/app/src/Order Refunds/Codeunits/ShpfyRefundsAPI.Codeunit.al index a6c5ab8c21..6b5b9e943c 100644 --- a/Apps/W1/Shopify/app/src/Order Refunds/Codeunits/ShpfyRefundsAPI.Codeunit.al +++ b/Apps/W1/Shopify/app/src/Order Refunds/Codeunits/ShpfyRefundsAPI.Codeunit.al @@ -31,11 +31,14 @@ codeunit 30228 "Shpfy Refunds API" RefundHeader: Record "Shpfy Refund Header"; GraphQLType: Enum "Shpfy GraphQL Type"; Parameters: Dictionary of [text, Text]; + ReturnLocations: Dictionary of [BigInteger, BigInteger]; JResponse: JsonToken; JLines: JsonArray; JLine: JsonToken; begin GetRefundHeader(RefundId, UpdatedAt, RefundHeader); + ReturnLocations := CollectReturnLocations(RefundHeader."Return Id"); + Parameters.Add('RefundId', Format(RefundId)); GraphQLType := "Shpfy GraphQL Type"::GetRefundLines; repeat @@ -46,8 +49,9 @@ codeunit 30228 "Shpfy Refunds API" Parameters.Set('After', JsonHelper.GetValueAsText(JResponse, 'data.refund.refundLineItems.pageInfo.endCursor')) else Parameters.Add('After', JsonHelper.GetValueAsText(JResponse, 'data.refund.refundLineItems.pageInfo.endCursor')); + foreach JLine in JLines do - FillInRefundLine(RefundId, JLine.AsObject(), IsNonZeroOrReturnRefund(RefundHeader)); + FillInRefundLine(RefundId, JLine.AsObject(), IsNonZeroOrReturnRefund(RefundHeader), ReturnLocations); until not JsonHelper.GetValueAsBoolean(JResponse, 'data.refund.refundLineItems.pageInfo.hasNextPage'); end; @@ -88,21 +92,34 @@ codeunit 30228 "Shpfy Refunds API" DataCapture.Add(Database::"Shpfy Refund Header", RefundHeader.SystemId, JResponse); end; - local procedure FillInRefundLine(RefundId: BigInteger; JLine: JsonObject; NonZeroOrReturnRefund: Boolean) + + local procedure CollectReturnLocations(ReturnId: BigInteger): Dictionary of [BigInteger, BigInteger] + var + ReturnsAPI: Codeunit "Shpfy Returns API"; + begin + if ReturnId <> 0 then + exit(ReturnsAPI.GetReturnLocations(ReturnId)); + end; + + local procedure FillInRefundLine(RefundId: BigInteger; JLine: JsonObject; NonZeroOrReturnRefund: Boolean; ReturnLocations: Dictionary of [BigInteger, BigInteger]) var DataCapture: Record "Shpfy Data Capture"; RefundLine: Record "Shpfy Refund Line"; RefundLineRecordRef: RecordRef; Id: BigInteger; + ReturnLocation: BigInteger; begin Id := CommunicationMgt.GetIdOfGId(JsonHelper.GetValueAsText(JLine, 'lineItem.id')); + if not RefundLine.Get(RefundId, Id) then begin RefundLine."Refund Line Id" := Id; RefundLine."Refund Id" := RefundId; RefundLine."Order Line Id" := Id; RefundLine.Insert(); end; + RefundLine."Restock Type" := RefundEnumConvertor.ConvertToReStockType(JsonHelper.GetValueAsText(JLine, 'restockType')); + RefundLineRecordRef.GetTable(RefundLine); JsonHelper.GetValueIntoField(JLine, 'quantity', RefundLineRecordRef, RefundLine.FieldNo(Quantity)); JsonHelper.GetValueIntoField(JLine, 'restocked', RefundLineRecordRef, RefundLine.FieldNo(Restocked)); @@ -113,8 +130,17 @@ codeunit 30228 "Shpfy Refunds API" JsonHelper.GetValueIntoField(JLine, 'totalTaxSet.shopMoney.amount', RefundLineRecordRef, RefundLine.FieldNo("Total Tax Amount")); JsonHelper.GetValueIntoField(JLine, 'totalTaxSet.presentmentMoney.amount', RefundLineRecordRef, RefundLine.FieldNo("Presentment Total Tax Amount")); RefundLineRecordRef.SetTable(RefundLine); + RefundLine."Can Create Credit Memo" := NonZeroOrReturnRefund; + RefundLine."Location Id" := JsonHelper.GetValueAsBigInteger(JLine, 'location.legacyResourceId'); + + // If refund was created from a return, the location needs to come from the return + // If Item was restocked to multiple locations, the return location is not known + if (RefundLine."Location Id" = 0) and (ReturnLocations.Get(RefundLine."Order Line Id", ReturnLocation)) then + RefundLine."Location Id" := ReturnLocation; + RefundLine.Modify(); + RefundLineRecordRef.Close(); DataCapture.Add(Database::"Shpfy Refund Line", RefundLine.SystemId, JLine); end; diff --git a/Apps/W1/Shopify/app/src/Order Refunds/Tables/ShpfyRefundLine.Table.al b/Apps/W1/Shopify/app/src/Order Refunds/Tables/ShpfyRefundLine.Table.al index 65d2030dfc..59248c70da 100644 --- a/Apps/W1/Shopify/app/src/Order Refunds/Tables/ShpfyRefundLine.Table.al +++ b/Apps/W1/Shopify/app/src/Order Refunds/Tables/ShpfyRefundLine.Table.al @@ -115,6 +115,12 @@ table 30145 "Shpfy Refund Line" CalcFormula = lookup("Shpfy Order Line"."Gift Card" where("Line Id" = field("Order Line Id"))); Editable = false; } + field(105; "Location Id"; BigInteger) + { + Caption = 'Location Id'; + DataClassification = SystemMetadata; + Editable = false; + } } keys { diff --git a/Apps/W1/Shopify/app/src/Order Return Refund Processing/Codeunits/ShpfyCreateSalesDocRefund.Codeunit.al b/Apps/W1/Shopify/app/src/Order Return Refund Processing/Codeunits/ShpfyCreateSalesDocRefund.Codeunit.al index 4c05820e44..8d2a888d1c 100644 --- a/Apps/W1/Shopify/app/src/Order Return Refund Processing/Codeunits/ShpfyCreateSalesDocRefund.Codeunit.al +++ b/Apps/W1/Shopify/app/src/Order Return Refund Processing/Codeunits/ShpfyCreateSalesDocRefund.Codeunit.al @@ -111,7 +111,6 @@ codeunit 30246 "Shpfy Create Sales Doc. Refund" SalesHeader.Validate("Document Date", DT2Date(RefundHeader."Created At")); if OrderMgt.FindTaxArea(OrderHeader, ShopifyTaxArea) and (ShopifyTaxArea."Tax Area Code" <> '') then SalesHeader.Validate("Tax Area Code", ShopifyTaxArea."Tax Area Code"); - SalesHeader.Validate("Location Code", Shop."Return Location"); end; SalesHeader."Shpfy Refund Id" := RefundHeader."Refund Id"; SalesHeader.Modify(true); @@ -143,6 +142,7 @@ codeunit 30246 "Shpfy Create Sales Doc. Refund" RefundLine: Record "Shpfy Refund Line"; ReturnLine: Record "Shpfy Return Line"; GiftCard: Record "Shpfy Gift Card"; + ShopLocation: Record "Shpfy Shop Location"; LineNo: Integer; OpenAmount: Decimal; IsHandled: Boolean; @@ -181,7 +181,13 @@ codeunit 30246 "Shpfy Create Sales Doc. Refund" SalesLine.Validate("No.", RefundLine."Item No."); if RefundLine."Variant Code" <> '' then SalesLine.Validate("Variant Code", RefundLine."Variant Code"); - SalesLine.Validate("Location Code", Shop."Return Location"); + + if ShopLocation.Get(Shop.Code, RefundLine."Location Id") then + SalesLine.Validate("Location Code", ShopLocation."Default Location Code"); + + If (Shop."Return Location Priority" = "Shpfy Return Location Priority"::"Default Return Location") or (SalesLine."Location Code" = '') then + SalesLine.Validate("Location Code", Shop."Return Location"); + end; SalesLine.Validate(Quantity, RefundLine.Quantity); SalesLine.Validate("Unit Price", RefundLine.Amount); @@ -233,7 +239,13 @@ codeunit 30246 "Shpfy Create Sales Doc. Refund" SalesLine.Validate("No.", ReturnLine."Item No."); if ReturnLine."Variant Code" <> '' then SalesLine.Validate("Variant Code", ReturnLine."Variant Code"); - SalesLine.Validate("Location Code", Shop."Return Location"); + + if ShopLocation.Get(Shop.Code, ReturnLine."Location Id") then + SalesLine.Validate("Location Code", ShopLocation."Default Location Code"); + + If (Shop."Return Location Priority" = "Shpfy Return Location Priority"::"Default Return Location") or (SalesLine."Location Code" = '') then + SalesLine.Validate("Location Code", Shop."Return Location"); + SalesLine.Validate(Quantity, ReturnLine.Quantity); SalesLine.Validate("Unit Price", ReturnLine."Discounted Total Amount" / ReturnLine.Quantity); end; diff --git a/Apps/W1/Shopify/app/src/Order Returns/Codeunits/ShpfyReturnsAPI.Codeunit.al b/Apps/W1/Shopify/app/src/Order Returns/Codeunits/ShpfyReturnsAPI.Codeunit.al index 0855c28be4..5de1dc01bb 100644 --- a/Apps/W1/Shopify/app/src/Order Returns/Codeunits/ShpfyReturnsAPI.Codeunit.al +++ b/Apps/W1/Shopify/app/src/Order Returns/Codeunits/ShpfyReturnsAPI.Codeunit.al @@ -32,11 +32,14 @@ codeunit 30250 "Shpfy Returns API" var GraphQLType: Enum "Shpfy GraphQL Type"; LineParameters: Dictionary of [text, Text]; + ReturnLocations: Dictionary of [BigInteger, BigInteger]; JResponse: JsonToken; JLines: JsonArray; JLine: JsonToken; begin GetReturnHeader(ReturnId); + ReturnLocations := GetReturnLocations(ReturnId); + LineParameters.Add('ReturnId', Format(ReturnId)); GraphQLType := "Shpfy GraphQL Type"::GetReturnLines; repeat @@ -48,7 +51,7 @@ codeunit 30250 "Shpfy Returns API" else LineParameters.Add('After', JsonHelper.GetValueAsText(JResponse, 'data.return.returnLineItems.pageInfo.endCursor')); foreach JLine in JLines do - FillInReturnLine(ReturnId, JLine.AsObject()); + FillInReturnLine(ReturnId, JLine.AsObject(), ReturnLocations); until not JsonHelper.GetValueAsBoolean(JResponse, 'data.return.returnLineItems.pageInfo.hasNextPage'); end; @@ -81,12 +84,96 @@ codeunit 30250 "Shpfy Returns API" DataCapture.Add(Database::"Shpfy Return Header", ReturnHeader.SystemId, JResponse); end; - local procedure FillInReturnLine(ReturnId: BigInteger; JLine: JsonObject) + /// + /// Get the return locations for return lines. + /// + /// Id of the return. + /// + /// If item was restocked to multiple locations, we cannot determine the return location for the return line, + /// and the order line id will not be included in the return locations. + /// + /// Dictionary of Order Line Id and Location Id. + internal procedure GetReturnLocations(ReturnId: BigInteger) ReturnLocations: Dictionary of [BigInteger, BigInteger] + var + GraphQLType: Enum "Shpfy GraphQL Type"; + LineParameters: Dictionary of [text, Text]; + JResponse: JsonToken; + JOrders: JsonArray; + JOrder: JsonToken; + begin + LineParameters.Add('ReturnId', Format(ReturnId)); + GraphQLType := "Shpfy GraphQL Type"::GetReverseFulfillmentOrders; + repeat + JResponse := CommunicationMgt.ExecuteGraphQL(GraphQLType, LineParameters); + + GraphQLType := "Shpfy GraphQL Type"::GetNextReverseFulfillmentOrders; + JOrders := JsonHelper.GetJsonArray(JResponse, 'data.return.reverseFulfillmentOrders.nodes'); + if Parameters.ContainsKey('After') then + Parameters.Set('After', JsonHelper.GetValueAsText(JResponse, 'data.return.reverseFulfillmentOrders.pageInfo.endCursor')) + else + Parameters.Add('After', JsonHelper.GetValueAsText(JResponse, 'data.return.reverseFulfillmentOrders.pageInfo.endCursor')); + + foreach JOrder in JOrders do + GetReturnLocationsFromReturnFulfillOrder(JsonHelper.GetValueAsText(JOrder, 'id'), ReturnLocations); + until not JsonHelper.GetValueAsBoolean(JResponse, 'data.return.reverseFulfillmentOrders.pageInfo.hasNextPage'); + end; + + local procedure GetReturnLocationsFromReturnFulfillOrder(FulfillOrderId: Text; var ReturnLocations: Dictionary of [BigInteger, BigInteger]) + var + GraphQLType: Enum "Shpfy GraphQL Type"; + LineParameters: Dictionary of [text, Text]; + JResponse: JsonToken; + JLines: JsonArray; + JLine: JsonToken; + begin + LineParameters.Add('FulfillOrderId', FulfillOrderId); + GraphQLType := "Shpfy GraphQL Type"::GetReverseFulfillmentOrderLines; + repeat + JResponse := CommunicationMgt.ExecuteGraphQL(GraphQLType, LineParameters); + + GraphQLType := "Shpfy GraphQL Type"::GetNextReverseFulfillmentOrders; + JLines := JsonHelper.GetJsonArray(JResponse, 'data.reverseFulfillmentOrder.lineItems.nodes'); + if Parameters.ContainsKey('After') then + Parameters.Set('After', JsonHelper.GetValueAsText(JResponse, 'data.reverseFulfillmentOrder.lineItems.pageInfo.endCursor')) + else + Parameters.Add('After', JsonHelper.GetValueAsText(JResponse, 'data.reverseFulfillmentOrder.lineItems.pageInfo.endCursor')); + + foreach JLine in JLines do + CollectLocationsFromLineDispositions(JLine, ReturnLocations); + until not JsonHelper.GetValueAsBoolean(JResponse, 'data.reverseFulfillmentOrder.lineItems.pageInfo.hasNextPage'); + end; + + local procedure CollectLocationsFromLineDispositions(JLine: JsonToken; ReturnLocations: Dictionary of [BigInteger, BigInteger]) + var + OrderLineId: BigInteger; + LocationId: BigInteger; + Dispositions: JsonArray; + Disposition: JsonToken; + begin + OrderLineId := CommunicationMgt.GetIdOfGId(JsonHelper.GetValueAsText(JLine, 'fulfillmentLineItem.lineItem.id')); + + Dispositions := JsonHelper.GetJsonArray(JLine, 'dispositions'); + if Dispositions.Count = 0 then + exit; + + // If dispositions have different locations (Item was restocked to multiple locations), + // we cannot determine the return location for the line + Dispositions.Get(0, Disposition); + LocationId := JsonHelper.GetValueAsBigInteger(Disposition, 'location.legacyResourceId'); + foreach Disposition in Dispositions do + if LocationId <> JsonHelper.GetValueAsBigInteger(Disposition, 'location.legacyResourceId') then + exit; + + ReturnLocations.Add(OrderLineId, LocationId); + end; + + local procedure FillInReturnLine(ReturnId: BigInteger; JLine: JsonObject; ReturnLocations: Dictionary of [BigInteger, BigInteger]) var DataCapture: Record "Shpfy Data Capture"; ReturnLine: Record "Shpfy Return Line"; ReturnLineRecordRef: RecordRef; Id: BigInteger; + ReturnLocation: BigInteger; begin Id := CommunicationMgt.GetIdOfGId(JsonHelper.GetValueAsText(JLine, 'id')); if not ReturnLine.Get(Id) then begin @@ -97,8 +184,13 @@ codeunit 30250 "Shpfy Returns API" ReturnLine.Insert(); end; ReturnLine."Return Reason" := ReturnEnumConvertor.ConvertToReturnReason(JsonHelper.GetValueAsText(JLine, 'returnReason')); + // If item was restocked to multiple locations, we cannot determine the return location for the line + if ReturnLocations.Get(ReturnLine."Order Line Id", ReturnLocation) then + ReturnLine."Location Id" := ReturnLocation; + ReturnLine.SetReturnReasonNote(JsonHelper.GetValueAsText(JLine, 'returnReasonNote')); ReturnLine.SetCustomerNote(JsonHelper.GetValueAsText(JLine, 'customerNote')); + ReturnLineRecordRef.GetTable(ReturnLine); JsonHelper.GetValueIntoField(JLine, 'quantity', ReturnLineRecordRef, ReturnLine.FieldNo(Quantity)); JsonHelper.GetValueIntoField(JLine, 'refundableQuantity', ReturnLineRecordRef, ReturnLine.FieldNo("Refundable Quantity")); diff --git a/Apps/W1/Shopify/app/src/Order Returns/Tables/ShpfyReturnLine.Table.al b/Apps/W1/Shopify/app/src/Order Returns/Tables/ShpfyReturnLine.Table.al index 9150f4d570..3598ff4855 100644 --- a/Apps/W1/Shopify/app/src/Order Returns/Tables/ShpfyReturnLine.Table.al +++ b/Apps/W1/Shopify/app/src/Order Returns/Tables/ShpfyReturnLine.Table.al @@ -112,6 +112,12 @@ table 30141 "Shpfy Return Line" FieldClass = FlowField; CalcFormula = lookup("Shpfy Order Line"."Variant Code" where("Line Id" = field("Order Line Id"))); } + field(104; "Location Id"; BigInteger) + { + Caption = 'Location Id'; + DataClassification = SystemMetadata; + Editable = false; + } } keys {