huginn_acumen_product_agent 1.5.2 → 1.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7dde4939a6f527acdc57c3cca3b489046521b4f9220e369d76424da6a34e18e5
4
- data.tar.gz: dce7f773ea6ff04bf58a98816d6d7f1624e56148c722ee694488c06a10cd84a9
3
+ metadata.gz: 15346dc00cb87c79547be2024b2957762649181385a8863e98159acc7fc7c106
4
+ data.tar.gz: 18face53f1022e63bb4b554ba60736e00f592775b38909d559f6f5e2c7eea792
5
5
  SHA512:
6
- metadata.gz: b665673955979aebd6a03fae4f240a40eb4ae4623103ee208bbcaf5ed5b220cc5619584bb0531b5cf8981c5cf2aa304907ab53bbcc402507689d38cb3064137b
7
- data.tar.gz: 76435c4a56a302ff36d193ca3e8cb1c42a6ab862e2536b1e31f9b3272826ef25f929450f369f59c5cb66becd189501754b7045e78e32782c8a5bdefe9a4dacba
6
+ metadata.gz: 3ee1716eb040c991c36911b8d9fc514e6b1084a351ea92f037fb02c46b384b2d9de00c2f51d23b31eff9d98fa597f7e365c13a225f8187da1a8b689dcf385b91
7
+ data.tar.gz: 6cfc6a2383668400b21de9386207eda46aa01510f17f9471823377bd6763615ecdf7d884f2d3d579c2a5432d6f49d6e931f0e1bcc3c8d93209aac39907e3aeaa
@@ -95,6 +95,8 @@ class AcumenClient
95
95
  <column_name>Inv_Product.Category</column_name>
96
96
  <column_name>Inv_Product.Next_Release</column_name>
97
97
  <column_name>Inv_Product.BO_Reason</column_name>
98
+ <column_name>Inv_Product.Not_On_Website</column_name>
99
+ <column_name>Inv_Product.Not_Active</column_name>
98
100
  </requested_output>
99
101
  </acusoapRequest>
100
102
  XML
@@ -11,7 +11,28 @@ module Agents
11
11
  default_schedule 'never'
12
12
 
13
13
  description <<-MD
14
- Huginn agent for sane ACUMEN product data.
14
+ Huginn agent for retrieving sane ACUMEN product data.
15
+
16
+ ## Agent Options
17
+ The following outlines the available options in this agent
18
+
19
+ ### Acumen Connection
20
+ * endpoint: The root URL for the Acumen API
21
+ * site_code: The site code from Acumen
22
+ * password: The Acumen API password
23
+
24
+ ### Variant Settings
25
+ * physical_formats: A list of the formats associated with a physical product
26
+ * digital_formats: A list of the formats associated with a digital product
27
+
28
+ ### Product Attributes
29
+ * attribute_to_property: An optional map linking Acumen attributes to Schema.org
30
+ product properties.
31
+
32
+ ### Other Options
33
+ * ignore_skus: An optional array of Acumen product skus that will be intentionally
34
+ excluded from any output.
35
+
15
36
  MD
16
37
 
17
38
  def default_options
@@ -22,7 +43,6 @@ module Agents
22
43
  'physical_formats' => [],
23
44
  'digital_formats' => [],
24
45
  'attribute_to_property' => {},
25
- 'contributor_types_map' => {},
26
46
  }
27
47
  end
28
48
 
@@ -51,8 +71,10 @@ module Agents
51
71
  errors.add(:base, "if provided, attribute_to_property must be a hash")
52
72
  end
53
73
 
54
- unless options['contributor_types_map'].is_a?(Hash)
55
- errors.add(:base, "if provided, contributor_types_map must be a hash")
74
+ if options['ignore_skus']
75
+ unless options['ignore_skus'].is_a?(Array)
76
+ errors.add(:base, "if provided, ignore_skus must be an array")
77
+ end
56
78
  end
57
79
  end
58
80
 
@@ -78,6 +100,7 @@ module Agents
78
100
  password = interpolated['password']
79
101
  physical_formats = interpolated['physical_formats']
80
102
  digital_formats = interpolated['digital_formats']
103
+ ignore_skus = interpolated['ignore_skus'] ? interpolated['ignore_skus'] : []
81
104
 
