jekyll-spree-client 0.1.7 → 0.1.12

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f7a67bab159ca15a9bdb21c85f14da4c5f401d91c04a9da7c8317d4e5bb4a15d
4
- data.tar.gz: 74eff3966ee98fd1baae257b5dfb243064ffe509c834173a3ffce34664f514fe
3
+ metadata.gz: 29f4a2f251e21575d7f5b4ef34af064f8fb80a7a2e494267d19336f201288c3d
4
+ data.tar.gz: 77521c26bb015d395fa515adf4270385c28de024a57725d08123c8c7d0daebd5
5
5
  SHA512:
6
- metadata.gz: 658045e9a4e79977df68d0945520c6a2d150a52e1574ae86c3dc71fcd842f45967672b202c784f2aa12826ce3bd512f8b04b505bfd1d402cc798e968e3b0a37d
7
- data.tar.gz: 7120d85321bff77a6ec69e39abd52801436de8daca45b9b9be19b64824c50c5912d8d2988ba81436dd94a6d8575f1ed6675de34310cec72ed1b89bdb442d5230
6
+ metadata.gz: 71480aa397d2fe3e0191833bc55194d6d287ac1825c5ebe01ecbb341a13d1de79f16d1686a2b6a4ebd879cc882584d9bab940ded155208988386110104d00a8b
7
+ data.tar.gz: f917c8e9cf3675801c8240ab88bc05f19368fd1597065ec7d789f4ec82ed5acab22733e5dc65ba7dfc63cc703ed197de4c09d1207f9e79f0d1663253a647b2dc
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
+ unless ENV['SPREE_API_KEY']
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'])
@@ -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].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.7
4
+ version: 0.1.12
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-04-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: spree-api-client