diff --git a/Apps/W1/Shopify/app/src/Base/Pages/ShpfyShopCard.Page.al b/Apps/W1/Shopify/app/src/Base/Pages/ShpfyShopCard.Page.al index 6c4dc6948d..943ceb4aed 100644 --- a/Apps/W1/Shopify/app/src/Base/Pages/ShpfyShopCard.Page.al +++ b/Apps/W1/Shopify/app/src/Base/Pages/ShpfyShopCard.Page.al @@ -410,6 +410,11 @@ page 30101 "Shpfy Shop Card" ApplicationArea = All; ToolTip = 'Specifies how to map companies.'; } + field("Shpfy Comp.Tax Id Mapping"; Rec."Shpfy Comp. Tax Id Mapping") + { + ApplicationArea = All; + ToolTip = 'Specifies how to map Shopify Tax ID with Business Central.'; + } field("Auto Create Unknown Companies"; Rec."Auto Create Unknown Companies") { ApplicationArea = All; diff --git a/Apps/W1/Shopify/app/src/Base/Tables/ShpfyShop.Table.al b/Apps/W1/Shopify/app/src/Base/Tables/ShpfyShop.Table.al index c7713c2ace..5e668203a5 100644 --- a/Apps/W1/Shopify/app/src/Base/Tables/ShpfyShop.Table.al +++ b/Apps/W1/Shopify/app/src/Base/Tables/ShpfyShop.Table.al @@ -793,6 +793,11 @@ table 30102 "Shpfy Shop" Caption = 'Weight Unit'; DataClassification = CustomerContent; } + field(130; "Shpfy Comp. Tax Id Mapping"; Enum "Shpfy Comp. Tax Id Mapping") + { + Caption = 'Company Tax Id Mapping'; + DataClassification = CustomerContent; + } field(200; "Shop Id"; Integer) { DataClassification = SystemMetadata; diff --git a/Apps/W1/Shopify/app/src/Catalogs/Codeunits/ShpfyCatalogAPI.Codeunit.al b/Apps/W1/Shopify/app/src/Catalogs/Codeunits/ShpfyCatalogAPI.Codeunit.al index f329bb41b0..7ba2e40e1f 100644 --- a/Apps/W1/Shopify/app/src/Catalogs/Codeunits/ShpfyCatalogAPI.Codeunit.al +++ b/Apps/W1/Shopify/app/src/Catalogs/Codeunits/ShpfyCatalogAPI.Codeunit.al @@ -1,6 +1,7 @@ namespace Microsoft.Integration.Shopify; using Microsoft.Finance.GeneralLedger.Setup; +using Microsoft.Sales.Customer; /// /// Codeunit Shpfy Catalog API (ID 30290). @@ -15,7 +16,7 @@ codeunit 30290 "Shpfy Catalog API" JsonHelper: Codeunit "Shpfy Json Helper"; ShopifyCatalogURLLbl: Label 'https://admin.shopify.com/store/%1/catalogs/%2/editor', Comment = '%1 - Shop Name, %2 - Catalog Id', Locked = true; - internal procedure CreateCatalog(ShopifyCompany: Record "Shpfy Company") + internal procedure CreateCatalog(ShopifyCompany: Record "Shpfy Company"; Customer: Record Customer) var Catalog: Record "Shpfy Catalog"; GraphQLType: Enum "Shpfy GraphQL Type"; @@ -32,6 +33,7 @@ codeunit 30290 "Shpfy Catalog API" Catalog."Shop Code" := Shop.Code; Catalog.Name := ShopifyCompany.Name; Catalog."Company SystemId" := ShopifyCompany.SystemId; + Catalog."Customer No." := Customer."No."; Catalog.Insert(); CreatePublication(Catalog); CreatePriceList(Catalog); diff --git a/Apps/W1/Shopify/app/src/Catalogs/Pages/ShpfyCatalogs.Page.al b/Apps/W1/Shopify/app/src/Catalogs/Pages/ShpfyCatalogs.Page.al index d0b0dd7dba..7d203d999f 100644 --- a/Apps/W1/Shopify/app/src/Catalogs/Pages/ShpfyCatalogs.Page.al +++ b/Apps/W1/Shopify/app/src/Catalogs/Pages/ShpfyCatalogs.Page.al @@ -28,7 +28,7 @@ page 30159 "Shpfy Catalogs" field("Customer No."; Rec."Customer No.") { ApplicationArea = All; - Visible = false; + Editable = false; ToolTip = 'Specifies the customer''s no. When Customer No. is Selected: Parameters like ''Customer Discount Group'', ''Customer Price Group'', and ''Allow Line Discount'' on the customer card take precedence over catalog settings'; } field(Name; Rec.Name) diff --git a/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompByDefaultComp.Codeunit.al b/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompByDefaultComp.Codeunit.al index 8466a6ab88..5262bc6985 100644 --- a/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompByDefaultComp.Codeunit.al +++ b/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompByDefaultComp.Codeunit.al @@ -1,9 +1,11 @@ namespace Microsoft.Integration.Shopify; +using Microsoft.Sales.Customer; + /// /// Codeunit Shpfy Comp. By Default Comp. (ID 30305) implements Interface Shpfy ICompany Mapping. /// -codeunit 30305 "Shpfy Comp. By Default Comp." implements "Shpfy ICompany Mapping" +codeunit 30305 "Shpfy Comp. By Default Comp." implements "Shpfy ICompany Mapping", "Shpfy IFind Company Mapping" { Access = Internal; @@ -15,4 +17,35 @@ codeunit 30305 "Shpfy Comp. By Default Comp." implements "Shpfy ICompany Mapping Shop.Get(ShopCode); exit(Shop."Default Company No."); end; + + internal procedure FindMapping(var ShopifyCompany: Record "Shpfy Company"; var TempShopifyCustomer: Record "Shpfy Customer" temporary): Boolean + var + Customer: Record Customer; + ShopifyCustomer: Record "Shpfy Customer"; + begin + if not IsNullGuid(ShopifyCompany."Customer SystemId") then + if Customer.GetBySystemId(ShopifyCompany."Customer SystemId") then + exit(true) + else begin + Clear(ShopifyCompany."Customer SystemId"); + ShopifyCompany.Modify(true); + end; + + if IsNullGuid(ShopifyCompany."Customer SystemId") then begin + Shop.Get(ShopifyCompany."Shop Code"); + if Customer.Get(Shop."Default Company No.") then begin + ShopifyCompany."Customer SystemId" := Customer.SystemId; + + if not ShopifyCustomer.Get(TempShopifyCustomer.Id) then begin + ShopifyCustomer.Copy(TempShopifyCustomer); + ShopifyCustomer."Customer SystemId" := Customer.SystemId; + ShopifyCustomer.Insert(true); + end; + + ShopifyCompany."Main Contact Customer Id" := ShopifyCustomer.Id; + ShopifyCompany.Modify(true); + exit(true); + end; + end; + end; } \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompByEmailPhone.Codeunit.al b/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompByEmailPhone.Codeunit.al index 0b90854534..9a65e4a13b 100644 --- a/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompByEmailPhone.Codeunit.al +++ b/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompByEmailPhone.Codeunit.al @@ -1,9 +1,11 @@ namespace Microsoft.Integration.Shopify; +using Microsoft.Sales.Customer; + /// /// Codeunit ShoShpfypify Comp. By Email/Phone (ID 30304) implements Interface Shpfy ICompany Mapping. /// -codeunit 30304 "Shpfy Comp. By Email/Phone" implements "Shpfy ICompany Mapping" +codeunit 30304 "Shpfy Comp. By Email/Phone" implements "Shpfy ICompany Mapping", "Shpfy IFind Company Mapping" { Access = Internal; @@ -11,20 +13,39 @@ codeunit 30304 "Shpfy Comp. By Email/Phone" implements "Shpfy ICompany Mapping" var ShopifyCompany: Record "Shpfy Company"; begin - ShopifyCompany.SetAutoCalcFields("Customer No."); if ShopifyCompany.Get(CompanyId) then begin if not IsNullGuid(ShopifyCompany."Customer SystemId") then begin ShopifyCompany.CalcFields("Customer No."); if ShopifyCompany."Customer No." = '' then begin Clear(ShopifyCompany."Customer SystemId"); - ShopifyCompany.Modify(); + ShopifyCompany.Modify(true); end else exit(ShopifyCompany."Customer No."); end; exit(CreateCompany(CompanyId, ShopCode, TemplateCode, AllowCreate)); end else exit(CreateCompany(CompanyId, ShopCode, TemplateCode, AllowCreate)); - exit(''); + end; + + internal procedure FindMapping(var ShopifyCompany: Record "Shpfy Company"; var TempShopifyCustomer: Record "Shpfy Customer" temporary): Boolean + var + Customer: Record Customer; + begin + if not IsNullGuid(ShopifyCompany."Customer SystemId") then + if Customer.GetBySystemId(ShopifyCompany."Customer SystemId") then + exit(true) + else begin + Clear(ShopifyCompany."Customer SystemId"); + ShopifyCompany.Modify(true); + end; + + if IsNullGuid(ShopifyCompany."Customer SystemId") then begin + if TempShopifyCustomer.Email <> '' then + exit(FindByEmail(ShopifyCompany, TempShopifyCustomer)); + + if TempShopifyCustomer."Phone No." <> '' then + exit(FindByPhoneNo(ShopifyCompany, TempShopifyCustomer)); + end; end; local procedure CreateCompany(CompanyId: BigInteger; ShopCode: Code[20]; TemplateCode: Code[20]; AllowCreate: Boolean): Code[20] @@ -37,11 +58,61 @@ codeunit 30304 "Shpfy Comp. By Email/Phone" implements "Shpfy ICompany Mapping" CompanyImport.SetAllowCreate(AllowCreate); CompanyImport.SetTemplateCode(TemplateCode); TempCompany.Id := CompanyId; - TempCompany.Insert(); + TempCompany.Insert(false); + CompanyImport.Run(TempCompany); CompanyImport.GetCompany(ShopifyCompany); if ShopifyCompany.Find() then ShopifyCompany.CalcFields("Customer No."); + exit(ShopifyCompany."Customer No."); end; + + local procedure FindByEmail(var ShopifyCompany: Record "Shpfy Company"; TempShopifyCustomer: Record "Shpfy Customer" temporary): Boolean + var + Customer: Record Customer; + ShopifyCustomer: Record "Shpfy Customer"; + begin + Customer.SetFilter("E-Mail", '@' + TempShopifyCustomer.Email); + if Customer.FindFirst() then begin + ShopifyCompany."Customer SystemId" := Customer.SystemId; + + if not ShopifyCustomer.Get(TempShopifyCustomer.Id) then begin + ShopifyCustomer.Copy(TempShopifyCustomer); + ShopifyCustomer."Customer SystemId" := Customer.SystemId; + ShopifyCustomer.Insert(true); + end; + + ShopifyCompany."Main Contact Customer Id" := ShopifyCustomer.Id; + ShopifyCompany.Modify(true); + exit(true); + end; + end; + + local procedure FindByPhoneNo(var ShopifyCompany: Record "Shpfy Company"; TempShopifyCustomer: Record "Shpfy Customer" temporary): Boolean + var + Customer: Record Customer; + ShopifyCustomer: Record "Shpfy Customer"; + CustomerMapping: Codeunit "Shpfy Customer Mapping"; + PhoneFilter: Text; + begin + PhoneFilter := CustomerMapping.CreatePhoneFilter(TempShopifyCustomer."Phone No."); + if PhoneFilter <> '' then begin + Clear(Customer); + Customer.SetFilter("Phone No.", PhoneFilter); + if Customer.FindFirst() then begin + ShopifyCompany."Customer SystemId" := Customer.SystemId; + + if not ShopifyCustomer.Get(TempShopifyCustomer.Id) then begin + ShopifyCustomer.Copy(TempShopifyCustomer); + ShopifyCustomer."Customer SystemId" := Customer.SystemId; + ShopifyCustomer.Insert(true); + end; + + ShopifyCompany."Main Contact Customer Id" := ShopifyCustomer.Id; + ShopifyCompany.Modify(true); + exit(true); + end; + end; + end; } \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompByTaxId.Codeunit.al b/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompByTaxId.Codeunit.al new file mode 100644 index 0000000000..9c5d293d1d --- /dev/null +++ b/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompByTaxId.Codeunit.al @@ -0,0 +1,96 @@ +namespace Microsoft.Integration.Shopify; + +using Microsoft.Sales.Customer; + +/// +/// Codeunit Shpfy Comp. By Tax Id (ID 30366) implements Interface Shpfy ICompany Mapping. +/// +codeunit 30366 "Shpfy Comp. By Tax Id" implements "Shpfy ICompany Mapping", "Shpfy IFind Company Mapping" +{ + Access = Internal; + + internal procedure DoMapping(CompanyId: BigInteger; ShopCode: Code[20]; TemplateCode: Code[20]; AllowCreate: Boolean): Code[20] + var + ShopifyCompany: Record "Shpfy Company"; + begin + if ShopifyCompany.Get(CompanyId) then begin + if not IsNullGuid(ShopifyCompany."Customer SystemId") then begin + ShopifyCompany.CalcFields("Customer No."); + if ShopifyCompany."Customer No." = '' then begin + Clear(ShopifyCompany."Customer SystemId"); + ShopifyCompany.Modify(true); + end else + exit(ShopifyCompany."Customer No."); + end; + exit(CreateCompany(CompanyId, ShopCode, TemplateCode, AllowCreate)); + end else + exit(CreateCompany(CompanyId, ShopCode, TemplateCode, AllowCreate)); + end; + + internal procedure FindMapping(var ShopifyCompany: Record "Shpfy Company"; var TempShopifyCustomer: Record "Shpfy Customer" temporary): Boolean + var + Customer: Record Customer; + CompanyLocation: Record "Shpfy Company Location"; + begin + if not IsNullGuid(ShopifyCompany."Customer SystemId") then + if Customer.GetBySystemId(ShopifyCompany."Customer SystemId") then + exit(true) + else begin + Clear(ShopifyCompany."Customer SystemId"); + ShopifyCompany.Modify(true); + end; + + if IsNullGuid(ShopifyCompany."Customer SystemId") then + if ShopifyCompany."Location Id" <> 0 then begin + CompanyLocation.Get(ShopifyCompany."Location Id"); + if CompanyLocation."Tax Registration Id" <> '' then + exit(FindByTaxRegistrationId(ShopifyCompany, TempShopifyCustomer, CompanyLocation)); + end; + end; + + local procedure CreateCompany(CompanyId: BigInteger; ShopCode: Code[20]; TemplateCode: Code[20]; AllowCreate: Boolean): Code[20] + var + ShopifyCompany: Record "Shpfy Company"; + TempShopifyCompany: Record "Shpfy Company" temporary; + CompanyImport: Codeunit "Shpfy Company Import"; + begin + CompanyImport.SetShop(ShopCode); + CompanyImport.SetAllowCreate(AllowCreate); + CompanyImport.SetTemplateCode(TemplateCode); + TempShopifyCompany.Id := CompanyId; + TempShopifyCompany.Insert(false); + + CompanyImport.Run(TempShopifyCompany); + CompanyImport.GetCompany(ShopifyCompany); + if ShopifyCompany.Find() then + ShopifyCompany.CalcFields("Customer No."); + + exit(ShopifyCompany."Customer No."); + end; + + local procedure FindByTaxRegistrationId(var ShopifyCompany: Record "Shpfy Company"; var TempShopifyCustomer: Record "Shpfy Customer" temporary; CompanyLocation: Record "Shpfy Company Location"): Boolean + var + Customer: Record Customer; + ShopifyCustomer: Record "Shpfy Customer"; + Shop: Record "Shpfy Shop"; + TaxRegistrationIdMapping: Interface "Shpfy Tax Registration Id Mapping"; + begin + Clear(Customer); + Shop.Get(ShopifyCompany."Shop Code"); + TaxRegistrationIdMapping := Shop."Shpfy Comp. Tax Id Mapping"; + TaxRegistrationIdMapping.SetMappingFiltersForCustomers(Customer, CompanyLocation); + if Customer.FindFirst() then begin + ShopifyCompany."Customer SystemId" := Customer.SystemId; + + if not ShopifyCustomer.Get(TempShopifyCustomer.Id) then begin + ShopifyCustomer.Copy(TempShopifyCustomer); + ShopifyCustomer."Customer SystemId" := Customer.SystemId; + ShopifyCustomer.Insert(true); + end; + + ShopifyCompany."Main Contact Customer Id" := ShopifyCustomer.Id; + ShopifyCompany.Modify(true); + exit(true); + end; + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompanyAPI.Codeunit.al b/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompanyAPI.Codeunit.al index 29ae5cccef..bf62c2c74d 100644 --- a/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompanyAPI.Codeunit.al +++ b/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompanyAPI.Codeunit.al @@ -24,7 +24,7 @@ codeunit 30286 "Shpfy Company API" CompanyContactId: BigInteger; CompanyContactRoles: Dictionary of [Text, BigInteger]; begin - GraphQuery := CreateCompanyGraphQLQuery(ShopifyCompany, CompanyLocation); + GraphQuery := CreateCompanyGraphQLQuery(ShopifyCompany, CompanyLocation, ShopifyCustomer); JResponse := CommunicationMgt.ExecuteGraphQL(GraphQuery); if JResponse.SelectToken('$.data.companyCreate.company', JItem) then if JItem.IsObject then begin @@ -69,6 +69,10 @@ codeunit 30286 "Shpfy Company API" GraphQuery := CreateGraphQueryUpdateLocation(CompanyLocation); if GraphQuery <> '' then JResponse := CommunicationMgt.ExecuteGraphQL(GraphQuery); + + UpdateCompanyLocationTaxId(CompanyLocation); + + UpdateCompanyLocationPaymentTerms(CompanyLocation); end; internal procedure SetShop(ShopifyShop: Record "Shpfy Shop") @@ -97,18 +101,24 @@ codeunit 30286 "Shpfy Company API" exit(true); end; - internal procedure CreateCompanyGraphQLQuery(var ShopifyCompany: Record "Shpfy Company"; CompanyLocation: Record "Shpfy Company Location"): Text + internal procedure CreateCompanyGraphQLQuery(var ShopifyCompany: Record "Shpfy Company"; CompanyLocation: Record "Shpfy Company Location"; ShopifyCustomer: Record "Shpfy Customer"): Text var GraphQuery: TextBuilder; + PaymentTermsTemplateIdTxt: Label 'gid://shopify/PaymentTermsTemplate/%1', Comment = '%1 = Payment Terms Template Id', Locked = true; begin GraphQuery.Append('{"query":"mutation {companyCreate(input: {company: {'); if ShopifyCompany.Name <> '' then AddFieldToGraphQuery(GraphQuery, 'name', ShopifyCompany.Name); + ShopifyCustomer.CalcFields("Customer No."); + if ShopifyCustomer."Customer No." <> '' then + AddFieldToGraphQuery(GraphQuery, 'externalId', ShopifyCustomer."Customer No."); GraphQuery.Remove(GraphQuery.Length - 1, 2); GraphQuery.Append('}, companyLocation: {billingSameAsShipping: true,'); AddFieldToGraphQuery(GraphQuery, 'name', CompanyLocation.Name); if CompanyLocation."Phone No." <> '' then AddFieldToGraphQuery(GraphQuery, 'phone', CompanyLocation."Phone No."); + if CompanyLocation."Tax Registration Id" <> '' then + AddFieldToGraphQuery(GraphQuery, 'taxRegistrationId', CompanyLocation."Tax Registration Id"); GraphQuery.Append('shippingAddress: {'); AddFieldToGraphQuery(GraphQuery, 'address1', CompanyLocation.Address); if CompanyLocation."Address 2" <> '' then @@ -123,6 +133,10 @@ codeunit 30286 "Shpfy Company API" AddFieldToGraphQuery(GraphQuery, 'countryCode', CompanyLocation."Country/Region Code", false); if CompanyLocation."Province Code" <> '' then AddFieldToGraphQuery(GraphQuery, 'zoneCode', CompanyLocation."Province Code"); + if CompanyLocation."Shpfy Payment Terms Id" <> 0 then begin + GraphQuery.Append('}, buyerExperienceConfiguration: {'); + AddFieldToGraphQuery(GraphQuery, 'paymentTermsTemplateId', StrSubstNo(PaymentTermsTemplateIdTxt, CompanyLocation."Shpfy Payment Terms Id")); + end; GraphQuery.Remove(GraphQuery.Length - 1, 2); GraphQuery.Append('}}}) {company {id, name, locations(first: 1) {edges {node {id, name}}}, contactRoles(first:10) {edges {node {id,name}}}}, userErrors {field, message}}}"}'); exit(GraphQuery.ToText()); @@ -217,6 +231,36 @@ codeunit 30286 "Shpfy Company API" end; end; + internal procedure UpdateCompanyLocationTaxId(var CompanyLocation: Record "Shpfy Company Location") + var + xCompanyLocation: Record "Shpfy Company Location"; + GraphQLType: Enum "Shpfy GraphQL Type"; + Parameters: Dictionary of [Text, Text]; + begin + xCompanyLocation.Get(CompanyLocation.Id); + if CompanyLocation."Tax Registration Id" = xCompanyLocation."Tax Registration Id" then + exit; + + Parameters.Add('LocationId', Format(CompanyLocation.Id)); + Parameters.Add('TaxId', Format(CompanyLocation."Tax Registration Id")); + CommunicationMgt.ExecuteGraphQL(GraphQLType::CreateCompanyLocationTaxId, Parameters); + end; + + internal procedure UpdateCompanyLocationPaymentTerms(var CompanyLocation: Record "Shpfy Company Location") + var + xCompanyLocation: Record "Shpfy Company Location"; + GraphQLType: Enum "Shpfy GraphQL Type"; + Parameters: Dictionary of [Text, Text]; + begin + xCompanyLocation.Get(CompanyLocation.Id); + if CompanyLocation."Shpfy Payment Terms Id" = xCompanyLocation."Shpfy Payment Terms Id" then + exit; + + Parameters.Add('LocationId', Format(CompanyLocation.Id)); + Parameters.Add('PaymentTermsId', Format(CompanyLocation."Shpfy Payment Terms Id")); + CommunicationMgt.ExecuteGraphQL(GraphQLType::UpdateCompanyLocationPaymentTerms, Parameters); + end; + internal procedure RetrieveShopifyCompanyIds(var CompanyIds: Dictionary of [BigInteger, DateTime]) var Id: BigInteger; @@ -293,12 +337,8 @@ codeunit 30286 "Shpfy Company API" internal procedure UpdateShopifyCompanyFields(var ShopifyCompany: Record "Shpfy Company"; JCompany: JsonObject) Result: Boolean var - CompanyLocation: Record "Shpfy Company Location"; UpdatedAt: DateTime; - JLocations: JsonArray; - JItem: JsonToken; OutStream: OutStream; - PhoneNo: Text; begin UpdatedAt := JsonHelper.GetValueAsDateTime(JCompany, 'updatedAt'); if UpdatedAt <= ShopifyCompany."Updated At" then @@ -317,32 +357,78 @@ codeunit 30286 "Shpfy Company API" end else Clear(ShopifyCompany.Note); ShopifyCompany.Modify(); + end; - if JsonHelper.GetJsonArray(JCompany, JLocations, 'locations.edges') then - if JLocations.Count = 1 then - if JLocations.Get(0, JItem) then begin - ShopifyCompany."Location Id" := CommunicationMgt.GetIdOfGId(JsonHelper.GetValueAsText(JItem, 'node.id')); - - CompanyLocation.SetRange(Id, ShopifyCompany."Location Id"); - if not CompanyLocation.FindFirst() then begin - CompanyLocation.Id := ShopifyCompany."Location Id"; - CompanyLocation."Company SystemId" := ShopifyCompany.SystemId; - CompanyLocation.Name := CopyStr(JsonHelper.GetValueAsText(JItem, 'node.name'), 1, MaxStrLen(CompanyLocation.Name)); - CompanyLocation.Insert(); - end; + internal procedure UpdateShopifyCompanyLocation(var ShopifyCompany: Record "Shpfy Company") + var + GraphQLType: Enum "Shpfy GraphQL Type"; + Parameters: Dictionary of [Text, Text]; + JResponse: JsonToken; + Cursor: Text; + IsDefaultCompanyLocation: Boolean; + begin + GraphQLType := "Shpfy GraphQL Type"::GetCompanyLocations; + Parameters.Add('CompanyId', Format(ShopifyCompany.Id)); + IsDefaultCompanyLocation := true; + repeat + JResponse := CommunicationMgt.ExecuteGraphQL(GraphQLType, Parameters); + if JResponse.IsObject() then + if ExtractShopifyCompanyLocations(ShopifyCompany, JResponse.AsObject(), Cursor, IsDefaultCompanyLocation) then begin + if Parameters.ContainsKey('After') then + Parameters.Set('After', Cursor) + else + Parameters.Add('After', Cursor); + GraphQLType := "Shpfy GraphQL Type"::GetNextCompanyLocations; + end else + break; + until not JsonHelper.GetValueAsBoolean(JResponse, 'data.companyLocations.pageInfo.hasNextPage'); + end; + + local procedure ExtractShopifyCompanyLocations(var ShopifyCompany: Record "Shpfy Company"; JResponse: JsonObject; var Cursor: Text; var IsDefaultCompanyLocation: Boolean): Boolean + var + CompanyLocation: Record "Shpfy Company Location"; + JLocations: JsonArray; + JLocation: JsonToken; + PhoneNo: Text; + CompanyLocationId: BigInteger; + begin + if JsonHelper.GetJsonArray(JResponse, JLocations, 'data.companyLocations.edges') then begin + foreach JLocation in JLocations do begin + Cursor := JsonHelper.GetValueAsText(JLocation.AsObject(), 'cursor'); + CompanyLocationId := CommunicationMgt.GetIdOfGId(JsonHelper.GetValueAsText(JLocation, 'node.id')); + if IsDefaultCompanyLocation then + ShopifyCompany."Location Id" := CompanyLocationId; + + CompanyLocation.SetRange(Id, CompanyLocationId); + if not CompanyLocation.FindFirst() then begin + CompanyLocation.Init(); + CompanyLocation.Id := CompanyLocationId; + CompanyLocation."Company SystemId" := ShopifyCompany.SystemId; + CompanyLocation.Name := CopyStr(JsonHelper.GetValueAsText(JLocation, 'node.name'), 1, MaxStrLen(CompanyLocation.Name)); + CompanyLocation.Insert(true); + end; - CompanyLocation.Address := CopyStr(JsonHelper.GetValueAsText(JItem, 'node.billingAddress.address1', MaxStrLen(CompanyLocation.Address)), 1, MaxStrLen(CompanyLocation.Address)); - CompanyLocation."Address 2" := CopyStr(JsonHelper.GetValueAsText(JItem, 'node.billingAddress.address2', MaxStrLen(CompanyLocation."Address 2")), 1, MaxStrLen(CompanyLocation."Address 2")); - CompanyLocation.Zip := CopyStr(JsonHelper.GetValueAsCode(JItem, 'node.billingAddress.zip', MaxStrLen(CompanyLocation.Zip)), 1, MaxStrLen(CompanyLocation.Zip)); - CompanyLocation.City := CopyStr(JsonHelper.GetValueAsText(JItem, 'node.billingAddress.city', MaxStrLen(CompanyLocation.City)), 1, MaxStrLen(CompanyLocation.City)); - CompanyLocation."Country/Region Code" := CopyStr(JsonHelper.GetValueAsCode(JItem, 'node.billingAddress.countryCode', MaxStrLen(CompanyLocation."Country/Region Code")), 1, MaxStrLen(CompanyLocation."Country/Region Code")); - CompanyLocation."Province Code" := CopyStr(JsonHelper.GetValueAsText(JItem, 'node.billingAddress.zoneCode', MaxStrLen(CompanyLocation."Province Code")), 1, MaxStrLen(CompanyLocation."Province Code")); - CompanyLocation."Province Name" := CopyStr(JsonHelper.GetValueAsText(JItem, 'node.billingAddress.province', MaxStrLen(CompanyLocation."Province Name")), 1, MaxStrLen(CompanyLocation."Province Name")); - PhoneNo := JsonHelper.GetValueAsText(JItem, 'node.billingAddress.phone'); - PhoneNo := CopyStr(DelChr(PhoneNo, '=', DelChr(PhoneNo, '=', '1234567890/+ .()')), 1, MaxStrLen(CompanyLocation."Phone No.")); - CompanyLocation."Phone No." := CopyStr(PhoneNo, 1, MaxStrLen(CompanyLocation."Phone No.")); - CompanyLocation."Tax Registration Id" := CopyStr(JsonHelper.GetValueAsText(JItem, 'node.taxRegistrationId', MaxStrLen(CompanyLocation."Tax Registration Id")), 1, MaxStrLen(CompanyLocation."Tax Registration Id")); - CompanyLocation.Modify(); + CompanyLocation.Address := CopyStr(JsonHelper.GetValueAsText(JLocation, 'node.billingAddress.address1', MaxStrLen(CompanyLocation.Address)), 1, MaxStrLen(CompanyLocation.Address)); + CompanyLocation."Address 2" := CopyStr(JsonHelper.GetValueAsText(JLocation, 'node.billingAddress.address2', MaxStrLen(CompanyLocation."Address 2")), 1, MaxStrLen(CompanyLocation."Address 2")); + CompanyLocation.Zip := CopyStr(JsonHelper.GetValueAsCode(JLocation, 'node.billingAddress.zip', MaxStrLen(CompanyLocation.Zip)), 1, MaxStrLen(CompanyLocation.Zip)); + CompanyLocation.City := CopyStr(JsonHelper.GetValueAsText(JLocation, 'node.billingAddress.city', MaxStrLen(CompanyLocation.City)), 1, MaxStrLen(CompanyLocation.City)); + CompanyLocation."Country/Region Code" := CopyStr(JsonHelper.GetValueAsCode(JLocation, 'node.billingAddress.countryCode', MaxStrLen(CompanyLocation."Country/Region Code")), 1, MaxStrLen(CompanyLocation."Country/Region Code")); + CompanyLocation."Province Code" := CopyStr(JsonHelper.GetValueAsText(JLocation, 'node.billingAddress.zoneCode', MaxStrLen(CompanyLocation."Province Code")), 1, MaxStrLen(CompanyLocation."Province Code")); + CompanyLocation."Province Name" := CopyStr(JsonHelper.GetValueAsText(JLocation, 'node.billingAddress.province', MaxStrLen(CompanyLocation."Province Name")), 1, MaxStrLen(CompanyLocation."Province Name")); + PhoneNo := JsonHelper.GetValueAsText(JLocation, 'node.billingAddress.phone'); + PhoneNo := CopyStr(DelChr(PhoneNo, '=', DelChr(PhoneNo, '=', '1234567890/+ .()')), 1, MaxStrLen(CompanyLocation."Phone No.")); + CompanyLocation."Phone No." := CopyStr(PhoneNo, 1, MaxStrLen(CompanyLocation."Phone No.")); +#pragma warning disable AA0139 + CompanyLocation."Tax Registration Id" := JsonHelper.GetValueAsText(JLocation, 'node.taxRegistrationId', MaxStrLen(CompanyLocation."Tax Registration Id")); +#pragma warning restore AA0139 + CompanyLocation."Shpfy Payment Terms Id" := CommunicationMgt.GetIdOfGId(JsonHelper.GetValueAsText(JLocation, 'node.buyerExperienceConfiguration.paymentTermsTemplate.id')); + if IsDefaultCompanyLocation then begin + CompanyLocation.Default := IsDefaultCompanyLocation; + IsDefaultCompanyLocation := false; end; + CompanyLocation.Modify(true); + end; + exit(true); + end; end; } \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompanyExport.Codeunit.al b/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompanyExport.Codeunit.al index 1146b1366e..632c95cb27 100644 --- a/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompanyExport.Codeunit.al +++ b/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompanyExport.Codeunit.al @@ -63,8 +63,9 @@ codeunit 30284 "Shpfy Company Export" ShopifyCompany.Insert(); if Shop."Auto Create Catalog" then - CatalogAPI.CreateCatalog(ShopifyCompany); + CatalogAPI.CreateCatalog(ShopifyCompany, Customer); + CompanyLocation.Default := true; CompanyLocation."Company SystemId" := ShopifyCompany.SystemId; CompanyLocation.Insert(); end; @@ -91,7 +92,9 @@ codeunit 30284 "Shpfy Company Export" TaxArea: Record "Shpfy Tax Area"; TempShopifyCompany: Record "Shpfy Company" temporary; TempCompanyLocation: Record "Shpfy Company Location" temporary; + TaxRegistrationIdMapping: Interface "Shpfy Tax Registration Id Mapping"; CountyCodeTooLongErr: Text; + ShpfyPaymentTermsId: BigInteger; begin TempShopifyCompany := ShopifyCompany; TempCompanyLocation := CompanyLocation; @@ -146,6 +149,12 @@ codeunit 30284 "Shpfy Company Export" CompanyLocation."Phone No." := Customer."Phone No."; + TaxRegistrationIdMapping := Shop."Shpfy Comp. Tax Id Mapping"; + CompanyLocation."Tax Registration Id" := TaxRegistrationIdMapping.GetTaxRegistrationId(Customer); + + if GetShopifyPaymentTermsIdFromCustomer(Customer, ShpfyPaymentTermsId) then + CompanyLocation."Shpfy Payment Terms Id" := ShpfyPaymentTermsId; + if HasDiff(ShopifyCompany, TempShopifyCompany) or HasDiff(CompanyLocation, TempCompanyLocation) then begin ShopifyCompany."Last Updated by BC" := CurrentDateTime; exit(true); @@ -206,4 +215,16 @@ codeunit 30284 "Shpfy Company Export" begin CreateCustomers := NewCustomers; end; + + local procedure GetShopifyPaymentTermsIdFromCustomer(Customer: Record Customer; var ShpfyPaymentTermsId: BigInteger): Boolean + var + ShopifyPaymentTerms: Record "Shpfy Payment Terms"; + begin + ShopifyPaymentTerms.SetRange("Shop Code", Shop.Code); + ShopifyPaymentTerms.SetRange("Payment Terms Code", Customer."Payment Terms Code"); + if ShopifyPaymentTerms.FindFirst() then begin + ShpfyPaymentTermsId := ShopifyPaymentTerms.Id; + exit(true); + end; + end; } \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompanyImport.Codeunit.al b/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompanyImport.Codeunit.al index ac661a69c6..5c7871aab3 100644 --- a/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompanyImport.Codeunit.al +++ b/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompanyImport.Codeunit.al @@ -20,6 +20,8 @@ codeunit 30301 "Shpfy Company Import" exit; end; + CompanyApi.UpdateShopifyCompanyLocation(ShopifyCompany); + Commit(); if CompanyMapping.FindMapping(ShopifyCompany, TempShopifyCustomer) then begin if Shop."Shopify Can Update Companies" then begin @@ -68,6 +70,7 @@ codeunit 30301 "Shpfy Company Import" begin Shop := ShopifyShop; CompanyApi.SetShop(Shop); + CompanyMapping.SetShop(Shop); end; internal procedure SetShop(ShopCode: Code[20]) diff --git a/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompanyMapping.Codeunit.al b/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompanyMapping.Codeunit.al index f75e339810..4237999eed 100644 --- a/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompanyMapping.Codeunit.al +++ b/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyCompanyMapping.Codeunit.al @@ -1,7 +1,5 @@ namespace Microsoft.Integration.Shopify; -using Microsoft.Sales.Customer; - /// /// Codeunit Shpfy Company Mapping (ID 30303). /// @@ -22,57 +20,14 @@ codeunit 30303 "Shpfy Company Mapping" internal procedure FindMapping(var ShopifyCompany: Record "Shpfy Company"; var TempShopifyCustomer: Record "Shpfy Customer" temporary): Boolean; var - Customer: Record Customer; - ShopifyCustomer: Record "Shpfy Customer"; - CustomerMapping: Codeunit "Shpfy Customer Mapping"; - PhoneFilter: Text; + CompByEmailPhone: Codeunit "Shpfy Comp. By Email/Phone"; + IMapping: Interface "Shpfy ICompany Mapping"; begin - if not IsNullGuid(ShopifyCompany."Customer SystemId") then - if Customer.GetBySystemId(ShopifyCompany."Customer SystemId") then - exit(true) - else begin - Clear(ShopifyCompany."Customer SystemId"); - ShopifyCompany.Modify(); - end; - - if IsNullGuid(ShopifyCompany."Customer SystemId") then begin - if TempShopifyCustomer.Email <> '' then begin - Customer.SetFilter("E-Mail", '@' + TempShopifyCustomer.Email); - if Customer.FindFirst() then begin - ShopifyCompany."Customer SystemId" := Customer.SystemId; - - if not ShopifyCustomer.Get(TempShopifyCustomer.Id) then begin - ShopifyCustomer.Copy(TempShopifyCustomer); - ShopifyCustomer."Customer SystemId" := Customer.SystemId; - ShopifyCustomer.Insert(); - end; - - ShopifyCompany."Main Contact Customer Id" := ShopifyCustomer.Id; - ShopifyCompany.Modify(); - exit(true); - end; - end; - if TempShopifyCustomer."Phone No." <> '' then begin - PhoneFilter := CustomerMapping.CreatePhoneFilter(TempShopifyCustomer."Phone No."); - if PhoneFilter <> '' then begin - Clear(Customer); - Customer.SetFilter("Phone No.", PhoneFilter); - if Customer.FindFirst() then begin - ShopifyCompany."Customer SystemId" := Customer.SystemId; - - if not ShopifyCustomer.Get(TempShopifyCustomer.Id) then begin - ShopifyCustomer.Copy(TempShopifyCustomer); - ShopifyCustomer."Customer SystemId" := Customer.SystemId; - ShopifyCustomer.Insert(); - end; - - ShopifyCompany."Main Contact Customer Id" := ShopifyCustomer.Id; - ShopifyCompany.Modify(); - exit(true); - end; - end; - end; - end; + IMapping := Shop."Company Mapping Type"; + if IMapping is "Shpfy IFind Company Mapping" then + exit((IMapping as "Shpfy IFind Company Mapping").FindMapping(ShopifyCompany, TempShopifyCustomer)) + else + CompByEmailPhone.FindMapping(ShopifyCompany, TempShopifyCustomer); end; internal procedure SetShop(Code: Code[20]) diff --git a/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyTaxRegistrationNo.Codeunit.al b/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyTaxRegistrationNo.Codeunit.al new file mode 100644 index 0000000000..edacba5ba0 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyTaxRegistrationNo.Codeunit.al @@ -0,0 +1,21 @@ +namespace Microsoft.Integration.Shopify; + +using Microsoft.Sales.Customer; + +/// +/// Codeunit Shpfy Tax Registration No. (ID 30367) implements Interface Shpfy Tax Registration Id Mapping. +/// +codeunit 30367 "Shpfy Tax Registration No." implements "Shpfy Tax Registration Id Mapping" +{ + Access = Internal; + + procedure GetTaxRegistrationId(var Customer: Record Customer): Text[150]; + begin + exit(Customer."Registration Number"); + end; + + procedure SetMappingFiltersForCustomers(var Customer: Record Customer; CompanyLocation: Record "Shpfy Company Location") + begin + Customer.SetRange("Registration Number", CompanyLocation."Tax Registration Id"); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyVATTaxRegistrationNo.Codeunit.al b/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyVATTaxRegistrationNo.Codeunit.al new file mode 100644 index 0000000000..c7ad6fa420 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Companies/Codeunits/ShpfyVATTaxRegistrationNo.Codeunit.al @@ -0,0 +1,21 @@ +namespace Microsoft.Integration.Shopify; + +using Microsoft.Sales.Customer; + +/// +/// Codeunit Shpfy VAT Tax Registration No. (ID 30368) implements Interface Shpfy Tax Registration Id Mapping. +/// +codeunit 30368 "Shpfy VAT Tax Registration No." implements "Shpfy Tax Registration Id Mapping" +{ + Access = Internal; + + procedure GetTaxRegistrationId(var Customer: Record Customer): Text[150]; + begin + exit(Customer."VAT Registration No."); + end; + + procedure SetMappingFiltersForCustomers(var Customer: Record Customer; CompanyLocation: Record "Shpfy Company Location") + begin + Customer.SetRange("VAT Registration No.", CompanyLocation."Tax Registration Id"); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Companies/Enums/ShpfyCompTaxIdMapping.Enum.al b/Apps/W1/Shopify/app/src/Companies/Enums/ShpfyCompTaxIdMapping.Enum.al new file mode 100644 index 0000000000..5faa7a8511 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Companies/Enums/ShpfyCompTaxIdMapping.Enum.al @@ -0,0 +1,21 @@ +namespace Microsoft.Integration.Shopify; + +/// +/// Enum Shopify Company Tax Id Mapping (ID 30165) implements Interface Shpfy Tax Registration Id Mapping. +/// +enum 30165 "Shpfy Comp. Tax Id Mapping" implements "Shpfy Tax Registration Id Mapping" +{ + Caption = 'Shopify Company Tax Id Mapping'; + Extensible = true; + + value(0; "Registration No.") + { + Caption = 'Registration No.'; + Implementation = "Shpfy Tax Registration Id Mapping" = "Shpfy Tax Registration No."; + } + value(1; "VAT Registration No.") + { + Caption = 'VAT Registration No.'; + Implementation = "Shpfy Tax Registration Id Mapping" = "Shpfy VAT Tax Registration No."; + } +} diff --git a/Apps/W1/Shopify/app/src/Companies/Enums/ShpfyCompanyMapping.Enum.al b/Apps/W1/Shopify/app/src/Companies/Enums/ShpfyCompanyMapping.Enum.al index b82b3bdd8a..84360d8680 100644 --- a/Apps/W1/Shopify/app/src/Companies/Enums/ShpfyCompanyMapping.Enum.al +++ b/Apps/W1/Shopify/app/src/Companies/Enums/ShpfyCompanyMapping.Enum.al @@ -18,5 +18,9 @@ enum 30151 "Shpfy Company Mapping" implements "Shpfy ICompany Mapping" Caption = 'Always take the default Company'; Implementation = "Shpfy ICompany Mapping" = "Shpfy Comp. By Default Comp."; } - + value(3; "By Tax Id") + { + Caption = 'By Tax Id'; + Implementation = "Shpfy ICompany Mapping" = "Shpfy Comp. By Tax Id"; + } } diff --git a/Apps/W1/Shopify/app/src/Companies/Interfaces/ShpfyIFindCompanyMapping.Interface.al b/Apps/W1/Shopify/app/src/Companies/Interfaces/ShpfyIFindCompanyMapping.Interface.al new file mode 100644 index 0000000000..8a433d0513 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Companies/Interfaces/ShpfyIFindCompanyMapping.Interface.al @@ -0,0 +1,9 @@ +namespace Microsoft.Integration.Shopify; + +/// +/// Interface "Shpfy ICustomer/Company Mapping." +/// +interface "Shpfy IFind Company Mapping" extends "Shpfy ICompany Mapping" +{ + procedure FindMapping(var ShopifyCompany: Record "Shpfy Company"; var TempShopifyCustomer: Record "Shpfy Customer" temporary): Boolean +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Companies/Interfaces/ShpfyTaxRegistrationIdMapping.Interface.al b/Apps/W1/Shopify/app/src/Companies/Interfaces/ShpfyTaxRegistrationIdMapping.Interface.al new file mode 100644 index 0000000000..bb6800b840 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Companies/Interfaces/ShpfyTaxRegistrationIdMapping.Interface.al @@ -0,0 +1,13 @@ +namespace Microsoft.Integration.Shopify; + +using Microsoft.Sales.Customer; + +/// +/// Interface "Shpfy Tax Registration Id Mapping" +/// +interface "Shpfy Tax Registration Id Mapping" +{ + procedure GetTaxRegistrationId(var Customer: Record Customer): Text[150]; + + procedure SetMappingFiltersForCustomers(var Customer: Record Customer; CompanyLocation: Record "Shpfy Company Location"); +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Companies/Pages/ShpfyCompLocations.Page.al b/Apps/W1/Shopify/app/src/Companies/Pages/ShpfyCompLocations.Page.al new file mode 100644 index 0000000000..5bde451bd1 --- /dev/null +++ b/Apps/W1/Shopify/app/src/Companies/Pages/ShpfyCompLocations.Page.al @@ -0,0 +1,41 @@ +namespace Microsoft.Integration.Shopify; + +/// +/// Page Shpfy Company Locations (ID 30165). +/// +page 30165 "Shpfy Comp. Locations" +{ + ApplicationArea = All; + Caption = 'Shopify Company Locations'; + Editable = false; + InsertAllowed = false; + DeleteAllowed = false; + ModifyAllowed = false; + PageType = List; + SourceTable = "Shpfy Company Location"; + UsageCategory = None; + + layout + { + area(content) + { + repeater(General) + { + field(Id; Rec.Id) { } + field("Company SystemId"; Rec."Company SystemId") { } + field("Default"; Rec."Default") { } + field(Address; Rec.Address) { } + field("Address 2"; Rec."Address 2") { } + field(Zip; Rec.Zip) { } + field(City; Rec.City) { } + field("Country/Region Code"; Rec."Country/Region Code") { } + field("Phone No."; Rec."Phone No.") { } + field(Name; Rec.Name) { } + field("Province Code"; Rec."Province Code") { } + field("Province Name"; Rec."Province Name") { } + field("Tax Registration Id"; Rec."Tax Registration Id") { } + field("Shpfy Payment Terms Id"; Rec."Shpfy Payment Terms Id") { } + } + } + } +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/Companies/Pages/ShpfyCompanies.Page.al b/Apps/W1/Shopify/app/src/Companies/Pages/ShpfyCompanies.Page.al index 39fd16175a..24e04c5e85 100644 --- a/Apps/W1/Shopify/app/src/Companies/Pages/ShpfyCompanies.Page.al +++ b/Apps/W1/Shopify/app/src/Companies/Pages/ShpfyCompanies.Page.al @@ -118,6 +118,18 @@ page 30156 "Shpfy Companies" RunPageLink = "Company SystemId" = field(SystemId); ToolTip = 'View a list of Shopify catalogs for the company.'; } + action(ShopifyLocations) + { + ApplicationArea = All; + Caption = 'Shopify Locations'; + Image = Warehouse; + Promoted = true; + PromotedOnly = true; + PromotedCategory = Category4; + RunObject = Page "Shpfy Comp. Locations"; + RunPageLink = "Company SystemId" = field(SystemId); + ToolTip = 'View a list of Shopify company locations.'; + } } area(Processing) diff --git a/Apps/W1/Shopify/app/src/Companies/Pages/ShpfyCompanyCard.Page.al b/Apps/W1/Shopify/app/src/Companies/Pages/ShpfyCompanyCard.Page.al index 8980b7073f..80d5470e7b 100644 --- a/Apps/W1/Shopify/app/src/Companies/Pages/ShpfyCompanyCard.Page.al +++ b/Apps/W1/Shopify/app/src/Companies/Pages/ShpfyCompanyCard.Page.al @@ -163,6 +163,18 @@ page 30157 "Shpfy Company Card" RunPageLink = "Company SystemId" = field(SystemId); ToolTip = 'View a list of Shopify catalogs for the company.'; } + action(ShopifyLocations) + { + ApplicationArea = All; + Caption = 'Shopify Locations'; + Image = Warehouse; + Promoted = true; + PromotedOnly = true; + PromotedCategory = Category4; + RunObject = Page "Shpfy Comp. Locations"; + RunPageLink = "Company SystemId" = field(SystemId); + ToolTip = 'View a list of Shopify company locations.'; + } } } diff --git a/Apps/W1/Shopify/app/src/Companies/Tables/ShpfyCompanyLocation.Table.al b/Apps/W1/Shopify/app/src/Companies/Tables/ShpfyCompanyLocation.Table.al index 7fd7dda0eb..b732f8cecc 100644 --- a/Apps/W1/Shopify/app/src/Companies/Tables/ShpfyCompanyLocation.Table.al +++ b/Apps/W1/Shopify/app/src/Companies/Tables/ShpfyCompanyLocation.Table.al @@ -15,63 +15,87 @@ table 30151 "Shpfy Company Location" Caption = 'Id'; DataClassification = SystemMetadata; Editable = false; + ToolTip = 'Specifies the unique identifier for the company location in Shopify.'; } field(2; "Company SystemId"; Guid) { Caption = 'Company SystemId'; DataClassification = SystemMetadata; Editable = false; + ToolTip = 'Specifies the unique identifier for the company in Shopify.'; } field(3; Address; Text[100]) { Caption = 'Address'; DataClassification = CustomerContent; + ToolTip = 'Specifies the address of the company location.'; } field(4; "Address 2"; Text[100]) { Caption = 'Address 2'; DataClassification = CustomerContent; + ToolTip = 'Specifies the second address line of the company location.'; } field(5; Zip; Code[20]) { Caption = 'Zip'; DataClassification = CustomerContent; + ToolTip = 'Specifies the postal code of the company location.'; } field(6; City; Text[50]) { Caption = 'City'; DataClassification = CustomerContent; + ToolTip = 'Specifies the city of the company location.'; } field(7; "Country/Region Code"; Code[2]) { Caption = 'Country/Region Code'; DataClassification = CustomerContent; + ToolTip = 'Specifies the country/region code of the company location.'; } field(8; "Phone No."; Text[30]) { Caption = 'Phone No.'; DataClassification = CustomerContent; + ToolTip = 'Specifies the phone number of the company location.'; } field(9; Name; Text[100]) { Caption = 'Name'; DataClassification = CustomerContent; Editable = false; + ToolTip = 'Specifies the name of the company location.'; } field(10; "Province Code"; Code[10]) { Caption = 'Province'; DataClassification = CustomerContent; + ToolTip = 'Specifies the province code of the company location.'; } field(11; "Province Name"; Text[50]) { Caption = 'Province Name'; DataClassification = CustomerContent; + ToolTip = 'Specifies the province name of the company location.'; } field(12; "Tax Registration Id"; Text[150]) { Caption = 'Tax Registration Id'; DataClassification = CustomerContent; + ToolTip = 'Specifies the tax registration identifier of the company location.'; + } + field(13; "Default"; Boolean) + { + Caption = 'Default'; + DataClassification = CustomerContent; + ToolTip = 'Specifies whether the location is the default location for the company.'; + } + field(14; "Shpfy Payment Terms Id"; BigInteger) + { + Caption = 'Shopify Payment Terms Id'; + DataClassification = CustomerContent; + ToolTip = 'Specifies the Shopify Payment Terms Id which is mapped with Customer''s Payment Terms.'; } } keys diff --git a/Apps/W1/Shopify/app/src/Customers/Codeunits/ShpfyCreateCustomer.Codeunit.al b/Apps/W1/Shopify/app/src/Customers/Codeunits/ShpfyCreateCustomer.Codeunit.al index f9ea70b37b..f4f661779f 100644 --- a/Apps/W1/Shopify/app/src/Customers/Codeunits/ShpfyCreateCustomer.Codeunit.al +++ b/Apps/W1/Shopify/app/src/Customers/Codeunits/ShpfyCreateCustomer.Codeunit.al @@ -115,6 +115,7 @@ codeunit 30110 "Shpfy Create Customer" ShopifyTaxArea: Record "Shpfy Tax Area"; CustContUpdate: Codeunit "CustCont-Update"; CustomerTemplMgt: Codeunit "Customer Templ. Mgt."; + UpdateCustomer: Codeunit "Shpfy Update Customer"; ICounty: Interface "Shpfy ICounty"; CountryCode: Code[20]; CurrentTemplateCode: Code[20]; @@ -151,16 +152,18 @@ codeunit 30110 "Shpfy Create Customer" if CompanyLocation."Phone No." <> '' then Customer.Validate("Phone No.", CompanyLocation."Phone No."); - if ShopifyTaxArea.Get(CompanyLocation."Country/Region Code", CompanyLocation."Province Name") then begin if (ShopifyTaxArea."Tax Area Code" <> '') then begin Customer.Validate("Tax Area Code", ShopifyTaxArea."Tax Area Code"); Customer.Validate("Tax Liable", ShopifyTaxArea."Tax Liable"); end; if (ShopifyTaxArea."VAT Bus. Posting Group" <> '') then - Customer.Validate("VAT Bus. Posting Group", ShopifyTaxArea."VAT Bus. Posting Group"); + Customer.Validate("VAT Bus. Posting Group", ShopifyTaxArea."VAT Bus. Posting Group"); end; + if CompanyLocation."Shpfy Payment Terms Id" <> 0 then + Customer.Validate("Payment Terms Code", UpdateCustomer.GetPaymentTermsCodeFromShopifyPaymentTermsId(CompanyLocation."Shpfy Payment Terms Id")); + Customer.Modify(); ShopifyCustomer.Copy(TempShopifyCustomer); diff --git a/Apps/W1/Shopify/app/src/Customers/Codeunits/ShpfyUpdateCustomer.Codeunit.al b/Apps/W1/Shopify/app/src/Customers/Codeunits/ShpfyUpdateCustomer.Codeunit.al index 1f862702cc..e7897f7817 100644 --- a/Apps/W1/Shopify/app/src/Customers/Codeunits/ShpfyUpdateCustomer.Codeunit.al +++ b/Apps/W1/Shopify/app/src/Customers/Codeunits/ShpfyUpdateCustomer.Codeunit.al @@ -165,6 +165,9 @@ codeunit 30124 "Shpfy Update Customer" Customer.Validate("VAT Bus. Posting Group", ShopifyTaxArea."VAT Bus. Posting Group"); end; + if CompanyLocation."Shpfy Payment Terms Id" <> 0 then + Customer.Validate("Payment Terms Code", GetPaymentTermsCodeFromShopifyPaymentTermsId(CompanyLocation."Shpfy Payment Terms Id")); + Customer.Modify(); end; @@ -186,4 +189,14 @@ codeunit 30124 "Shpfy Update Customer" begin Shop := ShopifyShop; end; + + internal procedure GetPaymentTermsCodeFromShopifyPaymentTermsId(ShpfyPaymentTermsId: BigInteger): Code[10] + var + ShpfyPaymentTerms: Record "Shpfy Payment Terms"; + begin + ShpfyPaymentTerms.SetRange("Shop Code", Shop.Code); + ShpfyPaymentTerms.SetRange(Id, ShpfyPaymentTermsId); + if ShpfyPaymentTerms.FindFirst() then + exit(ShpfyPaymentTerms."Payment Terms Code"); + end; } \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLCompLocations.Codeunit.al b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLCompLocations.Codeunit.al new file mode 100644 index 0000000000..ff618a4fd6 --- /dev/null +++ b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLCompLocations.Codeunit.al @@ -0,0 +1,24 @@ +namespace Microsoft.Integration.Shopify; + +codeunit 30168 "Shpfy GQL CompLocations" implements "Shpfy IGraphQL" +{ + Access = Internal; + + /// + /// GetGraphQL. + /// + /// Return value of type Text. + internal procedure GetGraphQL(): Text + begin + exit('{"query": "{companyLocations(first:20, query: \"company_id:''{{CompanyId}}''\") {pageInfo { hasNextPage } edges { cursor node { id name billingAddress {address1 address2 city countryCode phone province zip zoneCode} buyerExperienceConfiguration {paymentTermsTemplate {id}} taxRegistrationId}}}}"}'); + end; + + /// + /// GetExpectedCost. + /// + /// Return value of type Integer. + internal procedure GetExpectedCost(): Integer + begin + exit(24); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLCompany.Codeunit.al b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLCompany.Codeunit.al index e6a5806e2a..baf6ed8763 100644 --- a/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLCompany.Codeunit.al +++ b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLCompany.Codeunit.al @@ -13,7 +13,7 @@ codeunit 30302 "Shpfy GQL Company" implements "Shpfy IGraphQL" /// Return value of type Text. internal procedure GetGraphQL(): Text begin - exit('{"query":"{company(id: \"gid://shopify/Company/{{CompanyId}}\") {name id note createdAt updatedAt mainContact { id customer { id firstName lastName email phone}} locations(first:1, sortKey: CREATED_AT ) {edges { node { id name billingAddress {address1 address2 city countryCode phone province zip zoneCode} taxRegistrationId}}}}}"}'); + exit('{"query":"{company(id: \"gid://shopify/Company/{{CompanyId}}\") {name id note createdAt updatedAt mainContact { id customer { id firstName lastName email phone}}}}"}'); end; /// diff --git a/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLCreateCompLocationTaxID.Codeunit.al b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLCreateCompLocationTaxID.Codeunit.al new file mode 100644 index 0000000000..dfe7c5efab --- /dev/null +++ b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLCreateCompLocationTaxID.Codeunit.al @@ -0,0 +1,27 @@ +namespace Microsoft.Integration.Shopify; + +/// +/// Codeunit Shpfy GQL CreateCompLocTaxId (ID 30369) implements Interface Shpfy IGraphQL. +/// +codeunit 30369 "Shpfy GQL CreateCompLocTaxId" implements "Shpfy IGraphQL" +{ + Access = Internal; + + /// + /// GetGraphQL. + /// + /// Return value of type Text. + internal procedure GetGraphQL(): Text + begin + exit('{"query":"mutation {companyLocationCreateTaxRegistration(locationId: \"gid://shopify/CompanyLocation/{{LocationId}}\", taxId: \"{{TaxId}}\") {companyLocation {id, name, taxRegistrationId}, userErrors {field, message}}}"}'); + end; + + /// + /// GetExpectedCost. + /// + /// Return value of type Integer. + internal procedure GetExpectedCost(): Integer + begin + exit(4); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLNextCompLocations.Codeunit.al b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLNextCompLocations.Codeunit.al new file mode 100644 index 0000000000..33da544628 --- /dev/null +++ b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLNextCompLocations.Codeunit.al @@ -0,0 +1,24 @@ +namespace Microsoft.Integration.Shopify; + +codeunit 30215 "Shpfy GQL NextCompLocations" implements "Shpfy IGraphQL" +{ + Access = Internal; + + /// + /// GetGraphQL. + /// + /// Return value of type Text. + internal procedure GetGraphQL(): Text + begin + exit('{"query": "{companyLocations(first:20, after:\"{{After}}\", query: \"company_id:''{{CompanyId}}''\") {pageInfo { hasNextPage } edges { cursor node { id name billingAddress {address1 address2 city countryCode phone province zip zoneCode} buyerExperienceConfiguration {paymentTermsTemplate {id}} taxRegistrationId}}}}"}'); + end; + + /// + /// GetExpectedCost. + /// + /// Return value of type Integer. + internal procedure GetExpectedCost(): Integer + begin + exit(24); + end; +} diff --git a/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLUpdateLocPmtTerms.Codeunit.al b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLUpdateLocPmtTerms.Codeunit.al new file mode 100644 index 0000000000..2298fa6c73 --- /dev/null +++ b/Apps/W1/Shopify/app/src/GraphQL/Codeunits/ShpfyGQLUpdateLocPmtTerms.Codeunit.al @@ -0,0 +1,27 @@ +namespace Microsoft.Integration.Shopify; + +/// +/// Codeunit Shpfy GQL UpdateLocPmtTerms (ID 30370) implements Interface Shpfy IGraphQL. +/// +codeunit 30370 "Shpfy GQL UpdateLocPmtTerms" implements "Shpfy IGraphQL" +{ + Access = Internal; + + /// + /// GetGraphQL. + /// + /// Return value of type Text. + internal procedure GetGraphQL(): Text + begin + exit('{"query":"mutation {companyLocationUpdate(companyLocationId: \"gid://shopify/CompanyLocation/{{LocationId}}\", input: {buyerExperienceConfiguration: {paymentTermsTemplateId: \"gid://shopify/PaymentTermsTemplate/{{PaymentTermsId}}\"}}) {companyLocation {id, name}, userErrors {field, message}}}"}'); + end; + + /// + /// GetExpectedCost. + /// + /// Return value of type Integer. + internal procedure GetExpectedCost(): Integer + begin + exit(4); + end; +} \ No newline at end of file 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 dab96ed8ab..cbd55db539 100644 --- a/Apps/W1/Shopify/app/src/GraphQL/Enums/ShpfyGraphQLType.Enum.al +++ b/Apps/W1/Shopify/app/src/GraphQL/Enums/ShpfyGraphQLType.Enum.al @@ -490,4 +490,24 @@ enum 30111 "Shpfy GraphQL Type" implements "Shpfy IGraphQL" Caption = 'Get Product Image'; Implementation = "Shpfy IGraphQL" = "Shpfy GQL GetProductImage"; } + value(98; CreateCompanyLocationTaxId) + { + Caption = 'Create Company Location Tax Id'; + Implementation = "Shpfy IGraphQL" = "Shpfy GQL CreateCompLocTaxId"; + } + value(99; UpdateCompanyLocationPaymentTerms) + { + Caption = 'Update Company Location Payment Terms'; + Implementation = "Shpfy IGraphQL" = "Shpfy GQL UpdateLocPmtTerms"; + } + value(100; GetCompanyLocations) + { + Caption = 'Company Locations'; + Implementation = "Shpfy IGraphQL" = "Shpfy GQL CompLocations"; + } + value(101; GetNextCompanyLocations) + { + Caption = 'Next Get Company Locations'; + Implementation = "Shpfy IGraphQL" = "Shpfy GQL NextCompLocations"; + } } diff --git a/Apps/W1/Shopify/app/src/Logs/Codeunits/ShpfySkipRecordMgt.Codeunit.al b/Apps/W1/Shopify/app/src/Logs/Codeunits/ShpfySkipRecordMgt.Codeunit.al deleted file mode 100644 index 9c0f4a5eaf..0000000000 --- a/Apps/W1/Shopify/app/src/Logs/Codeunits/ShpfySkipRecordMgt.Codeunit.al +++ /dev/null @@ -1,44 +0,0 @@ -namespace Microsoft.Integration.Shopify; - -/// -/// Codeunit Shpfy Skip Record (ID 30313). -/// -codeunit 30313 "Shpfy Skipped Record" -{ - Access = Internal; - Permissions = tabledata "Shpfy Skipped Record" = rimd; - - /// - /// Creates log entry for skipped record. - /// - /// Related Shopify Id of the record. - /// Table Id of the record. - /// Record Id of the record. - /// Reason for skipping the record. - /// Shop record. - internal procedure LogSkippedRecord(ShopifyId: BigInteger; RecordId: RecordID; SkippedReason: Text[250]; Shop: Record "Shpfy Shop") - var - SkippedRecord: Record "Shpfy Skipped Record"; - begin - if Shop."Logging Mode" = Enum::"Shpfy Logging Mode"::Disabled then - exit; - SkippedRecord.Init(); - SkippedRecord.Validate("Shopify Id", ShopifyId); - SkippedRecord.Validate("Table ID", RecordId.TableNo()); - SkippedRecord.Validate("Record ID", RecordId); - SkippedRecord.Validate("Skipped Reason", SkippedReason); - SkippedRecord.Insert(true); - end; - - /// - /// Creates log entry for skipped recordwith empty Shopify Id. - /// - /// Record Id of the record. - /// Reason for skipping the record. - /// Shop record. - internal procedure LogSkippedRecord(RecordId: RecordID; SkippedReason: Text[250]; Shop: Record "Shpfy Shop") - begin - LogSkippedRecord(0, RecordId, SkippedReason, Shop); - end; - -} diff --git a/Apps/W1/Shopify/test/Catalogs/ShpfyCatalogAPISuscribers.Codeunit.al b/Apps/W1/Shopify/test/Catalogs/ShpfyCatalogAPISuscribers.Codeunit.al new file mode 100644 index 0000000000..e677d4d664 --- /dev/null +++ b/Apps/W1/Shopify/test/Catalogs/ShpfyCatalogAPISuscribers.Codeunit.al @@ -0,0 +1,64 @@ +codeunit 139625 "Shpfy Catalog API Subscribers" +{ + EventSubscriberInstance = Manual; + + [EventSubscriber(ObjectType::Codeunit, Codeunit::"Shpfy Communication Events", 'OnClientSend', '', true, false)] + local procedure OnClientSend(HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) + begin + MakeResponse(HttpRequestMessage, HttpResponseMessage); + end; + + [EventSubscriber(ObjectType::Codeunit, Codeunit::"Shpfy Communication Events", 'OnGetContent', '', true, false)] + local procedure OnGetContent(HttpResponseMessage: HttpResponseMessage; var Response: Text) + begin + HttpResponseMessage.Content.ReadAs(Response); + end; + + local procedure MakeResponse(HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) + var + Uri: Text; + GraphQlQuery: Text; + CreateCatalogGQLStartTok: Label '{"query": "mutation { catalogCreate(input: {title: ', Locked = true; + CreatePublicationGQLStartTok: Label '{"query": "mutation { publicationCreate(input: {autoPublish: true, catalogId:', Locked = true; + CreatePriceListGQLStartTok: Label '{"query": "mutation { priceListCreate(input: {name: ', Locked = true; + GraphQLCmdTxt: Label '/graphql.json', Locked = true; + begin + case HttpRequestMessage.Method of + 'POST': + begin + Uri := HttpRequestMessage.GetRequestUri(); + if Uri.EndsWith(GraphQLCmdTxt) then + if HttpRequestMessage.Content.ReadAs(GraphQlQuery) then + case true of + GraphQlQuery.StartsWith(CreateCatalogGQLStartTok): + HttpResponseMessage := GetCatalogResult(); + GraphQlQuery.StartsWith(CreatePublicationGQLStartTok): + HttpResponseMessage := GetEmptyResponse(); + GraphQlQuery.StartsWith(CreatePriceListGQLStartTok): + HttpResponseMessage := GetEmptyResponse(); + end; + end; + end; + end; + + local procedure GetCatalogResult(): HttpResponseMessage + var + Any: Codeunit Any; + HttpResponseMessage: HttpResponseMessage; + Body: Text; + begin + Body := StrSubstNo('{"data": {"catalogCreate": {"catalog": {"id": %1}}}}', Any.IntegerInRange(100000, 999999)); + HttpResponseMessage.Content.WriteFrom(Body); + exit(HttpResponseMessage); + end; + + local procedure GetEmptyResponse(): HttpResponseMessage + var + HttpResponseMessage: HttpResponseMessage; + Body: Text; + begin + Body := '{}'; + HttpResponseMessage.Content.WriteFrom(Body); + exit(HttpResponseMessage); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/test/Catalogs/ShpfyCatalogAPITest.Codeunit.al b/Apps/W1/Shopify/test/Catalogs/ShpfyCatalogAPITest.Codeunit.al index f50c1017d6..bee1cb27a3 100644 --- a/Apps/W1/Shopify/test/Catalogs/ShpfyCatalogAPITest.Codeunit.al +++ b/Apps/W1/Shopify/test/Catalogs/ShpfyCatalogAPITest.Codeunit.al @@ -61,4 +61,45 @@ codeunit 139645 "Shpfy Catalog API Test" LibraryAssert.IsTrue(Result, 'ExtractShopifyCatalogPrices'); LibraryAssert.RecordIsNotEmpty(TempCatalogPrice); end; + + [Test] + procedure UnitTestCreateCatalog() + var + Shop: Record "Shpfy Shop"; + Customer: Record Customer; + ShopifyCompany: Record "Shpfy Company"; + Catalog: Record "Shpfy Catalog"; + CatalogAPI: Codeunit "Shpfy Catalog API"; + ShopifyInitializeTest: Codeunit "Shpfy Initialize Test"; + CatalogAPISubscribers: Codeunit "Shpfy Catalog API Subscribers"; + LibrarySales: Codeunit "Library - Sales"; + begin + // [SCENARIO] Create a catalog for a company. + + // [GIVEN] Shop + Shop := ShopifyInitializeTest.CreateShop(); + // [GIVEN] Customer + LibrarySales.CreateCustomer(Customer); + // [GIVEN] A company record. + CreateCompany(ShopifyCompany, Customer.SystemId); + + // [WHEN] Invoke CatalogAPI.CreateCatalog + BindSubscription(CatalogAPISubscribers); + CatalogAPI.CreateCatalog(ShopifyCompany, Customer); + UnbindSubscription(CatalogAPISubscribers); + + // [THEN] A catalog is created. + Catalog.SetRange("Company SystemId", ShopifyCompany.SystemId); + Catalog.FindFirst(); + LibraryAssert.AreEqual(Customer."No.", Catalog."Customer No.", 'Customer No. is not transferred to catalog'); + end; + + local procedure CreateCompany(var ShopifyCompany: Record "Shpfy Company"; CustomerSystemId: Guid) + var + ShopifyCompanyInitialize: Codeunit "Shpfy Company Initialize"; + begin + ShopifyCompanyInitialize.CreateShopifyCompany(ShopifyCompany); + ShopifyCompany."Customer SystemId" := CustomerSystemId; + ShopifyCompany.Modify(false); + end; } diff --git a/Apps/W1/Shopify/test/Companies/ShpfyCompanyAPISubs.Codeunit.al b/Apps/W1/Shopify/test/Companies/ShpfyCompanyAPISubs.Codeunit.al new file mode 100644 index 0000000000..d111005cd3 --- /dev/null +++ b/Apps/W1/Shopify/test/Companies/ShpfyCompanyAPISubs.Codeunit.al @@ -0,0 +1,56 @@ +codeunit 139631 "Shpfy Company API Subs." +{ + EventSubscriberInstance = Manual; + + var + ExecutedQuery: Text; + + [EventSubscriber(ObjectType::Codeunit, Codeunit::"Shpfy Communication Events", 'OnClientSend', '', true, false)] + local procedure OnClientSend(HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) + begin + MakeResponse(HttpRequestMessage, HttpResponseMessage); + end; + + [EventSubscriber(ObjectType::Codeunit, Codeunit::"Shpfy Communication Events", 'OnGetContent', '', true, false)] + local procedure OnGetContent(HttpResponseMessage: HttpResponseMessage; var Response: Text) + begin + HttpResponseMessage.Content.ReadAs(Response); + end; + + local procedure MakeResponse(HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) + var + Uri: Text; + GraphQlQuery: Text; + ModifyLocationGQLStartTok: Label '{"query":"mutation {companyLocationUpdate(companyLocationId: ', Locked = true; + CreateTaxIdGQLStartTok: Label '{"query":"mutation {companyLocationCreateTaxRegistration(locationId:', Locked = true; + GraphQLCmdTxt: Label '/graphql.json', Locked = true; + begin + case HttpRequestMessage.Method of + 'POST': + begin + Uri := HttpRequestMessage.GetRequestUri(); + if Uri.EndsWith(GraphQLCmdTxt) then + if HttpRequestMessage.Content.ReadAs(GraphQlQuery) then + if GraphQlQuery.StartsWith(ModifyLocationGQLStartTok) or GraphQlQuery.StartsWith(CreateTaxIdGQLStartTok) then begin + HttpResponseMessage := GetEmptyResponse(); + ExecutedQuery := GraphQlQuery; + end; + end; + end; + end; + + local procedure GetEmptyResponse(): HttpResponseMessage + var + HttpResponseMessage: HttpResponseMessage; + Body: Text; + begin + Body := '{}'; + HttpResponseMessage.Content.WriteFrom(Body); + exit(HttpResponseMessage); + end; + + internal procedure GetExecutedQuery(): Text + begin + exit(ExecutedQuery); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/test/Companies/ShpfyCompanyAPITest.Codeunit.al b/Apps/W1/Shopify/test/Companies/ShpfyCompanyAPITest.Codeunit.al index b5bb716fe1..9b071be3e7 100644 --- a/Apps/W1/Shopify/test/Companies/ShpfyCompanyAPITest.Codeunit.al +++ b/Apps/W1/Shopify/test/Companies/ShpfyCompanyAPITest.Codeunit.al @@ -4,15 +4,20 @@ codeunit 139637 "Shpfy Company API Test" TestPermissions = Disabled; var + Shop: Record "Shpfy Shop"; + Any: Codeunit Any; LibraryAssert: Codeunit "Library Assert"; LibraryRandom: Codeunit "Library - Random"; + InitializeTest: Codeunit "Shpfy Initialize Test"; CompanyInitialize: Codeunit "Shpfy Company Initialize"; + IsInitialized: Boolean; [Test] procedure UnitTestCreateCompanyGraphQuery() var ShopifyCompany: Record "Shpfy Company"; CompanyLocation: Record "Shpfy Company Location"; + ShopifyCustomer: Record "Shpfy Customer"; CompanyAPI: Codeunit "Shpfy Company API"; GraphQL: Text; begin @@ -25,7 +30,7 @@ codeunit 139637 "Shpfy Company API Test" // [GIVEN] ShpfyCompanyLocation // [WHEN] Invoke CompanyAPI.CreateCompanyGraphQLQuery - GraphQL := CompanyAPI.CreateCompanyGraphQLQuery(ShopifyCompany, CompanyLocation); + GraphQL := CompanyAPI.CreateCompanyGraphQLQuery(ShopifyCompany, CompanyLocation, ShopifyCustomer); // [THEN] CompanyInitialize.CreateCompanyGraphQLResult() = GraphQL. LibraryAssert.AreEqual(CompanyInitialize.CreateCompanyGraphQLResult(), GraphQL, 'CreateCompanyGraphQuery'); @@ -140,6 +145,145 @@ codeunit 139637 "Shpfy Company API Test" LibraryAssert.AreEqual(ShopifyCompany.Name, Name, 'Name'); LibraryAssert.AreEqual(ShopifyCompany."Main Contact Id", CompanyContactId, 'Company Contact Id'); LibraryAssert.AreEqual(ShopifyCompany."Main Contact Customer Id", CustomerId, 'Customer Id'); - LibraryAssert.AreEqual(ShopifyCompany."Location Id", CompanyLocationId, 'Company Location Id'); + end; + + [Test] + procedure UnitTestCreateCompanyWithPaymentTerms() + var + ShopifyCompany: Record "Shpfy Company"; + CompanyLocation: Record "Shpfy Company Location"; + ShopifyCustomer: Record "Shpfy Customer"; + CompanyAPI: Codeunit "Shpfy Company API"; + GraphQL: Text; + begin + // [SCENARIO] Export company with payment terms. + + // [GIVEN] Shopify company + CompanyInitialize.CreateShopifyCompany(ShopifyCompany); + // [GIVEN] Shopify company location with payment terms id + CompanyLocation := CompanyInitialize.CreateShopifyCompanyLocation(ShopifyCompany); + CompanyLocation."Shpfy Payment Terms Id" := LibraryRandom.RandIntInRange(1000, 9999); + + // [WHEN] Invoke CompanyAPI.CreateCompanyGraphQLQuery + GraphQL := CompanyAPI.CreateCompanyGraphQLQuery(ShopifyCompany, CompanyLocation, ShopifyCustomer); + + // [THEN] The payment terms id is present in query. + LibraryAssert.IsTrue(GraphQL.Contains(StrSubstNo(CompanyInitialize.PaymentTermsGQLNode(), CompanyLocation."Shpfy Payment Terms Id")), 'Payment Terms Id'); + end; + + [Test] + procedure UnitTestUpdateCompanyWithPaymentTerms() + var + ShopifyCompany: Record "Shpfy Company"; + CompanyLocation: Record "Shpfy Company Location"; + GraphQL: Text; + begin + // [SCENARIO] Update Shopify company with payment terms. + Initialize(); + + // [GIVEN] Shopify company + CompanyInitialize.CreateShopifyCompany(ShopifyCompany); + // [GIVEN] Shopify company location with payment terms id + CompanyLocation := CompanyInitialize.CreateShopifyCompanyLocation(ShopifyCompany); + CompanyLocation."Shpfy Payment Terms Id" := LibraryRandom.RandIntInRange(1000, 9999); + CompanyLocation.Modify(false); + // [GIVEN] Shopify company location with changed payment terms id + CompanyLocation."Shpfy Payment Terms Id" := LibraryRandom.RandIntInRange(1000, 9999); + + // [WHEN] Invoke CompanyAPI.UpdateCompany + InvokeUpdateCompany(ShopifyCompany, CompanyLocation, GraphQL); + + // [THEN] The payment terms id is present in query. + LibraryAssert.IsTrue(GraphQL.Contains(StrSubstNo(CompanyInitialize.PaymentTermsGQLNode(), CompanyLocation."Shpfy Payment Terms Id")), 'Payment terms modification missing in query.'); + end; + + [Test] + procedure UnitTestUpdateCompanyLocationWithTaxId() + var + ShopifyCompany: Record "Shpfy Company"; + CompanyLocation: Record "Shpfy Company Location"; + GraphQL: Text; + begin + // [SCENARIO] Update Shopify company location with tax id. + Initialize(); + + // [GIVEN] Shopify company + CompanyInitialize.CreateShopifyCompany(ShopifyCompany); + // [GIVEN] Shopify company location with tax id + CompanyLocation := CompanyInitialize.CreateShopifyCompanyLocation(ShopifyCompany); + CompanyLocation."Tax Registration Id" := Any.AlphanumericText(20); + CompanyLocation.Modify(false); + // [GIVEN] Shopify company location with changed tax id + CompanyLocation."Tax Registration Id" := Any.AlphanumericText(20); + + // [WHEN] Invoke CompanyAPI.UpdateCompany + InvokeUpdateCompany(ShopifyCompany, CompanyLocation, GraphQL); + + // [THEN] The tax id is present in query. + LibraryAssert.IsTrue(GraphQL.Contains(CompanyInitialize.TaxIdGQLNode(CompanyLocation)), 'Tax Registration Id missing in query.'); + end; + + [Test] + procedure UnitTestCreateCompanyGraphQueryWithExternalId() + var + Customer: Record Customer; + ShopifyCompany: Record "Shpfy Company"; + CompanyLocation: Record "Shpfy Company Location"; + ShopifyCustomer: Record "Shpfy Customer"; + CompanyAPI: Codeunit "Shpfy Company API"; + GraphQL: Text; + begin + // [SCENARIO] Creating the GrapghQL query to create a new company in Shopify with external id. + Initialize(); + + // [GIVEN] Customer record + CreateCustomer(Customer); + // [GIVEN] Shopify Company connected with customer + CompanyInitialize.CreateShopifyCompany(ShopifyCompany); + // [GIVEN] Shopify Customer connected with customer + CreateShopifyCustomer(ShopifyCustomer, Customer.SystemId); + + // [WHEN] Invoke CompanyAPI.CreateCompanyGraphQLQuery + GraphQL := CompanyAPI.CreateCompanyGraphQLQuery(ShopifyCompany, CompanyLocation, ShopifyCustomer); + + // [THEN] The external id is present in query. + LibraryAssert.IsTrue(GraphQL.Contains(CompanyInitialize.ExternalIdGQLNode(Customer)), 'externalId missing in query.'); + end; + + local procedure Initialize() + begin + Any.SetDefaultSeed(); + + if IsInitialized then + exit; + Shop := InitializeTest.CreateShop(); + IsInitialized := true; + end; + + local procedure InvokeUpdateCompany(var ShopifyCompany: Record "Shpfy Company"; var CompanyLocation: Record "Shpfy Company Location"; var GraphQL: Text) + var + CompanyAPI: Codeunit "Shpfy Company API"; + CompanyAPISubs: Codeunit "Shpfy Company API Subs."; + begin + BindSubscription(CompanyAPISubs); + CompanyAPI.SetShop(Shop); + CompanyAPI.UpdateCompany(ShopifyCompany, CompanyLocation); + GraphQL := CompanyAPISubs.GetExecutedQuery(); + UnbindSubscription(CompanyAPISubs); + end; + + local procedure CreateCustomer(var Customer: Record Customer) + begin + Customer.Init(); + Customer."No." := Any.AlphanumericText(20); + Customer.Insert(false); + end; + + local procedure CreateShopifyCustomer(var ShopifyCustomer: Record "Shpfy Customer"; CustomerSystemId: Guid) + begin + ShopifyCustomer.Init(); + ShopifyCustomer.Id := Any.IntegerInRange(10000, 99999); + ShopifyCustomer."Customer SystemId" := CustomerSystemId; + ShopifyCustomer.Insert(false); end; } diff --git a/Apps/W1/Shopify/test/Companies/ShpfyCompanyExportTest.Codeunit.al b/Apps/W1/Shopify/test/Companies/ShpfyCompanyExportTest.Codeunit.al index af85097dc4..93561b92c0 100644 --- a/Apps/W1/Shopify/test/Companies/ShpfyCompanyExportTest.Codeunit.al +++ b/Apps/W1/Shopify/test/Companies/ShpfyCompanyExportTest.Codeunit.al @@ -4,8 +4,17 @@ codeunit 139636 "Shpfy Company Export Test" TestPermissions = Disabled; var + Shop: Record "Shpfy Shop"; + InitializeTest: Codeunit "Shpfy Initialize Test"; + Any: Codeunit Any; LibraryAssert: Codeunit "Library Assert"; CompanyExport: Codeunit "Shpfy Company Export"; + IsInitialized: Boolean; + + trigger OnRun() + begin + IsInitialized := false; + end; [Test] procedure UnitTestFillInShopifyCustomerData() @@ -13,9 +22,8 @@ codeunit 139636 "Shpfy Company Export Test" Customer: Record Customer; ShopifyCompany: Record "Shpfy Company"; CompanyLocation: Record "Shpfy Company Location"; - Shop: Record "Shpfy Shop"; - InitializeTest: Codeunit "Shpfy Initialize Test"; Result: Boolean; + ShopifyPaymentTermsId: BigInteger; begin // [SCENARIO] Convert an existing company record to a "Shpfy Company" and "Shpfy Company Location" record. @@ -45,5 +53,95 @@ codeunit 139636 "Shpfy Company Export Test" LibraryAssert.AreEqual(Customer."Post Code", CompanyLocation.Zip, 'Post Code'); LibraryAssert.AreEqual(Customer.City, CompanyLocation.City, 'City'); LibraryAssert.AreEqual(Customer."Country/Region Code", CompanyLocation."Country/Region Code", 'Country'); + LibraryAssert.AreEqual(ShopifyPaymentTermsId, CompanyLocation."Shpfy Payment Terms Id", 'Payment Terms Id should be 0'); + end; + + [Test] + procedure UnitTestFillInShopifyCustomerDataWithLocationPaymentTerm() + var + Customer: Record Customer; + ShopifyCompany: Record "Shpfy Company"; + CompanyLocation: Record "Shpfy Company Location"; + PaymentTermsCode: Code[10]; + ShopifyPaymentTermsId: BigInteger; + begin + // [SCENARIO] Export company with payment terms. + Initialize(); + + // [GIVEN] Payment terms + PaymentTermsCode := CreatePaymentTerms(); + // [GIVEN] Shopify payment terms + ShopifyPaymentTermsId := CreateShopifyPaymentTerms(PaymentTermsCode); + // [GIVEN] Customer record with payment terms + CreateCustomer(Customer, PaymentTermsCode); + // [GIVEN] Shopify Company + CreateCompany(ShopifyCompany, Customer.SystemId); + // [GIVEN] Company Location + CreateCompanyLocation(CompanyLocation, ShopifyCompany.SystemId, ShopifyPaymentTermsId); + + // [WHEN] Invoke FillInShopifyCompany + CompanyExport.FillInShopifyCompany(Customer, ShopifyCompany, CompanyLocation); + + // [THEN] The payment terms id is set in the company location record. + LibraryAssert.AreEqual(ShopifyPaymentTermsId, CompanyLocation."Shpfy Payment Terms Id", 'Payment Terms Id'); + end; + + local procedure Initialize() + begin + Any.SetDefaultSeed(); + + if IsInitialized then + exit; + Shop := InitializeTest.CreateShop(); + + IsInitialized := true; + + Commit(); + end; + + local procedure CreatePaymentTerms(): Code[10] + var + PaymentTerms: Record "Payment Terms"; + begin + PaymentTerms.Init(); + PaymentTerms.Code := Any.AlphanumericText(10); + PaymentTerms.Insert(false); + exit(PaymentTerms.Code); + end; + + local procedure CreateShopifyPaymentTerms(var PaymentTermsCode: Code[10]): BigInteger + var + ShopifyPaymentTerms: Record "Shpfy Payment Terms"; + begin + ShopifyPaymentTerms.Init(); + ShopifyPaymentTerms.Id := Any.IntegerInRange(10000, 99999); + ShopifyPaymentTerms."Payment Terms Code" := PaymentTermsCode; + ShopifyPaymentTerms.Insert(false); + exit(ShopifyPaymentTerms.Id); + end; + + local procedure CreateCustomer(var Customer: Record Customer; PaymentTermsCode: Code[10]) + begin + Customer.Init(); + Customer."No." := Any.AlphanumericText(20); + Customer."Payment Terms Code" := PaymentTermsCode; + Customer.Insert(false); + end; + + local procedure CreateCompany(var ShopifyCompany: Record "Shpfy Company"; CustomerSystemId: Guid) + begin + ShopifyCompany.Init(); + ShopifyCompany.Id := Any.IntegerInRange(10000, 99999); + ShopifyCompany."Customer SystemId" := CustomerSystemId; + ShopifyCompany.Insert(false); + end; + + local procedure CreateCompanyLocation(var CompanyLocation: Record "Shpfy Company Location"; ShopifyCompanySystemId: Guid; PaymentTermsId: BigInteger) + begin + CompanyLocation.Init(); + CompanyLocation."Company SystemId" := ShopifyCompanySystemId; + CompanyLocation.Id := Any.IntegerInRange(10000, 99999); + CompanyLocation."Shpfy Payment Terms Id" := PaymentTermsId; + CompanyLocation.Insert(false); end; } diff --git a/Apps/W1/Shopify/test/Companies/ShpfyCompanyImportSubs.Codeunit.al b/Apps/W1/Shopify/test/Companies/ShpfyCompanyImportSubs.Codeunit.al new file mode 100644 index 0000000000..4945537178 --- /dev/null +++ b/Apps/W1/Shopify/test/Companies/ShpfyCompanyImportSubs.Codeunit.al @@ -0,0 +1,77 @@ +codeunit 139630 "Shpfy Company Import Subs." +{ + EventSubscriberInstance = Manual; + + var + LocationValues: Dictionary of [Text, Text]; + CompanyImportExecuted: Boolean; + + [EventSubscriber(ObjectType::Codeunit, Codeunit::"Shpfy Communication Events", 'OnClientSend', '', true, false)] + local procedure OnClientSend(HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) + begin + MakeResponse(HttpRequestMessage, HttpResponseMessage); + end; + + [EventSubscriber(ObjectType::Codeunit, Codeunit::"Shpfy Communication Events", 'OnGetContent', '', true, false)] + local procedure OnGetContent(HttpResponseMessage: HttpResponseMessage; var Response: Text) + begin + HttpResponseMessage.Content.ReadAs(Response); + end; + + local procedure MakeResponse(HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) + var + Uri: Text; + GraphQlQuery: Text; + GetCompanyGQLStartTok: Label '{"query":"{company(id: \"gid://shopify/Company/', Locked = true; + GetCompanyGQLEndTok: Label '\") {name id note createdAt updatedAt mainContact { id customer { id firstName lastName email phone}}}}"}', Locked = true; + GetLocationsStartTok: Label '{"query": "{companyLocations(first:20, query: \"company_id:', Locked = true; + GraphQLCmdTxt: Label '/graphql.json', Locked = true; + begin + case HttpRequestMessage.Method of + 'POST': + begin + Uri := HttpRequestMessage.GetRequestUri(); + if Uri.EndsWith(GraphQLCmdTxt) then + if HttpRequestMessage.Content.ReadAs(GraphQlQuery) then + case true of + GraphQlQuery.StartsWith(GetCompanyGQLStartTok) and GraphQlQuery.EndsWith(GetCompanyGQLEndTok): + HttpResponseMessage := GetCompanyResponse(); + GraphQlQuery.StartsWith(GetLocationsStartTok): + HttpResponseMessage := GetLocationsResponse(); + end; + end; + end; + end; + + local procedure GetCompanyResponse(): HttpResponseMessage + var + HttpResponseMessage: HttpResponseMessage; + Body: Text; + begin + Body := StrSubstNo('{ "data": { "company" :{ "mainContact" : {}, "updatedAt" : "%1" } }}', Format(CurrentDateTime, 0, 9)); + HttpResponseMessage.Content.WriteFrom(Body); + exit(HttpResponseMessage); + end; + + local procedure GetLocationsResponse(): HttpResponseMessage + var + CompanyInitialize: Codeunit "Shpfy Company Initialize"; + HttpResponseMessage: HttpResponseMessage; + Body: Text; + begin + Body := CompanyInitialize.CreateLocationResponse(LocationValues); + HttpResponseMessage.Content.WriteFrom(Body); + exit(HttpResponseMessage); + end; + + internal procedure GetCompanyImportExecuted(): Boolean + begin + exit(CompanyImportExecuted); + end; + + internal procedure SetLocationValues(NewLocationValues: Dictionary of [Text, Text]) + begin + LocationValues := NewLocationValues; + end; + +} \ No newline at end of file diff --git a/Apps/W1/Shopify/test/Companies/ShpfyCompanyImportTest.Codeunit.al b/Apps/W1/Shopify/test/Companies/ShpfyCompanyImportTest.Codeunit.al index 64afb0a084..58372fbda5 100644 --- a/Apps/W1/Shopify/test/Companies/ShpfyCompanyImportTest.Codeunit.al +++ b/Apps/W1/Shopify/test/Companies/ShpfyCompanyImportTest.Codeunit.al @@ -4,7 +4,11 @@ codeunit 139647 "Shpfy Company Import Test" TestPermissions = Disabled; var + Shop: Record "Shpfy Shop"; LibraryAssert: Codeunit "Library Assert"; + Any: Codeunit Any; + InitializeTest: Codeunit "Shpfy Initialize Test"; + IsInitialized: Boolean; [Test] procedure UnitTestFindMappingBetweenCompanyAndCustomer() @@ -12,13 +16,11 @@ codeunit 139647 "Shpfy Company Import Test" Customer: Record Customer; ShopifyCompany: Record "Shpfy Company"; ShopifyCustomer: Record "Shpfy Customer"; - Shop: Record "Shpfy Shop"; - InitializeTest: Codeunit "Shpfy Initialize Test"; CompanyMapping: Codeunit "Shpfy Company Mapping"; Result: Boolean; begin // [SCENARIO] Importing a company record that is already mapped to a customer record via email. - Shop := InitializeTest.CreateShop(); + Initialize(); Shop."B2B Enabled" := true; // [GIVEN] Shop, Shopify company and Shopify customer @@ -36,4 +38,212 @@ codeunit 139647 "Shpfy Company Import Test" LibraryAssert.IsTrue(Result, 'Result'); LibraryAssert.AreEqual(ShopifyCompany."Customer SystemId", Customer.SystemId, 'Customer SystemId'); end; + + [Test] + procedure UnitTestImportCompanyWithLocation() + var + ShopifyCompany: Record "Shpfy Company"; + LocationValues: Dictionary of [Text, Text]; + EmptyGuid: Guid; + begin + // [SCENARIO] Importing a company with location with defined payment term. + Initialize(); + + // [GIVEN] Shopify company + CreateCompany(ShopifyCompany, EmptyGuid); + // [GIVEN] Company location values in Shopify + CreateLocationValues(LocationValues); + + // [WHEN] Invoke CompanyImport + InvokeCompanyImport(ShopifyCompany, LocationValues); + + // [THEN] Location is created with the correct payment term and all other . + VerifyShopifyCompanyLocationValues(ShopifyCompany, LocationValues); + end; + + [Test] + procedure UnitTestUpdateCustomerFromCompanyWithPaymentTerms() + var + Customer: Record Customer; + ShopifyCompany: Record "Shpfy Company"; + CompanyLocation: Record "Shpfy Company Location"; + UpdateCustomer: Codeunit "Shpfy Update Customer"; + PaymentTermsCode: Code[10]; + ShopifyPaymentTermsId: BigInteger; + begin + // [SCENARIO] Update a customer from a company with location with defined payment term and existing payment terms in BC. + Initialize(); + + // [GIVEN] Payment terms + PaymentTermsCode := CreatePaymentTerms(); + // [GIVEN] Shopify payment terms + ShopifyPaymentTermsId := CreateShopifyPaymentTerms(PaymentTermsCode); + // [GIVEN] Customer record with payment terms + CreateCustomerWithPaymentTerms(Customer, PaymentTermsCode); + // [GIVEN] Shopify Company + CreateCompany(ShopifyCompany, Customer.SystemId); + // [GIVEN] Company Location + CreateCompanyLocation(CompanyLocation, ShopifyCompany, ShopifyPaymentTermsId); + + // [WHEN] Invoke UpdateCustomerFromCompany + UpdateCustomer.UpdateCustomerFromCompany(ShopifyCompany); + + // [THEN] Customer record is updated with the correct payment terms. + Customer.GetBySystemId(Customer.SystemId); + LibraryAssert.AreEqual(Customer."Payment Terms Code", PaymentTermsCode, 'Payment Terms Code'); + end; + + [Test] + procedure UnitTestCreateCustomerFromCompanyWithPaymentTerms() + var + Customer: Record Customer; + TempShopifyCustomer: Record "Shpfy Customer" temporary; + ShopifyCompany: Record "Shpfy Company"; + CompanyLocation: Record "Shpfy Company Location"; + CreateCustomer: Codeunit "Shpfy Create Customer"; + PaymentTermsCode: Code[10]; + ShopifyPaymentTermsId: BigInteger; + EmptyGuid: Guid; + begin + // [SCENARIO] Create a customer from a company with location with defined payment term. + Initialize(); + + // [GIVEN] Payment terms + PaymentTermsCode := CreatePaymentTerms(); + // [GIVEN] Shopify payment terms + ShopifyPaymentTermsId := CreateShopifyPaymentTerms(PaymentTermsCode); + // [GIVEN] Shopify Company + CreateCompany(ShopifyCompany, EmptyGuid); + // [GIVEN] Company Location + CreateCompanyLocation(CompanyLocation, ShopifyCompany, ShopifyPaymentTermsId); + // [GIVEN] TempShopifyCustomer + CreateTempShopifyCustomer(TempShopifyCustomer); + + // [WHEN] Invoke CreateCustomerFromCompany + CreateCustomer.SetShop(Shop); + CreateCustomer.SetTemplateCode(Shop."Customer Templ. Code"); + CreateCustomer.CreateCustomerFromCompany(ShopifyCompany, TempShopifyCustomer); + + // [THEN] Customer record is created with the correct payment terms. + Customer.GetBySystemId(ShopifyCompany."Customer SystemId"); + LibraryAssert.AreEqual(Customer."Payment Terms Code", PaymentTermsCode, 'Payment Terms Code'); + end; + + local procedure Initialize() + begin + Any.SetDefaultSeed(); + if IsInitialized then + exit; + Shop := InitializeTest.CreateShop(); + IsInitialized := true; + + Commit(); + end; + + local procedure CreatePaymentTerms(): Code[10] + var + PaymentTerms: Record "Payment Terms"; + begin + PaymentTerms.Init(); + PaymentTerms.Code := Any.AlphanumericText(10); + PaymentTerms.Insert(false); + exit(PaymentTerms.Code); + end; + + local procedure CreateShopifyPaymentTerms(PaymentTermsCode: Code[10]): BigInteger + var + ShopifyPaymentTerms: Record "Shpfy Payment Terms"; + begin + ShopifyPaymentTerms.Init(); + ShopifyPaymentTerms.Id := Any.IntegerInRange(10000, 99999); + ShopifyPaymentTerms."Payment Terms Code" := PaymentTermsCode; + ShopifyPaymentTerms.Insert(false); + exit(ShopifyPaymentTerms.Id); + end; + + local procedure CreateCustomerWithPaymentTerms(var Customer: Record Customer; PaymentTermsCode: Code[10]) + begin + Customer.Init(); + Customer."No." := Any.AlphanumericText(20); + Customer."Payment Terms Code" := PaymentTermsCode; + Customer.Insert(false); + end; + + local procedure CreateCompany(var ShopifyCompany: Record "Shpfy Company"; CustomerSystemId: Guid) + begin + ShopifyCompany.Init(); + ShopifyCompany.Id := Any.IntegerInRange(10000, 99999); + ShopifyCompany."Customer SystemId" := CustomerSystemId; + ShopifyCompany."Shop Id" := Shop."Shop Id"; + ShopifyCompany.Insert(false); + end; + + local procedure CreateCompanyLocation(var CompanyLocation: Record "Shpfy Company Location"; var ShopifyCompany: Record "Shpfy Company"; PaymentTermsId: BigInteger) + begin + CompanyLocation.Init(); + CompanyLocation."Company SystemId" := ShopifyCompany.SystemId; + CompanyLocation.Id := Any.IntegerInRange(10000, 99999); + CompanyLocation."Shpfy Payment Terms Id" := PaymentTermsId; + CompanyLocation.Insert(false); + + ShopifyCompany."Location Id" := CompanyLocation.Id; + ShopifyCompany.Modify(false); + end; + + local procedure CreateTempShopifyCustomer(var TempShopifyCustomer: Record "Shpfy Customer" temporary) + begin + TempShopifyCustomer.Init(); + TempShopifyCustomer.Id := Any.IntegerInRange(10000, 99999); + TempShopifyCustomer.Insert(false); + end; + + local procedure InvokeCompanyImport(var ShopifyCompany: Record "Shpfy Company"; LocationValues: Dictionary of [Text, Text]) + var + CompanyImport: Codeunit "Shpfy Company Import"; + CompanyImportSubs: Codeunit "Shpfy Company Import Subs."; + begin + BindSubscription(CompanyImportSubs); + CompanyImportSubs.SetLocationValues(LocationValues); + CompanyImport.SetShop(Shop); + ShopifyCompany.SetRange("Id", ShopifyCompany.Id); + CompanyImport.Run(ShopifyCompany); + UnbindSubscription(CompanyImportSubs); + end; + + local procedure VerifyShopifyCompanyLocationValues(var ShopifyCompany: Record "Shpfy Company"; LocationValues: Dictionary of [Text, Text]) + var + CompanyLocation: Record "Shpfy Company Location"; + Id, PaymentTermsId : BigInteger; + begin + Evaluate(Id, LocationValues.Get('id')); + Evaluate(PaymentTermsId, LocationValues.Get('paymentTermsTemplateId')); + CompanyLocation.SetRange("Company SystemId", ShopifyCompany.SystemId); + LibraryAssert.IsTrue(CompanyLocation.FindFirst(), 'Company location does not exist'); + LibraryAssert.AreEqual(Id, CompanyLocation.Id, 'Id not imported'); + LibraryAssert.AreEqual(LocationValues.Get('address1'), CompanyLocation.Address, 'Address not imported'); + LibraryAssert.AreEqual(LocationValues.Get('address2'), CompanyLocation."Address 2", 'Address 2 not imported'); + LibraryAssert.AreEqual(LocationValues.Get('phone'), CompanyLocation."Phone No.", 'Phone No. not imported'); + LibraryAssert.AreEqual(LocationValues.Get('zip'), CompanyLocation.Zip, 'Zip not imported'); + LibraryAssert.AreEqual(LocationValues.Get('city'), CompanyLocation.City, 'City not imported'); + LibraryAssert.AreEqual(LocationValues.Get('countryCode').ToUpper(), CompanyLocation."Country/Region Code", 'Country/Region Code not imported'); + LibraryAssert.AreEqual(LocationValues.Get('zoneCode').ToUpper(), CompanyLocation."Province Code", 'Province Code not imported'); + LibraryAssert.AreEqual(LocationValues.Get('province'), CompanyLocation."Province Name", 'Province Name not imported'); + LibraryAssert.AreEqual(PaymentTermsId, CompanyLocation."Shpfy Payment Terms Id", 'Payment Terms Id not imported'); + LibraryAssert.AreEqual(LocationValues.Get('taxRegistrationId'), CompanyLocation."Tax Registration Id", 'Tax Registration id not imported'); + end; + + local procedure CreateLocationValues(LocationValues: Dictionary of [Text, Text]) + begin + LocationValues.Add('id', Format(Any.IntegerInRange(10000, 99999))); + LocationValues.Add('address1', Any.AlphanumericText(20)); + LocationValues.Add('address2', Any.AlphanumericText(20)); + LocationValues.Add('phone', Format(Any.IntegerInRange(1000, 9999))); + LocationValues.Add('zip', Format(Any.IntegerInRange(1000, 9999))); + LocationValues.Add('city', Any.AlphanumericText(20)); + LocationValues.Add('countryCode', Any.AlphanumericText(2)); + LocationValues.Add('zoneCode', Any.AlphanumericText(2)); + LocationValues.Add('province', Any.AlphanumericText(20)); + LocationValues.Add('paymentTermsTemplateId', Format(Any.IntegerInRange(10000, 99999))); + LocationValues.Add('taxRegistrationId', Any.AlphanumericText(50)); + end; } \ No newline at end of file diff --git a/Apps/W1/Shopify/test/Companies/ShpfyCompanyInitialize.Codeunit.al b/Apps/W1/Shopify/test/Companies/ShpfyCompanyInitialize.Codeunit.al index 5f6a668583..48ed43e555 100644 --- a/Apps/W1/Shopify/test/Companies/ShpfyCompanyInitialize.Codeunit.al +++ b/Apps/W1/Shopify/test/Companies/ShpfyCompanyInitialize.Codeunit.al @@ -3,7 +3,6 @@ codeunit 139638 "Shpfy Company Initialize" SingleInstance = true; var - Any: Codeunit Any; internal procedure CreateShopifyCompanyLocation() CompanyLocation: Record "Shpfy Company Location" @@ -97,4 +96,50 @@ codeunit 139638 "Shpfy Company Initialize" JResult.ReadFrom(StrSubstNo(ResultLbl, Name, CompanyContactId, CustomerId, CompanyLocationId)); exit(JResult); end; + + internal procedure PaymentTermsGQLNode(): Text + begin + exit('buyerExperienceConfiguration: {paymentTermsTemplateId: \"gid://shopify/PaymentTermsTemplate/%1\"}'); + end; + + internal procedure CreateLocationResponse(LocationValues: Dictionary of [Text, Text]): Text + var + Any: Codeunit Any; + JObject: JsonObject; + JCompanyLocations: JsonObject; + JEdges: JsonArray; + JNode: JsonObject; + JBillingAddress: JsonObject; + JPaymentTerms: JsonObject; + LocationResponse: Text; + begin + JNode.Add('id', StrSubstNo('gid://shopify/CompanyLocation/%1', LocationValues.Get('id'))); + JBillingAddress.Add('address1', LocationValues.Get('address1')); + JBillingAddress.Add('address2', LocationValues.Get('address2')); + JBillingAddress.Add('city', LocationValues.Get('city')); + JBillingAddress.Add('countryCode', LocationValues.Get('countryCode')); + JBillingAddress.Add('zip', LocationValues.Get('zip')); + JBillingAddress.Add('phone', LocationValues.Get('phone')); + JBillingAddress.Add('zoneCode', LocationValues.Get('zoneCode')); + JBillingAddress.Add('province', LocationValues.Get('province')); + JNode.Add('billingAddress', JBillingAddress); + JNode.Add('taxRegistrationId', LocationValues.Get('taxRegistrationId')); + JPaymentTerms.ReadFrom(StrSubstNo('{"paymentTermsTemplate": {id: "gid://shopify/PaymentTermsTemplate/%1"}}', LocationValues.Get('paymentTermsTemplateId'))); + JNode.Add('buyerExperienceConfiguration', JPaymentTerms); + JEdges.Add(JNode); + JCompanyLocations.Add('edges', JEdges); + JObject.Add('companyLocations', JCompanyLocations); + JObject.WriteTo(LocationResponse); + exit(LocationResponse); + end; + + internal procedure TaxIdGQLNode(CompanyLocation: Record "Shpfy Company Location"): Text + begin + exit(StrSubstNo('locationId: \"gid://shopify/CompanyLocation/%1\", taxId: \"%2\"', CompanyLocation.Id, CompanyLocation."Tax Registration Id")); + end; + + internal procedure ExternalIdGQLNode(Customer: Record Customer): Text + begin + exit(StrSubstNo('externalId: \"%1\"', Customer."No.")); + end; } diff --git a/Apps/W1/Shopify/test/Companies/ShpfyCompanyMappingSubs.Codeunit.al b/Apps/W1/Shopify/test/Companies/ShpfyCompanyMappingSubs.Codeunit.al new file mode 100644 index 0000000000..f464dc7d48 --- /dev/null +++ b/Apps/W1/Shopify/test/Companies/ShpfyCompanyMappingSubs.Codeunit.al @@ -0,0 +1,56 @@ +codeunit 139629 "Shpfy Company Mapping Subs." +{ + EventSubscriberInstance = Manual; + + var + CompanyImportExecuted: Boolean; + + [EventSubscriber(ObjectType::Codeunit, Codeunit::"Shpfy Communication Events", 'OnClientSend', '', true, false)] + local procedure OnClientSend(HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) + begin + MakeResponse(HttpRequestMessage, HttpResponseMessage); + end; + + [EventSubscriber(ObjectType::Codeunit, Codeunit::"Shpfy Communication Events", 'OnGetContent', '', true, false)] + local procedure OnGetContent(HttpResponseMessage: HttpResponseMessage; var Response: Text) + begin + HttpResponseMessage.Content.ReadAs(Response); + end; + + local procedure MakeResponse(HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) + var + Uri: Text; + GraphQlQuery: Text; + GetCompanyGQLStartTok: Label '{"query":"{company(id: \"gid://shopify/Company/', Locked = true; + GetCompanyGQLEndTok: Label '\") {name id note createdAt updatedAt mainContact { id customer { id firstName lastName email phone}}}}"}', Locked = true; + GraphQLCmdTxt: Label '/graphql.json', Locked = true; + begin + case HttpRequestMessage.Method of + 'POST': + begin + Uri := HttpRequestMessage.GetRequestUri(); + if Uri.EndsWith(GraphQLCmdTxt) then + if HttpRequestMessage.Content.ReadAs(GraphQlQuery) then + if GraphQlQuery.StartsWith(GetCompanyGQLStartTok) and GraphQlQuery.EndsWith(GetCompanyGQLEndTok) then begin + HttpResponseMessage := GetEmptyResponse(); + CompanyImportExecuted := true; + end; + end; + end; + end; + + local procedure GetEmptyResponse(): HttpResponseMessage + var + HttpResponseMessage: HttpResponseMessage; + Body: Text; + begin + Body := '{}'; + HttpResponseMessage.Content.WriteFrom(Body); + exit(HttpResponseMessage); + end; + + internal procedure GetCompanyImportExecuted(): Boolean + begin + exit(CompanyImportExecuted); + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/test/Companies/ShpfyCompanyMappingTest.Codeunit.al b/Apps/W1/Shopify/test/Companies/ShpfyCompanyMappingTest.Codeunit.al new file mode 100644 index 0000000000..d2bcb5c942 --- /dev/null +++ b/Apps/W1/Shopify/test/Companies/ShpfyCompanyMappingTest.Codeunit.al @@ -0,0 +1,533 @@ +codeunit 139627 "Shpfy Company Mapping Test" +{ + Subtype = Test; + TestPermissions = Disabled; + + var + Shop: Record "Shpfy Shop"; + LibraryAssert: Codeunit "Library Assert"; + Any: Codeunit Any; + ShopifyInitializeTest: Codeunit "Shpfy Initialize Test"; + IsInitialized: Boolean; + + trigger OnRun() + begin + IsInitialized := false; + end; + + [Test] + procedure UnitTestFindMappingByDefaultCompanyMapping() + var + Customer: Record Customer; + ShopifyCompany: Record "Shpfy Company"; + TempShopifyCustomer: Record "Shpfy Customer" temporary; + FindMappingResult: Boolean; + begin + // [SCENARIO] FindMapping using DefaultCompanyMapping + Initialize(); + + // [GIVEN] Customer + CreateCustomer(Customer); + // [GIVEN] Shop with Company Mapping Type as Default Company Mapping + SetDefaultCompanyMapping(Customer); + // [GIVEN] Shopify Company with customer system id + CreateShopifyCompanyWithCustomerSysId(ShopifyCompany, Customer.SystemId); + + // [WHEN] FindMapping is called + InvokeFindMapping(ShopifyCompany, TempShopifyCustomer, FindMappingResult); + + // [THEN] The result is true + LibraryAssert.IsTrue(FindMappingResult, 'Mapping was not found.'); + end; + + [Test] + procedure UnitTestDoMappingByDefaultCompanyMappingWithRandomGuid() + var + Customer: Record Customer; + ShopifyCompany: Record "Shpfy Company"; + TempShopifyCustomer: Record "Shpfy Customer" temporary; + ShopifyCustomer: Record "Shpfy Customer"; + FindMappingResult: Boolean; + begin + // [SCENARIO] DoMapping using DefaultCompanyMapping with random guid for Shopify Company Customer System Id + Initialize(); + + // [GIVEN] Customer + CreateCustomer(Customer); + // [GIVEN] Shop with Company Mapping Type as Default Company Mapping + SetDefaultCompanyMapping(Customer); + // [GIVEN] Shopify Company with random guid for customer system id + CreateShopifyCompanyWithCustomerSysId(ShopifyCompany, CreateGuid()); + // [GIVEN] TempShopifyCustomer + CreateTempShopifyCustomer(TempShopifyCustomer, 0); + + // [WHEN] FindMapping is invoked + InvokeFindMapping(ShopifyCompany, TempShopifyCustomer, FindMappingResult); + + // [THEN] FindMapping result is true + LibraryAssert.IsTrue(FindMappingResult, 'Mapping was not found.'); + // [THEN] Shopify Customer is created + LibraryAssert.IsTrue(ShopifyCustomer.Get(TempShopifyCustomer.Id), 'Shopify Customer was not created.'); + // [THEN] Shopify Customer has the same customer system id as the Customer record + LibraryAssert.AreEqual(Customer.SystemId, ShopifyCustomer."Customer SystemId", 'Customer system Id not transferred to shopify customer.'); + // [THEN] Shopify Company has the same customer system id as the Customer record + ShopifyCompany.Get(ShopifyCompany.Id); + LibraryAssert.AreEqual(Customer.SystemId, ShopifyCompany."Customer SystemId", 'Customer system Id not transferred to shopify company.'); + // [THEN] Shopify Company main contact customer id is the same as the Shopify Customer id + LibraryAssert.AreEqual(ShopifyCustomer.Id, ShopifyCompany."Main Contact Customer Id", 'Main Contact Customer Id different than customer id.'); + end; + + [Test] + procedure UnitTestDoMappingByDefaultCompanyMappingWithEmptyGuid() + var + Customer: Record Customer; + ShopifyCompany: Record "Shpfy Company"; + TempShopifyCustomer: Record "Shpfy Customer" temporary; + ShopifyCustomer: Record "Shpfy Customer"; + FindMappingResult: Boolean; + EmptyGuid: Guid; + begin + // [SCENARIO] DoMapping using DefaultCompanyMapping with empty guid for Shopify Company Customer System Id + Initialize(); + + // [GIVEN] Customer + CreateCustomer(Customer); + // [GIVEN] Shop with Company Mapping Type as Default Company Mapping + SetDefaultCompanyMapping(Customer); + // [GIVEN] Shopify Company with empty guid for customer system id + CreateShopifyCompanyWithCustomerSysId(ShopifyCompany, EmptyGuid); + // [GIVEN] TempShopifyCustomer + CreateTempShopifyCustomer(TempShopifyCustomer, 0); + + // [WHEN] FindMapping is invoked + InvokeFindMapping(ShopifyCompany, TempShopifyCustomer, FindMappingResult); + + // [THEN] FindMapping result is true + LibraryAssert.IsTrue(FindMappingResult, 'Mapping was not found.'); + // [THEN] Shopify Customer is created + LibraryAssert.IsTrue(ShopifyCustomer.Get(TempShopifyCustomer.Id), 'Shopify Customer was not created.'); + // [THEN] Shopify Customer has the same customer system id as the Customer record + LibraryAssert.AreEqual(Customer.SystemId, ShopifyCustomer."Customer SystemId", 'Customer system Id not transferred to shopify customer.'); + // [THEN] Shopify Company has the same customer system id as the Customer record + ShopifyCompany.Get(ShopifyCompany.Id); + LibraryAssert.AreEqual(Customer.SystemId, ShopifyCompany."Customer SystemId", 'Customer system Id not transferred to shopify company.'); + // [THEN] Shopify Company main contact customer id is the same as the Shopify Customer id + LibraryAssert.AreEqual(ShopifyCustomer.Id, ShopifyCompany."Main Contact Customer Id", 'Main Contact Customer Id different than customer id.'); + end; + + [Test] + procedure UnitTestDoMappingByDefaultCompanyMappingWithExistingShopifyCustomer() + var + Customer: Record Customer; + ShopifyCompany: Record "Shpfy Company"; + TempShopifyCustomer: Record "Shpfy Customer" temporary; + ShopifyCustomer: Record "Shpfy Customer"; + ShopifyCustomerId: BigInteger; + FindMappingResult: Boolean; + EmptyGuid: Guid; + begin + // [SCENARIO] DoMapping using DefaultCompanyMapping with existing Shopify Customer + Initialize(); + + // [GIVEN] Customer + CreateCustomer(Customer); + // [GIVEN] Shop with Company Mapping Type as Default Company Mapping + SetDefaultCompanyMapping(Customer); + // [GIVEN] Shopify Company with customer system id + CreateShopifyCompanyWithCustomerSysId(ShopifyCompany, EmptyGuid); + // [GIVEN] Shopify Customer + ShopifyCustomerId := Any.IntegerInRange(10000, 99999); + CreateShopifyCustomer(ShopifyCustomer, ShopifyCustomerId); + // [GIVEN] TempShopifyCustomer + CreateTempShopifyCustomer(TempShopifyCustomer, ShopifyCustomerId); + + // [WHEN] FindMapping is invoked + InvokeFindMapping(ShopifyCompany, TempShopifyCustomer, FindMappingResult); + + // [THEN] FindMapping result is true + LibraryAssert.IsTrue(FindMappingResult, 'Mapping was not found.'); + // [THEN] Main Contact Customer Id is the same as the Shopify Customer id + ShopifyCompany.Get(ShopifyCompany.Id); + LibraryAssert.AreEqual(ShopifyCustomerId, ShopifyCompany."Main Contact Customer Id", 'Main contact customer Id different than customer id.'); + // [THEN] Shopify company customer system id is the same as the customer record + LibraryAssert.AreEqual(Customer.SystemId, ShopifyCompany."Customer SystemId", 'Customer system Id not transferred to shopify company.'); + end; + + [Test] + procedure UnitTestDoMappingByDefaultCompanyMapping() + var + Customer: Record Customer; + ShopifyCompanyId: BigInteger; + DoMappingResult: Code[20]; + begin + // [SCENARIO] DoMapping using DefaultCompanyMapping + Initialize(); + + // [GIVEN] Customer + CreateCustomer(Customer); + // [GIVEN] Shop with Company Mapping Type as Default Company Mapping + SetDefaultCompanyMapping(Customer); + // [GIVEN] Shopify Company Id + ShopifyCompanyId := Any.IntegerInRange(10000, 99999); + + // [WHEN] DoMapping is called + InvokeDoMapping(ShopifyCompanyId, DoMappingResult); + + // [THEN] The result is the same as the Customer No. field of the Customer record + LibraryAssert.AreEqual(Customer."No.", DoMappingResult, 'Mapping result is different than default company no.'); + end; + + [Test] + procedure UnitTestFindMappingByTaxId() + var + Customer: Record Customer; + ShopifyCompany: Record "Shpfy Company"; + TempShopifyCustomer: Record "Shpfy Customer" temporary; + FindMappingResult: Boolean; + begin + // [SCENARIO] FindMapping using By Tax Id + Initialize(); + + // [GIVEN] Shop with Company Mapping Type as By Tax Id + SetMappingByTaxId(); + // [GIVEN] Customer + CreateCustomer(Customer); + // [GIVEN] Shopify Company with customer system id + CreateShopifyCompanyWithCustomerSysId(ShopifyCompany, Customer.SystemId); + + // [WHEN] FindMapping is called + InvokeFindMapping(ShopifyCompany, TempShopifyCustomer, FindMappingResult); + + // [THEN] The result is true + LibraryAssert.IsTrue(FindMappingResult, 'Mapping was not found.'); + end; + + [Test] + procedure UnitTestFindMappingByTaxIdWithRegistrationNo() + var + Customer: Record Customer; + ShopifyCompany: Record "Shpfy Company"; + ShopifyCustomer: Record "Shpfy Customer"; + TempShopifyCustomer: Record "Shpfy Customer" temporary; + FindMappingResult: Boolean; + EmptyGuid: Guid; + begin + // [SCENARIO] FindMapping using By Tax Id with Registration No. + Initialize(); + + // [GIVEN] Shop with Company Mapping Type as By Tax Id + SetMappingByTaxId(); + // [GIVEN] Shop with Tax Registration Id Mapping as Registration No. + SetCompTaxIdMapping(Enum::"Shpfy Comp. Tax Id Mapping"::"Registration No."); + // [GIVEN] Customer with Registration No. + CreateCustomerWithRegistrationNo(Customer); + // [GIVEN] TempShopifyCustomer + CreateTempShopifyCustomer(TempShopifyCustomer, 0); + // [GIVEN] Shopify Company with empty guid for customer system id + CreateShopifyCompanyWithCustomerSysId(ShopifyCompany, EmptyGuid); + // [GIVEN] Company Location with Tax Registration Id + CreateCompanyLocationWithTaxId(ShopifyCompany, Customer."Registration Number"); + + // [WHEN] FindMapping is called + InvokeFindMapping(ShopifyCompany, TempShopifyCustomer, FindMappingResult); + + // [THEN] The result is true + LibraryAssert.IsTrue(FindMappingResult, 'Mapping was not found.'); + // [THEN] Shopify customer is created + LibraryAssert.IsTrue(ShopifyCustomer.Get(TempShopifyCustomer.Id), 'Shopify Customer was not created.'); + // [THEN] Shopify customer has the same customer system id as the customer record + LibraryAssert.AreEqual(Customer.SystemId, ShopifyCustomer."Customer SystemId", 'Customer system Id not transferred to shopify customer.'); + // [THEN] Shopify company has the same customer system id as the customer record + ShopifyCompany.Get(ShopifyCompany.Id); + LibraryAssert.AreEqual(ShopifyCustomer.Id, ShopifyCompany."Main Contact Customer Id", 'Customer system Id not transferred to shopify company.'); + // [THEN] Shopify company customer system id is the same as the customer record + LibraryAssert.AreEqual(Customer.SystemId, ShopifyCompany."Customer SystemId", 'Customer system Id not transferred to shopify company.'); + end; + + [Test] + procedure UnitTestFindMappingByTaxIdWithRegistrationNoAndRandomCustomerSysId() + var + Customer: Record Customer; + ShopifyCompany: Record "Shpfy Company"; + TempShopifyCustomer: Record "Shpfy Customer" temporary; + ShopifyCustomer: Record "Shpfy Customer"; + FindMappingResult: Boolean; + begin + // [SCENARIO] FindMapping using By Tax Id with Registration No. and random customer system id + Initialize(); + + // [GIVEN] Shop with Company Mapping Type as By Tax Id + SetMappingByTaxId(); + // [GIVEN] Shop with Tax Registration Id Mapping as Registration No. + SetCompTaxIdMapping(Enum::"Shpfy Comp. Tax Id Mapping"::"Registration No."); + // [GIVEN] Customer with Registration No. + CreateCustomerWithRegistrationNo(Customer); + // [GIVEN] TempShopifyCustomer + CreateTempShopifyCustomer(TempShopifyCustomer, 0); + // [GIVEN] Shopify Company with random guid for customer system id + CreateShopifyCompanyWithCustomerSysId(ShopifyCompany, CreateGuid()); + // [GIVEN] Company Location with Tax Registration Id + CreateCompanyLocationWithTaxId(ShopifyCompany, Customer."Registration Number"); + + // [WHEN] FindMapping is called + InvokeFindMapping(ShopifyCompany, TempShopifyCustomer, FindMappingResult); + + // [THEN] The result is true + LibraryAssert.IsTrue(FindMappingResult, 'Mapping was not found.'); + // [THEN] Shopify customer is created + LibraryAssert.IsTrue(ShopifyCustomer.Get(TempShopifyCustomer.Id), 'Shopify Customer was not created.'); + // [THEN] Shopify customer has the same customer system id as the customer record + LibraryAssert.AreEqual(Customer.SystemId, ShopifyCustomer."Customer SystemId", 'Customer system Id not transferred to shopify customer.'); + // [THEN] Shopify company has the same customer system id as the customer record + ShopifyCompany.Get(ShopifyCompany.Id); + LibraryAssert.AreEqual(ShopifyCustomer.Id, ShopifyCompany."Main Contact Customer Id", 'Customer system Id not transferred to shopify company.'); + // [THEN] Shopify company customer system id is the same as the customer record + LibraryAssert.AreEqual(Customer.SystemId, ShopifyCompany."Customer SystemId", 'Customer system Id not transferred to shopify company.'); + end; + + [Test] + procedure UnitTestFindMappingByTaxIdWithRegistrationNoAndExistingShopifyCustomer() + var + Customer: Record Customer; + ShopifyCompany: Record "Shpfy Company"; + ShopifyCustomer: Record "Shpfy Customer"; + TempShopifyCustomer: Record "Shpfy Customer" temporary; + FindMappingResult: Boolean; + EmptyGuid: Guid; + begin + // [SCENARIO] FindMapping using By Tax Id with Registration No. and existing Shopify Customer + Initialize(); + + // [GIVEN] Shop with Company Mapping Type as By Tax Id + SetMappingByTaxId(); + // [GIVEN] Shop with Tax Registration Id Mapping as Registration No. + SetCompTaxIdMapping(Enum::"Shpfy Comp. Tax Id Mapping"::"Registration No."); + // [GIVEN] Customer with Registration No. + CreateCustomerWithRegistrationNo(Customer); + // [GIVEN] Shopify Customer + CreateShopifyCustomer(ShopifyCustomer, 0); + // [GIVEN] TempShopifyCustomer + CreateTempShopifyCustomer(TempShopifyCustomer, ShopifyCustomer.Id); + // [GIVEN] Shopify Company with empty guid for customer system id + CreateShopifyCompanyWithCustomerSysId(ShopifyCompany, EmptyGuid); + // [GIVEN] Company Location with Tax Registration Id + CreateCompanyLocationWithTaxId(ShopifyCompany, Customer."Registration Number"); + + // [WHEN] FindMapping is called + InvokeFindMapping(ShopifyCompany, TempShopifyCustomer, FindMappingResult); + + // [THEN] The result is true + LibraryAssert.IsTrue(FindMappingResult, 'Mapping was not found.'); + // [THEN] Main Contact Customer Id is the same as the Shopify Customer id + ShopifyCompany.Get(ShopifyCompany.Id); + LibraryAssert.AreEqual(ShopifyCustomer.Id, ShopifyCompany."Main Contact Customer Id", 'Main contact customer Id different than customer id.'); + // [THEN] Shopify company customer system id is the same as the customer record + LibraryAssert.AreEqual(Customer.SystemId, ShopifyCompany."Customer SystemId", 'Customer system Id not transferred to shopify company.'); + end; + + [Test] + procedure UnitTestFindMappingByTaxIdWithVATRegistrationNo() + var + Customer: Record Customer; + ShopifyCompany: Record "Shpfy Company"; + ShopifyCustomer: Record "Shpfy Customer"; + TempShopifyCustomer: Record "Shpfy Customer" temporary; + FindMappingResult: Boolean; + EmptyGuid: Guid; + begin + // [SCENARIO] FindMapping using By Tax Id with VAT Registration No. + Initialize(); + + // [GIVEN] Shop with Company Mapping Type as By Tax Id + SetMappingByTaxId(); + // [GIVEN] Shop with Tax Registration Id Mapping as VAT Registration No. + SetCompTaxIdMapping(Enum::"Shpfy Comp. Tax Id Mapping"::"VAT Registration No."); + // [GIVEN] Customer with VAT Registration No. + CreateCustomerWithVATRegistrationNo(Customer); + // [GIVEN] Shopify Company + CreateShopifyCompanyWithCustomerSysId(ShopifyCompany, EmptyGuid); + // [GIVEN] Company Location with Tax Registration Id + CreateCompanyLocationWithTaxId(ShopifyCompany, Customer."VAT Registration No."); + // [GIVEN] Shopify Customer + CreateShopifyCustomer(ShopifyCustomer, 0); + // [GIVEN] TempShopifyCustomer + CreateTempShopifyCustomer(TempShopifyCustomer, ShopifyCustomer.Id); + + // [WHEN] FindMapping is called + InvokeFindMapping(ShopifyCompany, TempShopifyCustomer, FindMappingResult); + + // [THEN] The result is true + LibraryAssert.IsTrue(FindMappingResult, 'Mapping was not found.'); + // [THEN] Shopify company main contact customer id is the same as the Shopify Customer id + ShopifyCompany.Get(ShopifyCompany.Id); + LibraryAssert.AreEqual(ShopifyCustomer.Id, ShopifyCompany."Main Contact Customer Id", 'Main contact customer Id different than customer id.'); + // [THEN] Shopify company customer system id is the same as the customer record + LibraryAssert.AreEqual(Customer.SystemId, ShopifyCompany."Customer SystemId", 'Customer system Id not transferred to shopify company.'); + end; + + [Test] + procedure UnitTestDoMappingByTaxId() + var + Customer: Record Customer; + ShopifyCompany: Record "Shpfy Company"; + DoMappingResult: Code[20]; + begin + // [SCENARIO] DoMapping using By Tax Id mapping + Initialize(); + + // [GIVEN] Shop with Company Mapping Type as By Tax Id + SetMappingByTaxId(); + // [GIVEN] Customer + CreateCustomer(Customer); + // [GIVEN] Shopify Company with customer system id + CreateShopifyCompanyWithCustomerSysId(ShopifyCompany, Customer.SystemId); + + // [WHEN] DoMapping is called + InvokeDoMapping(ShopifyCompany.Id, DoMappingResult); + + // [THEN] The result is the same as the Customer No. field of the Customer record + LibraryAssert.AreEqual(Customer."No.", DoMappingResult, 'Mapping result is different than default company no.'); + end; + + [Test] + procedure UnitTestDoMappingByTaxIdWithEmptyGuid() + var + Customer: Record Customer; + ShopifyCompany: Record "Shpfy Company"; + CompanyMappingSubs: Codeunit "Shpfy Company Mapping Subs."; + DoMappingResult: Code[20]; + EmptyGuid: Guid; + begin + // [SCENARIO] DoMapping using By Tax Id mapping with empty guid for Shopify Company Customer System Id + Initialize(); + + // [GIVEN] Shop with Company Mapping Type as By Tax Id + SetMappingByTaxId(); + // [GIVEN] Customer + CreateCustomer(Customer); + // [GIVEN] Shopify Company with empty guid for customer system id + CreateShopifyCompanyWithCustomerSysId(ShopifyCompany, EmptyGuid); + + // [WHEN] DoMapping is called + BindSubscription(CompanyMappingSubs); + InvokeDoMapping(ShopifyCompany.Id, DoMappingResult); + UnbindSubscription(CompanyMappingSubs); + + // [THEN] Company Import codeunit is executed + LibraryAssert.IsTrue(CompanyMappingSubs.GetCompanyImportExecuted(), 'Company Import codeunit was not executed.'); + end; + + + local procedure Initialize() + begin + Any.SetDefaultSeed(); + + if IsInitialized then + exit; + + Shop := ShopifyInitializeTest.CreateShop(); + + IsInitialized := true; + Commit(); + end; + + local procedure CreateShopifyCompanyWithCustomerSysId(var ShopifyCompany: Record "Shpfy Company"; CustomerSystemId: Guid) + begin + ShopifyCompany.Init(); + ShopifyCompany.Id := Any.IntegerInRange(10000, 99999); + ShopifyCompany."Shop Code" := Shop."Code"; + ShopifyCompany."Customer SystemId" := CustomerSystemId; + ShopifyCompany.Insert(false); + end; + + local procedure CreateCustomer(var Customer: Record Customer) + begin + Customer.Init(); + Customer."No." := Any.AlphanumericText(20); + Customer.Insert(false); + end; + + local procedure SetDefaultCompanyMapping(var Customer: Record Customer) + begin + Shop."Company Mapping Type" := Enum::"Shpfy Company Mapping"::DefaultCompany; + Shop."Default Company No." := Customer."No."; + Shop.Modify(false); + end; + + local procedure CreateTempShopifyCustomer(var TempShopifyCustomer: Record "Shpfy Customer" temporary; Id: BigInteger) + begin + TempShopifyCustomer.Init(); + if Id <> 0 then + TempShopifyCustomer.Id := Id + else + TempShopifyCustomer.Id := Any.IntegerInRange(10000, 99999); + TempShopifyCustomer.Insert(false); + end; + + local procedure CreateShopifyCustomer(var ShopifyCustomer: Record "Shpfy Customer"; Id: BigInteger) + begin + ShopifyCustomer.Init(); + if Id <> 0 then + ShopifyCustomer.Id := Id + else + ShopifyCustomer.Id := Any.IntegerInRange(10000, 99999); + ShopifyCustomer.Insert(false); + end; + + local procedure InvokeFindMapping(var ShopifyCompany: Record "Shpfy Company"; var TempShopifyCustomer: Record "Shpfy Customer" temporary; var FindMappingResult: Boolean) + var + CompanyMapping: Codeunit "Shpfy Company Mapping"; + begin + CompanyMapping.SetShop(ShopifyCompany."Shop Code"); + FindMappingResult := CompanyMapping.FindMapping(ShopifyCompany, TempShopifyCustomer); + end; + + local procedure InvokeDoMapping(CompanyId: BigInteger; var DoMappingResult: Code[20]) + var + CompanyMapping: Codeunit "Shpfy Company Mapping"; + begin + CompanyMapping.SetShop(Shop); + DoMappingResult := CompanyMapping.DoMapping(CompanyId, '', false) + end; + + local procedure SetMappingByTaxId() + begin + Shop."Company Mapping Type" := Enum::"Shpfy Company Mapping"::"By Tax Id"; + Shop.Modify(false); + end; + + local procedure CreateCustomerWithRegistrationNo(var Customer: Record Customer) + begin + CreateCustomer(Customer); + Customer."Registration Number" := Any.AlphanumericText(20); + Customer.Modify(false); + end; + + local procedure CreateCompanyLocationWithTaxId(var ShopifyCompany: Record "Shpfy Company"; TaxId: Text[150]) + var + CompanyLocation: Record "Shpfy Company Location"; + begin + CompanyLocation.Init(); + CompanyLocation.Id := Any.IntegerInRange(10000, 99999); + CompanyLocation."Company SystemId" := ShopifyCompany.SystemId; + CompanyLocation."Tax Registration Id" := TaxId; + CompanyLocation.Insert(false); + + ShopifyCompany."Location Id" := CompanyLocation.Id; + ShopifyCompany.Modify(false); + end; + + local procedure CreateCustomerWithVATRegistrationNo(var Customer: Record Customer) + begin + CreateCustomer(Customer); + Customer."VAT Registration No." := Any.AlphanumericText(20); + Customer.Modify(false); + end; + + local procedure SetCompTaxIdMapping(ShopifyCompTaxIdMapping: Enum Microsoft.Integration.Shopify."Shpfy Comp. Tax Id Mapping") + begin + Shop."Shpfy Comp. Tax Id Mapping" := ShopifyCompTaxIdMapping; + Shop.Modify(false); + end; + +} diff --git a/Apps/W1/Shopify/test/Companies/ShpfyTaxIdMappingTest.Codeunit.al b/Apps/W1/Shopify/test/Companies/ShpfyTaxIdMappingTest.Codeunit.al new file mode 100644 index 0000000000..2a5aeabc61 --- /dev/null +++ b/Apps/W1/Shopify/test/Companies/ShpfyTaxIdMappingTest.Codeunit.al @@ -0,0 +1,156 @@ +codeunit 139628 "Shpfy Tax Id Mapping Test" +{ + Subtype = Test; + TestPermissions = Disabled; + + var + Any: Codeunit Any; + LibraryAssert: Codeunit "Library Assert"; + IsInitialized: Boolean; + + trigger OnRun() + begin + IsInitialized := false; + end; + + [Test] + procedure UnitTestGetTaxRegistrationIdForRegistrationNo() + var + Customer: Record Customer; + TaxRegistrationIdMapping: Interface "Shpfy Tax Registration Id Mapping"; + RegistrationNo: Text[50]; + RegistrationNoResult: Text[50]; + begin + // [SCENARIO] GetTaxRegistrationId for Tax Registration No. implementation of mapping + Initialize(); + + // [GIVEN] Registration No. + RegistrationNo := Any.AlphanumericText(50); + // [GIVEN] Customer + CreateCustomerWithRegistrationNo(Customer, RegistrationNo); + // [GIVEN] TaxRegistrationIdMapping interface is "Registration No." + TaxRegistrationIdMapping := Enum::"Shpfy Comp. Tax Id Mapping"::"Registration No."; + + // [WHEN] GetTaxRegistrationId is called + RegistrationNoResult := TaxRegistrationIdMapping.GetTaxRegistrationId(Customer); + + // [THEN] The result is the same as the Registration No. field of the Customer record + LibraryAssert.AreEqual(RegistrationNo, RegistrationNoResult, 'Registration No.'); + end; + + [Test] + procedure UnitTestGetTaxRegistrationIdForVATRegistrationNo() + var + Customer: Record Customer; + TaxRegistrationIdMapping: Interface "Shpfy Tax Registration Id Mapping"; + VATRegistrationNo: Text[20]; + VATRegistrationNoResult: Text[50]; + begin + // [SCENARIO] GetTaxRegistrationId for VAT Registration No. implementation of mapping + Initialize(); + + // [GIVEN] VAT Registration No. + VATRegistrationNo := Any.AlphanumericText(20); + // [GIVEN] Customer + CreateCustomerWithVATRegNo(Customer, VATRegistrationNo); + // [GIVEN] TaxRegistrationIdMapping interface is "VAT Registration No." + TaxRegistrationIdMapping := Enum::"Shpfy Comp. Tax Id Mapping"::"VAT Registration No."; + + // [WHEN] GetTaxRegistrationId is called + VATRegistrationNoResult := TaxRegistrationIdMapping.GetTaxRegistrationId(Customer); + + // [THEN] The result is the same as the VAT Registration No. field of the Customer record + LibraryAssert.AreEqual(VATRegistrationNo, VATRegistrationNoResult, 'VAT Registration No.'); + end; + + [Test] + procedure UnitTestSetMappingFiltersForCustomersWithRegistrationNo() + var + Customer: Record Customer; + CompanyLocation: Record "Shpfy Company Location"; + TaxRegistrationIdMapping: Interface "Shpfy Tax Registration Id Mapping"; + RegistrationNo: Text[50]; + begin + // [SCENARIO] SetMappingFiltersForCustomers for Tax Registration Id implementation of mapping + Initialize(); + + // [GIVEN] Registration No. + RegistrationNo := Any.AlphanumericText(50); + // [GIVEN] Customer record with Registration No. + CreateCustomerWithRegistrationNo(Customer, RegistrationNo); + // [GIVEN] CompanyLocation record with Tax Registration Id + CreateLocationWithTaxId(CompanyLocation, RegistrationNo); + // [GIVEN] TaxRegistrationIdMapping interface is "Registration No." + TaxRegistrationIdMapping := Enum::"Shpfy Comp. Tax Id Mapping"::"Registration No."; + + // [WHEN] SetMappingFiltersForCustomers is called + TaxRegistrationIdMapping.SetMappingFiltersForCustomers(Customer, CompanyLocation); + + // [THEN] The range of the Customer record is set to the Tax Registration Id of the CompanyLocation record + LibraryAssert.AreEqual(RegistrationNo, Customer.GetFilter("Registration Number"), 'Registration No. filter is not set correctly.'); + end; + + [Test] + procedure UnitTestSetMappingFiltersForCustomersWithVATRegistrationNo() + var + Customer: Record Customer; + CompanyLocation: Record "Shpfy Company Location"; + TaxRegistrationIdMapping: Interface "Shpfy Tax Registration Id Mapping"; + VATRegistrationNo: Text[20]; + begin + // [SCENARIO] SetMappingFiltersForCustomers for VAT Registration No. implementation of mapping + Initialize(); + + // [GIVEN] VAT Registration No. + VATRegistrationNo := Any.AlphanumericText(20); + // [GIVEN] Customer record with VAT Registration No. + CreateCustomerWithRegistrationNo(Customer, VATRegistrationNo); + // [GIVEN] CompanyLocation record with Tax Registration Id + CreateLocationWithTaxId(CompanyLocation, VATRegistrationNo); + // [GIVEN] TaxRegistrationIdMapping interface is "VAT Registration No." + TaxRegistrationIdMapping := Enum::"Shpfy Comp. Tax Id Mapping"::"VAT Registration No."; + + // [WHEN] SetMappingFiltersForCustomers is called + TaxRegistrationIdMapping.SetMappingFiltersForCustomers(Customer, CompanyLocation); + + // [THEN] The range of the Customer record is set to the Tax Registration Id of the CompanyLocation record + LibraryAssert.AreEqual(VATRegistrationNo, Customer.GetFilter("VAT Registration No."), 'VAT Registration No. filter is not set correctly.'); + end; + + + local procedure Initialize() + begin + Any.SetDefaultSeed(); + + if IsInitialized then + exit; + + IsInitialized := true; + + Commit(); + end; + + local procedure CreateCustomerWithRegistrationNo(var Customer: Record Customer; var RegistrationNo: Text[50]) + begin + Customer.Init(); + Customer."No." := Any.AlphanumericText(20); + Customer."Registration Number" := RegistrationNo; + Customer.Insert(false); + end; + + local procedure CreateCustomerWithVATRegNo(var Customer: Record Customer; var VATRegistrationNo: Text[20]) + begin + Customer.Init(); + Customer."No." := Any.AlphanumericText(20); + Customer."VAT Registration No." := VATRegistrationNo; + Customer.Insert(false); + end; + + local procedure CreateLocationWithTaxId(var CompanyLocation: Record "Shpfy Company Location"; var RegistrationNo: Text[50]) + begin + CompanyLocation.Init(); + CompanyLocation.Id := Any.IntegerInRange(10000, 99999); + CompanyLocation."Tax Registration Id" := RegistrationNo; + CompanyLocation.Insert(false); + end; +} \ No newline at end of file