diff --git a/Apps/W1/Shopify/app/app.json b/Apps/W1/Shopify/app/app.json index 0be3e1f856..3ddb14510c 100644 --- a/Apps/W1/Shopify/app/app.json +++ b/Apps/W1/Shopify/app/app.json @@ -21,7 +21,7 @@ "idRanges": [ { "from": 30100, - "to": 30350 + "to": 30360 } ], "internalsVisibleTo": [ diff --git a/Apps/W1/Shopify/app/src/Base/Tables/ShpfyMetafield.Table.al b/Apps/W1/Shopify/app/src/Base/Tables/ShpfyMetafield.Table.al deleted file mode 100644 index f368c2ab82..0000000000 --- a/Apps/W1/Shopify/app/src/Base/Tables/ShpfyMetafield.Table.al +++ /dev/null @@ -1,103 +0,0 @@ -namespace Microsoft.Integration.Shopify; - -/// -/// Table Shpfy Metafield (ID 30101). -/// -table 30101 "Shpfy Metafield" -{ - Access = Internal; - Caption = 'Shopify Metafield'; - DataClassification = CustomerContent; - - fields - { - field(1; Id; BigInteger) - { - Caption = 'Id'; - DataClassification = SystemMetadata; - Editable = false; - } - - field(2; Namespace; Text[100]) - { - Caption = 'Namespace'; - DataClassification = SystemMetadata; - } - - field(3; "Owner Resource"; Text[50]) - { - Caption = 'Owner Resource'; - DataClassification = SystemMetadata; - - trigger OnValidate() - begin - case "Owner Resource" of - 'customer': - "Parent Table No." := Database::"Shpfy Customer"; - end; - end; - } - - field(4; "Owner Id"; BigInteger) - { - Caption = 'Owner Id'; - DataClassification = SystemMetadata; - } - - - field(5; Name; Text[30]) - { - Caption = 'Key'; - DataClassification = CustomerContent; - } - - field(6; "Value Type"; enum "Shpfy Metafield Value Type") - { - Caption = 'Value Type'; - DataClassification = CustomerContent; - } - - field(7; Value; Text[250]) - { - Caption = 'Value'; - DataClassification = CustomerContent; - } - - field(101; "Parent Table No."; Integer) - { - Caption = 'Parent Table No.'; - DataClassification = SystemMetadata; - Editable = false; - - trigger OnValidate() - begin - case "Parent Table No." of - Database::"Shpfy Customer": - "Owner Resource" := 'customer'; - end; - end; - } - } - - keys - { - key(PK; Id) - { - Clustered = true; - } - } - - - trigger OnInsert() - var - Metafield: Record "Shpfy Metafield"; - begin - if Namespace = '' then - Namespace := 'Microsoft.Dynamics365.BusinessCentral'; - if Id = 0 then - if Metafield.FindFirst() and (Metafield.Id < 0) then - Id := Metafield.Id - 1 - else - Id := -1; - end; -} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Customers/Codeunits/ShpfyCustomerExport.Codeunit.al b/Apps/W1/Shopify/app/src/Customers/Codeunits/ShpfyCustomerExport.Codeunit.al index ec62eec90b..363fe23448 100644 --- a/Apps/W1/Shopify/app/src/Customers/Codeunits/ShpfyCustomerExport.Codeunit.al +++ b/Apps/W1/Shopify/app/src/Customers/Codeunits/ShpfyCustomerExport.Codeunit.al @@ -64,7 +64,7 @@ codeunit 30116 "Shpfy Customer Export" Metafield.Namespace := 'Microsoft.Dynamics365.BusinessCentral'; Metafield.Validate("Parent Table No.", Database::"Shpfy Customer"); Metafield."Owner Id" := ShopifyCustomer.Id; - Metafield."Value Type" := Metafield."Value Type"::String; + Metafield.Type := Metafield.Type::string; Metafield.Value := Format(MetadataFieldRef.Value); end; end; diff --git a/Apps/W1/Shopify/app/src/Customers/Tables/ShpfyCustomer.Table.al b/Apps/W1/Shopify/app/src/Customers/Tables/ShpfyCustomer.Table.al index b8ad162bec..c194c2e1a0 100644 --- a/Apps/W1/Shopify/app/src/Customers/Tables/ShpfyCustomer.Table.al +++ b/Apps/W1/Shopify/app/src/Customers/Tables/ShpfyCustomer.Table.al @@ -148,6 +148,7 @@ table 30105 "Shpfy Customer" if not Tag.IsEmpty() then Tag.DeleteAll(); + Metafield.SetRange("Parent Table No.", Database::"Shpfy Customer"); Metafield.SetRange("Owner Id", Id); if not Metafield.IsEmpty then Metafield.DeleteAll(); diff --git a/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLMetafieldsSet.Codeunit.al b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLMetafieldsSet.Codeunit.al new file mode 100644 index 0000000000..f04cfc1cab --- /dev/null +++ b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLMetafieldsSet.Codeunit.al @@ -0,0 +1,27 @@ +namespace Microsoft.Integration.Shopify; + +/// +/// Codeunit Shpfy GQL MetafieldSet (ID 30168) implements Interface Shpfy IGraphQL. +/// +codeunit 30350 "Shpfy GQL MetafieldsSet" implements "Shpfy IGraphQL" +{ + Access = Internal; + + /// + /// GetGraphQL. + /// + /// Return value of type Text. + internal procedure GetGraphQL(): Text + begin + exit('{"query": "mutation { metafieldsSet(metafields: [{{Metafields}}]) { metafields {legacyResourceId namespace key} userErrors {field, message}}}"}'); + end; + + /// + /// GetExpectedCost. + /// + /// Return value of type Integer. + internal procedure GetExpectedCost(): Integer + begin + exit(10); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLProductById.Codeunit.al b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLProductById.Codeunit.al index 183fcc8147..a8a559b5c2 100644 --- a/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLProductById.Codeunit.al +++ b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLProductById.Codeunit.al @@ -13,7 +13,7 @@ codeunit 30146 "Shpfy GQL ProductById" implements "Shpfy IGraphQL" /// Return value of type Text. internal procedure GetGraphQL(): Text begin - exit('{"query":"{product(id: \"gid://shopify/Product/{{ProductId}}\") {createdAt updatedAt hasOnlyDefaultVariant description(truncateAt: {{MaxLengthDescription}}) descriptionHtml onlineStorePreviewUrl onlineStoreUrl productType status tags title vendor seo{description, title} images(first: 1) {edges{node{id}}} metafields(namespace: \"Microsoft.Dynamics365.BusinessCentral\", first: 10) {edges {node {id namespace type legacyResourceId key value}}}}}"}'); + exit('{"query":"{product(id: \"gid://shopify/Product/{{ProductId}}\") {createdAt updatedAt hasOnlyDefaultVariant description(truncateAt: {{MaxLengthDescription}}) descriptionHtml onlineStorePreviewUrl onlineStoreUrl productType status tags title vendor seo{description, title} images(first: 1) {edges{node{id}}} metafields(first: 50) {edges {node {id namespace type legacyResourceId key value}}}}}"}'); end; /// diff --git a/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLProductMetafieldIds.Codeunit.al b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLProductMetafieldIds.Codeunit.al new file mode 100644 index 0000000000..f70ba9b255 --- /dev/null +++ b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLProductMetafieldIds.Codeunit.al @@ -0,0 +1,28 @@ +namespace Microsoft.Integration.Shopify; + +/// +/// Codeunit Shpfy GQL ProductMetafieldIds (ID 30332) implements Interface Shpfy IGraphQL. +/// +codeunit 30332 "Shpfy GQL ProductMetafieldIds" implements "Shpfy IGraphQL" +{ + Access = Internal; + + /// + /// GetGraphQL. + /// + /// Return value of type Text. + internal procedure GetGraphQL(): Text + begin + exit('{"query":"{product(id: \"gid://shopify/Product/{{ProductId}}\") { metafields(first: 50) {edges{node{legacyResourceId updatedAt}}}}}"}'); + end; + + /// + /// GetExpectedCost. + /// + /// Return value of type Integer. + internal procedure GetExpectedCost(): Integer + begin + exit(50); + end; + +} diff --git a/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLVariantById.Codeunit.al b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLVariantById.Codeunit.al index 3973390897..8bb1d2c9c4 100644 --- a/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLVariantById.Codeunit.al +++ b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLVariantById.Codeunit.al @@ -13,7 +13,7 @@ codeunit 30150 "Shpfy GQL VariantById" implements "Shpfy IGraphQL" /// Return value of type Text. internal procedure GetGraphQL(): Text begin - exit('{"query":"{productVariant(id: \"gid://shopify/ProductVariant/{{VariantId}}\") {createdAt updatedAt availableForSale barcode compareAtPrice displayName inventoryPolicy position price sku taxCode taxable title weight product{id}selectedOptions{name value} inventoryItem{countryCodeOfOrigin createdAt id inventoryHistoryUrl legacyResourceId provinceCodeOfOrigin requiresShipping sku tracked updatedAt unitCost { amount currencyCode }} metafields(namespace: \"Microsoft.Dynamics365.BusinessCentral\", first: 10) {edges {node {id namespace ownerType legacyResourceId key value}}}}}"}'); + exit('{"query":"{productVariant(id: \"gid://shopify/ProductVariant/{{VariantId}}\") {createdAt updatedAt availableForSale barcode compareAtPrice displayName inventoryPolicy position price sku taxCode taxable title weight product{id}selectedOptions{name value} inventoryItem{countryCodeOfOrigin createdAt id inventoryHistoryUrl legacyResourceId provinceCodeOfOrigin requiresShipping sku tracked updatedAt unitCost { amount currencyCode }} metafields(first: 50) {edges {node {id namespace ownerType legacyResourceId key value}}}}}"}'); end; /// diff --git a/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLVariantMetafieldIds.Codeunit.al b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLVariantMetafieldIds.Codeunit.al new file mode 100644 index 0000000000..4bf3e281b7 --- /dev/null +++ b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLVariantMetafieldIds.Codeunit.al @@ -0,0 +1,28 @@ +namespace Microsoft.Integration.Shopify; + +/// +/// Codeunit Shpfy GQL VariantMetafieldIds (ID 30336) implements Interface Shpfy IGraphQL. +/// +codeunit 30336 "Shpfy GQL VariantMetafieldIds" implements "Shpfy IGraphQL" +{ + Access = Internal; + + /// + /// GetGraphQL. + /// + /// Return value of type Text. + internal procedure GetGraphQL(): Text + begin + exit('{"query":"{productVariant(id: \"gid://shopify/ProductVariant/{{VariantId}}\") { metafields(first: 50) {edges{ node{legacyResourceId updatedAt}}}}}"}'); + end; + + /// + /// GetExpectedCost. + /// + /// Return value of type Integer. + internal procedure GetExpectedCost(): Integer + begin + exit(50); + 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 3157f92a53..8c9626b419 100644 --- a/Apps/W1/Shopify/app/src/GraphQL/Enums/ShpfyGraphQLType.Enum.al +++ b/Apps/W1/Shopify/app/src/GraphQL/Enums/ShpfyGraphQLType.Enum.al @@ -405,6 +405,21 @@ enum 30111 "Shpfy GraphQL Type" implements "Shpfy IGraphQL" Caption = 'Get Order Transactions'; Implementation = "Shpfy IGraphQL" = "Shpfy GQL OrderTransactions"; } + value(79; MetafieldSet) + { + Caption = 'MetfieldSet'; + Implementation = "Shpfy IGraphQL" = "Shpfy GQL MetafieldsSet"; + } + value(80; ProductMetafieldIds) + { + Caption = 'Product Metafield Ids'; + Implementation = "Shpfy IGraphQL" = "Shpfy GQL ProductMetafieldIds"; + } + value(81; VariantMetafieldIds) + { + Caption = 'Variant Metafield Ids'; + Implementation = "Shpfy IGraphQL" = "Shpfy GQL VariantMetafieldIds"; + } value(85; ProductVariantDelete) { Caption = 'Product Variant Delete'; diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeBoolean.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeBoolean.Codeunit.al new file mode 100644 index 0000000000..9b1b65d3a7 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeBoolean.Codeunit.al @@ -0,0 +1,27 @@ +namespace Microsoft.Integration.Shopify; + +codeunit 30338 "Shpfy Mtfld Type Boolean" implements "Shpfy IMetafield Type" +{ + procedure HasAssistEdit(): Boolean + begin + exit(false); + end; + + procedure IsValidValue(Value: Text): Boolean + var + DummyBoolean: Boolean; + begin + exit(Evaluate(DummyBoolean, Value, 9)); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + begin + Value := Value; + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit('true'); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeCollectRef.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeCollectRef.Codeunit.al new file mode 100644 index 0000000000..25e78a3bdd --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeCollectRef.Codeunit.al @@ -0,0 +1,29 @@ +namespace Microsoft.Integration.Shopify; + +using System.Utilities; + +codeunit 30321 "Shpfy Mtfld Type Collect. Ref" implements "Shpfy IMetafield Type" +{ + procedure HasAssistEdit(): Boolean + begin + exit(false); + end; + + procedure IsValidValue(Value: Text): Boolean + var + Regex: Codeunit Regex; + begin + exit(Regex.IsMatch(Value, '^gid:\/\/shopify\/Collection\/\d+$')); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + begin + Value := Value; + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit('gid://shopify/Collection/1234567890'); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeColor.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeColor.Codeunit.al new file mode 100644 index 0000000000..55759bda36 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeColor.Codeunit.al @@ -0,0 +1,29 @@ +namespace Microsoft.Integration.Shopify; + +using System.Utilities; + +codeunit 30319 "Shpfy Mtfld Type Color" implements "Shpfy IMetafield Type" +{ + procedure HasAssistEdit(): Boolean + begin + exit(false); + end; + + procedure IsValidValue(Value: Text): Boolean + var + Regex: Codeunit Regex; + begin + exit(Regex.IsMatch(Value, '^#[0-9A-Fa-f]{6}$')); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + begin + Value := Value; + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit('#fff123'); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeDate.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeDate.Codeunit.al new file mode 100644 index 0000000000..96b530e90c --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeDate.Codeunit.al @@ -0,0 +1,27 @@ +namespace Microsoft.Integration.Shopify; + +codeunit 30318 "Shpfy Mtfld Type Date" implements "Shpfy IMetafield Type" +{ + procedure HasAssistEdit(): Boolean + begin + exit(false); + end; + + procedure IsValidValue(Value: Text): Boolean + var + DummyDate: Date; + begin + exit(Evaluate(DummyDate, Value, 9)); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + begin + Value := Value; + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit('2022-02-02'); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeDateTime.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeDateTime.Codeunit.al new file mode 100644 index 0000000000..e83ed841ed --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeDateTime.Codeunit.al @@ -0,0 +1,27 @@ +namespace Microsoft.Integration.Shopify; + +codeunit 30315 "Shpfy Mtfld Type DateTime" implements "Shpfy IMetafield Type" +{ + procedure HasAssistEdit(): Boolean + begin + exit(false); + end; + + procedure IsValidValue(Value: Text): Boolean + var + DummyDateTime: DateTime; + begin + exit(Evaluate(DummyDateTime, Value, 9)); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + begin + Value := Value; + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit('2022-01-01T12:30:00'); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeDimension.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeDimension.Codeunit.al new file mode 100644 index 0000000000..107cac0063 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeDimension.Codeunit.al @@ -0,0 +1,70 @@ +namespace Microsoft.Integration.Shopify; + +codeunit 30351 "Shpfy Mtfld Type Dimension" implements "Shpfy IMetafield Type" +{ + var + DimensionJsonTemplateTxt: Label '{"value": %1, "unit": "%2"}', Locked = true; + + procedure HasAssistEdit(): Boolean + begin + exit(true); + end; + + procedure IsValidValue(Value: Text): Boolean + var + Dimension: Decimal; + Unit: Enum "Shpfy Metafield Dimension Type"; + begin + exit(TryExtractValues(Value, Dimension, Unit)); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + var + MetafieldAssistEdit: Page "Shpfy Metafield Assist Edit"; + Dimension: Decimal; + Unit: Enum "Shpfy Metafield Dimension Type"; + begin + if Value <> '' then + if not TryExtractValues(Value, Dimension, Unit) then begin + Clear(Dimension); + Clear(Unit); + end; + + if MetafieldAssistEdit.OpenForDimension(Dimension, Unit) then begin + MetafieldAssistEdit.GetDimensionValue(Dimension, Unit); + Value := StrSubstNo(DimensionJsonTemplateTxt, Format(Dimension, 0, 9), GetDimensionTypeName(Unit)); + end else + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit(StrSubstNo(DimensionJsonTemplateTxt, '1.5', 'cm')); + end; + + [TryFunction] + local procedure TryExtractValues(Value: Text; var Dimension: Decimal; var Unit: Enum "Shpfy Metafield Dimension Type") + var + JToken: JsonToken; + JObject: JsonObject; + begin + JObject.ReadFrom(Value); + JObject.SelectToken('value', JToken); + Dimension := JToken.AsValue().AsDecimal(); + JObject.SelectToken('unit', JToken); + Unit := ConvertToDimensionType(JToken.AsValue().AsText()); + + if JObject.Keys.Count() <> 2 then + Error(''); + end; + + local procedure GetDimensionTypeName(DimensionType: Enum "Shpfy Metafield Dimension Type"): Text + begin + exit(DimensionType.Names().Get(DimensionType.Ordinals().IndexOf(DimensionType.AsInteger()))); + end; + + local procedure ConvertToDimensionType(Value: Text) Type: Enum "Shpfy Metafield Dimension Type" + begin + exit(Enum::"Shpfy Metafield Dimension Type".FromInteger(Type.Ordinals().Get(Type.Names().IndexOf(Value)))); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeFileRef.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeFileRef.Codeunit.al new file mode 100644 index 0000000000..9e5c357782 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeFileRef.Codeunit.al @@ -0,0 +1,29 @@ +namespace Microsoft.Integration.Shopify; + +using System.Utilities; + +codeunit 30322 "Shpfy Mtfld Type File Ref" implements "Shpfy IMetafield Type" +{ + procedure HasAssistEdit(): Boolean + begin + exit(false); + end; + + procedure IsValidValue(Value: Text): Boolean + var + Regex: Codeunit Regex; + begin + exit(Regex.IsMatch(Value, '^gid:\/\/shopify\/(GenericFile|MediaImage|Video)\/\d+$')); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + begin + Value := Value; + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit('gid://shopify/MediaImage/1234567890'); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeInteger.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeInteger.Codeunit.al new file mode 100644 index 0000000000..28a7406b37 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeInteger.Codeunit.al @@ -0,0 +1,37 @@ +namespace Microsoft.Integration.Shopify; + +codeunit 30339 "Shpfy Mtfld Type Integer" implements "Shpfy IMetafield Type" +{ + procedure HasAssistEdit(): Boolean + begin + exit(false); + end; + + procedure IsValidValue(Value: Text): Boolean + var + DummyInteger: BigInteger; + MinInt: BigInteger; + MaxInt: BigInteger; + begin + if not Evaluate(DummyInteger, Value, 9) then + exit(false); + + Evaluate(MinInt, '-9007199254740991', 9); + Evaluate(MaxInt, '9007199254740991', 9); + if (DummyInteger < MinInt) or (DummyInteger > MaxInt) then + exit(false); + + exit(true); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + begin + Value := Value; + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit('123'); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeJson.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeJson.Codeunit.al new file mode 100644 index 0000000000..95d5732b99 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeJson.Codeunit.al @@ -0,0 +1,27 @@ +namespace Microsoft.Integration.Shopify; + +codeunit 30353 "Shpfy Mtfld Type Json" implements "Shpfy IMetafield Type" +{ + procedure HasAssistEdit(): Boolean + begin + exit(false); + end; + + procedure IsValidValue(Value: Text): Boolean + var + JsonObject: JsonObject; + begin + exit(JsonObject.ReadFrom(Value)); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + begin + Value := Value; + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit('{"ingredient": "flour", "amount": 0.3}'); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeMetaobjRef.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeMetaobjRef.Codeunit.al new file mode 100644 index 0000000000..9053ac668d --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeMetaobjRef.Codeunit.al @@ -0,0 +1,29 @@ +namespace Microsoft.Integration.Shopify; + +using System.Utilities; + +codeunit 30327 "Shpfy Mtfld Type Metaobj. Ref" implements "Shpfy IMetafield Type" +{ + procedure HasAssistEdit(): Boolean + begin + exit(false); + end; + + procedure IsValidValue(Value: Text): Boolean + var + Regex: Codeunit Regex; + begin + exit(Regex.IsMatch(Value, '^gid:\/\/shopify\/Metaobject\/\d+$')); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + begin + Value := Value; + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit('gid://shopify/Metaobject/1234567890'); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeMixedRef.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeMixedRef.Codeunit.al new file mode 100644 index 0000000000..ca7dca2ed4 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeMixedRef.Codeunit.al @@ -0,0 +1,29 @@ +namespace Microsoft.Integration.Shopify; + +using System.Utilities; + +codeunit 30331 "Shpfy Mtfld Type Mixed Ref" implements "Shpfy IMetafield Type" +{ + procedure HasAssistEdit(): Boolean + begin + exit(false); + end; + + procedure IsValidValue(Value: Text): Boolean + var + Regex: Codeunit Regex; + begin + exit(Regex.IsMatch(Value, '^gid:\/\/shopify\/[A-Za-z]+\/\d+$')); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + begin + Value := Value; + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit('gid://shopify/Product/1234567890'); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeMoney.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeMoney.Codeunit.al new file mode 100644 index 0000000000..2acb6640d6 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeMoney.Codeunit.al @@ -0,0 +1,74 @@ +namespace Microsoft.Integration.Shopify; + +using Microsoft.Finance.Currency; + +codeunit 30317 "Shpfy Mtfld Type Money" implements "Shpfy IMetafield Type" +{ + var + MoneyJsonTemplateTxt: Label '{"amount": "%1", "currency_code": "%2"}', Locked = true; + + procedure HasAssistEdit(): Boolean + begin + exit(true); + end; + + procedure IsValidValue(Value: Text): Boolean + var + Amount: Decimal; + CurrencyCode: Code[10]; + begin + exit(TryExtractValues(Value, Amount, CurrencyCode)); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + var + MetafieldAssistEdit: Page "Shpfy Metafield Assist Edit"; + Amount: Decimal; + CurrencyCode: Code[10]; + begin + if Value <> '' then + if not TryExtractValues(Value, Amount, CurrencyCode) then begin + Clear(Amount); + Clear(CurrencyCode); + end; + + if MetafieldAssistEdit.OpenForMoney(Amount, CurrencyCode) then begin + MetafieldAssistEdit.GetMoneyValue(Amount, CurrencyCode); + Value := StrSubstNo(MoneyJsonTemplateTxt, Format(Amount, 0, 9), CurrencyCode); + exit(true); + end else + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit(StrSubstNo(MoneyJsonTemplateTxt, '5.99', 'CAD')); + end; + + /// + /// Tried to extract the amount and currency code from the JSON string. + /// + /// JSON string with the following format: {"amount": "5.99", "currency_code": "CAD"} + /// Return value: the amount extracted from the JSON string. + /// Return value: the currency code extracted from the JSON string. + /// True if no errors occurred during the extraction. + [TryFunction] + internal procedure TryExtractValues(Value: Text; var Amount: Decimal; var CurrencyCode: Code[10]) + var + Currency: Record Currency; + JToken: JsonToken; + JObject: JsonObject; + begin + JObject.ReadFrom(Value); + JObject.SelectToken('amount', JToken); + Amount := JToken.AsValue().AsDecimal(); + JObject.SelectToken('currency_code', JToken); +#pragma warning disable AA0139 + CurrencyCode := JToken.AsValue().AsText(); +#pragma warning restore AA0139 + Currency.Get(CurrencyCode); + + if JObject.Keys.Count() <> 2 then + Error(''); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeMultiText.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeMultiText.Codeunit.al new file mode 100644 index 0000000000..5ddb65e64f --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeMultiText.Codeunit.al @@ -0,0 +1,30 @@ +namespace Microsoft.Integration.Shopify; + +codeunit 30352 "Shpfy Mtfld Type Multi Text" implements "Shpfy IMetafield Type" +{ + procedure HasAssistEdit(): Boolean + begin + exit(true); + end; + + procedure IsValidValue(Value: Text): Boolean + begin + exit(true); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + var + MetafieldAssistEdit: Page "Shpfy Metafield Assist Edit"; + begin + if MetafieldAssistEdit.OpenForMultiLineText(Value) then begin + MetafieldAssistEdit.GetMultiLineText(Value); + exit(true); + end else + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit('Ingredients\Flour\Water\Milk\Eggs'); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeNumDecimal.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeNumDecimal.Codeunit.al new file mode 100644 index 0000000000..7d6b11c8d6 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeNumDecimal.Codeunit.al @@ -0,0 +1,30 @@ +namespace Microsoft.Integration.Shopify; + +using System.Utilities; + +codeunit 30354 "Shpfy Mtfld Type Num Decimal" implements "Shpfy IMetafield Type" +{ + procedure HasAssistEdit(): Boolean + begin + exit(false); + end; + + procedure IsValidValue(Value: Text): Boolean + var + Regex: Codeunit Regex; + begin + // +/-9999999999999.999999999 + exit(Regex.IsMatch(Value, '^[-+]?\d{1,13}(?:\.\d{1,9})?$')); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + begin + Value := Value; + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit('123.45'); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeNumInteger.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeNumInteger.Codeunit.al new file mode 100644 index 0000000000..dbce1c839b --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeNumInteger.Codeunit.al @@ -0,0 +1,37 @@ +namespace Microsoft.Integration.Shopify; + +codeunit 30320 "Shpfy Mtfld Type Num Integer" implements "Shpfy IMetafield Type" +{ + procedure HasAssistEdit(): Boolean + begin + exit(false); + end; + + procedure IsValidValue(Value: Text): Boolean + var + DummyInteger: BigInteger; + MinInt: BigInteger; + MaxInt: BigInteger; + begin + if not Evaluate(DummyInteger, Value, 9) then + exit(false); + + Evaluate(MinInt, '-9007199254740991', 9); + Evaluate(MaxInt, '9007199254740991', 9); + if (DummyInteger < MinInt) or (DummyInteger > MaxInt) then + exit(false); + + exit(true); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + begin + Value := Value; + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit('123'); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypePageRef.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypePageRef.Codeunit.al new file mode 100644 index 0000000000..81401c2ee1 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypePageRef.Codeunit.al @@ -0,0 +1,29 @@ +namespace Microsoft.Integration.Shopify; + +using System.Utilities; + +codeunit 30328 "Shpfy Mtfld Type Page Ref" implements "Shpfy IMetafield Type" +{ + procedure HasAssistEdit(): Boolean + begin + exit(false); + end; + + procedure IsValidValue(Value: Text): Boolean + var + Regex: Codeunit Regex; + begin + exit(Regex.IsMatch(Value, '^gid:\/\/shopify\/OnlinePage\/\d+$')); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + begin + Value := Value; + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit('gid://shopify/OnlinePage/1234567890'); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeProductRef.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeProductRef.Codeunit.al new file mode 100644 index 0000000000..e9c765c5d6 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeProductRef.Codeunit.al @@ -0,0 +1,29 @@ +namespace Microsoft.Integration.Shopify; + +using System.Utilities; + +codeunit 30329 "Shpfy Mtfld Type Product Ref" implements "Shpfy IMetafield Type" +{ + procedure HasAssistEdit(): Boolean + begin + exit(false); + end; + + procedure IsValidValue(Value: Text): Boolean + var + Regex: Codeunit Regex; + begin + exit(Regex.IsMatch(Value, '^gid:\/\/shopify\/Product\/\d+$')); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + begin + Value := Value; + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit('gid://shopify/Product/1234567890'); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeSingleText.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeSingleText.Codeunit.al new file mode 100644 index 0000000000..5a207003f6 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeSingleText.Codeunit.al @@ -0,0 +1,25 @@ +namespace Microsoft.Integration.Shopify; + +codeunit 30323 "Shpfy Mtfld Type Single Text" implements "Shpfy IMetafield Type" +{ + procedure HasAssistEdit(): Boolean + begin + exit(false); + end; + + procedure IsValidValue(Value: Text): Boolean + begin + exit(true); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + begin + Value := Value; + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit('VIP shipping method'); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeString.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeString.Codeunit.al new file mode 100644 index 0000000000..ddb25456f8 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeString.Codeunit.al @@ -0,0 +1,25 @@ +namespace Microsoft.Integration.Shopify; + +codeunit 30337 "Shpfy Mtfld Type String" implements "Shpfy IMetafield Type" +{ + procedure HasAssistEdit(): Boolean + begin + exit(false); + end; + + procedure IsValidValue(Value: Text): Boolean + begin + exit(true); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + begin + Value := Value; + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit('Example'); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeUrl.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeUrl.Codeunit.al new file mode 100644 index 0000000000..bbb87ff1fc --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeUrl.Codeunit.al @@ -0,0 +1,29 @@ +namespace Microsoft.Integration.Shopify; + +using System.Utilities; + +codeunit 30324 "Shpfy Mtfld Type Url" implements "Shpfy IMetafield Type" +{ + procedure HasAssistEdit(): Boolean + begin + exit(false); + end; + + procedure IsValidValue(Value: Text): Boolean + var + Regex: Codeunit Regex; + begin + exit(Regex.IsMatch(Value, '^(http|https|mailto|sms|tel)://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?$')); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + begin + Value := Value; + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit('https://www.shopify.com'); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeVariantRef.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeVariantRef.Codeunit.al new file mode 100644 index 0000000000..e3fe97876d --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeVariantRef.Codeunit.al @@ -0,0 +1,29 @@ +namespace Microsoft.Integration.Shopify; + +using System.Utilities; + +codeunit 30330 "Shpfy Mtfld Type Variant Ref" implements "Shpfy IMetafield Type" +{ + procedure HasAssistEdit(): Boolean + begin + exit(false); + end; + + procedure IsValidValue(Value: Text): Boolean + var + Regex: Codeunit Regex; + begin + exit(Regex.IsMatch(Value, '^gid:\/\/shopify\/Variant\/\d+$')); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + begin + Value := Value; + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit('gid://shopify/Variant/1234567890'); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeVolume.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeVolume.Codeunit.al new file mode 100644 index 0000000000..18faa414ef --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeVolume.Codeunit.al @@ -0,0 +1,72 @@ +namespace Microsoft.Integration.Shopify; + +codeunit 30325 "Shpfy Mtfld Type Volume" implements "Shpfy IMetafield Type" +{ + var + VolumeJsonTemplateTxt: Label '{"value": %1,"unit":"%2"}', Locked = true; + + procedure HasAssistEdit(): Boolean + begin + exit(true); + end; + + procedure IsValidValue(Value: Text): Boolean + var + Volume: Decimal; + Unit: Enum "Shpfy Metafield Volume Type"; + begin + exit(TryExtractValues(Value, Volume, Unit)); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + var + MetafieldAssistEdit: Page "Shpfy Metafield Assist Edit"; + Volume: Decimal; + Unit: Enum "Shpfy Metafield Volume Type"; + begin + if Value <> '' then + if not TryExtractValues(Value, Volume, Unit) then begin + Clear(Volume); + Clear(Unit); + end; + + if MetafieldAssistEdit.OpenForVolume(Volume, Unit) then begin + MetafieldAssistEdit.GetVolumeValue(Volume, Unit); + Value := StrSubstNo(VolumeJsonTemplateTxt, Format(Volume, 0, 9), GetVolumeTypeName(Unit)); + exit(true); + end else + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit(StrSubstNo(VolumeJsonTemplateTxt, '20.0', 'ml')); + end; + + + [TryFunction] + local procedure TryExtractValues(Value: Text; var Volume: Decimal; var Unit: Enum "Shpfy Metafield Volume Type") + var + JToken: JsonToken; + JObject: JsonObject; + begin + JObject.ReadFrom(Value); + JObject.SelectToken('value', JToken); + Volume := JToken.AsValue().AsDecimal(); + JObject.SelectToken('unit', JToken); + Unit := ConvertToVolumeType(JToken.AsValue().AsText()); + + if JObject.Keys.Count() <> 2 then + Error(''); + end; + + local procedure GetVolumeTypeName(VolumeType: Enum "Shpfy Metafield Volume Type"): Text + begin + exit(VolumeType.Names().Get(VolumeType.Ordinals().IndexOf(VolumeType.AsInteger()))); + end; + + local procedure ConvertToVolumeType(Value: Text) Type: Enum "Shpfy Metafield Volume Type" + begin + exit(Enum::"Shpfy Metafield Volume Type".FromInteger(Type.Ordinals().Get(Type.Names().IndexOf(Value)))); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeWeight.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeWeight.Codeunit.al new file mode 100644 index 0000000000..5bf2777206 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IMetafieldType/ShpfyMtfldTypeWeight.Codeunit.al @@ -0,0 +1,72 @@ +namespace Microsoft.Integration.Shopify; + +codeunit 30326 "Shpfy Mtfld Type Weight" implements "Shpfy IMetafield Type" +{ + var + WeightJsonTemplateTxt: Label '{"value": %1,"unit":"%2"}', Locked = true; + + procedure HasAssistEdit(): Boolean + begin + exit(true); + end; + + procedure IsValidValue(Value: Text): Boolean + var + Weight: Decimal; + Unit: Enum "Shpfy Metafield Weight Type"; + begin + exit(TryExtractValues(Value, Weight, Unit)); + end; + + procedure AssistEdit(var Value: Text[2048]): Boolean + var + MetafieldAssistEdit: Page "Shpfy Metafield Assist Edit"; + Weight: Decimal; + Unit: Enum "Shpfy Metafield Weight Type"; + begin + if Value <> '' then + if not TryExtractValues(Value, Weight, Unit) then begin + Clear(Weight); + Clear(Unit); + end; + + if MetafieldAssistEdit.OpenForWeight(Weight, Unit) then begin + MetafieldAssistEdit.GetWeightValue(Weight, Unit); + Value := StrSubstNo(WeightJsonTemplateTxt, Format(Weight, 0, 9), GetWeightTypeName(Unit)); + exit(true); + end else + exit(false); + end; + + procedure GetExampleValue(): Text + begin + exit(StrSubstNo(WeightJsonTemplateTxt, '2.5', 'kg')); + end; + + + [TryFunction] + local procedure TryExtractValues(Value: Text; var Weight: Decimal; var Unit: Enum "Shpfy Metafield Weight Type") + var + JToken: JsonToken; + JObject: JsonObject; + begin + JObject.ReadFrom(Value); + JObject.SelectToken('value', JToken); + Weight := JToken.AsValue().AsDecimal(); + JObject.SelectToken('unit', JToken); + Unit := ConvertToWeightType(JToken.AsValue().AsText()); + + if JObject.Keys.Count() <> 2 then + Error(''); + end; + + local procedure GetWeightTypeName(WeightType: Enum "Shpfy Metafield Weight Type"): Text + begin + exit(WeightType.Names().Get(WeightType.Ordinals().IndexOf(WeightType.AsInteger()))); + end; + + local procedure ConvertToWeightType(Value: Text) Type: Enum "Shpfy Metafield Weight Type" + begin + exit(Enum::"Shpfy Metafield Weight Type".FromInteger(Type.Ordinals().Get(Type.Names().IndexOf(Value)))); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IOwnerType/ShpfyMetafieldOwnerCustomer.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IOwnerType/ShpfyMetafieldOwnerCustomer.Codeunit.al new file mode 100644 index 0000000000..98646f1731 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IOwnerType/ShpfyMetafieldOwnerCustomer.Codeunit.al @@ -0,0 +1,19 @@ +namespace Microsoft.Integration.Shopify; + +codeunit 30333 "Shpfy Metafield Owner Customer" implements "Shpfy IMetafield Owner Type" +{ + procedure GetTableId(): Integer + begin + exit(Database::"Shpfy Customer"); + end; + + procedure RetrieveMetafieldIdsFromShopify(OwnerId: BigInteger): Dictionary of [BigInteger, DateTime] + begin + Error('Not implemented'); + end; + + procedure GetShopCode(OwnerId: BigInteger): Code[20] + begin + exit('Not implemented'); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IOwnerType/ShpfyMetafieldOwnerProduct.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IOwnerType/ShpfyMetafieldOwnerProduct.Codeunit.al new file mode 100644 index 0000000000..3998b83f29 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IOwnerType/ShpfyMetafieldOwnerProduct.Codeunit.al @@ -0,0 +1,42 @@ +namespace Microsoft.Integration.Shopify; + +codeunit 30334 "Shpfy Metafield Owner Product" implements "Shpfy IMetafield Owner Type" +{ + procedure GetTableId(): Integer + begin + exit(Database::"Shpfy Product"); + end; + + procedure RetrieveMetafieldIdsFromShopify(OwnerId: BigInteger) MetafieldIds: Dictionary of [BigInteger, DateTime] + var + CommunicationMgt: Codeunit "Shpfy Communication Mgt."; + JsonHelper: Codeunit "Shpfy Json Helper"; + Parameters: Dictionary of [Text, Text]; + GraphQLType: Enum "Shpfy GraphQL Type"; + JResponse: JsonToken; + JMetafields: JsonArray; + JNode: JsonObject; + JItem: JsonToken; + Id: BigInteger; + UpdatedAt: DateTime; + begin + Parameters.Add('ProductId', Format(OwnerId)); + GraphQLType := GraphQLType::ProductMetafieldIds; + JResponse := CommunicationMgt.ExecuteGraphQL(GraphQLType, Parameters); + if JsonHelper.GetJsonArray(JResponse, JMetafields, 'data.product.metafields.edges') then + foreach JItem in JMetafields do + if JsonHelper.GetJsonObject(JItem.AsObject(), JNode, 'node') then begin + Id := CommunicationMgt.GetIdOfGId(JsonHelper.GetValueAsText(JNode, 'legacyResourceId')); + UpdatedAt := JsonHelper.GetValueAsDateTime(JNode, 'updatedAt'); + MetafieldIds.Add(Id, UpdatedAt); + end; + end; + + procedure GetShopCode(OwnerId: BigInteger): Code[20] + var + Product: Record "Shpfy Product"; + begin + Product.Get(OwnerId); + exit(Product."Shop Code"); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/IOwnerType/ShpfyMetafieldOwnerVariant.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IOwnerType/ShpfyMetafieldOwnerVariant.Codeunit.al new file mode 100644 index 0000000000..3a9ff1e4b0 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/IOwnerType/ShpfyMetafieldOwnerVariant.Codeunit.al @@ -0,0 +1,42 @@ +namespace Microsoft.Integration.Shopify; + +codeunit 30335 "Shpfy Metafield Owner Variant" implements "Shpfy IMetafield Owner Type" +{ + procedure GetTableId(): Integer + begin + exit(Database::"Shpfy Variant"); + end; + + procedure RetrieveMetafieldIdsFromShopify(OwnerId: BigInteger) MetafieldIds: Dictionary of [BigInteger, DateTime] + var + CommunicationMgt: Codeunit "Shpfy Communication Mgt."; + JsonHelper: Codeunit "Shpfy Json Helper"; + Parameters: Dictionary of [Text, Text]; + GraphQLType: Enum "Shpfy GraphQL Type"; + JResponse: JsonToken; + JMetafields: JsonArray; + JNode: JsonObject; + JItem: JsonToken; + Id: BigInteger; + UpdatedAt: DateTime; + begin + Parameters.Add('VariantId', Format(OwnerId)); + GraphQLType := GraphQLType::VariantMetafieldIds; + JResponse := CommunicationMgt.ExecuteGraphQL(GraphQLType, Parameters); + if JsonHelper.GetJsonArray(JResponse, JMetafields, 'data.product.metafields.edges') then + foreach JItem in JMetafields do + if JsonHelper.GetJsonObject(JItem.AsObject(), JNode, 'node') then begin + Id := CommunicationMgt.GetIdOfGId(JsonHelper.GetValueAsText(JNode, 'legacyResourceId')); + UpdatedAt := JsonHelper.GetValueAsDateTime(JNode, 'updatedAt'); + MetafieldIds.Add(Id, UpdatedAt); + end; + end; + + procedure GetShopCode(OwnerId: BigInteger): Code[20] + var + Variant: Record "Shpfy Variant"; + begin + Variant.Get(OwnerId); + exit(Variant."Shop Code"); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Codeunits/ShpfyMetafieldAPI.Codeunit.al b/Apps/W1/Shopify/app/src/Metafields/Codeunits/ShpfyMetafieldAPI.Codeunit.al new file mode 100644 index 0000000000..bd3ba3ad8d --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Codeunits/ShpfyMetafieldAPI.Codeunit.al @@ -0,0 +1,237 @@ +namespace Microsoft.Integration.Shopify; + +codeunit 30316 "Shpfy Metafield API" +{ + Access = Internal; + + var + JsonHelper: Codeunit "Shpfy Json Helper"; + + #region To Shopify + /// + /// Creates or updates the metafields in Shopify. + /// + /// + /// Only metafields that have been updated in BC since last update in Shopify will be updated. + /// MetafieldSet mutation only accepts 25 metafields at a time, so the function will create multiple queries if needed. + /// + /// + /// + internal procedure CreateOrUpdateMetafieldsInShopify(ParentTableId: Integer; OwnerId: BigInteger) + var + TempMetafieldSet: Record "Shpfy Metafield" temporary; + MetafieldIds: Dictionary of [BigInteger, DateTime]; + Continue: Boolean; + Count: Integer; + GraphQuery: TextBuilder; + begin + MetafieldIds := RetrieveMetafieldsFromShopify(ParentTableId, OwnerId); + CollectMetafieldsInBC(ParentTableId, OwnerId, TempMetafieldSet, MetafieldIds); + + // MetafieldsSet mutation only accepts 25 metafields at a time + Continue := true; + if TempMetafieldSet.FindSet() then + while Continue do begin + Count := 0; + Continue := false; + GraphQuery.Clear(); + + repeat + if Count = GetMaxMetafieldsToUpdate() then begin + Continue := true; + Clear(Count); + break; + end; + + CreateMetafieldQuery(TempMetafieldSet, GraphQuery); + Count += 1; + until TempMetafieldSet.Next() = 0; + + UpdateMetafields(GraphQuery.ToText()); + end; + end; + + local procedure GetMaxMetafieldsToUpdate(): Integer + begin + exit(25); + end; + + local procedure RetrieveMetafieldsFromShopify(ParentTableId: Integer; OwnerId: BigInteger): Dictionary of [BigInteger, DateTime] + var + Metafield: Record "Shpfy Metafield"; + IMetafieldOwnerType: Interface "Shpfy IMetafield Owner Type"; + begin + IMetafieldOwnerType := Metafield.GetOwnerType(ParentTableId); + exit(IMetafieldOwnerType.RetrieveMetafieldIdsFromShopify(OwnerId)); + end; + + local procedure CollectMetafieldsInBC(ParentTableId: Integer; OwnerId: BigInteger; var TempMetafieldSet: Record "Shpfy Metafield" temporary; MetafieldIds: Dictionary of [BigInteger, DateTime]) + var + Metafield: Record "Shpfy Metafield"; + UpdatedAt: DateTime; + begin + Metafield.SetRange("Parent Table No.", ParentTableId); + Metafield.SetRange("Owner Id", OwnerId); + if Metafield.FindSet() then + repeat + if MetafieldIds.Get(Metafield.Id, UpdatedAt) then begin + if Metafield."Last Updated by BC" > UpdatedAt then begin + TempMetafieldSet := Metafield; + TempMetafieldSet.Insert(false); + end; + end else begin + TempMetafieldSet := Metafield; + TempMetafieldSet.Insert(false); + end; + until Metafield.Next() = 0; + end; + + /// + /// Updates the metafields in Shopify. + /// + /// GraphQL query for the metafields. + internal procedure UpdateMetafields(MetafieldsQuery: Text) JResponse: JsonToken + var + CommunicationMgt: Codeunit "Shpfy Communication Mgt."; + Parameters: Dictionary of [Text, Text]; + begin + Parameters.Add('Metafields', MetafieldsQuery); + JResponse := CommunicationMgt.ExecuteGraphQL(Enum::"Shpfy GraphQL Type"::MetafieldSet, Parameters); + end; + + /// + /// Creates a GraphQL query for a metafield. + /// + /// Metafield record to create the query for. + /// Return value: TextBuilder to append the query to. + internal procedure CreateMetafieldQuery(MetafieldSet: Record "Shpfy Metafield"; GraphQuery: TextBuilder) + begin + GraphQuery.Append('{'); + GraphQuery.Append('key: \"'); + GraphQuery.Append(MetafieldSet.Name); + GraphQuery.Append('\",'); + GraphQuery.Append('namespace: \"'); + GraphQuery.Append(MetafieldSet."Namespace"); + GraphQuery.Append('\",'); + GraphQuery.Append('ownerId: \"gid://shopify/'); + GraphQuery.Append(MetafieldSet.GetOwnerTypeName()); + GraphQuery.Append('/'); + GraphQuery.Append(Format(MetafieldSet."Owner Id")); + GraphQuery.Append('\",'); + GraphQuery.Append('value: \"'); + GraphQuery.Append(EscapeGrapQLData(MetafieldSet.Value)); + GraphQuery.Append('\",'); + GraphQuery.Append('type: \"'); + GraphQuery.Append(GetTypeName(MetafieldSet.Type)); + GraphQuery.Append('\"'); + GraphQuery.Append('},'); + end; + + local procedure EscapeGrapQLData(Data: Text): Text + begin + exit(Data.Replace('\', '\\\\').Replace('"', '\\\"')); + end; + + local procedure GetTypeName(Type: Enum "Shpfy Metafield Type"): Text + begin + exit(Enum::"Shpfy Metafield Type".Names().Get(Enum::"Shpfy Metafield Type".Ordinals().IndexOf(Type.AsInteger()))); + end; + #endregion + + #region From Shopify + /// + /// Updates the metafields in Business Central from Shopify. + /// + /// + /// Metafields with a value longer than 2048 characters will not be imported. + /// Some metafield types are unsupported in Business Central (i.e. Rating). + /// + /// JSON array of metafields from Shopify. + /// Table id of the parent resource. + /// Id of the parent resource. + internal procedure UpdateMetafieldsFromShopify(JMetafields: JsonArray; ParentTableNo: Integer; OwnerId: BigInteger) + var + JNode: JsonObject; + JItem: JsonToken; + MetafieldIds: List of [BigInteger]; + MetafieldId: BigInteger; + begin + CollectMetafieldIds(OwnerId, MetafieldIds); + + foreach JItem in JMetafields do begin + JsonHelper.GetJsonObject(JItem.AsObject(), JNode, 'node'); + MetafieldId := UpdateMetadataField(ParentTableNo, OwnerId, JNode); + MetafieldIds.Remove(MetafieldId); + end; + + DeleteUnusedMetafields(MetafieldIds); + end; + + local procedure UpdateMetadataField(ParentTableNo: Integer; OwnerId: BigInteger; JNode: JsonObject): BigInteger + var + Metafield: Record "Shpfy Metafield"; + ValueText: Text; + Type: Enum "Shpfy Metafield Type"; + begin + // Shopify has no limit on the length of the value, but Business Central has a limit of 2048 characters. + // If the value is longer than 2048 characters, Metafield is not imported. + ValueText := JsonHelper.GetValueAsText(JNode, 'value'); + if StrLen(ValueText) > MaxStrLen(Metafield.Value) then + exit(0); + + // Some metafield types are unsupported in Business Central (i.e. Rating) + if not ConvertToMetafieldType(JsonHelper.GetValueAsText(JNode, 'type'), Type) then + exit(0); + + + Metafield.Validate("Parent Table No.", ParentTableNo); + Metafield."Owner Id" := OwnerId; + Metafield.Id := JsonHelper.GetValueAsBigInteger(JNode, 'legacyResourceId'); + Metafield.Type := Type; +#pragma warning disable AA0139 + Metafield."Namespace" := JsonHelper.GetValueAsText(JNode, 'namespace'); + Metafield.Name := JsonHelper.GetValueAsText(JNode, 'key'); + Metafield.Value := ValueText; +#pragma warning restore AA0139 + if not Metafield.Modify(false) then + Metafield.Insert(false); + + exit(Metafield.Id); + end; + + local procedure ConvertToMetafieldType(Value: Text; var Type: Enum "Shpfy Metafield Type"): Boolean + var + EnumOrdinal: Integer; + begin + // Some metafield types are unsupported in Business Central (i.e. Rating) + if not Enum::"Shpfy Metafield Type".Ordinals().Get(Enum::"Shpfy Metafield Type".Names().IndexOf(Value), EnumOrdinal) then + exit(false); + + Type := Enum::"Shpfy Metafield Type".FromInteger(EnumOrdinal); + exit(true); + end; + + local procedure CollectMetafieldIds(ProductId: BigInteger; MetafieldIds: List of [BigInteger]) + var + Metafield: Record "Shpfy Metafield"; + begin + MetaField.SetRange("Parent Table No.", Database::"Shpfy Product"); + Metafield.SetRange("Owner Id", ProductId); + if Metafield.FindSet() then + repeat + MetafieldIds.Add(Metafield.Id); + until Metafield.Next() = 0; + end; + + local procedure DeleteUnusedMetafields(MetafieldIds: List of [BigInteger]) + var + Metafield: Record "Shpfy Metafield"; + MetafieldId: BigInteger; + begin + foreach MetafieldId in MetafieldIds do begin + Metafield.Get(MetafieldId); + Metafield.Delete(false); + end; + end; + #endregion +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Enums/ShpfyMetafieldDimensionType.Enum.al b/Apps/W1/Shopify/app/src/Metafields/Enums/ShpfyMetafieldDimensionType.Enum.al new file mode 100644 index 0000000000..1c3c72cb46 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Enums/ShpfyMetafieldDimensionType.Enum.al @@ -0,0 +1,35 @@ +namespace Microsoft.Integration.Shopify; + +enum 30160 "Shpfy Metafield Dimension Type" +{ + Access = Internal; + + value(0; in) + { + Caption = 'in'; + } + + value(1; ft) + { + Caption = 'ft'; + } + + value(2; yd) + { + Caption = 'yd'; + } + value(3; mm) + { + Caption = 'mm'; + } + + value(4; cm) + { + Caption = 'cm'; + } + + value(5; m) + { + Caption = 'm'; + } +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Enums/ShpfyMetafieldOwnerType.Enum.al b/Apps/W1/Shopify/app/src/Metafields/Enums/ShpfyMetafieldOwnerType.Enum.al new file mode 100644 index 0000000000..71d42d21c1 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Enums/ShpfyMetafieldOwnerType.Enum.al @@ -0,0 +1,24 @@ +namespace Microsoft.Integration.Shopify; + +enum 30156 "Shpfy Metafield Owner Type" implements "Shpfy IMetafield Owner Type" +{ + Access = Internal; + + value(0; Customer) + { + Caption = 'Customer'; + Implementation = "Shpfy IMetafield Owner Type" = "Shpfy Metafield Owner Customer"; + } + + value(1; Product) + { + Caption = 'Product'; + Implementation = "Shpfy IMetafield Owner Type" = "Shpfy Metafield Owner Product"; + } + + value(2; ProductVariant) + { + Caption = 'Variant'; + Implementation = "Shpfy IMetafield Owner Type" = "Shpfy Metafield Owner Variant"; + } +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Enums/ShpfyMetafieldType.Enum.al b/Apps/W1/Shopify/app/src/Metafields/Enums/ShpfyMetafieldType.Enum.al new file mode 100644 index 0000000000..b4c21fb5b4 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Enums/ShpfyMetafieldType.Enum.al @@ -0,0 +1,161 @@ +namespace Microsoft.Integration.Shopify; + +/// +/// Enum Shpfy Metafield Type (ID 30159). +/// +enum 30159 "Shpfy Metafield Type" implements "Shpfy IMetafield Type" +{ + Access = Internal; + Caption = 'Shopify Metafield Type'; + + Extensible = false; + + value(0; string) + { + Caption = 'String'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type String"; + } + + value(1; integer) + { + Caption = 'Integer'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type Integer"; + } + + value(2; json) + { + Caption = 'JSON'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type JSON"; + } + + value(3; boolean) + { + Caption = 'True or false'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type Boolean"; + } + + value(4; color) + { + Caption = 'Color'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type Color"; + } + + value(5; date) + { + Caption = 'Date'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type Date"; + } + + value(6; date_time) + { + Caption = 'Date and time'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type DateTime"; + } + + value(7; dimension) + { + Caption = 'Dimension'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type Dimension"; + } + + value(8; money) + { + Caption = 'Money'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type Money"; + } + + value(9; multi_line_text_field) + { + Caption = 'Multi-line text'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type Multi Text"; + } + + value(10; number_decimal) + { + Caption = 'Decimal'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type Num Decimal"; + } + + value(11; number_integer) + { + Caption = 'Integer'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type Num Integer"; + } + + // Intentionally commented out as we are not supporting this type at the moment + // value(12; rating) + // { + // Caption = 'Rating'; + // } + + // Intentionally commented out as we are not supporting this type at the moment + // value(13; rich_text_field) + // { + // Caption = 'Rich text'; + // } + + value(14; single_line_text_field) + { + Caption = 'Single line text'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type Single Text"; + } + + value(15; url) + { + Caption = 'URL'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type URL"; + } + + value(16; volume) + { + Caption = 'Volume'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type Volume"; + } + + value(17; weight) + { + Caption = 'Weight'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type Weight"; + } + value(18; collection_reference) + { + Caption = 'Collection reference'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type Collect. Ref"; + } + + value(19; file_reference) + { + Caption = 'File'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type File Ref"; + } + + value(20; metaobject_reference) + { + Caption = 'Metaobject'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type Metaobj. Ref"; + } + + value(21; mixed_reference) + { + Caption = 'Mixed reference'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type Mixed Ref"; + } + + value(22; page_reference) + { + Caption = 'Page'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type Page Ref"; + } + + value(23; product_reference) + { + Caption = 'Product'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type Product Ref"; + } + + value(24; variant_reference) + { + Caption = 'Variant'; + Implementation = "Shpfy IMetafield Type" = "Shpfy Mtfld Type Variant Ref"; + } +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Base/Enums/ShpfyMetafieldValueType.Enum.al b/Apps/W1/Shopify/app/src/Metafields/Enums/ShpfyMetafieldValueType.Enum.al similarity index 75% rename from Apps/W1/Shopify/app/src/Base/Enums/ShpfyMetafieldValueType.Enum.al rename to Apps/W1/Shopify/app/src/Metafields/Enums/ShpfyMetafieldValueType.Enum.al index dc3bb8acd4..fcf76e44aa 100644 --- a/Apps/W1/Shopify/app/src/Base/Enums/ShpfyMetafieldValueType.Enum.al +++ b/Apps/W1/Shopify/app/src/Metafields/Enums/ShpfyMetafieldValueType.Enum.al @@ -8,6 +8,9 @@ enum 30102 "Shpfy Metafield Value Type" Access = Internal; Caption = 'Shopify Metafield Value Type'; Extensible = false; + ObsoleteState = Pending; + ObsoleteReason = 'Value Type is obsolete in Shopify API. Use Metafield Type instead.'; + ObsoleteTag = '25.0'; value(0; String) { diff --git a/Apps/W1/Shopify/app/src/Metafields/Enums/ShpfyMetafieldVolumeType.Enum.al b/Apps/W1/Shopify/app/src/Metafields/Enums/ShpfyMetafieldVolumeType.Enum.al new file mode 100644 index 0000000000..c1b87eb4ea --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Enums/ShpfyMetafieldVolumeType.Enum.al @@ -0,0 +1,59 @@ +namespace Microsoft.Integration.Shopify; + +enum 30158 "Shpfy Metafield Volume Type" +{ + Access = Internal; + + value(0; ml) + { + Caption = 'ml'; + } + + value(1; cl) + { + Caption = 'cl'; + } + + value(2; l) + { + Caption = 'L'; + } + value(3; m3) + { + Caption = 'm3'; + } + + value(4; us_fl_oz) + { + Caption = 'fl oz'; + } + + value(5; us_pt) + { + Caption = 'pt'; + } + value(6; us_qt) + { + Caption = 'qt'; + } + value(7; us_gal) + { + Caption = 'gal'; + } + value(8; imp_fl_oz) + { + Caption = 'imp fl oz'; + } + value(9; imp_pt) + { + Caption = 'imp pt'; + } + value(10; imp_qt) + { + Caption = 'imp qt'; + } + value(11; imp_gal) + { + Caption = 'imp gal'; + } +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Enums/ShpfyMetafieldWeightType.Enum.al b/Apps/W1/Shopify/app/src/Metafields/Enums/ShpfyMetafieldWeightType.Enum.al new file mode 100644 index 0000000000..2581e24b3a --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Enums/ShpfyMetafieldWeightType.Enum.al @@ -0,0 +1,26 @@ +namespace Microsoft.Integration.Shopify; + +enum 30157 "Shpfy Metafield Weight Type" +{ + Access = Internal; + + value(0; kg) + { + Caption = 'kg'; + } + + value(1; g) + { + Caption = 'g'; + } + + value(2; lb) + { + Caption = 'lb'; + } + + value(3; oz) + { + Caption = 'oz'; + } +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Interfaces/ShpfyIMetafieldOwnerType.Interface.al b/Apps/W1/Shopify/app/src/Metafields/Interfaces/ShpfyIMetafieldOwnerType.Interface.al new file mode 100644 index 0000000000..f11f3540f7 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Interfaces/ShpfyIMetafieldOwnerType.Interface.al @@ -0,0 +1,29 @@ +namespace Microsoft.Integration.Shopify; + +/// +/// Interface used to for metafield operations related to metafield owner resource. +/// +interface "Shpfy IMetafield Owner Type" +{ + Access = Internal; + + /// + /// Returns the table id where the owner record is stored in BC. + /// + /// Table id. + procedure GetTableId(): Integer + + /// + /// Retrieves metafields belonging to the owner resource in a dictionary with the last updated at timestamp. + /// + /// Id of the owner resource. + /// Dictionary of metafield ids and last updated at timestamp. + procedure RetrieveMetafieldIdsFromShopify(OwnerId: BigInteger): Dictionary of [BigInteger, DateTime] + + /// + /// Retrieves the shop code from the owner resource. + /// + /// Id of the owner resource. + /// Shop code. + procedure GetShopCode(OwnerId: BigInteger): Code[20] +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Interfaces/ShpfyIMetafieldType.Interface.al b/Apps/W1/Shopify/app/src/Metafields/Interfaces/ShpfyIMetafieldType.Interface.al new file mode 100644 index 0000000000..47dc65200d --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Interfaces/ShpfyIMetafieldType.Interface.al @@ -0,0 +1,35 @@ +namespace Microsoft.Integration.Shopify; + +/// +/// Interface used for validating and editing values of a Shopify Metafield. +/// +interface "Shpfy IMetafield Type" +{ + Access = Internal; + + /// + /// Determines if Type defines an Assist Edit dialog. + /// + /// True if Type defines an Assist Edit dialog, otherwise false. + procedure HasAssistEdit(): Boolean + + /// + /// Determines if provided value is valid for Type. + /// + /// Value to validate. + /// True if value is valid, otherwise False. + procedure IsValidValue(Value: Text): Boolean + + /// + /// Opens a dialog to assist in editing the value. + /// + /// Value to edit. Value may be modified. + /// True if value was edited, otherwise False. + procedure AssistEdit(var Value: Text[2048]): Boolean + + /// + /// Returns an example value for the Type. + /// + /// Example value. + procedure GetExampleValue(): Text +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Pages/ShpfyMetafieldAssistEdit.Page.al b/Apps/W1/Shopify/app/src/Metafields/Pages/ShpfyMetafieldAssistEdit.Page.al new file mode 100644 index 0000000000..623fcd5ffc --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Pages/ShpfyMetafieldAssistEdit.Page.al @@ -0,0 +1,264 @@ +namespace Microsoft.Integration.Shopify; + +using Microsoft.Finance.Currency; + +page 30164 "Shpfy Metafield Assist Edit" +{ + Caption = 'Metafield Assist Edit'; + PageType = StandardDialog; + ApplicationArea = All; + UsageCategory = Administration; + + layout + { + area(Content) + { + group(MoneyGroup) + { + Visible = IsMoneyVisible; + ShowCaption = false; + + field(MoneyValue; MoneyValue) + { + Caption = 'Value'; + ToolTip = 'Enter the amount.'; + } + field(MoneyCurrency; MoneyCurrency) + { + Caption = 'Currency'; + ToolTip = 'Enter the currency code.'; + TableRelation = Currency; + } + } + group(DimensionGroup) + { + Visible = IsDimensionVisible; + ShowCaption = false; + + field(DimensionValue; DimensionValue) + { + Caption = 'Value'; + ToolTip = 'Enter the value.'; + } + field(DimensionUnit; DimensionUnit) + { + Caption = 'Unit'; + ToolTip = 'Enter the unit of measure.'; + } + } + group(VolumeGroup) + { + Visible = IsVolumeVisible; + ShowCaption = false; + + field(VolumeValue; VolumeValue) + { + Caption = 'Value'; + ToolTip = 'Enter the value.'; + } + field(VolumeUnit; VolumeUnit) + { + Caption = 'Unit'; + ToolTip = 'Enter the unit of measure.'; + } + } + group(WeightGroup) + { + Visible = IsWeightVisible; + ShowCaption = false; + + field(WeightValue; WeightValue) + { + Caption = 'Value'; + ToolTip = 'Enter the value.'; + } + field(WeightUnit; WeightUnit) + { + Caption = 'Unit'; + ToolTip = 'Enter the unit of measure.'; + } + } + group(MultiLineTextGroup) + { + Visible = IsMultiLineTextVisible; + ShowCaption = false; + + field(MultiLineText; MultiLineText) + { + Caption = 'Text'; + ToolTip = 'Enter the text.'; + MultiLine = true; + ExtendedDatatype = RichContent; + + trigger OnValidate() + var + TextTooLongErr: Label 'The text is too long. The maximum length is 2048 characters.'; + begin + if StrLen(MultiLineText) > 2048 then + Error(ErrorInfo.Create(TextTooLongErr)); + end; + } + } + } + } + + #region Money + var + IsMoneyVisible: Boolean; + MoneyValue: Decimal; + MoneyCurrency: Code[10]; + + /// + /// Opens the page for assisting with input of money values. + /// + /// The amount to preset on the page. + /// The currency code to preset on the page. + /// True if the user clicks OK; otherwise, false. + internal procedure OpenForMoney(Amount: Decimal; CurrencyCode: Code[10]): Boolean + begin + IsMoneyVisible := true; + MoneyValue := Amount; + MoneyCurrency := CurrencyCode; + + exit(CurrPage.RunModal() = Action::OK); + end; + + /// + /// Gets the money value and currency code. + /// + /// Return value: The money value. + /// Return value: The currency code. + internal procedure GetMoneyValue(var Amount: Decimal; var Currency: Code[10]) + begin + Amount := MoneyValue; + Currency := MoneyCurrency; + end; + #endregion + + #region Dimension + var + IsDimensionVisible: Boolean; + DimensionValue: Decimal; + DimensionUnit: Enum "Shpfy Metafield Dimension Type"; + + /// + /// Opens the page for assisting with input of dimension values. + /// + /// The dimension to preset on the page. + /// The unit of measure to preset on the page. + /// True if the user clicks OK; otherwise, false. + internal procedure OpenForDimension(Dimension: Decimal; Unit: Enum "Shpfy Metafield Dimension Type"): Boolean + begin + IsDimensionVisible := true; + DimensionValue := Dimension; + DimensionUnit := Unit; + + exit(CurrPage.RunModal() = Action::OK); + end; + + /// + /// Gets the dimension value and unit of measure. + /// + /// Return value: The dimension value. + /// Return value: The unit of measure. + internal procedure GetDimensionValue(var Value: Decimal; var Unit: Enum "Shpfy Metafield Dimension Type") + begin + Value := DimensionValue; + Unit := DimensionUnit; + end; + #endregion + + #region Volume + var + IsVolumeVisible: Boolean; + VolumeValue: Decimal; + VolumeUnit: Enum "Shpfy Metafield Volume Type"; + + /// + /// Opens the page for assisting with input of volume values. + /// + /// The volume to preset on the page. + /// The unit of measure to preset on the page. + /// True if the user clicks OK; otherwise, false. + internal procedure OpenForVolume(Volume: Decimal; Unit: Enum "Shpfy Metafield Volume Type"): Boolean + begin + IsVolumeVisible := true; + VolumeValue := Volume; + VolumeUnit := Unit; + + exit(CurrPage.RunModal() = Action::OK); + end; + + /// + /// Gets the volume value and unit of measure. + /// + /// Return value: The volume value. + /// Return value: The unit of measure. + internal procedure GetVolumeValue(var Volume: Decimal; var Unit: Enum "Shpfy Metafield Volume Type") + begin + Volume := VolumeValue; + Unit := VolumeUnit; + end; + #endregion + + #region Weight + var + IsWeightVisible: Boolean; + WeightValue: Decimal; + WeightUnit: Enum "Shpfy Metafield Weight Type"; + + /// + /// Opens the page for assisting with input of weight values. + /// + /// The weight to preset on the page. + /// The unit of measure to preset on the page. + /// True if the user clicks OK; otherwise, false. + internal procedure OpenForWeight(Weight: Decimal; Unit: Enum "Shpfy Metafield Weight Type"): Boolean + begin + IsWeightVisible := true; + WeightValue := Weight; + WeightUnit := Unit; + + exit(CurrPage.RunModal() = Action::OK); + end; + + /// + /// Gets the weight value and unit of measure. + /// + /// Return value: The weight value. + /// Return value: The unit of measure. + internal procedure GetWeightValue(var Value: Decimal; var Unit: Enum "Shpfy Metafield Weight Type") + begin + Value := WeightValue; + Unit := WeightUnit; + end; + #endregion + + #region MultiLineText + var + IsMultiLineTextVisible: Boolean; + MultiLineText: Text; + + /// + /// Opens the page for assisting with input of multi-line text. + /// + /// The text to preset on the page. + /// True if the user clicks OK; otherwise, false. + internal procedure OpenForMultiLineText(Text: Text[2048]): Boolean + begin + IsMultiLineTextVisible := true; + MultiLineText := Text; + + exit(CurrPage.RunModal() = Action::OK); + end; + + /// + /// Gets the multi-line text. + /// + /// Return value: The multi-line text. + internal procedure GetMultiLineText(var Text: Text[2048]) + begin + Text := CopyStr(MultiLineText, 1, MaxStrLen(Text)); + end; + #endregion +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Pages/ShpfyMetafields.Page.al b/Apps/W1/Shopify/app/src/Metafields/Pages/ShpfyMetafields.Page.al new file mode 100644 index 0000000000..2029380a48 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Pages/ShpfyMetafields.Page.al @@ -0,0 +1,130 @@ +namespace Microsoft.Integration.Shopify; + +/// +/// Page Shpfy Metafields (ID 30163). +/// +page 30163 "Shpfy Metafields" +{ + Caption = 'Shopify Metafields'; + Extensible = false; + PageType = List; + SourceTable = "Shpfy Metafield"; + UsageCategory = None; + ApplicationArea = All; + DelayedInsert = true; + + layout + { + area(Content) + { + repeater(Metafields) + { + Editable = IsPageEditable; + + field(Namespace; Rec.Namespace) + { + ToolTip = 'Specifies the namespace of the metafield.'; + } + field(Type; Rec.Type) + { + ToolTip = 'Specifies the type of value for the metafield.'; + } + field(Name; Rec.Name) + { + ToolTip = 'Specifies the key of the metafield.'; + } + field(Value; Rec.Value) + { + ToolTip = 'Specifies the value of the metafield.'; + Editable = IsValueEditable; + + trigger OnAssistEdit() + var + IMetafieldType: Interface "Shpfy IMetafield Type"; + begin + IMetafieldType := Rec.Type; + + if IMetafieldType.HasAssistEdit() then + if IMetafieldType.AssistEdit(Rec.Value) then + Rec.Validate(Value); + end; + } + } + } + } + + trigger OnNewRecord(BelowxRec: Boolean) + begin + Evaluate(Rec."Parent Table No.", Rec.GetFilter("Parent Table No.")); + Rec.Validate("Parent Table No."); + Evaluate(Rec."Owner Id", Rec.GetFilter("Owner Id")); + end; + + trigger OnAfterGetCurrRecord() + var + IMetafieldType: Interface "Shpfy IMetafield Type"; + begin + IMetafieldType := Rec.Type; + IsValueEditable := not IMetafieldType.HasAssistEdit(); + end; + + trigger OnInsertRecord(BelowxRec: Boolean): Boolean + begin + Rec.TestField(Namespace); + Rec.TestField(Name); + Rec.Validate(Value); + + Rec.Id := SendMetafieldToShopify(); + end; + + var + Shop: Record "Shpfy Shop"; + IsPageEditable: Boolean; + IsValueEditable: Boolean; + + /// + /// Opens the page displaying metafields for the specified resource. + /// + /// Table id of the resource. + /// System Id of the resource. + internal procedure RunForResource(ParentTableId: Integer; OwnerId: BigInteger; ShopCode: Code[20]) + var + Metafield: Record "Shpfy Metafield"; + begin + Shop.Get(ShopCode); + IsPageEditable := (Shop."Sync Item" = Shop."Sync Item"::"To Shopify") and (Shop."Can Update Shopify Products"); + + Metafield.SetRange("Parent Table No.", ParentTableId); + Metafield.SetRange("Owner Id", OwnerId); + + CurrPage.SetTableView(Metafield); + CurrPage.RunModal(); + end; + + local procedure SendMetafieldToShopify(): BigInteger + var + JsonHelper: Codeunit "Shpfy Json Helper"; + MetafieldAPI: Codeunit "Shpfy Metafield API"; + ShpfyCommunicationMgt: Codeunit "Shpfy Communication Mgt."; + UserErrorOnShopifyErr: Label 'Something went wrong while sending the metafield to Shopify. Check Shopify Log Entries for more details.'; + GraphQuery: TextBuilder; + JResponse: JsonToken; + JMetafields: JsonArray; + JUserErrors: JsonArray; + JItem: JsonToken; + begin + ShpfyCommunicationMgt.SetShop(Shop); + + MetafieldAPI.CreateMetafieldQuery(Rec, GraphQuery); + JResponse := MetafieldAPI.UpdateMetafields(GraphQuery.ToText()); + + JsonHelper.GetJsonArray(JResponse, JUserErrors, 'data.metafieldsSet.userErrors'); + + if JUserErrors.Count() = 0 then begin + JsonHelper.GetJsonArray(JResponse, JMetafields, 'data.metafieldsSet.metafields'); + JMetafields.Get(0, JItem); + exit(JsonHelper.GetValueAsBigInteger(JItem, 'legacyResourceId')); + end else + Error(UserErrorOnShopifyErr); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Metafields/Tables/ShpfyMetafield.Table.al b/Apps/W1/Shopify/app/src/Metafields/Tables/ShpfyMetafield.Table.al new file mode 100644 index 0000000000..6e7955daa8 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Metafields/Tables/ShpfyMetafield.Table.al @@ -0,0 +1,219 @@ +namespace Microsoft.Integration.Shopify; + +using Microsoft.Finance.GeneralLedger.Setup; + +/// +/// Table Shpfy Metafield (ID 30101). +/// +table 30101 "Shpfy Metafield" +{ + Access = Internal; + Caption = 'Shopify Metafield'; + DataClassification = CustomerContent; + DrillDownPageId = "Shpfy Metafields"; + LookupPageId = "Shpfy Metafields"; + + fields + { + field(1; Id; BigInteger) + { + Caption = 'Id'; + DataClassification = SystemMetadata; + Editable = false; + } + +#pragma warning disable AS0086 // false positive on extending the field length on internal table + field(2; Namespace; Text[255]) + { + Caption = 'Namespace'; + DataClassification = SystemMetadata; + } +#pragma warning restore AS0086 + + field(3; "Owner Resource"; Text[50]) + { + Caption = 'Owner Resource'; + DataClassification = SystemMetadata; + ObsoleteState = Pending; + ObsoleteReason = 'Owner Resource is obsolete. Use Owner Type instead.'; + ObsoleteTag = '25.0'; + + trigger OnValidate() + begin + case "Owner Resource" of + 'Customer': + Validate("Owner Type", "Owner Type"::Customer); + 'Product': + Validate("Owner Type", "Owner Type"::Product); + 'Variant': + Validate("Owner Type", "Owner Type"::ProductVariant); + end; + end; + } + + field(4; "Owner Id"; BigInteger) + { + Caption = 'Owner Id'; + DataClassification = SystemMetadata; + } + +#pragma warning disable AS0086 // false positive on extending the field length on internal table + field(5; Name; Text[64]) + { + Caption = 'Key'; + DataClassification = CustomerContent; + } +#pragma warning restore AS0086 + + field(6; "Value Type"; Enum "Shpfy Metafield Value Type") + { + Caption = 'Value Type'; + DataClassification = CustomerContent; + ObsoleteState = Pending; + ObsoleteReason = 'Value Type is obsolete in Shopify API. Use Type instead.'; + ObsoleteTag = '25.0'; + } + +#pragma warning disable AS0086 // false positive on extending the field length on internal table + field(7; Value; Text[2048]) + { + Caption = 'Value'; + DataClassification = CustomerContent; + + trigger OnValidate() + var + ValueNotValidErr: Label 'The value is not valid for the type. Example value: '; + IMetafieldType: Interface "Shpfy IMetafield Type"; + begin + IMetafieldType := Rec.Type; + if not IMetafieldType.IsValidValue(Value) then + Error(ErrorInfo.Create(ValueNotValidErr + IMetafieldType.GetExampleValue())); + + if Rec.Type = Rec.Type::money then + CheckShopCurrency(Value); + end; + } +#pragma warning restore AS0086 + field(8; Type; Enum "Shpfy Metafield Type") + { + Caption = 'Type'; + DataClassification = CustomerContent; + } + field(9; "Last Updated by BC"; DateTime) + { + Caption = 'Last Updated by BC'; + DataClassification = SystemMetadata; + } + field(10; "Owner Type"; Enum "Shpfy Metafield Owner Type") + { + Caption = 'Owner Type'; + DataClassification = SystemMetadata; + + trigger OnValidate() + var + IMetafieldOwnerType: Interface "Shpfy IMetafield Owner Type"; + begin + IMetafieldOwnerType := Rec."Owner Type"; + "Parent Table No." := IMetafieldOwnerType.GetTableId(); + end; + } + + field(101; "Parent Table No."; Integer) + { + Caption = 'Parent Table No.'; + DataClassification = SystemMetadata; + Editable = false; + + trigger OnValidate() + begin + "Owner Type" := GetOwnerType("Parent Table No."); + end; + } + } + + keys + { + key(PK; Id) + { + Clustered = true; + } + key(Idx1; "Parent Table No.", "Owner Id") + { + } + } + + trigger OnInsert() + var + Metafield: Record "Shpfy Metafield"; + begin + if Namespace = '' then + Namespace := 'Microsoft.Dynamics365.BusinessCentral'; + if Id = 0 then + if Metafield.FindFirst() and (Metafield.Id < 0) then + Id := Metafield.Id - 1 + else + Id := -1; + end; + + trigger OnModify() + begin + "Last Updated by BC" := CurrentDateTime; + end; + + /// + /// Get the owner type based on the resources's owner table number. + /// + /// The owning resource table number. + internal procedure GetOwnerType(ParentTableNo: Integer): Enum "Shpfy Metafield Owner Type" + begin + case ParentTableNo of + Database::"Shpfy Customer": + exit("Owner Type"::Customer); + Database::"Shpfy Product": + exit("Owner Type"::Product); + Database::"Shpfy Variant": + exit("Owner Type"::ProductVariant); + end; + end; + + /// + /// Returns the name of the enum value for the owner type. Used when the full owner resource id needs to be built. + /// + /// The name of the owner type. + internal procedure GetOwnerTypeName(): Text + begin + exit("Owner Type".Names().Get("Owner Type".Ordinals().IndexOf("Owner Type".AsInteger()))); + end; + + local procedure CheckShopCurrency(MetafieldValue: Text[2048]) + var + ShpfyMtfldTypeMoney: Codeunit "Shpfy Mtfld Type Money"; + CurrencyCode: Code[10]; + ShopCurrencyCode: Code[10]; + Amount: Decimal; + CurrencyCodeMismatchErr: Label 'The currency code must match the shop currency code. Shop currency code: %1', Comment = '%1 - Shop currency code'; + begin + ShopCurrencyCode := GetShopCurrencyCode(); + + ShpfyMtfldTypeMoney.TryExtractValues(MetafieldValue, Amount, CurrencyCode); + if CurrencyCode <> ShopCurrencyCode then + Error(ErrorInfo.Create(StrSubstNo(CurrencyCodeMismatchErr, ShopCurrencyCode))); + end; + + local procedure GetShopCurrencyCode(): Code[10] + var + GeneralLedgerSetup: Record "General Ledger Setup"; + Shop: Record "Shpfy Shop"; + IMetafieldOwnerType: Interface "Shpfy IMetafield Owner Type"; + begin + IMetafieldOwnerType := Rec."Owner Type"; + Shop.Get(IMetafieldOwnerType.GetShopCode(Rec."Owner Id")); + + if Shop."Currency Code" <> '' then + exit(Shop."Currency Code") + else begin + GeneralLedgerSetup.Get(); + exit(GeneralLedgerSetup."LCY Code"); + end; + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Products/Codeunits/ShpfyProductAPI.Codeunit.al b/Apps/W1/Shopify/app/src/Products/Codeunits/ShpfyProductAPI.Codeunit.al index 3878464a4b..2ae6043bf5 100644 --- a/Apps/W1/Shopify/app/src/Products/Codeunits/ShpfyProductAPI.Codeunit.al +++ b/Apps/W1/Shopify/app/src/Products/Codeunits/ShpfyProductAPI.Codeunit.al @@ -564,7 +564,9 @@ codeunit 30176 "Shpfy Product API" /// Return variable "Result" of type Boolean. internal procedure UpdateShopifyProductFields(var ShopifyProduct: record "Shpfy Product"; JProduct: JsonObject) Result: Boolean var + MetafieldAPI: Codeunit "Shpfy Metafield API"; UpdatedAt: DateTime; + JMetafields: JsonArray; begin UpdatedAt := JsonHelper.GetValueAsDateTime(JProduct, 'updatedAt'); if UpdatedAt < ShopifyProduct."Updated At" then @@ -584,7 +586,7 @@ codeunit 30176 "Shpfy Product API" ShopifyProduct."Product Type" := JsonHelper.GetValueAsText(JProduct, 'productType', MaxStrLen(ShopifyProduct."Product Type")); #pragma warning restore AA0139 ShopifyProduct.UpdateTags(JsonHelper.GetArrayAsText(JProduct, 'tags')); -#pragma warning disable AA0139 +#pragma warning disable AA0139 ShopifyProduct.Title := JsonHelper.GetValueAsText(JProduct, 'title', MaxStrLen(ShopifyProduct.Title)); ShopifyProduct.Vendor := JsonHelper.GetValueAsText(JProduct, 'vendor', MaxStrLen(ShopifyProduct.Vendor)); ShopifyProduct."SEO Description" := JsonHelper.GetValueAsText(JProduct, 'seo.description', MaxStrLen(ShopifyProduct."SEO Description")); @@ -592,8 +594,10 @@ codeunit 30176 "Shpfy Product API" #pragma warning restore AA0139 ShopifyProduct.Status := ConvertToProductStatus(JsonHelper.GetValueAsText(JProduct, 'status')); ShopifyProduct.Modify(false); - end; + if JsonHelper.GetJsonArray(JProduct, JMetafields, 'metafields.edges') then + MetafieldAPI.UpdateMetafieldsFromShopify(JMetafields, Database::"Shpfy Product", ShopifyProduct.Id); + end; local procedure ConvertToProductStatus(Value: Text): Enum "Shpfy Product Status" begin diff --git a/Apps/W1/Shopify/app/src/Products/Codeunits/ShpfyProductExport.Codeunit.al b/Apps/W1/Shopify/app/src/Products/Codeunits/ShpfyProductExport.Codeunit.al index 911006d55b..2ac5c9fb87 100644 --- a/Apps/W1/Shopify/app/src/Products/Codeunits/ShpfyProductExport.Codeunit.al +++ b/Apps/W1/Shopify/app/src/Products/Codeunits/ShpfyProductExport.Codeunit.al @@ -693,10 +693,27 @@ codeunit 30178 "Shpfy Product Export" end; until ItemUnitofMeasure.Next() = 0; end; - UpdateProductTranslations(ShopifyProduct.Id, Item) + + UpdateMetafields(ShopifyProduct.Id); + UpdateProductTranslations(ShopifyProduct.Id, Item); end; end; + local procedure UpdateMetafields(ProductId: BigInteger) + var + ShpfyVariant: Record "Shpfy Variant"; + MetafieldAPI: Codeunit "Shpfy Metafield API"; + begin + MetafieldAPI.CreateOrUpdateMetafieldsInShopify(Database::"Shpfy Product", ProductId); + + ShpfyVariant.SetRange("Product Id", ProductId); + ShpfyVariant.ReadIsolation := IsolationLevel::ReadCommitted; + if ShpfyVariant.FindSet() then + repeat + MetafieldAPI.CreateOrUpdateMetafieldsInShopify(Database::"Shpfy Variant", ShpfyVariant.Id); + until ShpfyVariant.Next() = 0; + end; + /// /// Updates a product variant in Shopify. Used when item variant does not exist in BC, but variants per UoM are maintained in Shopify. /// diff --git a/Apps/W1/Shopify/app/src/Products/Codeunits/ShpfyVariantAPI.Codeunit.al b/Apps/W1/Shopify/app/src/Products/Codeunits/ShpfyVariantAPI.Codeunit.al index 340ed848a6..edc6d2ff57 100644 --- a/Apps/W1/Shopify/app/src/Products/Codeunits/ShpfyVariantAPI.Codeunit.al +++ b/Apps/W1/Shopify/app/src/Products/Codeunits/ShpfyVariantAPI.Codeunit.al @@ -500,6 +500,7 @@ codeunit 30189 "Shpfy Variant API" /// Return variable "Result" of type Boolean. internal procedure UpdateShopifyVariantFields(ShopifyProduct: Record "Shpfy Product"; var ShopifyVariant: Record "Shpfy Variant"; var ShopifyInventoryItem: Record "Shpfy Inventory Item"; JVariant: JsonObject) Result: Boolean var + MetafieldAPI: Codeunit "Shpfy Metafield API"; RecordRef: RecordRef; UpdatedAt: DateTime; JMetafields: JsonArray; @@ -595,7 +596,7 @@ codeunit 30189 "Shpfy Variant API" end; if JsonHelper.GetJsonObject(JVariant, JNode, 'metafields') then if JsonHelper.GetJsonArray(JNode, JMetafields, 'edges') then - foreach JItem in JMetafields do; + MetafieldAPI.UpdateMetafieldsFromShopify(JMetafields, Database::"Shpfy Variant", ShopifyVariant.Id); end; /// diff --git a/Apps/W1/Shopify/app/src/Products/Pages/ShpfyProducts.Page.al b/Apps/W1/Shopify/app/src/Products/Pages/ShpfyProducts.Page.al index 29ce2f2628..3635ac301a 100644 --- a/Apps/W1/Shopify/app/src/Products/Pages/ShpfyProducts.Page.al +++ b/Apps/W1/Shopify/app/src/Products/Pages/ShpfyProducts.Page.al @@ -315,6 +315,24 @@ page 30126 "Shpfy Products" Tags.RunModal(); end; } + action(Metafields) + { + ApplicationArea = All; + Caption = 'Metafields'; + Image = PriceAdjustment; + Promoted = true; + PromotedCategory = Process; + PromotedIsBig = true; + PromotedOnly = true; + ToolTip = 'Add metafields to a product. This can be used for adding custom data fields to products in Shopify.'; + + trigger OnAction() + var + Metafields: Page "Shpfy Metafields"; + begin + Metafields.RunForResource(Database::"Shpfy Product", Rec.Id, Rec."Shop Code"); + end; + } group(Sync) { action(SyncProducts) diff --git a/Apps/W1/Shopify/app/src/Products/Pages/ShpfyVariants.Page.al b/Apps/W1/Shopify/app/src/Products/Pages/ShpfyVariants.Page.al index 3291b4e345..39b3107e07 100644 --- a/Apps/W1/Shopify/app/src/Products/Pages/ShpfyVariants.Page.al +++ b/Apps/W1/Shopify/app/src/Products/Pages/ShpfyVariants.Page.al @@ -213,6 +213,20 @@ page 30127 "Shpfy Variants" end; end; } + action(Metafields) + { + ApplicationArea = All; + Caption = 'Metafields'; + Image = PriceAdjustment; + ToolTip = 'Add metafields to a variant. This can be used for adding custom data fields to variants in Shopify.'; + + trigger OnAction() + var + Metafields: Page "Shpfy Metafields"; + begin + Metafields.RunForResource(Database::"Shpfy Variant", Rec.Id, Rec."Shop Code"); + end; + } action(AddItemsAsVariants) { ApplicationArea = All; diff --git a/Apps/W1/Shopify/app/src/Products/Tables/ShpfyProduct.Table.al b/Apps/W1/Shopify/app/src/Products/Tables/ShpfyProduct.Table.al index 751923005f..aa699d3747 100644 --- a/Apps/W1/Shopify/app/src/Products/Tables/ShpfyProduct.Table.al +++ b/Apps/W1/Shopify/app/src/Products/Tables/ShpfyProduct.Table.al @@ -152,6 +152,7 @@ table 30127 "Shpfy Product" var Shop: Record "Shpfy Shop"; ShopifyVariant: Record "Shpfy Variant"; + Metafield: Record "Shpfy Metafield"; IRemoveProduct: Interface "Shpfy IRemoveProductAction"; begin if Shop.Get(Rec."Shop Code") then begin @@ -161,6 +162,11 @@ table 30127 "Shpfy Product" ShopifyVariant.SetRange("Product Id", Id); if not ShopifyVariant.IsEmpty then ShopifyVariant.DeleteAll(true); + + Metafield.SetRange("Parent Table No.", Database::"Shpfy Product"); + Metafield.SetRange("Owner Id", Id); + if not Metafield.IsEmpty then + Metafield.DeleteAll(); end; /// diff --git a/Apps/W1/Shopify/app/src/Products/Tables/ShpfyVariant.Table.al b/Apps/W1/Shopify/app/src/Products/Tables/ShpfyVariant.Table.al index 85032e64c5..500f760cbd 100644 --- a/Apps/W1/Shopify/app/src/Products/Tables/ShpfyVariant.Table.al +++ b/Apps/W1/Shopify/app/src/Products/Tables/ShpfyVariant.Table.al @@ -192,9 +192,15 @@ table 30129 "Shpfy Variant" trigger OnDelete() var InventoryItem: Record "Shpfy Inventory Item"; + Metafield: Record "Shpfy Metafield"; begin InventoryItem.SetRange("Variant Id", Id); if not InventoryItem.IsEmpty then InventoryItem.DeleteAll(); + + Metafield.SetRange("Parent Table No.", Database::"Shpfy Variant"); + Metafield.SetRange("Owner Id", Id); + if not Metafield.IsEmpty then + Metafield.DeleteAll(); end; }