jekyll-spree-client 0.1.8 → 0.1.13

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: 6d61e03498ee1c84997ca8c13b5bed76f972ba1f2de004475b2a06246fcbe05d
4
- data.tar.gz: 0f966ba2fb7ef2f2e9343fdec035a73d6232c3c84f908ea056c8b2e8f38fea53
3
+ metadata.gz: c3313a5acca299870b21648a253999a7bda4fae1c50a8ada64ba08bf710ee677
4
+ data.tar.gz: 15ce97b96ab22eb484960cea96a98549bc6ba972ba82599442f67d5ed6c32925
5
5
  SHA512:
6
- metadata.gz: e3b78dc6de970d05a7f5a9ff41f3dbf270bf85babf784310a6cac3b5f049b56e0169ebac3518d909a2123803af844467a8c20de3f794b10258845f1ba8ac3ff9
7
- data.tar.gz: fc55c726b86464cf3fb0639a645fd75201c43e07e90facad64829408c79317c1473a8854b447c2da5740c8763c9bd5cf89de44b54be2ebd5f5e13f8a3db88cbd
6
+ metadata.gz: 061be8dc0a119fd8b106e08dd5edc7506aa2d297fd213012f1442744349bcb8d0e955c1887597154510368e9c866e59e597d484f33ede18cf74e76caeb28c27e
7
+ data.tar.gz: 2a6e0c0e080ba05a8d94d7b383d445fe7e7aa96b113f053ece6b9528d9e80ad1bfc886f41cad37e97c5bfbb533ab44d4e4099600ef7e6501cc3d4a6ea05d4db3
data/README.md CHANGED
@@ -16,16 +16,6 @@ conversion unless you store prices as strings.
16
16
 
17
17
  You can use Integer and Floats now!
18
18
 