82
105
  auth = {
83
106
  'site_code' => site_code,
@@ -89,6 +112,7 @@ module Agents
89
112
  ids = event.payload['ids']
90
113
  products = get_products_by_ids(client, ids)
91
114
  products = get_product_variants(client, products, physical_formats, digital_formats)
115
+ products = get_master_products_by_id(client, products)
92
116
  products = get_product_categories(client, products)
93
117
  products = get_product_contributors(client, products)
94
118
 
@@ -104,7 +128,9 @@ module Agents
104
128
  end
105
129
 
106
130
  products.each do |product|
107
- create_event payload: product
131
+ unless ignore_skus.include?(product['sku'])
132
+ create_event payload: product
133
+ end
108
134
  end
109
135
  end
110
136
 
@@ -10,6 +10,8 @@ module AcumenProductQueryConcern
10
10
 
11
11
  def get_products_by_ids(acumen_client, ids)
12
12
  response = acumen_client.get_products(ids)
13
+ products = []
14
+
13
15
  products = parse_product_request(response)
14
16
 
15
17
  response = acumen_client.get_products_marketing(ids)
@@ -69,6 +71,34 @@ module AcumenProductQueryConcern
69
71
  products
70
72
  end
71
73
 
74
+ def get_master_products_by_id(client, products)
75
+ master_products = []
76
+
77
+ products.each do |product|
78
+ wrapper_id = product['identifier']
79
+ master_id = 0
80
+ product['model'].each do |variant|
81
+ if variant['acumenAttributes']['is_master'] && variant['isAvailableForPurchase']
82
+ master_id = variant['identifier']
83
+ end
84
+ end
85
+ if wrapper_id == master_id || master_id == 0
86
+ master_products.push(product)
87
+ else
88
+ if (master_products.find { |p| p['identifier'] == master_id }).nil?
89
+ reloaded_product = get_products_by_ids(client, [master_id.to_s])[0]
90
+
91
+ unless reloaded_product.nil?
92
+ reloaded_product['model'] = product['model']
93
+ master_products.push(reloaded_product)
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ master_products
100
+ end
101
+
72
102
  def get_product_variants(acumen_client, products, physical_formats, digital_formats)
73
103
  ids = products.map { |product| product['identifier'] }
74
104
  # fetch product/variant relationships
@@ -86,20 +116,27 @@ module AcumenProductQueryConcern
86
116
 
87
117
  def get_product_categories(acumen_client, products)
88
118
  # fetch categories
89
- skus = products.map { |product| product['sku'] }
90
- response = acumen_client.get_product_categories(skus)
91
- categories = process_product_categories_query(response)
119
+ categories_map = {}
120
+
121
+ skus = products.map { |product| product['model'].map { |m| m['sku'] } }
122
+ skus.each do |sku_set|
123
+ sku_set.each do |sku|
124
+ response = acumen_client.get_product_categories([sku])
125
+ categories = process_product_categories_query(response)
126
+ categories_map[sku] = categories != {} ? categories[sku] : []
127
+ end
128
+ end
92
129
 
93
130
  # map categories to products
94
131
  products.each do |product|
95
- sku = product['sku']
96
- if categories[sku]
97
- active = categories[sku].select { |c| c['inactive'] == '0' }
98
- product['categories'] = active.map do |category|
99
- {
100
- '@type' => 'Thing',
101
- 'identifier' => category['category_id']
102
- }
132
+ product['model'].each do |variant|
133
+ variant['categories'] = []
134
+ categories = categories_map[variant['sku']].select { |c| c['inactive'] == '0' }
135
+ categories.map do |c|
136
+ variant['categories'].push({
137
+ '@type' => 'Thing',
138
+ 'identifier' => c['category_id']
139
+ })
103
140
  end
104
141
  end
105
142
  end
@@ -120,6 +157,7 @@ module AcumenProductQueryConcern
120
157
  variant['@type'] = 'ProductModel'
121
158
  variant['isDefault'] = false
122
159
  variant['isTaxable'] = field_value(p, 'Inv_Product.Taxable') == '1'
160
+ variant['isAvailableForPurchase'] = field_value(p, 'Inv_Product.Not_On_Website') == '0'
123
161
  variant['acumenAttributes'] = {
124
162
  'is_master' => field_value(p, 'Inv_Product.OnWeb_LinkOnly') == '0'
125
163
  }
@@ -154,6 +192,7 @@ module AcumenProductQueryConcern
154
192
  'info_alpha_1' => field_value(p, 'Inv_Product.Info_Alpha_1'),
155
193
  'info_boolean_1' => field_value(p, 'Inv_Product.Info_Boolean_1'),
156
194
  },
195
+ 'isAvailableForPurchase' => field_value(p, variant['isAvailableForPurchase']),
157
196
  }
158
197
 
159
198
  category = field_value(p, 'Inv_Product.Category')
@@ -397,6 +436,7 @@ module AcumenProductQueryConcern
397
436
  result.each do |product|
398
437
  if product['model'].length == 1
399
438
  product['model'][0]['isDefault'] = true
439
+ set_base_sku(product, product['model'][0]['sku'])
400
440
  next
401
441
  else
402
442
  physical_formats.each do |val|
@@ -417,6 +457,17 @@ module AcumenProductQueryConcern
417
457
  end
418
458
  end
419
459
  end
460
+
461
+ model_ids = product['model'].map { |m| m['identifier'] }
462
+ primary_variant = product['model'].select { |m| m['identifier'] == model_ids.min }.first
463
+
464
+ # Set the base SKU to the SKU of the oldest record.
465
+ # The base_sku property is designed to be a system value specific to the inegration using this agent.
466
+ # As a result, we don't particularly care what that value is so long as we can retrieve it consistently
467
+ # across executions. If a paperback product is created first, this will always return that product's SKU
468
+ # as the base. This gives us a consistent way to link Acumen products to an external system where database
469
+ # IDs may not match.
470
+ set_base_sku(product, primary_variant ? primary_variant['sku'] : product['model'][0]['sku'])
420
471
  end
421
472
  result
422
473
  end
@@ -436,6 +487,18 @@ module AcumenProductQueryConcern
436
487
  field[key]['__content__'] if field[key]
437
488
  end
438
489
 
490
+ def set_base_sku(product, sku)
491
+
492
+ product['additionalProperty'].push({
493
+ '@type' => 'PropertyValue',
494
+ 'propertyID' => 'baseSku',
495
+ 'name' => 'Base SKU',
496
+ 'value' => sku,
497
+ })
498
+
499
+ product
500
+ end
501
+
439
502
  def quantitative_value(value, unit)
440
503
  {
441
504
  '@type' => 'QuantitativeValue',
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: huginn_acumen_product_agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.2
4
+ version: 1.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jacob Spizziri
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-01 00:00:00.000000000 Z
11
+ date: 2020-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler