Skip to content

Commit eb8dd44

Browse files
aidasberesineviciusaidasberesineviciusTine Staric
authored
[Shopify] Connector - Different shipping charges types (#26708)
This pull request does not have a related issue as it's part of delivery for development agreed directly with @AndreiPanko Quick summary: The Shopify Shipping Method Mapping page/table was extended to include a new Shipping Charges Type field, allowing users to select from GL, Item, or Item Charge. Depending on this selection, the Shipping Charges No. field opens the related table (item, GL, or item charges), and when an order is created, the shipping charge line reflects the new type and number. For Item Charges, a default allocation process is run for all item lines. The settings in the Shopify Shipping Method Mapping now take priority over those in the Shopify Shop - GL Account settings. Additionally, if the Shipping Agent Code and Shipping Agent Service fields are populated, they are automatically populated in the sales order as well. Fixes #26819 [AB#449477](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/449477) --------- Co-authored-by: aidasberesinevicius <[email protected]> Co-authored-by: Tine Staric <[email protected]>
1 parent 096df31 commit eb8dd44

7 files changed

+253
-4
lines changed

Apps/W1/Shopify/app/src/Order handling/Codeunits/ShpfyOrderEvents.Codeunit.al

+19
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,25 @@ codeunit 30162 "Shpfy Order Events"
7878
begin
7979
end;
8080

81+
[IntegrationEvent(false, false)]
82+
/// <summary>
83+
/// Description for OnBeforeMapShipmentAgent.
84+
/// </summary>
85+
/// <param name="ShopifyOrderHeader">Parameter of type Record "Shopify Order Header".</param>
86+
/// <param name="Handled">Parameter of type Boolean.</param>
87+
internal procedure OnBeforeMapShipmentAgent(var ShopifyOrderHeader: Record "Shpfy Order Header"; var Handled: Boolean)
88+
begin
89+
end;
90+
91+
[IntegrationEvent(false, false)]
92+
/// <summary>
93+
/// Description for OnAfterMapShipmentAgent.
94+
/// </summary>
95+
/// <param name="ShopifyOrderHeader">Parameter of type Record "Shopify Order Header".</param>
96+
internal procedure OnAfterMapShipmentAgent(var ShopifyOrderHeader: Record "Shpfy Order Header")
97+
begin
98+
end;
99+
81100
[IntegrationEvent(false, false)]
82101
/// <summary>
83102
/// Description for OnBeforeMapPaymentMethod.

Apps/W1/Shopify/app/src/Order handling/Codeunits/ShpfyOrderMapping.Codeunit.al

+22
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ codeunit 30163 "Shpfy Order Mapping"
127127
end;
128128

129129
MapShippingMethodCode(OrderHeader);
130+
MapShippingAgent(OrderHeader);
130131
MapPaymentMethodCode(OrderHeader);
131132
OrderHeader.Modify();
132133
exit((OrderHeader."Bill-to Customer No." <> '') and (OrderHeader."Sell-to Customer No." <> ''));
@@ -163,6 +164,7 @@ codeunit 30163 "Shpfy Order Mapping"
163164
end;
164165

165166
MapShippingMethodCode(OrderHeader);
167+
MapShippingAgent(OrderHeader);
166168
MapPaymentMethodCode(OrderHeader);
167169
OrderHeader.Modify();
168170
exit((OrderHeader."Bill-to Customer No." <> '') and (OrderHeader."Sell-to Customer No." <> ''));
@@ -247,6 +249,26 @@ codeunit 30163 "Shpfy Order Mapping"
247249
end;
248250
end;
249251

252+
local procedure MapShippingAgent(var OrderHeader: Record "Shpfy Order Header")
253+
var
254+
OrderShippingCharges: Record "Shpfy Order Shipping Charges";
255+
ShipmentMethodMapping: Record "Shpfy Shipment Method Mapping";
256+
IsHandled: Boolean;
257+
begin
258+
if OrderHeader."Shipping Agent Code" = '' then begin
259+
OrderEvents.OnBeforeMapShipmentAgent(OrderHeader, IsHandled);
260+
if not IsHandled then begin
261+
OrderShippingCharges.SetRange("Shopify Order Id", OrderHeader."Shopify Order Id");
262+
if OrderShippingCharges.FindFirst() then
263+
if ShipmentMethodMapping.Get(OrderHeader."Shop Code", OrderShippingCharges.Title) then begin
264+
OrderHeader."Shipping Agent Code" := ShipmentMethodMapping."Shipping Agent Code";
265+
OrderHeader."Shipping Agent Service Code" := ShipmentMethodMapping."Shipping Agent Service Code";
266+
end;
267+
OrderEvents.OnAfterMapShipmentAgent(OrderHeader);
268+
end;
269+
end;
270+
end;
271+
250272
local procedure MapPaymentMethodCode(var OrderHeader: Record "Shpfy Order Header")
251273
var
252274
OrderTransaction: Record "Shpfy Order Transaction";

Apps/W1/Shopify/app/src/Order handling/Codeunits/ShpfyProcessOrder.Codeunit.al

+113-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
namespace Microsoft.Integration.Shopify;
22

33
using Microsoft.Inventory.Item;
4+
using Microsoft.Finance.Currency;
45
using Microsoft.Sales.Document;
56
using Microsoft.Foundation.Address;
67
using Microsoft.Sales.History;
@@ -118,6 +119,10 @@ codeunit 30166 "Shpfy Process Order"
118119
SalesHeader.Validate("Tax Area Code", ShopifyTaxArea."Tax Area Code");
119120
if ShopifyOrderHeader."Shipping Method Code" <> '' then
120121
SalesHeader.Validate("Shipment Method Code", ShopifyOrderHeader."Shipping Method Code");
122+
if ShopifyOrderHeader."Shipping Agent Code" <> '' then begin
123+
SalesHeader.Validate("Shipping Agent Code", ShopifyOrderHeader."Shipping Agent Code");
124+
SalesHeader.Validate("Shipping Agent Service Code", ShopifyOrderHeader."Shipping Agent Service Code");
125+
end;
121126
if ShopifyOrderHeader."Payment Method Code" <> '' then
122127
SalesHeader.Validate("Payment Method Code", ShopifyOrderHeader."Payment Method Code");
123128

@@ -173,8 +178,10 @@ codeunit 30166 "Shpfy Process Order"
173178
ShopifyOrderLine: Record "Shpfy Order Line";
174179
OrderShippingCharges: Record "Shpfy Order Shipping Charges";
175180
ShopLocation: Record "Shpfy Shop Location";
181+
ShipmentMethodMapping: Record "Shpfy Shipment Method Mapping";
176182
SuppressAsmWarning: Codeunit "Shpfy Suppress Asm Warning";
177183
IsHandled: Boolean;
184+
ShipmentChargeType: Boolean;
178185
ShopfyOrderNoLbl: Label 'Shopify Order No.: %1', Comment = '%1 = Order No.';
179186
begin
180187
BindSubscription(SuppressAsmWarning);
@@ -230,31 +237,133 @@ codeunit 30166 "Shpfy Process Order"
230237
OrderShippingCharges.Reset();
231238
OrderShippingCharges.SetRange("Shopify Order Id", ShopifyOrderHeader."Shopify Order Id");
232239
OrderShippingCharges.SetFilter(Amount, '>0');
233-
if OrderShippingCharges.FindSet() then begin
234-
ShopifyShop.TestField("Shipping Charges Account");
240+
if OrderShippingCharges.FindSet() then
235241
repeat
236242
IsHandled := false;
237243
OrderEvents.OnBeforeCreateShippingCostSalesLine(ShopifyOrderHeader, OrderShippingCharges, SalesHeader, SalesLine, IsHandled);
238244
if not IsHandled then begin
245+
246+
if ShipmentMethodMapping.Get(ShopifyShop.Code, OrderShippingCharges.Title) then
247+
if ShipmentMethodMapping."Shipping Charges Type" <> ShipmentMethodMapping."Shipping Charges Type"::" " then begin
248+
ShipmentMethodMapping.TestField("Shipping Charges No.");
249+
ShipmentChargeType := true;
250+
end;
251+
252+
if not ShipmentChargeType then
253+
ShopifyShop.TestField("Shipping Charges Account");
254+
239255
SalesLine.Init();
240256
SalesLine.SetHideValidationDialog(true);
241257
SalesLine.Validate("Document Type", SalesHeader."Document Type");
242258
SalesLine.Validate("Document No.", SalesHeader."No.");
243259
SalesLine.Validate("Line No.", GetNextLineNo(SalesHeader));
244260
SalesLine.Insert(true);
245261

246-
SalesLine.Validate(Type, SalesLine.Type::"G/L Account");
247-
SalesLine.Validate("No.", ShopifyShop."Shipping Charges Account");
262+
if ShipmentChargeType then begin
263+
SalesLine.Validate(Type, ShipmentMethodMapping."Shipping Charges Type");
264+
SalesLine.Validate("No.", ShipmentMethodMapping."Shipping Charges No.");
265+
end else begin
266+
SalesLine.Validate(Type, SalesLine.Type::"G/L Account");
267+
SalesLine.Validate("No.", ShopifyShop."Shipping Charges Account");
268+
end;
269+
270+
SalesLine.Validate("Shipping Agent Code", ShipmentMethodMapping."Shipping Agent Code");
271+
SalesLine.Validate("Shipping Agent Service Code", ShipmentMethodMapping."Shipping Agent Service Code");
248272
SalesLine.Validate(Quantity, 1);
249273
SalesLine.Validate(Description, OrderShippingCharges.Title);
250274
SalesLine.Validate("Unit Price", OrderShippingCharges.Amount);
251275
SalesLine.Validate("Line Discount Amount", OrderShippingCharges."Discount Amount");
252276
SalesLine."Shpfy Order No." := ShopifyOrderHeader."Shopify Order No.";
253277
SalesLine.Modify(true);
278+
279+
if SalesLine.Type = SalesLine.Type::"Charge (Item)" then
280+
AssignItemCharges(SalesHeader, SalesLine);
254281
end;
255282
OrderEvents.OnAfterCreateShippingCostSalesLine(ShopifyOrderHeader, OrderShippingCharges, SalesHeader, SalesLine);
256283
until OrderShippingCharges.Next() = 0;
284+
end;
285+
286+
local procedure AssignItemCharges(SalesHeader: Record "Sales Header"; SalesLine: Record "Sales Line")
287+
var
288+
AssignItemChargeSales: Codeunit "Item Charge Assgnt. (Sales)";
289+
ItemChargeAssgntLineAmt: Decimal;
290+
AssignableQty: Decimal;
291+
begin
292+
SalesLine.TestField("No.");
293+
SalesLine.TestField(Quantity);
294+
295+
PrepareAssignItemChargesLines(SalesHeader, SalesLine, AssignableQty, ItemChargeAssgntLineAmt);
296+
AssignItemChargeSales.AssignItemCharges(SalesLine, AssignableQty, ItemChargeAssgntLineAmt, AssignableQty, ItemChargeAssgntLineAmt, AssignItemChargeSales.AssignEquallyMenuText());
297+
end;
298+
299+
local procedure PrepareAssignItemChargesLines(
300+
SalesHeader: Record "Sales Header";
301+
SalesLine: Record "Sales Line";
302+
var AssignableQty: Decimal;
303+
var ItemChargeAssgntLineAmt: Decimal
304+
)
305+
var
306+
ItemChargeAssgntSales: Record "Item Charge Assignment (Sales)";
307+
begin
308+
GetItemChargeAssgntLineAmt(SalesHeader, SalesLine, ItemChargeAssgntSales, ItemChargeAssgntLineAmt);
309+
GetAssignableQty(SalesLine, ItemChargeAssgntSales, AssignableQty);
310+
end;
311+
312+
local procedure GetItemChargeAssgntLineAmt(
313+
SalesHeader: Record "Sales Header";
314+
SalesLine: Record "Sales Line";
315+
var ItemChargeAssgntSales: Record "Item Charge Assignment (Sales)";
316+
var ItemChargeAssgntLineAmt: Decimal
317+
)
318+
var
319+
Currency: Record Currency;
320+
begin
321+
SalesHeader := SalesLine.GetSalesHeader();
322+
Currency.Initialize(SalesHeader."Currency Code");
323+
if (SalesLine."Inv. Discount Amount" = 0) and (SalesLine."Line Discount Amount" = 0) and
324+
(not SalesHeader."Prices Including VAT")
325+
then
326+
ItemChargeAssgntLineAmt := SalesLine."Line Amount"
327+
else
328+
if SalesHeader."Prices Including VAT" then
329+
ItemChargeAssgntLineAmt :=
330+
Round(SalesLine.CalcLineAmount() / (1 + SalesLine."VAT %" / 100), Currency."Amount Rounding Precision")
331+
else
332+
ItemChargeAssgntLineAmt := SalesLine.CalcLineAmount();
333+
334+
ItemChargeAssgntSales.Reset();
335+
ItemChargeAssgntSales.SetRange("Document Type", SalesLine."Document Type");
336+
ItemChargeAssgntSales.SetRange("Document No.", SalesLine."Document No.");
337+
ItemChargeAssgntSales.SetRange("Document Line No.", SalesLine."Line No.");
338+
ItemChargeAssgntSales.SetRange("Item Charge No.", SalesLine."No.");
339+
if not ItemChargeAssgntSales.FindLast() then begin
340+
ItemChargeAssgntSales."Document Type" := SalesLine."Document Type";
341+
ItemChargeAssgntSales."Document No." := SalesLine."Document No.";
342+
ItemChargeAssgntSales."Document Line No." := SalesLine."Line No.";
343+
ItemChargeAssgntSales."Item Charge No." := SalesLine."No.";
344+
ItemChargeAssgntSales."Unit Cost" :=
345+
Round(ItemChargeAssgntLineAmt / SalesLine.Quantity, Currency."Unit-Amount Rounding Precision");
257346
end;
347+
348+
ItemChargeAssgntLineAmt :=
349+
Round(ItemChargeAssgntLineAmt * (SalesLine."Qty. to Invoice" / SalesLine.Quantity), Currency."Amount Rounding Precision");
350+
end;
351+
352+
local procedure GetAssignableQty(
353+
SalesLine: Record "Sales Line";
354+
ItemChargeAssgntSales: Record "Item Charge Assignment (Sales)";
355+
var AssignableQty: Decimal
356+
)
357+
var
358+
AssignItemChargeSales: Codeunit "Item Charge Assgnt. (Sales)";
359+
begin
360+
if SalesLine.IsCreditDocType() then
361+
AssignItemChargeSales.CreateDocChargeAssgn(ItemChargeAssgntSales, SalesLine."Return Receipt No.")
362+
else
363+
AssignItemChargeSales.CreateDocChargeAssgn(ItemChargeAssgntSales, SalesLine."Shipment No.");
364+
365+
SalesLine.CalcFields("Qty. to Assign", "Item Charge Qty. to Handle", "Qty. Assigned");
366+
AssignableQty := SalesLine."Qty. to Invoice" + SalesLine."Quantity Invoiced" - SalesLine."Qty. Assigned";
258367
end;
259368

260369
/// <summary>

Apps/W1/Shopify/app/src/Order handling/Pages/ShpfyOrder.Page.al

+10
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,16 @@ page 30113 "Shpfy Order"
6262
ApplicationArea = All;
6363
ToolTip = 'Specifies how items on the Shopify Order are shipped to the customer.';
6464
}
65+
field(ShippingAgentCode; Rec."Shipping Agent Code")
66+
{
67+
ApplicationArea = All;
68+
ToolTip = 'Specifies which shipping agent is used to transport the items on the Shopify Order to the customer.';
69+
}
70+
field(ShippingAgentServiceCode; Rec."Shipping Agent Service Code")
71+
{
72+
ApplicationArea = All;
73+
ToolTip = 'Specifies the code that represents the default shipping agent service you are using for this Shopify Order.';
74+
}
6575
field("Payment Method"; Rec."Payment Method Code")
6676
{
6777
ApplicationArea = All;

Apps/W1/Shopify/app/src/Order handling/Tables/ShpfyOrderHeader.Table.al

+16
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,22 @@ table 30118 "Shpfy Order Header"
735735
Caption = 'Has Order State Error';
736736
DataClassification = SystemMetadata;
737737
}
738+
field(1021; "Shipping Agent Code"; Code[10])
739+
{
740+
Caption = 'Shipping Agent Code';
741+
TableRelation = "Shipping Agent";
742+
743+
trigger OnValidate()
744+
begin
745+
if "Shipping Agent Code" <> xRec."Shipping Agent Code" then
746+
Clear("Shipping Agent Service Code");
747+
end;
748+
}
749+
field(1022; "Shipping Agent Service Code"; Code[10])
750+
{
751+
Caption = 'Shipping Agent Service Code';
752+
TableRelation = "Shipping Agent Services".Code where("Shipping Agent Code" = field("Shipping Agent Code"));
753+
}
738754
}
739755
keys
740756
{

Apps/W1/Shopify/app/src/Shipping/Pages/ShpfyShipmentMethodsMapping.Page.al

+21
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,27 @@ page 30129 "Shpfy Shipment Methods Mapping"
2626
ApplicationArea = All;
2727
ToolTip = 'Specifies the shipping method in D365BC.';
2828
}
29+
field("Shipping Charges Type"; Rec."Shipping Charges Type")
30+
{
31+
ApplicationArea = All;
32+
ToolTip = 'Specifies the value of the Shipping Charges Type field.';
33+
}
34+
field("Shipping Charges No."; Rec."Shipping Charges No.")
35+
{
36+
ApplicationArea = All;
37+
ShowMandatory = Rec."Shipping Charges Type" <> Rec."Shipping Charges Type"::" ";
38+
ToolTip = 'Specifies the value of the Shipping Charges No. field.';
39+
}
40+
field("Shipping Agent Code"; Rec."Shipping Agent Code")
41+
{
42+
ApplicationArea = All;
43+
ToolTip = 'Specifies the code for the shipping agent who is transporting the items.';
44+
}
45+
field("Shipping Agent Service Code"; Rec."Shipping Agent Service Code")
46+
{
47+
ApplicationArea = All;
48+
ToolTip = 'Specifies the code for the service, such as a one-day delivery, that is offered by the shipping agent.';
49+
}
2950
}
3051
}
3152
}