19
- ### Update
20
-
21
- The issue is that Spree expects to receive prices in the locale format
22
- (ie, "200,00") but will return them on Ruby's `to_s` conversion
23
- ("200.0") so we need to reconvert them to our current format and juggle
24
- between them.
25
-
26
- We'll deal with `Integer` for now until we find [a better
27
- solution](https://github.com/spree/spree/issues/10556).
28
-
29
19
  ## Installation
30
20
 
31
21
  Add this line to your site's Gemfile:
@@ -77,8 +67,10 @@ Add the required fields in their frontmatter:
77
67
  ---
78
68
  layout: post
79
69
  title: A product
70
+ description: With a description
80
71
  sku: A unique ID
81
72
  price: 100.00
73
+ cost_price: 50.0
82
74
  stock: 100
83
75
  weight: 100
84
76
  height: 100
@@ -90,18 +82,64 @@ depth: 100
90
82
  The layout doesn't matter, but we recommend to use a layout for
91
83
  products.
92
84
 
85
+ ### Layouts
86
+
87
+ You'll need four layouts and at least a corresponding post, one for each
88
+ step of the buying process.
89
+
90
+ * `cart` the cart, shows the order details
91
+ * `shipment` shipping and billing addresses, shipping rates apply here
92
+ * `payment` select payment methods
93
+ * `confirmation` order confirmation page
94
+
95
+ They'll be available on Liquid under the `site.STEP` keys.
96
+
97
+ ### Hooks
98
+
99
+ If you need to do some data manipulation before and after
100
+ synchronization is done, you can use hooks. In a `_plugins/spree.rb`
101
+ file:
102
+
103
+ ```ruby
104
+ Jekyll::Hooks.register :spree, :pre_render do |spree|
105
+ spree.local_products.each do |product|
106
+ product.data['_description'] = product.data['description']
107
+ product.data['description'] = product.data['productore']&.data&.dig('title')
108
+ end
109
+ end
110
+
111
+ Jekyll::Hooks.register :spree, :post_render do |spree|
112
+ spree.local_products.each do |product|
113
+ product.data['description'] = product.data.delete '_description'
114
+
115
+ product.data.delete 'description' unless product.data['description']
116
+ end
117
+ end
118
+ ```
119
+
120
+ This plugin gets the description value from another document (they're
121
+ linked using
122
+ [jekyll-linked-posts](https://0xacab.org/sutty/jekyll/jekyll-linked-posts/),
123
+ it's a real example!), and then recovers it.
124
+
125
+ * `pre_render` runs just before starting synchronization
126
+ * `post_render` run after synchronization and before writing changes
127
+
93
128
  ### Building the site
94
129
 
95
130
  During site build, the plugin will communicate with the Spree API and
96
- create products when they don't exist or update their price, current
97
- stock and the other values.
131
+ create products when they don't exist or locally update their price,
132
+ current stock and the other values.
98
133
 
99
134
  Some fields will appear on the frontmatter:
100
135
 
101
136
  ```yaml
102
137
  variant_id: 1
103
138
  in_stock: true
104
- sync_error: 2020-10-10 00:00:00 UTC
139
+ errors:
140
+ time: 2020-10-10 00:00:00 UTC
141
+ messages:
142
+ - Something went wrong
105
143
  ```
106
144
 
107
145
  * `variant_id` is the ID in the Spree database.
@@ -109,11 +147,27 @@ sync_error: 2020-10-10 00:00:00 UTC
109
147
  * `in_stock` is true or false according to availability (Spree decides
110
148
  this).
111
149
 
112
- * `sync_error` if the synchronization fails there will be a timestamp
113
- here.
150
+ * `errors` if the synchronization fails there will be a timestamp and
151
+ some messages here.
114
152
 
115
153
  ## Notes
116
154
 
155
+ * Synchronization follows this rules.
156
+
157
+ If the product doesn't exist on Spree, it's created.
158
+
159
+ If it does, the Jekyll document is updated with price, weight,
160
+ dimensions and stock.
161
+
162
+ It means once the product is created on Spree, Spree manages this
163
+ variables.
164
+
165
+ But Product properties like description and metadata are updated from
166
+ Jekyll to Spree.
167
+
168
+ We want this to change in the near future but we need to think a way
169
+ to prevent conflicts.
170
+
117
171
  * All products are created as "master variants" on Spree. There will be
118
172
  no pictures, taxonomies or other values, only basic product
119
173
  information.
@@ -126,11 +180,12 @@ sync_error: 2020-10-10 00:00:00 UTC
126
180
  * Stock is added to the default stock location, meaning the first active
127
181
  one. The API doesn't show or allows to query the actual default.
128
182
 
129
- * The `price` is in the default currency.
183
+ * `price` and `cost_price` are expressed in Spree's default currency.
130
184
 
131
185
  * If you install the `jekyll-write-and-commit-changes` plugin it will
132
- save the data back to disk when you build with `JEKYLL_ENV=production`
133
- environment variable.
186
+ save the data back to disk when you build. Using the
187
+ `JEKYLL_ENV=production` environment variable will also commit changes
188
+ to git.
134
189
 
135
190
  * Check the shipping category ID on Spree, since there's no API for it,
136
191
  you need to provide it manually, default is `1`.
@@ -6,7 +6,20 @@ require_relative 'jekyll/spree_client'
6
6
  # matter. The SKU needs to be unique, but this plugin doesn't ensure
7
7
  # that. Duplicated SKUs will be silently ignored for now.
8
8
  Jekyll::Hooks.register :site, :post_read do |site|
9
- next unless ENV['SPREE_API_KEY']
9
+ # Ordered articles
10
+ posts = site.site_payload['site']['posts']
11
+
12
+ # Make steps available to other articles
13
+ %w[cart shipment payment confirmation].each do |step|
14
+ site.config[step] = posts.find do |doc|
15
+ doc.data['layout'] == step
16
+ end
17
+ end
18
+
19
+ if ENV['SPREE_API_KEY'].nil? || ENV['SPREE_API_KEY'].empty?
20
+ Jekyll.logger.warn "SPREE_API_KEY environment variable missing, skipping syncrhonization"
21
+ next
22
+ end
10
23
 
11
24
  config = site.config['spree']&.transform_keys(&:to_sym) || {}
12
25
  config.merge!(site: site, api_key: ENV['SPREE_API_KEY'], spree_url: ENV['SPREE_URL'])
@@ -18,14 +31,4 @@ Jekyll::Hooks.register :site, :post_read do |site|
18
31
  if ENV['JEKYLL_ENV'] == 'production' && site.respond_to?(:repository)
19
32
  site.repository.commit site.data.dig(site.config['locale'], 'spree', 'commit') || 'Spree synchronization'
20
33
  end
21
-
22
- # Ordered articles
23
- posts = site.site_payload['site']['posts']
24
-
25
- # Make steps available to other articles
26
- %w[cart shipment payment confirmation].each do |step|
27
- site.config[step] = posts.find do |doc|
28
- doc.data['layout'] == step
29
- end
30
- end
31
34
  end
@@ -33,7 +33,21 @@ module Jekyll
33
33
  #
34
34
  # @return [Array]
35
35
  def variant_fields
36
- @variant_fields ||= %w[price weight height width depth].freeze
36
+ @variant_fields ||= %w[price weight height width depth cost_price pay_what_you_can].freeze
37
+ end
38
+
39
+ # Fields that can change locally and we need to sync to Spree
40
+ #
41
+ # @return [Array]
42
+ def product_fields
43
+ @product_fields ||= %w[name description meta_description meta_keywords meta_title].freeze
44
+ end
45
+
46
+ # All fields, using during creation
47
+ #
48
+ # @return [Array]
49
+ def create_fields
50
+ @create_fields ||= product_fields + variant_fields
37
51
  end
38
52
 
39
53
  # Spree Client
@@ -56,6 +70,8 @@ module Jekyll
56
70
  end
57
71
 
58
72
  def sync!
73
+ Jekyll::Hooks.trigger :spree, :pre_render, self
74
+
59
75
  # The API allows to query several SKUs at the same time, so we send
60
76
  # groups of 10 products.
61
77
  local_products.each_slice(10) do |products|
@@ -68,13 +84,18 @@ module Jekyll
68
84
  products.each do |p|
69
85
  mark_with_error p,
70
86
  i18n.dig('spree', 'errors', 'api') || "Couldn't obtain variants, the store may be down or API key is incorrect"
71
- local_save p.save
72
87
  end
73
88
 
74
89
  next
75
90
  end
76
91
 
77
92
  products.each do |product|
93
+ # Products have names, not titles, so we save them for later
94
+ product.data['_name'] = product.data['name'] if product.data.key? 'name'
95
+ product.data['name'] = product.data['title']
96
+
97
+ # Remove previous errors
98
+ product.data.delete 'errors'
78
99
  # Find the corresponding Spree variant in the response
79
100
  variant = response['variants'].find do |v|
80
101
  v[sku_field] == product.data[sku_field]
@@ -86,8 +107,16 @@ module Jekyll
86
107
  else
87
108
  create product
88
109
  end
110
+
111
+ product.data['name'] = product.data.delete('_name') if product.data.key? '_name'
89
112
  end
90
113
  end
114
+
115
+ Jekyll::Hooks.trigger :spree, :post_render, self
116
+
117
+ local_products.each do |product|
118
+ local_save product
119
+ end
91
120
  end
92
121
 
93
122
  private
@@ -150,6 +179,22 @@ module Jekyll
150
179
  # @param [Hash]
151
180
  # @return [true,false]
152
181
  def update(product, variant)
182
+ # Sync local changes to Spree
183
+ remote_product = product.data.slice(*product_fields).transform_keys(&:to_sym)
184
+ # Only when they haven't changed, so we don't waste time sending a
185
+ # request.
186
+ unless remote_product == variant.slice(*product_fields).transform_keys(&:to_sym)
187
+ # XXX: We don't have the product ID with the variant but we have
188
+ # the slug.
189
+ remote_product[:id] = variant['slug']
190
+ remote_product[:sku] = product.data[sku_field]
191
+
192
+ unless remote_products.update **remote_product
193
+ Jekyll.logger.error "Couldn't update #{product.data['title']}"
194
+ mark_with_error product, error_messages
195
+ end
196
+ end
197
+
153
198
  # XXX: The API replies with stringified numbers so we convert them
154
199
  # back to the type we're using locally.
155
200
  variant.slice(*variant_fields).each do |k, v|
@@ -162,9 +207,8 @@ module Jekyll
162
207
 
163
208
  product.data['in_stock'] = variant['in_stock']
164
209
  product.data['variant_id'] = variant['id']
165
- product.data.delete 'errors'
166
210
 
167
- local_save product
211
+ product
168
212
  end
169
213
 
170
214
  # If the product doesn't exist, create it.
@@ -172,23 +216,18 @@ module Jekyll
172
216
  # @param [Jekyll::Document]
173
217
  # @return [true,false]
174
218
  def create(product)
175
- new_product = product.data.slice(*variant_fields).transform_keys(&:to_sym)
219
+ new_product = product.data.slice(*create_fields).transform_keys(&:to_sym)
176
220
  new_product[:sku] = product.data[sku_field]
177
- new_product[:name] = product.data['title']
178
221
 
179
222
  unless remote_products.create **new_product
180
223
  Jekyll.logger.error "Couldn't create #{product.data['title']}"
181
224
  mark_with_error product, error_messages
182
- local_save product
183
225
 
184
226
  return false
185
227
  end
186
228
 
187
229
  product.data['variant_id'] = remote_products.response.dig('master', 'id')
188
230
 
189
- # Save the variant ID
190
- local_save product
191
-
192
231
  # Add the initial stock
193
232
  spree.stock_items(id: product.data['variant_id'], stock_location_id: stock_location['id'])
194
233
  .stock_movements.create(quantity: product.data['stock'])
@@ -202,7 +241,7 @@ module Jekyll
202
241
  errors.map do |error|
203
242
  field + ' ' + error
204
243
  end
205
- end.flatten
244
+ end&.flatten
206
245
  end
207
246
  end
208
247
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jekyll-spree-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.1.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - f
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-01 00:00:00.000000000 Z
11
+ date: 2021-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: spree-api-client