solidus_advanced_pricing 0.1.0

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.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +53 -0
  3. data/.gem_release.yml +5 -0
  4. data/.github/stale.yml +1 -0
  5. data/.github/workflows/lint.yml +25 -0
  6. data/.github/workflows/test.yml +86 -0
  7. data/.github_changelog_generator +2 -0
  8. data/.gitignore +21 -0
  9. data/.rspec +2 -0
  10. data/.rubocop.yml +5 -0
  11. data/CHANGELOG.md +3 -0
  12. data/Gemfile +64 -0
  13. data/LICENSE +26 -0
  14. data/README.md +377 -0
  15. data/Rakefile +41 -0
  16. data/app/assets/javascripts/spree/backend/solidus_advanced_pricing.js +2 -0
  17. data/app/assets/javascripts/spree/frontend/solidus_advanced_pricing.js +2 -0
  18. data/app/assets/stylesheets/spree/backend/solidus_advanced_pricing.css +4 -0
  19. data/app/assets/stylesheets/spree/frontend/solidus_advanced_pricing.css +4 -0
  20. data/app/decorators/models/solidus_advanced_pricing/spree/app_configuration_decorator.rb +17 -0
  21. data/app/decorators/models/solidus_advanced_pricing/spree/permitted_attributes_decorator.rb +27 -0
  22. data/app/decorators/models/solidus_advanced_pricing/spree/price_decorator.rb +56 -0
  23. data/app/decorators/models/solidus_advanced_pricing/spree/role_decorator.rb +24 -0
  24. data/app/decorators/models/solidus_advanced_pricing/spree/variant_decorator.rb +52 -0
  25. data/app/models/solidus_advanced_pricing/price_selector.rb +73 -0
  26. data/app/models/solidus_advanced_pricing/price_type.rb +80 -0
  27. data/app/models/solidus_advanced_pricing/price_type_cache.rb +45 -0
  28. data/app/models/solidus_advanced_pricing/pricing_options.rb +107 -0
  29. data/app/overrides/spree/admin/prices/_form/add_advanced_fields.html.erb.deface +2 -0
  30. data/app/overrides/spree/admin/prices/_master_variant_table/add_advanced_columns.html.erb.deface +2 -0
  31. data/app/overrides/spree/admin/prices/_master_variant_table/add_advanced_headers.html.erb.deface +4 -0
  32. data/app/overrides/spree/admin/prices/_table/add_advanced_columns.html.erb.deface +2 -0
  33. data/app/overrides/spree/admin/prices/_table/add_advanced_headers.html.erb.deface +4 -0
  34. data/app/overrides/spree/admin/shared/_configuration_menu/add_price_types_link.html.erb.deface +4 -0
  35. data/bin/console +17 -0
  36. data/bin/rails +7 -0
  37. data/bin/rails-engine +13 -0
  38. data/bin/rails-sandbox +16 -0
  39. data/bin/rake +7 -0
  40. data/bin/sandbox +85 -0
  41. data/bin/setup +8 -0
  42. data/config/locales/en.yml +44 -0
  43. data/config/routes.rb +34 -0
  44. data/db/migrate/20260915000001_create_solidus_advanced_pricing_price_types.rb +16 -0
  45. data/db/migrate/20260915000002_seed_solidus_advanced_pricing_price_types.rb +34 -0
  46. data/db/migrate/20260915000003_add_advanced_pricing_to_spree_prices.rb +21 -0
  47. data/docs/superpowers/specs/2026-09-14-solidus-advanced-pricing-design.md +351 -0
  48. data/lib/components/admin/solidus_admin/price_types/index/component.rb +65 -0
  49. data/lib/controllers/admin/solidus_admin/price_types_controller.rb +26 -0
  50. data/lib/controllers/api/spree/api/prices_controller.rb +32 -0
  51. data/lib/controllers/backend/spree/admin/price_types_controller.rb +40 -0
  52. data/lib/generators/solidus_advanced_pricing/install/install_generator.rb +33 -0
  53. data/lib/generators/solidus_advanced_pricing/install/templates/initializer.rb +7 -0
  54. data/lib/solidus_advanced_pricing/configuration.rb +21 -0
  55. data/lib/solidus_advanced_pricing/engine.rb +41 -0
  56. data/lib/solidus_advanced_pricing/testing_support/factories/price_type_factory.rb +13 -0
  57. data/lib/solidus_advanced_pricing/testing_support/factories.rb +4 -0
  58. data/lib/solidus_advanced_pricing/version.rb +5 -0
  59. data/lib/solidus_advanced_pricing.rb +19 -0
  60. data/lib/views/api/spree/api/prices/_price.json.jbuilder +8 -0
  61. data/lib/views/api/spree/api/prices/index.json.jbuilder +3 -0
  62. data/lib/views/api/spree/api/prices/show.json.jbuilder +1 -0
  63. data/lib/views/backend/spree/admin/price_types/_form.html.erb +20 -0
  64. data/lib/views/backend/spree/admin/price_types/edit.html.erb +9 -0
  65. data/lib/views/backend/spree/admin/price_types/index.html.erb +31 -0
  66. data/lib/views/backend/spree/admin/price_types/new.html.erb +9 -0
  67. data/lib/views/backend/spree/admin/prices/_advanced_columns.html.erb +7 -0
  68. data/lib/views/backend/spree/admin/prices/_advanced_fields.html.erb +46 -0
  69. data/solidus_advanced_pricing.gemspec +39 -0
  70. metadata +228 -0
@@ -0,0 +1,8 @@
1
+ json.call(price, :id, :variant_id, :amount, :currency, :country_iso, :role_id, :valid_from, :valid_to)
2
+ json.display_amount price.display_amount.to_s
3
+ json.price_type_code price.price_type&.code
4
+ json.price_type_name price.price_type&.name
5
+
6
+ if can?(:update, price)
7
+ json.admin_notes price.admin_notes
8
+ end
@@ -0,0 +1,3 @@
1
+ json.prices(@prices) do |price|
2
+ json.partial!("spree/api/prices/price", price: price)
3
+ end
@@ -0,0 +1 @@
1
+ json.partial!("spree/api/prices/price", price: @price)
@@ -0,0 +1,20 @@
1
+ <div class="row">
2
+ <div class="col-6">
3
+ <%= f.field_container :name do %>
4
+ <%= f.label :name %>
5
+ <%= f.text_field :name, class: 'fullwidth' %>
6
+ <% end %>
7
+ </div>
8
+ <div class="col-6">
9
+ <%= f.field_container :code do %>
10
+ <%= f.label :code %>
11
+ <%= f.text_field :code, class: 'fullwidth' %>
12
+ <% end %>
13
+ </div>
14
+ <div class="col-6">
15
+ <%= f.field_container :position do %>
16
+ <%= f.label :position %>
17
+ <%= f.number_field :position, class: 'fullwidth' %>
18
+ <% end %>
19
+ </div>
20
+ </div>
@@ -0,0 +1,9 @@
1
+ <% admin_breadcrumb(link_to plural_resource_name(SolidusAdvancedPricing::PriceType), spree.admin_price_types_path) %>
2
+ <% admin_breadcrumb(@price_type.name) %>
3
+
4
+ <%= form_for @price_type, as: :price_type, url: spree.admin_price_type_path(@price_type) do |f| %>
5
+ <fieldset class="no-border-top">
6
+ <%= render 'form', f: f %>
7
+ <%= render 'spree/admin/shared/edit_resource_links' %>
8
+ </fieldset>
9
+ <% end %>
@@ -0,0 +1,31 @@
1
+ <% admin_breadcrumb(plural_resource_name(SolidusAdvancedPricing::PriceType)) %>
2
+
3
+ <% content_for :page_actions do %>
4
+ <li>
5
+ <%= link_to t('spree.actions.new'), spree.new_admin_price_type_path, class: 'btn btn-primary' %>
6
+ </li>
7
+ <% end %>
8
+
9
+ <table class="index">
10
+ <thead>
11
+ <tr>
12
+ <th><%= SolidusAdvancedPricing::PriceType.human_attribute_name(:name) %></th>
13
+ <th><%= SolidusAdvancedPricing::PriceType.human_attribute_name(:code) %></th>
14
+ <th><%= SolidusAdvancedPricing::PriceType.human_attribute_name(:position) %></th>
15
+ <th class="actions"></th>
16
+ </tr>
17
+ </thead>
18
+ <tbody>
19
+ <% @collection.each do |price_type| %>
20
+ <tr id="<%= spree_dom_id price_type %>">
21
+ <td><%= price_type.name %></td>
22
+ <td><%= price_type.code %></td>
23
+ <td><%= price_type.position %></td>
24
+ <td class="actions">
25
+ <%= link_to_edit price_type, no_text: true %>
26
+ <%= link_to_delete price_type, no_text: true %>
27
+ </td>
28
+ </tr>
29
+ <% end %>
30
+ </tbody>
31
+ </table>
@@ -0,0 +1,9 @@
1
+ <% admin_breadcrumb(link_to plural_resource_name(SolidusAdvancedPricing::PriceType), spree.admin_price_types_path) %>
2
+ <% admin_breadcrumb(t('spree.actions.new')) %>
3
+
4
+ <%= form_for @price_type, as: :price_type, url: spree.admin_price_types_path do |f| %>
5
+ <fieldset class="no-border-top">
6
+ <%= render 'form', f: f %>
7
+ <%= render 'spree/admin/shared/new_resource_links' %>
8
+ </fieldset>
9
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <td><%= price.price_type&.name %></td>
2
+ <td><%= price.role&.name || t('solidus_advanced_pricing.all_customers') %></td>
3
+ <td>
4
+ <% if price.valid_from || price.valid_to %>
5
+ <%= [price.valid_from&.to_date, price.valid_to&.to_date].map { |d| d || '—' }.join(' → ') %>
6
+ <% end %>
7
+ </td>
@@ -0,0 +1,46 @@
1
+ <div data-hook="admin_product_price_advanced_fields">
2
+ <div class="col-4">
3
+ <%= f.field_container :price_type do %>
4
+ <%= f.label :price_type_id, SolidusAdvancedPricing::PriceType.model_name.human %>
5
+ <%= f.collection_select :price_type_id,
6
+ SolidusAdvancedPricing::PriceType.ordered,
7
+ :id, :name,
8
+ {},
9
+ { class: 'custom-select fullwidth' } %>
10
+ <% end %>
11
+ </div>
12
+
13
+ <div class="col-4">
14
+ <%= f.field_container :role do %>
15
+ <%= f.label :role_id, Spree::Role.model_name.human %>
16
+ <%= f.collection_select :role_id,
17
+ Spree::Role.order(:name),
18
+ :id, :name,
19
+ { include_blank: t('solidus_advanced_pricing.all_customers') },
20
+ { class: 'custom-select fullwidth' } %>
21
+ <span class="field-hint"><%= t('solidus_advanced_pricing.role_hint') %></span>
22
+ <% end %>
23
+ </div>
24
+
25
+ <div class="col-2">
26
+ <%= f.field_container :valid_from do %>
27
+ <%= f.label :valid_from %>
28
+ <%= f.text_field :valid_from, value: f.object.valid_from&.iso8601, class: 'fullwidth datepicker' %>
29
+ <% end %>
30
+ </div>
31
+
32
+ <div class="col-2">
33
+ <%= f.field_container :valid_to do %>
34
+ <%= f.label :valid_to %>
35
+ <%= f.text_field :valid_to, value: f.object.valid_to&.iso8601, class: 'fullwidth datepicker' %>
36
+ <% end %>
37
+ </div>
38
+
39
+ <div class="col-12">
40
+ <%= f.field_container :admin_notes do %>
41
+ <%= f.label :admin_notes %>
42
+ <%= f.text_area :admin_notes, rows: 2, class: 'fullwidth' %>
43
+ <span class="field-hint"><%= t('solidus_advanced_pricing.admin_notes_hint') %></span>
44
+ <% end %>
45
+ </div>
46
+ </div>
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/solidus_advanced_pricing/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "solidus_advanced_pricing"
7
+ spec.version = SolidusAdvancedPricing::VERSION
8
+ spec.authors = ["Patrick McMorran"]
9
+ spec.email = "pat.mcmorran@fcpeuro.com"
10
+
11
+ spec.summary = "Price types, validity windows and role targeting for Solidus prices"
12
+ spec.description = "Adds an admin-managed price type, an optional validity window, optional single-role targeting and internal admin notes to Spree::Price, selected through Solidus' own variant_price_selector_class seam."
13
+ spec.homepage = "https://github.com/solidusio-contrib/solidus_advanced_pricing#readme"
14
+ spec.license = "BSD-3-Clause"
15
+
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["source_code_uri"] = "https://github.com/solidusio-contrib/solidus_advanced_pricing"
18
+ spec.metadata["changelog_uri"] = "https://github.com/solidusio-contrib/solidus_advanced_pricing/blob/main/CHANGELOG.md"
19
+
20
+ spec.required_ruby_version = ">= 3.1"
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ files = Dir.chdir(__dir__) { `git ls-files -z`.split("\x0") }
25
+
26
+ spec.files = files.grep_v(%r{^(test|spec|features)/})
27
+ spec.bindir = "exe"
28
+ spec.executables = files.grep(%r{^exe/}) { |f| File.basename(f) }
29
+ spec.require_paths = ["lib"]
30
+
31
+ spec.add_dependency "deface", "~> 1.9"
32
+ spec.add_dependency "solidus_core", [">= 4.5", "< 5"]
33
+ spec.add_dependency "solidus_support", "~> 0.14"
34
+
35
+ spec.add_development_dependency "solidus_backend", [">= 4.5", "< 5"]
36
+ spec.add_development_dependency "solidus_api", [">= 4.5", "< 5"]
37
+ spec.add_development_dependency "solidus_dev_support", "~> 2.12"
38
+ spec.add_development_dependency "db-query-matchers", "~> 0.12"
39
+ end
metadata ADDED
@@ -0,0 +1,228 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: solidus_advanced_pricing
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Patrick McMorran
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: deface
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '1.9'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '1.9'
26
+ - !ruby/object:Gem::Dependency
27
+ name: solidus_core
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '4.5'
33
+ - - "<"
34
+ - !ruby/object:Gem::Version
35
+ version: '5'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '4.5'
43
+ - - "<"
44
+ - !ruby/object:Gem::Version
45
+ version: '5'
46
+ - !ruby/object:Gem::Dependency
47
+ name: solidus_support
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - "~>"
51
+ - !ruby/object:Gem::Version
52
+ version: '0.14'
53
+ type: :runtime
54
+ prerelease: false
55
+ version_requirements: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '0.14'
60
+ - !ruby/object:Gem::Dependency
61
+ name: solidus_backend
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '4.5'
67
+ - - "<"
68
+ - !ruby/object:Gem::Version
69
+ version: '5'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '4.5'
77
+ - - "<"
78
+ - !ruby/object:Gem::Version
79
+ version: '5'
80
+ - !ruby/object:Gem::Dependency
81
+ name: solidus_api
82
+ requirement: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '4.5'
87
+ - - "<"
88
+ - !ruby/object:Gem::Version
89
+ version: '5'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '4.5'
97
+ - - "<"
98
+ - !ruby/object:Gem::Version
99
+ version: '5'
100
+ - !ruby/object:Gem::Dependency
101
+ name: solidus_dev_support
102
+ requirement: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - "~>"
105
+ - !ruby/object:Gem::Version
106
+ version: '2.12'
107
+ type: :development
108
+ prerelease: false
109
+ version_requirements: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - "~>"
112
+ - !ruby/object:Gem::Version
113
+ version: '2.12'
114
+ - !ruby/object:Gem::Dependency
115
+ name: db-query-matchers
116
+ requirement: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - "~>"
119
+ - !ruby/object:Gem::Version
120
+ version: '0.12'
121
+ type: :development
122
+ prerelease: false
123
+ version_requirements: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - "~>"
126
+ - !ruby/object:Gem::Version
127
+ version: '0.12'
128
+ description: Adds an admin-managed price type, an optional validity window, optional
129
+ single-role targeting and internal admin notes to Spree::Price, selected through
130
+ Solidus' own variant_price_selector_class seam.
131
+ email: pat.mcmorran@fcpeuro.com
132
+ executables: []
133
+ extensions: []
134
+ extra_rdoc_files: []
135
+ files:
136
+ - ".circleci/config.yml"
137
+ - ".gem_release.yml"
138
+ - ".github/stale.yml"
139
+ - ".github/workflows/lint.yml"
140
+ - ".github/workflows/test.yml"
141
+ - ".github_changelog_generator"
142
+ - ".gitignore"
143
+ - ".rspec"
144
+ - ".rubocop.yml"
145
+ - CHANGELOG.md
146
+ - Gemfile
147
+ - LICENSE
148
+ - README.md
149
+ - Rakefile
150
+ - app/assets/javascripts/spree/backend/solidus_advanced_pricing.js
151
+ - app/assets/javascripts/spree/frontend/solidus_advanced_pricing.js
152
+ - app/assets/stylesheets/spree/backend/solidus_advanced_pricing.css
153
+ - app/assets/stylesheets/spree/frontend/solidus_advanced_pricing.css
154
+ - app/decorators/models/solidus_advanced_pricing/spree/app_configuration_decorator.rb
155
+ - app/decorators/models/solidus_advanced_pricing/spree/permitted_attributes_decorator.rb
156
+ - app/decorators/models/solidus_advanced_pricing/spree/price_decorator.rb
157
+ - app/decorators/models/solidus_advanced_pricing/spree/role_decorator.rb
158
+ - app/decorators/models/solidus_advanced_pricing/spree/variant_decorator.rb
159
+ - app/models/solidus_advanced_pricing/price_selector.rb
160
+ - app/models/solidus_advanced_pricing/price_type.rb
161
+ - app/models/solidus_advanced_pricing/price_type_cache.rb
162
+ - app/models/solidus_advanced_pricing/pricing_options.rb
163
+ - app/overrides/spree/admin/prices/_form/add_advanced_fields.html.erb.deface
164
+ - app/overrides/spree/admin/prices/_master_variant_table/add_advanced_columns.html.erb.deface
165
+ - app/overrides/spree/admin/prices/_master_variant_table/add_advanced_headers.html.erb.deface
166
+ - app/overrides/spree/admin/prices/_table/add_advanced_columns.html.erb.deface
167
+ - app/overrides/spree/admin/prices/_table/add_advanced_headers.html.erb.deface
168
+ - app/overrides/spree/admin/shared/_configuration_menu/add_price_types_link.html.erb.deface
169
+ - bin/console
170
+ - bin/rails
171
+ - bin/rails-engine
172
+ - bin/rails-sandbox
173
+ - bin/rake
174
+ - bin/sandbox
175
+ - bin/setup
176
+ - config/locales/en.yml
177
+ - config/routes.rb
178
+ - db/migrate/20260915000001_create_solidus_advanced_pricing_price_types.rb
179
+ - db/migrate/20260915000002_seed_solidus_advanced_pricing_price_types.rb
180
+ - db/migrate/20260915000003_add_advanced_pricing_to_spree_prices.rb
181
+ - docs/superpowers/specs/2026-09-14-solidus-advanced-pricing-design.md
182
+ - lib/components/admin/solidus_admin/price_types/index/component.rb
183
+ - lib/controllers/admin/solidus_admin/price_types_controller.rb
184
+ - lib/controllers/api/spree/api/prices_controller.rb
185
+ - lib/controllers/backend/spree/admin/price_types_controller.rb
186
+ - lib/generators/solidus_advanced_pricing/install/install_generator.rb
187
+ - lib/generators/solidus_advanced_pricing/install/templates/initializer.rb
188
+ - lib/solidus_advanced_pricing.rb
189
+ - lib/solidus_advanced_pricing/configuration.rb
190
+ - lib/solidus_advanced_pricing/engine.rb
191
+ - lib/solidus_advanced_pricing/testing_support/factories.rb
192
+ - lib/solidus_advanced_pricing/testing_support/factories/price_type_factory.rb
193
+ - lib/solidus_advanced_pricing/version.rb
194
+ - lib/views/api/spree/api/prices/_price.json.jbuilder
195
+ - lib/views/api/spree/api/prices/index.json.jbuilder
196
+ - lib/views/api/spree/api/prices/show.json.jbuilder
197
+ - lib/views/backend/spree/admin/price_types/_form.html.erb
198
+ - lib/views/backend/spree/admin/price_types/edit.html.erb
199
+ - lib/views/backend/spree/admin/price_types/index.html.erb
200
+ - lib/views/backend/spree/admin/price_types/new.html.erb
201
+ - lib/views/backend/spree/admin/prices/_advanced_columns.html.erb
202
+ - lib/views/backend/spree/admin/prices/_advanced_fields.html.erb
203
+ - solidus_advanced_pricing.gemspec
204
+ homepage: https://github.com/solidusio-contrib/solidus_advanced_pricing#readme
205
+ licenses:
206
+ - BSD-3-Clause
207
+ metadata:
208
+ homepage_uri: https://github.com/solidusio-contrib/solidus_advanced_pricing#readme
209
+ source_code_uri: https://github.com/solidusio-contrib/solidus_advanced_pricing
210
+ changelog_uri: https://github.com/solidusio-contrib/solidus_advanced_pricing/blob/main/CHANGELOG.md
211
+ rdoc_options: []
212
+ require_paths:
213
+ - lib
214
+ required_ruby_version: !ruby/object:Gem::Requirement
215
+ requirements:
216
+ - - ">="
217
+ - !ruby/object:Gem::Version
218
+ version: '3.1'
219
+ required_rubygems_version: !ruby/object:Gem::Requirement
220
+ requirements:
221
+ - - ">="
222
+ - !ruby/object:Gem::Version
223
+ version: '0'
224
+ requirements: []
225
+ rubygems_version: 4.0.21
226
+ specification_version: 4
227
+ summary: Price types, validity windows and role targeting for Solidus prices
228
+ test_files: []