Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically resolve to_shopify mapping chain from oldest to current version #517

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 39 additions & 4 deletions dev/lib/product_taxonomy/models/integration_version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,32 @@ def generate_all_distributions(output_path:, logger:, current_shopify_version: n
#
# @return [Array<IntegrationVersion>]
def load_all_from_source(current_shopify_version: nil, base_path: INTEGRATIONS_PATH)
integrations = YAML.safe_load_file(File.expand_path("integrations.yml", base_path))
integrations.pluck("available_versions").flatten.map do |integration_version|
integration_path = File.expand_path(integration_version, base_path)
load_from_source(integration_path:, current_shopify_version:)
integrations_yaml = YAML.safe_load_file(File.expand_path("integrations.yml", base_path))
integrations_yaml.flat_map do |integration_yaml|
versions = integration_yaml["available_versions"].sort.map do |version_path|
load_from_source(
integration_path: File.expand_path(version_path, base_path),
current_shopify_version:,
)
end

resolve_to_shopify_mappings_chain(versions) if integration_yaml["name"] == "shopify"

versions
end
end

# Resolve a set of IntegrationVersion to_shopify mappings so that each one maps to the latest version of the
# Shopify taxonomy.
#
# @param versions [Array<IntegrationVersion>] The versions to resolve, ordered from oldest to newest.
def resolve_to_shopify_mappings_chain(versions)
# Resolve newest version against current taxonomy
versions.last.resolve_to_shopify_mappings(nil)

# Resolve each older version against the one following it
versions.each_cons(2).reverse_each do |previous, next_version|
previous.resolve_to_shopify_mappings(next_version)
end
end

Expand Down Expand Up @@ -155,6 +177,19 @@ def generate_distribution(output_path:, direction:)
)
end

# Resolve the output categories of to_shopify mappings to the next version of the Shopify taxonomy.
#
# @param next_integration_version [IntegrationVersion | nil] The IntegrationVersion defining mappings to the next
# newer version of the Shopify taxonomy. If nil, the latest version of the Shopify taxonomy is used.
def resolve_to_shopify_mappings(next_integration_version)
@to_shopify_mappings.each do |mapping|
newer_mapping = next_integration_version&.to_shopify_mappings&.find do
_1.input_category["id"] == mapping.output_category
end
mapping.output_category = newer_mapping&.output_category || Category.find_by(id: mapping.output_category)
end
end

# For a mapping to an external taxonomy, get the IDs of external categories that are not mapped from Shopify.
#
# @return [Array<String>] IDs of external categories not mapped from the Shopify taxonomy. Empty if there are no
Expand Down
16 changes: 12 additions & 4 deletions dev/lib/product_taxonomy/models/mapping_rule.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ def load_rules_from_source(integration_path:, direction:, full_names_by_id:)

is_to_shopify = direction == :to_shopify
input_category = is_to_shopify ? full_names_by_id[input_id] : Category.find_by(id: input_id)
output_category = is_to_shopify ? Category.find_by(id: output_id) : full_names_by_id[output_id]
# We set output_category to be the raw output ID if is_to_shopify is true, with an expectation that it will
# be resolved to a `Category` before the rule is serialized to JSON or TXT.
# See `IntegrationVersion#resolve_to_shopify_mappings`.
output_category = is_to_shopify ? output_id : full_names_by_id[output_id]

raise ArgumentError, "Input category not found for mapping rule: #{rule}" unless input_category
raise ArgumentError, "Output category not found for mapping rule: #{rule}" unless output_category
Expand All @@ -41,7 +44,8 @@ def load_rules_from_source(integration_path:, direction:, full_names_by_id:)
end
end

attr_reader :input_category, :output_category
attr_reader :input_category
attr_accessor :output_category

def initialize(input_category:, output_category:)
@input_category = input_category
Expand Down Expand Up @@ -87,19 +91,23 @@ def category_json(category)
id: category["id"].to_s,
full_name: category["full_name"],
}
else
elsif category.is_a?(Category)
{
id: category.gid,
full_name: category.full_name,
}
else
raise ArgumentError, "Mapping rule category not resolved. Raw value: #{category}"
end
end