Apps/W1/Shopify/app/src/Shipping/Tables/ShpfyShipmentMethodMapping.Table.al

+52
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
namespace Microsoft.Integration.Shopify;
22

33
using Microsoft.Foundation.Shipping;
4+
using Microsoft.Sales.Document;
5+
using Microsoft.Finance.GeneralLedger.Account;
6+
using Microsoft.Inventory.Item;
47

58
/// <summary>
69
/// Table Shpfy Shipment Method Mapping (ID 30131).
@@ -31,6 +34,55 @@ table 30131 "Shpfy Shipment Method Mapping"
3134
DataClassification = CustomerContent;
3235
TableRelation = "Shipment Method";
3336
}
37+
field(4; "Shipping Charges Type"; Enum "Sales Line Type")
38+
{
39+
Caption = 'Shipping Charges Type';
40+
DataClassification = CustomerContent;
41+
ValuesAllowed = " ", "G/L Account", Item, "Charge (Item)";
42+
43+
trigger OnValidate()
44+
begin
45+
if "Shipping Charges Type" <> xRec."Shipping Charges Type" then
46+
Clear("Shipping Charges No.");
47+
end;
48+
}
49+
field(5; "Shipping Charges No."; Code[20])
50+
{
51+
Caption = 'Shipping Charges No.';
52+
TableRelation = if ("Shipping Charges Type" = const("G/L Account")) "G/L Account"
53+
else
54+
if ("Shipping Charges Type" = const(Item)) Item
55+
else
56+
if ("Shipping Charges Type" = const("Charge (Item)")) "Item Charge";
57+
58+
trigger OnValidate()
59+
var
60+
GLAccount: Record "G/L Account";
61+
ShpfyShop: Record "Shpfy Shop";
62+
begin
63+
if "Shipping Charges Type" = "Shipping Charges Type"::"G/L Account" then
64+
if GLAccount.Get("Shipping Charges No.") then
65+
ShpfyShop.CheckGLAccount(GLAccount);
66+
end;
67+
}
68+
field(6; "Shipping Agent Code"; Code[10])
69+
{
70+
AccessByPermission = TableData "Shipping Agent Services" = R;
71+
Caption = 'Shipping Agent Code';
72+
TableRelation = "Shipping Agent";
73+
74+
trigger OnValidate()
75+
begin
76+
if "Shipping Agent Code" <> xRec."Shipping Agent Code" then
77+
Clear("Shipping Agent Service Code");
78+
end;
79+
}
80+
field(7; "Shipping Agent Service Code"; Code[10])
81+
{
82+
AccessByPermission = TableData "Shipping Agent Services" = R;
83+
Caption = 'Shipping Agent Service Code';
84+
TableRelation = "Shipping Agent Services".Code where("Shipping Agent Code" = field("Shipping Agent Code"));
85+
}
3486
}
3587

3688
keys

0 commit comments

Comments
 (0)