Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,10 @@ page 30101 "Shpfy Shop Card"
{
ApplicationArea = All;
}
field(UseShopifyOrderNo; Rec."Use Shopify Order No.")
{
ApplicationArea = All;
}
field(ArchiveProcessOrders; Rec."Archive Processed Orders")
{
ApplicationArea = All;
Expand Down
5 changes: 5 additions & 0 deletions src/Apps/W1/Shopify/App/src/Base/Tables/ShpfyShop.Table.al
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,11 @@ table 30102 "Shpfy Shop"
Caption = 'Currency Handling';
InitValue = "Shop Currency";
}
field(136; "Use Shopify Order No."; Boolean)
{
Caption = 'Use Shopify Order No.';
ToolTip = 'Specifies whether the Shopify order number is used as the document number on the created Sales Order or Sales Invoice. The number series must have Allow Manual Nos. enabled.';
}
field(200; "Shop Id"; Integer)
{
DataClassification = SystemMetadata;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ codeunit 30161 "Shpfy Import Order"
exit(false);
OrderHeader."Shopify Order Id" := OrderId;
OrderHeader."Shop Code" := Shop.Code;
OrderHeader."Use Shopify Order No." := Shop."Use Shopify Order No.";
ICountyFromJson := Shop."County Source";

OrderHeaderRecordRef.GetTable(OrderHeader);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ codeunit 30166 "Shpfy Process Order"
DocLinkToBCDoc: Record "Shpfy Doc. Link To Doc.";
OrdersAPI: Codeunit "Shpfy Orders API";
BCDocumentTypeConvert: Codeunit "Shpfy BC Document Type Convert";
InvalidCharTok: Label '@', Locked = true;
InvalidShopifyOrderErr: Label '%1 cannot start with %2.', Comment = '%1 = Shopify Order No. field caption, %2 = Invalid Character';
IsHandled: Boolean;
begin
OrderEvents.OnBeforeCreateSalesHeader(ShopifyOrderHeader, SalesHeader, LastCreatedDocumentId, IsHandled);
Expand All @@ -79,6 +81,11 @@ codeunit 30166 "Shpfy Process Order"
SalesHeader.Validate("Document Type", SalesHeader."Document Type"::Invoice)
else
SalesHeader.Validate("Document Type", SalesHeader."Document Type"::Order);
if ShopifyOrderHeader."Use Shopify Order No." and (ShopifyOrderHeader."Shopify Order No." <> '') then begin
if ShopifyOrderHeader."Shopify Order No.".StartsWith(InvalidCharTok) then
Error(InvalidShopifyOrderErr, ShopifyOrderHeader.FieldCaption("Shopify Order No."), InvalidCharTok);
SalesHeader.Validate("No.", CopyStr(ShopifyOrderHeader."Shopify Order No.", 1, MaxStrLen(SalesHeader."No.")));
end;
SalesHeader.Insert(true);
LastCreatedDocumentId := SalesHeader.SystemId;
SalesHeader.Validate("Sell-to Customer No.", ShopifyOrderHeader."Sell-to Customer No.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ page 30113 "Shpfy Order"
ApplicationArea = All;
ToolTip = 'Specifies the purchase order number that is associated with the Shopify order.';
}
field(UseShopifyOrderNo; Rec."Use Shopify Order No.")
{
ApplicationArea = All;
Editable = not Rec.Processed;
}
field(Closed; Rec.Closed)
{
ApplicationArea = All;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,12 @@ table 30118 "Shpfy Order Header"
FieldClass = FlowField;
CalcFormula = exist("Shpfy Order Tax Line" where("Parent Id" = field("Shopify Order Id"), "Channel Liable" = const(true)));
}
field(135; "Use Shopify Order No."; Boolean)
{
Caption = 'Use Shopify Order No.';
DataClassification = SystemMetadata;
ToolTip = 'Specifies whether the Shopify order number is used as the document number for this specific order.';
}
field(500; "Shop Code"; Code[20])
{
Caption = 'Shop Code';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ namespace Microsoft.Integration.Shopify.Test;
using Microsoft.Finance.Currency;
using Microsoft.Finance.SalesTax;
using Microsoft.Foundation.Address;
using Microsoft.Foundation.NoSeries;
using Microsoft.Integration.Shopify;
using Microsoft.Inventory.Item;
using Microsoft.Inventory.Journal;
using Microsoft.Sales.Customer;
using Microsoft.Sales.Document;
using Microsoft.Sales.Setup;
using System.TestLibraries.Utilities;

codeunit 139608 "Shpfy Orders API Test"
Expand Down Expand Up @@ -1272,6 +1274,219 @@ codeunit 139608 "Shpfy Orders API Test"
LibraryAssert.AreEqual(ExpectedChannelLiable, OrderHeader."Channel Liable Taxes", StrSubstNo(OrderHeaderChannelLiableMismatchTxt, ScenarioName));
end;

[Test]
procedure UnitTestImportOrderPropagatesUseShopifyOrderNo()
var
Shop: Record "Shpfy Shop";
OrderHeader: Record "Shpfy Order Header";
CommunicationMgt: Codeunit "Shpfy Communication Mgt.";
ImportOrder: Codeunit "Shpfy Import Order";
OrderHandlingHelper: Codeunit "Shpfy Order Handling Helper";
begin
// [SCENARIO] When Shop."Use Shopify Order No." is true, importing an order propagates the setting to OrderHeader.
Initialize();

// [GIVEN] Shopify Shop with "Use Shopify Order No." enabled
Shop := CommunicationMgt.GetShopRecord();
Shop."Customer Mapping Type" := "Shpfy Customer Mapping"::"By EMail/Phone";
Shop."Use Shopify Order No." := true;
if not Shop.Modify() then
Shop.Insert();
ImportOrder.SetShop(Shop.Code);

// [WHEN] Shopify order is imported
OrderHandlingHelper.ImportShopifyOrder(Shop, OrderHeader, ImportOrder, false);

// [THEN] OrderHeader."Use Shopify Order No." = true
LibraryAssert.IsTrue(OrderHeader."Use Shopify Order No.", 'OrderHeader."Use Shopify Order No." should be true when Shop setting is enabled');
end;

[Test]
procedure UnitTestImportOrderPropagatesUseShopifyOrderNoDisabled()
var
Shop: Record "Shpfy Shop";
OrderHeader: Record "Shpfy Order Header";
CommunicationMgt: Codeunit "Shpfy Communication Mgt.";
ImportOrder: Codeunit "Shpfy Import Order";
OrderHandlingHelper: Codeunit "Shpfy Order Handling Helper";
begin
// [SCENARIO] When Shop."Use Shopify Order No." is false, importing an order propagates the setting to OrderHeader.
Initialize();

// [GIVEN] Shopify Shop with "Use Shopify Order No." disabled
Shop := CommunicationMgt.GetShopRecord();
Shop."Customer Mapping Type" := "Shpfy Customer Mapping"::"By EMail/Phone";
Shop."Use Shopify Order No." := false;
if not Shop.Modify() then
Shop.Insert();
ImportOrder.SetShop(Shop.Code);

// [WHEN] Shopify order is imported
OrderHandlingHelper.ImportShopifyOrder(Shop, OrderHeader, ImportOrder, false);

// [THEN] OrderHeader."Use Shopify Order No." = false
LibraryAssert.IsFalse(OrderHeader."Use Shopify Order No.", 'OrderHeader."Use Shopify Order No." should be false when Shop setting is disabled');
end;

[Test]
procedure UnitTestCreateSalesOrderWithShopifyOrderNo()
var
Shop: Record "Shpfy Shop";
OrderHeader: Record "Shpfy Order Header";
SalesHeader: Record "Sales Header";
CommunicationMgt: Codeunit "Shpfy Communication Mgt.";
ImportOrder: Codeunit "Shpfy Import Order";
ProcessOrders: Codeunit "Shpfy Process Orders";
OrderHandlingHelper: Codeunit "Shpfy Order Handling Helper";
begin
// [SCENARIO] When "Use Shopify Order No." is enabled, the created Sales Order uses the Shopify order number as its document number.
Initialize();

// [GIVEN] Shopify Shop
Shop := CommunicationMgt.GetShopRecord();
Shop."Customer Mapping Type" := "Shpfy Customer Mapping"::"By EMail/Phone";
if not Shop.Modify() then
Shop.Insert();
ImportOrder.SetShop(Shop.Code);

// [GIVEN] Sales Order number series allows manual entry
SetManualNosOnOrderNoSeries();

// [GIVEN] Imported Shopify order with "Use Shopify Order No." enabled
OrderHandlingHelper.ImportShopifyOrder(Shop, OrderHeader, ImportOrder, false);
OrderHeader."Use Shopify Order No." := true;
OrderHeader.Modify();
Commit();

// [WHEN] Order is processed
ProcessOrders.ProcessShopifyOrder(OrderHeader);
OrderHeader.GetBySystemId(OrderHeader.SystemId);

// [THEN] Sales document is created with Shopify Order No. as document number
SalesHeader.SetRange("Shpfy Order Id", OrderHeader."Shopify Order Id");
LibraryAssert.IsTrue(SalesHeader.FindLast(), 'Sales document is created from Shopify order');
LibraryAssert.AreEqual(OrderHeader."Shopify Order No.", SalesHeader."No.", 'Sales document number should equal Shopify Order No.');
end;

[Test]
procedure UnitTestCreateSalesOrderWithoutShopifyOrderNo()
var
Shop: Record "Shpfy Shop";
OrderHeader: Record "Shpfy Order Header";
SalesHeader: Record "Sales Header";
CommunicationMgt: Codeunit "Shpfy Communication Mgt.";
ImportOrder: Codeunit "Shpfy Import Order";
ProcessOrders: Codeunit "Shpfy Process Orders";
OrderHandlingHelper: Codeunit "Shpfy Order Handling Helper";
begin
// [SCENARIO] When "Use Shopify Order No." is disabled, the created Sales Order uses the standard number series.
Initialize();

// [GIVEN] Shopify Shop
Shop := CommunicationMgt.GetShopRecord();
Shop."Customer Mapping Type" := "Shpfy Customer Mapping"::"By EMail/Phone";
if not Shop.Modify() then
Shop.Insert();
ImportOrder.SetShop(Shop.Code);

// [GIVEN] Imported Shopify order with "Use Shopify Order No." disabled
OrderHandlingHelper.ImportShopifyOrder(Shop, OrderHeader, ImportOrder, false);
OrderHeader."Use Shopify Order No." := false;
OrderHeader.Modify();
Commit();

// [WHEN] Order is processed
ProcessOrders.ProcessShopifyOrder(OrderHeader);
OrderHeader.GetBySystemId(OrderHeader.SystemId);

// [THEN] Sales document is created with a number from the number series, not the Shopify Order No.
SalesHeader.SetRange("Shpfy Order Id", OrderHeader."Shopify Order Id");
LibraryAssert.IsTrue(SalesHeader.FindLast(), 'Sales document is created from Shopify order');
LibraryAssert.AreNotEqual(OrderHeader."Shopify Order No.", SalesHeader."No.", 'Sales document number should not equal Shopify Order No. when feature is disabled');
end;

[Test]
procedure UnitTestCreateSalesOrderWithShopifyOrderNoInvalidChar()
var
Shop: Record "Shpfy Shop";
OrderHeader: Record "Shpfy Order Header";
CommunicationMgt: Codeunit "Shpfy Communication Mgt.";
ImportOrder: Codeunit "Shpfy Import Order";
ProcessOrders: Codeunit "Shpfy Process Orders";
OrderHandlingHelper: Codeunit "Shpfy Order Handling Helper";
begin
// [SCENARIO] When "Use Shopify Order No." is enabled and the Shopify Order No. starts with "@", processing fails with an error.
Initialize();

// [GIVEN] Shopify Shop
Shop := CommunicationMgt.GetShopRecord();
Shop."Customer Mapping Type" := "Shpfy Customer Mapping"::"By EMail/Phone";
if not Shop.Modify() then
Shop.Insert();
ImportOrder.SetShop(Shop.Code);

// [GIVEN] Sales Order number series allows manual entry
SetManualNosOnOrderNoSeries();

// [GIVEN] Imported Shopify order with invalid Shopify Order No. starting with "@"
OrderHandlingHelper.ImportShopifyOrder(Shop, OrderHeader, ImportOrder, false);
OrderHeader."Use Shopify Order No." := true;
OrderHeader."Shopify Order No." := '@INVALID123';
OrderHeader.Modify();
Commit();

// [WHEN] Order is processed
ProcessOrders.ProcessShopifyOrder(OrderHeader);
OrderHeader.GetBySystemId(OrderHeader.SystemId);

// [THEN] Order has an error because Shopify Order No. starts with "@"
LibraryAssert.IsTrue(OrderHeader."Has Error", 'Order should have an error when Shopify Order No. starts with @');
LibraryAssert.IsTrue(OrderHeader."Error Message".Contains('@'), 'Error message should mention the invalid character @');
end;

[Test]
procedure UnitTestCreateSalesInvoiceWithShopifyOrderNo()
var
Shop: Record "Shpfy Shop";
OrderHeader: Record "Shpfy Order Header";
SalesHeader: Record "Sales Header";
CommunicationMgt: Codeunit "Shpfy Communication Mgt.";
ImportOrder: Codeunit "Shpfy Import Order";
ProcessOrders: Codeunit "Shpfy Process Orders";
OrderHandlingHelper: Codeunit "Shpfy Order Handling Helper";
begin
// [SCENARIO] When "Use Shopify Order No." is enabled and a fulfilled order creates an invoice, the Sales Invoice uses the Shopify order number.
Initialize();

// [GIVEN] Shopify Shop with "Create Invoices From Orders" enabled
Shop := CommunicationMgt.GetShopRecord();
Shop."Customer Mapping Type" := "Shpfy Customer Mapping"::"By EMail/Phone";
Shop."Create Invoices From Orders" := true;
if not Shop.Modify() then
Shop.Insert();
ImportOrder.SetShop(Shop.Code);

// [GIVEN] Sales Invoice number series allows manual entry
SetManualNosOnInvoiceNoSeries();

// [GIVEN] Imported fulfilled Shopify order with "Use Shopify Order No." enabled
OrderHandlingHelper.ImportShopifyOrder(Shop, OrderHeader, ImportOrder, false);
OrderHeader."Use Shopify Order No." := true;
OrderHeader."Fulfillment Status" := "Shpfy Order Fulfill. Status"::Fulfilled;
OrderHeader.Modify();
Commit();

// [WHEN] Order is processed
ProcessOrders.ProcessShopifyOrder(OrderHeader);
OrderHeader.GetBySystemId(OrderHeader.SystemId);

// [THEN] Sales Invoice is created with the Shopify Order No. as document number
SalesHeader.SetRange("Shpfy Order Id", OrderHeader."Shopify Order Id");
LibraryAssert.IsTrue(SalesHeader.FindLast(), 'Sales document is created from Shopify order');
LibraryAssert.AreEqual(SalesHeader."Document Type", SalesHeader."Document Type"::Invoice, 'Sales document should be an Invoice for fulfilled orders');
LibraryAssert.AreEqual(OrderHeader."Shopify Order No.", SalesHeader."No.", 'Sales Invoice number should equal Shopify Order No.');
end;

local procedure CreateTaxArea(var TaxArea: Record "Tax Area"; var ShopifyTaxArea: Record "Shpfy Tax Area"; Shop: Record "Shpfy Shop")
var
ShopifyCustomerTemplate: Record "Shpfy Customer Template";
Expand Down Expand Up @@ -1485,4 +1700,28 @@ codeunit 139608 "Shpfy Orders API Test"
JTaxLines.Add(JTaxLine);
JOrder.Add('taxLines', JTaxLines);
end;

local procedure SetManualNosOnOrderNoSeries()
var
SalesReceivablesSetup: Record "Sales & Receivables Setup";
NoSeries: Record "No. Series";
begin
SalesReceivablesSetup.Get();
if NoSeries.Get(SalesReceivablesSetup."Order Nos.") then begin
NoSeries."Manual Nos." := true;
NoSeries.Modify();
end;
end;

local procedure SetManualNosOnInvoiceNoSeries()
var
SalesReceivablesSetup: Record "Sales & Receivables Setup";
NoSeries: Record "No. Series";
begin
SalesReceivablesSetup.Get();
if NoSeries.Get(SalesReceivablesSetup."Invoice Nos.") then begin
NoSeries."Manual Nos." := true;
NoSeries.Modify();
end;
end;
}
Loading