def category_txt(category)
if category.is_a?(Hash)
category["full_name"]
else
elsif category.is_a?(Category)
category.full_name
else
raise ArgumentError, "Mapping rule category not resolved. Raw value: #{category}"
end
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
- id: 1
full_name: Animals & Pet Supplies (foocommerce)
full_name: Apparel & Accessories (foocommerce)
- id: 2
full_name: Animals & Pet Supplies > Live Animals (foocommerce)
full_name: Apparel & Accessories > Clothing (foocommerce)
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
---
rules:
- input:
product_category_id: ap
product_category_id: aa
output:
product_category_id:
- '1'
- input:
product_category_id: ap-1
product_category_id: aa-1
output:
product_category_id:
- '2'
2 changes: 2 additions & 0 deletions dev/test/fixtures/data/integrations/integrations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@
- name: shopify
available_versions:
- shopify/2020-01
- shopify/2021-01
- shopify/2022-01
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
- id: 1
full_name: Animals & Pet Supplies (old shopify)
full_name: Apparel & Accessories (2020-01)
- id: 2
full_name: Animals & Pet Supplies > Live Animals (old shopify)
full_name: Apparel & Accessories > Clothing (2020-01)
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
---
input_taxonomy: shopify/2020-01
output_taxonomy: shopify/2021-01
rules:
- input:
product_category_id: 1
output:
product_category_id:
- ap
- aa
- input:
product_category_id: 2
output:
product_category_id:
- ap-1
- aa-1
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
- id: aa-1
full_name: Apparel & Accessories > Clothing (2021-01)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
input_taxonomy: shopify/2021-01
output_taxonomy: shopify/2022-01
rules:
- input:
product_category_id: aa-1
output:
product_category_id:
- aa-2
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
- id: aa-2
full_name: Apparel & Accessories > Clothing Accessories (2022-01)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
input_taxonomy: shopify/2022-01
output_taxonomy: shopify/2025-01-unstable
rules:
- input:
product_category_id: aa-2
output:
product_category_id:
- aa-3
125 changes: 125 additions & 0 deletions dev/test/fixtures/dist/en/integrations/all_mappings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
{
"version": "2025-01-unstable",
"mappings": [
{
"input_taxonomy": "shopify/2025-01-unstable",
"output_taxonomy": "foocommerce/1.0.0",
"rules": [
{
"input": {
"category": {
"id": "gid://shopify/TaxonomyCategory/aa",
"full_name": "Apparel & Accessories"
}
},
"output": {
"category": [
{
"id": "1",
"full_name": "Apparel & Accessories (foocommerce)"
}
]
}
},
{
"input": {
"category": {
"id": "gid://shopify/TaxonomyCategory/aa-1",
"full_name": "Apparel & Accessories > Clothing"
}
},
"output": {
"category": [
{
"id": "2",
"full_name": "Apparel & Accessories > Clothing (foocommerce)"
}
]
}
}
]
},
{
"input_taxonomy": "shopify/2020-01",
"output_taxonomy": "shopify/2025-01-unstable",
"rules": [
{
"input": {
"category": {
"id": "1",
"full_name": "Apparel & Accessories (2020-01)"
}
},
"output": {
"category": [
{
"id": "gid://shopify/TaxonomyCategory/aa",
"full_name": "Apparel & Accessories"
}
]
}
},
{
"input": {
"category": {
"id": "2",
"full_name": "Apparel & Accessories > Clothing (2020-01)"
}
},
"output": {
"category": [
{
"id": "gid://shopify/TaxonomyCategory/aa-3",
"full_name": "Apparel & Accessories > Costumes & Accessories"
}
]
}
}
]
},
{
"input_taxonomy": "shopify/2021-01",
"output_taxonomy": "shopify/2025-01-unstable",
"rules": [
{
"input": {
"category": {
"id": "aa-1",
"full_name": "Apparel & Accessories > Clothing (2021-01)"
}
},
"output": {
"category": [
{
"id": "gid://shopify/TaxonomyCategory/aa-3",
"full_name": "Apparel & Accessories > Costumes & Accessories"
}
]
}
}
]
},
{
"input_taxonomy": "shopify/2022-01",
"output_taxonomy": "shopify/2025-01-unstable",
"rules": [
{
"input": {
"category": {
"id": "aa-2",
"full_name": "Apparel & Accessories > Clothing Accessories (2022-01)"
}
},
"output": {
"category": [
{
"id": "gid://shopify/TaxonomyCategory/aa-3",
"full_name": "Apparel & Accessories > Costumes & Accessories"
}
]
}
}
]
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"version": "2025-01-unstable",
"mappings": [
{
"input_taxonomy": "shopify/2025-01-unstable",
"output_taxonomy": "foocommerce/1.0.0",
"rules": [
{
"input": {
"category": {
"id": "gid://shopify/TaxonomyCategory/aa",
"full_name": "Apparel & Accessories"
}
},
"output": {
"category": [
{
"id": "1",
"full_name": "Apparel & Accessories (foocommerce)"
}
]
}
},
{
"input": {
"category": {
"id": "gid://shopify/TaxonomyCategory/aa-1",
"full_name": "Apparel & Accessories > Clothing"
}
},
"output": {
"category": [
{
"id": "2",
"full_name": "Apparel & Accessories > Clothing (foocommerce)"
}
]
}
}
]
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Shopify Product Taxonomy - Mapping shopify/2025-01-unstable to foocommerce/1.0.0
# Format:
# → {base taxonomy category name}
# ⇒ {mapped taxonomy category name}

→ Apparel & Accessories
⇒ Apparel & Accessories (foocommerce)

→ Apparel & Accessories > Clothing
⇒ Apparel & Accessories > Clothing (foocommerce)
Loading
Loading