Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
namespace Microsoft.Integration.Shopify;

/// <summary>
/// Codeunit Shpfy GQL GetProductOptions (ID 30345) implements Interface Shpfy IGraphQL.
/// </summary>
codeunit 30345 "Shpfy GQL GetProductOptions" implements "Shpfy IGraphQL"
{
Access = Internal;

/// <summary>
/// GetGraphQL.
/// </summary>
/// <returns>Return value of type Text.</returns>
internal procedure GetGraphQL(): Text
begin
exit('{"query":"{product(id: \"gid://shopify/Product/{{ProductId}}\") {id title options {id name}}}"}');
end;

/// <summary>
/// GetExpectedCost.
/// </summary>
/// <returns>Return value of type Integer.</returns>
internal procedure GetExpectedCost(): Integer
begin
exit(2);
end;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
namespace Microsoft.Integration.Shopify;

/// <summary>
/// Codeunit Shpfy GQL ProductVariantDelete (ID 30344) implements Interface Shpfy IGraphQL.
/// </summary>
codeunit 30344 "Shpfy GQL ProductVariantDelete" implements "Shpfy IGraphQL"
{
Access = Internal;

/// <summary>
/// GetGraphQL.
/// </summary>
/// <returns>Return value of type Text.</returns>
internal procedure GetGraphQL(): Text
begin
exit('{"query":"mutation {productVariantDelete(id: \"gid://shopify/ProductVariant/{{VariantId}}\") {deletedProductVariantId userErrors{field message}}}"}');
end;

/// <summary>
/// GetExpectedCost.
/// </summary>
/// <returns>Return value of type Integer.</returns>
internal procedure GetExpectedCost(): Integer
begin
exit(10);
end;
}
10 changes: 10 additions & 0 deletions Apps/W1/Shopify/app/src/GraphQL/Enums/ShpfyGraphQLType.Enum.al
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,16 @@ enum 30111 "Shpfy GraphQL Type" implements "Shpfy IGraphQL"
Caption = 'Get Order Transactions';
Implementation = "Shpfy IGraphQL" = "Shpfy GQL OrderTransactions";
}
value(85; ProductVariantDelete)
{
Caption = 'Product Variant Delete';
Implementation = "Shpfy IGraphQL" = "Shpfy GQL ProductVariantDelete";
}
value(86; GetProductOptions)
{
Caption = 'Get Product Options';
Implementation = "Shpfy IGraphQL" = "Shpfy GQL GetProductOptions";
}
value(87; GetReverseFulfillmentOrders)
{
Caption = 'Get Reverse Fulfillment Orders';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
namespace Microsoft.Integration.Shopify;

using Microsoft.Inventory.Item;

codeunit 30343 "Shpfy Create Item As Variant"
{
TableNo = Item;
Access = Internal;

var
Shop: Record "Shpfy Shop";
ShopifyProduct: Record "Shpfy Product";
CreateProduct: Codeunit "Shpfy Create Product";
VariantApi: Codeunit "Shpfy Variant API";
ProductApi: Codeunit "Shpfy Product API";
DefaultVariantId: BigInteger;

trigger OnRun()
begin
CreateVariantFromItem(Rec);
end;

/// <summary>
/// Creates a variant from a given item and adds it to the parent product.
/// </summary>
/// <param name="Item">The item to be added as a variant.</param>
internal procedure CreateVariantFromItem(var Item: Record "Item")
var
TempShopifyVariant: Record "Shpfy Variant" temporary;
begin
CreateProduct.CreateTempShopifyVariantFromItem(Item, TempShopifyVariant);
TempShopifyVariant."Product Id" := ShopifyProduct."Id";
TempShopifyVariant.Title := Item."No.";
TempShopifyVariant."Option 1 Name" := 'Variant';
TempShopifyVariant."Option 1 Value" := Item."No.";

if VariantApi.AddProductVariant(TempShopifyVariant) then begin
ShopifyProduct."Has Variants" := true;
ShopifyProduct.Modify(true);
end;
end;


/// <summary>
/// Checks if items can be added as variants to the product. The items cannot be added as variants if:
/// - The product has more than one option.
/// - The UoM as Variant setting is enabled.
/// </summary>
internal procedure CheckProductAndShopSettings()
var
MultipleOptionsErr: Label 'The product has more than one option. Items cannot be added as variants to a product with multiple options.';
UOMAsVariantEnabledErr: Label 'Items cannot be added as variants to a product with the "%1" setting enabled for this store.', Comment = '%1 - UoM as Variant field caption';
Options: Dictionary of [Text, Text];
begin
if Shop."UoM as Variant" then
Error(UOMAsVariantEnabledErr, Shop.FieldCaption("UoM as Variant"));

Options := ProductApi.GetProductOptions(ShopifyProduct.Id);

if Options.Count > 1 then
Error(MultipleOptionsErr);
end;

/// <summary>
/// Finds the default variant ID for the product if the product has no variants.
/// If new variants will be added, the default variant will be removed.
/// </summary>
internal procedure FindDefaultVariantId()
var
ProductVariantIds: Dictionary of [BigInteger, DateTime];
begin
if not ShopifyProduct."Has Variants" then begin
VariantApi.RetrieveShopifyProductVariantIds(ShopifyProduct, ProductVariantIds);
DefaultVariantId := ProductVariantIds.Keys.Get(1);
end;
end;

/// <summary>
/// Removes the default variant if new variants were added to the product.
/// </summary>
internal procedure RemoveDefaultVariant()
var
ShopifyVariant: Record "Shpfy Variant";
begin
if (DefaultVariantId <> 0) and ShopifyProduct."Has Variants" then begin
VariantApi.DeleteProductVariant(DefaultVariantId);
if ShopifyVariant.Get(DefaultVariantId) then
ShopifyVariant.Delete(true);
end;
end;

/// <summary>
/// Sets the parent product to which the variant will be added.
/// </summary>
/// <param name="ShopifyProductId">The parent Shopify product ID.</param>
internal procedure SetParentProduct(ShopifyProductId: BigInteger)
begin
ShopifyProduct.Get(ShopifyProductId);
SetShop(ShopifyProduct."Shop Code");
end;

local procedure SetShop(ShopCode: Code[20])
begin
Shop.Get(ShopCode);
VariantApi.SetShop(Shop);
ProductApi.SetShop(Shop);
CreateProduct.SetShop(Shop);
end;

}
Original file line number Diff line number Diff line change
Expand Up @@ -87,22 +87,7 @@ codeunit 30174 "Shpfy Create Product"
ProductPriceCalc.CalcPrice(Item, ItemVariant.Code, ItemUnitofMeasure.Code, TempShopifyVariant."Unit Cost", TempShopifyVariant.Price, TempShopifyVariant."Compare at Price");
TempShopifyVariant.Title := ItemVariant.Description;
TempShopifyVariant."Inventory Policy" := Shop."Default Inventory Policy";
case Shop."SKU Mapping" of
Shop."SKU Mapping"::"Bar Code":
TempShopifyVariant.SKU := TempShopifyVariant.Barcode;
Shop."SKU Mapping"::"Item No.":
TempShopifyVariant.SKU := Item."No.";
Shop."SKU Mapping"::"Variant Code":
if ItemVariant.Code <> '' then
TempShopifyVariant.SKU := ItemVariant.Code;
Shop."SKU Mapping"::"Item No. + Variant Code":
if ItemVariant.Code <> '' then
TempShopifyVariant.SKU := Item."No." + Shop."SKU Field Separator" + ItemVariant.Code
else
TempShopifyVariant.SKU := Item."No.";
Shop."SKU Mapping"::"Vendor Item No.":
TempShopifyVariant.SKU := Item."Vendor Item No.";
end;
TempShopifyVariant.SKU := GetVariantSKU(TempShopifyVariant.Barcode, Item."No.", ItemVariant.Code, Item."Vendor Item No.");
TempShopifyVariant."Tax Code" := Item."Tax Group Code";
TempShopifyVariant.Taxable := true;
TempShopifyVariant.Weight := Item."Gross Weight";
Expand All @@ -125,22 +110,7 @@ codeunit 30174 "Shpfy Create Product"
ProductPriceCalc.CalcPrice(Item, ItemVariant.Code, Item."Sales Unit of Measure", TempShopifyVariant."Unit Cost", TempShopifyVariant.Price, TempShopifyVariant."Compare at Price");
TempShopifyVariant.Title := ItemVariant.Description;
TempShopifyVariant."Inventory Policy" := Shop."Default Inventory Policy";
case Shop."SKU Mapping" of
Shop."SKU Mapping"::"Bar Code":
TempShopifyVariant.SKU := TempShopifyVariant.Barcode;
Shop."SKU Mapping"::"Item No.":
TempShopifyVariant.SKU := Item."No.";
Shop."SKU Mapping"::"Variant Code":
if ItemVariant.Code <> '' then
TempShopifyVariant.SKU := ItemVariant.Code;
Shop."SKU Mapping"::"Item No. + Variant Code":
if ItemVariant.Code <> '' then
TempShopifyVariant.SKU := Item."No." + Shop."SKU Field Separator" + ItemVariant.Code
else
TempShopifyVariant.SKU := Item."No.";
Shop."SKU Mapping"::"Vendor Item No.":
TempShopifyVariant.SKU := CopyStr(GetVendorItemNo(Item."No.", ItemVariant.Code, Item."Sales Unit of Measure"), 1, MaxStrLen(TempShopifyVariant.SKU));
end;
TempShopifyVariant.SKU := GetVariantSKU(TempShopifyVariant.Barcode, Item."No.", ItemVariant.Code, GetVendorItemNo(Item."No.", ItemVariant.Code, Item."Sales Unit of Measure"));
TempShopifyVariant."Tax Code" := Item."Tax Group Code";
TempShopifyVariant.Taxable := true;
TempShopifyVariant.Weight := Item."Gross Weight";
Expand All @@ -157,6 +127,7 @@ codeunit 30174 "Shpfy Create Product"
ItemUnitofMeasure.SetRange("Item No.", Item."No.");
if ItemUnitofMeasure.FindSet(false) then
repeat
TempShopifyProduct."Has Variants" := true;
Id += 1;
Clear(TempShopifyVariant);
TempShopifyVariant.Id := Id;
Expand All @@ -165,22 +136,7 @@ codeunit 30174 "Shpfy Create Product"
ProductPriceCalc.CalcPrice(Item, '', ItemUnitofMeasure.Code, TempShopifyVariant."Unit Cost", TempShopifyVariant.Price, TempShopifyVariant."Compare at Price");
TempShopifyVariant.Title := Item.Description;
TempShopifyVariant."Inventory Policy" := Shop."Default Inventory Policy";
case Shop."SKU Mapping" of
Shop."SKU Mapping"::"Bar Code":
TempShopifyVariant.SKU := TempShopifyVariant.Barcode;
Shop."SKU Mapping"::"Item No.":
TempShopifyVariant.SKU := Item."No.";
Shop."SKU Mapping"::"Variant Code":
if ItemVariant.Code <> '' then
TempShopifyVariant.SKU := ItemVariant.Code;
SHop."SKU Mapping"::"Item No. + Variant Code":
if ItemVariant.Code <> '' then
TempShopifyVariant.SKU := Item."No." + Shop."SKU Field Separator" + ItemVariant.Code
else
TempShopifyVariant.SKU := Item."No.";
Shop."SKU Mapping"::"Vendor Item No.":
TempShopifyVariant.SKU := Item."Vendor Item No.";
end;
TempShopifyVariant.SKU := GetVariantSKU(TempShopifyVariant.Barcode, Item."No.", '', Item."Vendor Item No.");
TempShopifyVariant."Tax Code" := Item."Tax Group Code";
TempShopifyVariant.Taxable := true;
TempShopifyVariant.Weight := Item."Gross Weight";
Expand All @@ -191,39 +147,11 @@ codeunit 30174 "Shpfy Create Product"
TempShopifyVariant."UoM Option Id" := 1;
TempShopifyVariant.Insert(false);
until ItemUnitofMeasure.Next() = 0;
end else begin
Clear(TempShopifyVariant);
TempShopifyVariant."Available For Sales" := true;
TempShopifyVariant.Barcode := CopyStr(GetBarcode(Item."No.", '', Item."Sales Unit of Measure"), 1, MaxStrLen(TempShopifyVariant.Barcode));
ProductPriceCalc.CalcPrice(Item, '', Item."Sales Unit of Measure", TempShopifyVariant."Unit Cost", TempShopifyVariant.Price, TempShopifyVariant."Compare at Price");
TempShopifyVariant.Title := ItemVariant.Description;
TempShopifyVariant."Inventory Policy" := Shop."Default Inventory Policy";
case Shop."SKU Mapping" of
Shop."SKU Mapping"::"Bar Code":
TempShopifyVariant.SKU := TempShopifyVariant.Barcode;
Shop."SKU Mapping"::"Item No.":
TempShopifyVariant.SKU := Item."No.";
Shop."SKU Mapping"::"Variant Code":
if ItemVariant.Code <> '' then
TempShopifyVariant.SKU := ItemVariant.Code;
SHop."SKU Mapping"::"Item No. + Variant Code":
if ItemVariant.Code <> '' then
TempShopifyVariant.SKU := Item."No." + Shop."SKU Field Separator" + ItemVariant.Code
else
TempShopifyVariant.SKU := Item."No.";
Shop."SKU Mapping"::"Vendor Item No.":
TempShopifyVariant.SKU := Item."Vendor Item No.";
end;
TempShopifyVariant."Tax Code" := Item."Tax Group Code";
TempShopifyVariant.Taxable := true;
TempShopifyVariant.Weight := Item."Gross Weight";
TempShopifyVariant."Shop Code" := Shop.Code;
TempShopifyVariant."Item SystemId" := Item.SystemId;
TempShopifyVariant.Insert(false);
end;
end else
CreateTempShopifyVariantFromItem(Item, TempShopifyVariant);

TempShopifyProduct.Insert(false);
Events.OnAfterCreateTempShopifyProduct(Item, TempShopifyProduct, TempShopifyVariant, TempShopifyTag);

end;

/// <summary>
Expand All @@ -246,8 +174,8 @@ codeunit 30174 "Shpfy Create Product"
/// <param name="ItemNo">Parameter of type Code[20].</param>
/// <param name="VariantCode">Parameter of type Code[10].</param>
/// <param name="UoM">Parameter of type Code[10].</param>
/// <returns>Return value of type Text.</returns>
local procedure GetVendorItemNo(ItemNo: Code[20]; VariantCode: Code[10]; UoM: Code[10]): Text;
/// <returns>Return value of type Code[50].</returns>
local procedure GetVendorItemNo(ItemNo: Code[20]; VariantCode: Code[10]; UoM: Code[10]): Code[50];
var
Item: Record Item;
ItemReferenceMgt: Codeunit "Shpfy Item Reference Mgt.";
Expand All @@ -256,6 +184,48 @@ codeunit 30174 "Shpfy Create Product"
exit(ItemReferenceMgt.GetItemReference(ItemNo, VariantCode, UoM, "Item Reference Type"::Vendor, Item."Vendor No."));
end;

local procedure GetVariantSKU(BarCode: Text[50]; ItemNo: Text[20]; VariantCode: Text[10]; VendorItemNo: Text[50]): Text[50]
begin
case Shop."SKU Mapping" of
Shop."SKU Mapping"::"Bar Code":
exit(BarCode);
Shop."SKU Mapping"::"Item No.":
exit(ItemNo);
Shop."SKU Mapping"::"Variant Code":
if VariantCode <> '' then
exit(VariantCode);
Shop."SKU Mapping"::"Item No. + Variant Code":
if VariantCode <> '' then
exit(ItemNo + Shop."SKU Field Separator" + VariantCode)
else
exit(ItemNo);
Shop."SKU Mapping"::"Vendor Item No.":
exit(VendorItemNo);
end;
end;

/// <summary>
/// Creates a temporary Shopify variant with information from an item.
/// </summary>
/// <param name="Item">The item to create the variant from.</param>
/// <param name="TempShopifyVariant">The temporary Shopify variant record set where the variant will be inserted.</param>
internal procedure CreateTempShopifyVariantFromItem(Item: Record Item; var TempShopifyVariant: Record "Shpfy Variant" temporary)
begin
Clear(TempShopifyVariant);
TempShopifyVariant."Available For Sales" := true;
TempShopifyVariant.Barcode := CopyStr(GetBarcode(Item."No.", '', Item."Sales Unit of Measure"), 1, MaxStrLen(TempShopifyVariant.Barcode));
ProductPriceCalc.CalcPrice(Item, '', Item."Sales Unit of Measure", TempShopifyVariant."Unit Cost", TempShopifyVariant.Price, TempShopifyVariant."Compare at Price");
TempShopifyVariant.Title := ''; // Title will be assigned to "Default Title" in Shopify as no Options are set.
TempShopifyVariant."Inventory Policy" := Shop."Default Inventory Policy";
TempShopifyVariant.SKU := GetVariantSKU(TempShopifyVariant.Barcode, Item."No.", '', Item."Vendor Item No.");
TempShopifyVariant."Tax Code" := Item."Tax Group Code";
TempShopifyVariant.Taxable := true;
TempShopifyVariant.Weight := Item."Gross Weight";
TempShopifyVariant."Shop Code" := Shop.Code;
TempShopifyVariant."Item SystemId" := Item.SystemId;
TempShopifyVariant.Insert(false);
end;

/// <summary>
/// Set Shop.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -608,4 +608,24 @@ codeunit 30176 "Shpfy Product API"
begin
exit(Value.Names.Get(Value.Ordinals.IndexOf(Value.AsInteger())).ToUpper());
end;

/// <summary>
/// Gets all the Product Options for a product.
/// </summary>
/// <param name="ShopifyProductId">Shopify product ID for which the options are to be retrieved.</param>
/// <returns>Dictionary of option IDs and option names.</returns>
internal procedure GetProductOptions(ShopifyProductId: BigInteger) Options: Dictionary of [text, Text]
var
Parameters: Dictionary of [Text, Text];
JResponse: JsonToken;
JOptions: JsonArray;
JOption: JsonToken;
begin
Parameters.Add('ProductId', Format(ShopifyProductId));
JResponse := CommunicationMgt.ExecuteGraphQL(Enum::"Shpfy GraphQL Type"::GetProductOptions, Parameters);

JsonHelper.GetJsonArray(JResponse, JOptions, 'data.product.options');
foreach JOption in JOptions do
Options.Add(JsonHelper.GetValueAsText(JOption, 'id'), JsonHelper.GetValueAsText(JOption, 'name'));
end;
}
Loading