spree_core 5.0.2 → 5.1.0.beta

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 (87) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/logo.png +0 -0
  3. data/app/finders/spree/products/find.rb +28 -1
  4. data/app/finders/spree/taxons/find.rb +1 -1
  5. data/app/helpers/spree/integrations_helper.rb +15 -0
  6. data/app/javascript/spree/core/controllers/disable_submit_button_controller.js +19 -0
  7. data/app/mailers/spree/invitation_mailer.rb +24 -0
  8. data/app/models/concerns/spree/integrations_concern.rb +11 -0
  9. data/app/models/concerns/spree/product_scopes.rb +6 -6
  10. data/app/models/concerns/spree/translatable_resource.rb +4 -0
  11. data/app/models/concerns/spree/translatable_resource_scopes.rb +17 -3
  12. data/app/models/concerns/spree/unique_name.rb +2 -0
  13. data/app/models/concerns/spree/user_management.rb +33 -0
  14. data/app/models/concerns/spree/user_methods.rb +19 -0
  15. data/app/models/concerns/spree/user_roles.rb +43 -17
  16. data/app/models/spree/ability.rb +8 -6
  17. data/app/models/spree/asset.rb +1 -6
  18. data/app/models/spree/base.rb +1 -0
  19. data/app/models/spree/base_analytics_event_handler.rb +7 -2
  20. data/app/models/spree/classification.rb +13 -0
  21. data/app/models/spree/custom_domain.rb +2 -1
  22. data/app/models/spree/export.rb +1 -1
  23. data/app/models/spree/integration.rb +63 -0
  24. data/app/models/spree/invitation.rb +153 -0
  25. data/app/models/spree/invitations/store.rb +6 -0
  26. data/app/models/spree/order.rb +17 -1
  27. data/app/models/spree/order_merger.rb +7 -5
  28. data/app/models/spree/page_blocks/products/buy_buttons.rb +8 -0
  29. data/app/models/spree/page_blocks/products/quantity_selector.rb +4 -0
  30. data/app/models/spree/page_blocks/products/variant_picker.rb +4 -0
  31. data/app/models/spree/page_sections/featured_product.rb +4 -0
  32. data/app/models/spree/page_sections/image_banner.rb +12 -0
  33. data/app/models/spree/page_sections/image_with_text.rb +12 -0
  34. data/app/models/spree/page_sections/newsletter.rb +1 -1
  35. data/app/models/spree/page_sections/rich_text.rb +11 -0
  36. data/app/models/spree/page_sections/video.rb +8 -0
  37. data/app/models/spree/product.rb +10 -2
  38. data/app/models/spree/product_property.rb +1 -1
  39. data/app/models/spree/property.rb +3 -1
  40. data/app/models/spree/reports/sales_total.rb +5 -1
  41. data/app/models/spree/role.rb +16 -0
  42. data/app/models/spree/role_user.rb +32 -1
  43. data/app/models/spree/shipment.rb +1 -1
  44. data/app/models/spree/shipment_handler.rb +1 -0
  45. data/app/models/spree/shipping_method.rb +1 -1
  46. data/app/models/spree/store.rb +12 -5
  47. data/app/models/spree/store_credit_category.rb +4 -0
  48. data/app/models/spree/taxon.rb +4 -3
  49. data/app/models/spree/theme.rb +37 -4
  50. data/app/models/spree/variant.rb +9 -1
  51. data/app/services/spree/country_to_timezone.rb +273 -0
  52. data/app/services/spree/seeds/admin_user.rb +4 -2
  53. data/app/services/spree/seeds/all.rb +3 -1
  54. data/app/services/spree/seeds/digital_delivery.rb +20 -0
  55. data/app/services/spree/seeds/returns_environment.rb +27 -0
  56. data/app/services/spree/seeds/tax_categories.rb +12 -0
  57. data/app/services/spree/stores/settings_defaults_by_country.rb +38 -0
  58. data/app/services/spree/tags/bulk_add.rb +13 -7
  59. data/app/views/spree/invitation_mailer/invitation_accepted.html.erb +12 -0
  60. data/app/views/spree/invitation_mailer/invitation_email.html.erb +21 -0
  61. data/config/locales/en.yml +48 -10
  62. data/db/migrate/20230110142344_backfill_friendly_id_slug_locale.rb +3 -1
  63. data/db/migrate/20250407085228_create_spree_integrations.rb +12 -0
  64. data/db/migrate/20250410061306_create_spree_invitations.rb +20 -0
  65. data/db/migrate/20250418174652_add_resource_to_spree_role_users.rb +8 -0
  66. data/db/migrate/20250508060800_add_selected_locale_to_spree_admin_users.rb +8 -0
  67. data/db/migrate/20250509143831_add_session_id_to_spree_assets.rb +5 -0
  68. data/lib/generators/spree/authentication/devise/devise_generator.rb +5 -2
  69. data/lib/generators/spree/authentication/devise/templates/authentication_helpers.rb.tt +3 -3
  70. data/lib/generators/spree/install/install_generator.rb +5 -0
  71. data/lib/spree/core/controller_helpers/auth.rb +16 -14
  72. data/lib/spree/core/controller_helpers/currency.rb +11 -0
  73. data/lib/spree/core/controller_helpers/order.rb +2 -1
  74. data/lib/spree/core/controller_helpers/strong_parameters.rb +3 -2
  75. data/lib/spree/core/engine.rb +12 -8
  76. data/lib/spree/core/version.rb +1 -1
  77. data/lib/spree/core.rb +1 -0
  78. data/lib/spree/permitted_attributes.rb +118 -13
  79. data/lib/spree/testing_support/capybara_config.rb +1 -1
  80. data/lib/spree/testing_support/factories/integration_factory.rb +7 -0
  81. data/lib/spree/testing_support/factories/invitation_factory.rb +6 -0
  82. data/lib/spree/testing_support/factories/promotion_action_factory.rb +4 -0
  83. data/lib/spree/testing_support/factories/stock_item_factory.rb +5 -1
  84. data/lib/spree/testing_support/factories/user_factory.rb +14 -1
  85. data/lib/spree/translation_migrations.rb +27 -15
  86. data/lib/tasks/core.rake +8 -0
  87. metadata +41 -4
@@ -113,6 +113,9 @@ module Spree
113
113
  end
114
114
  end
115
115
 
116
+ # Creates a new preview for the theme
117
+ #
118
+ # @return [Spree::Theme]
116
119
  def create_preview
117
120
  ActiveRecord::Base.connected_to(role: :writing) do
118
121
  ApplicationRecord.transaction do
@@ -152,16 +155,46 @@ module Spree
152
155
  end
153
156
  end
154
157
 
158
+ # Returns an array of available layout section classes for the theme
159
+ #
160
+ # @return [Array<Class>]
155
161
  def available_layout_sections
156
- Rails.application.config.spree.theme_layout_sections
162
+ [
163
+ *Rails.application.config.spree.theme_layout_sections,
164
+ *custom_layout_sections
165
+ ]
166
+ end
167
+
168
+ # Returns an array of custom layout section classes for the theme
169
+ #
170
+ # @return [Array<Class>]
171
+ def custom_layout_sections
172
+ # you can override this method in your theme to return a list of custom layout sections for your theme
173
+ # [Spree::PageSections::Custom, Spree::PageSections::Custom2]
174
+ []
157
175
  end
158
176
 
177
+ # Returns an array of available page section classes for the theme
178
+ #
179
+ # @return [Array<Class>]
159
180
  def available_page_sections
160
181
  return @available_page_sections if @available_page_sections
161
182
 
162
- @available_page_sections ||= Rails.application.config.spree.page_sections.find_all do |section_class|
163
- section_class.role == 'content'
164
- end.sort_by(&:name)
183
+ @available_page_sections ||= [
184
+ *Rails.application.config.spree.page_sections.find_all do |section_class|
185
+ section_class.role == 'content'
186
+ end,
187
+ *custom_page_sections
188
+ ].sort_by(&:name)
189
+ end
190
+
191
+ # Returns an array of custom page section classes for the theme
192
+ #
193
+ # @return [Array<Class>]
194
+ def custom_page_sections
195
+ # you can override this method in your theme to return a list of custom page sections for your theme
196
+ # [Spree::PageSections::Custom, Spree::PageSections::Custom2]
197
+ []
165
198
  end
166
199
 
167
200
  def restore_defaults!
@@ -73,6 +73,8 @@ module Spree
73
73
  after_create :create_stock_items
74
74
  after_create :set_master_out_of_stock, unless: :is_master?
75
75
  after_commit :clear_line_items_cache, on: :update
76
+
77
+ after_create :create_default_stock_item, unless: :track_inventory?
76
78
  after_update_commit :handle_track_inventory_change
77
79
 
78
80
  after_commit :remove_prices_from_master_variant, on: [:create, :update], unless: :is_master?
@@ -553,11 +555,17 @@ module Spree
553
555
  line_items.update_all(updated_at: Time.current)
554
556
  end
555
557
 
558
+ def create_default_stock_item
559
+ return if stock_items.any?
560
+
561
+ Spree::Store.current.default_stock_location.set_up_stock_item(self)
562
+ end
563
+
556
564
  def handle_track_inventory_change
557
565
  return unless track_inventory_previously_changed?
558
566
  return if track_inventory
559
567
 
560
- stock_items.update_all(backorderable: true, count_on_hand: 0, updated_at: Time.current)
568
+ stock_items.update_all(count_on_hand: 0, updated_at: Time.current)
561
569
  end
562
570
 
563
571
  def remove_prices_from_master_variant
@@ -0,0 +1,273 @@
1
+ module Spree
2
+ class CountryToTimezone
3
+ prepend Spree::ServiceModule::Base
4
+
5
+ CAPITAL_CITIES = {
6
+ "AD"=>"Andorra la Vella",
7
+ "AE"=>"Abu Dhabi",
8
+ "AF"=>"Kabul",
9
+ "AG"=>"Saint John's",
10
+ "AI"=>"The Valley",
11
+ "AL"=>"Tirana",
12
+ "AM"=>"Yerevan",
13
+ "AN"=>"Willemstad",
14
+ "AO"=>"Luanda",
15
+ "AQ"=>nil,
16
+ "AR"=>"Buenos Aires",
17
+ "AS"=>"Pago Pago",
18
+ "AT"=>"Vienna",
19
+ "AU"=>"Canberra",
20
+ "AW"=>"Oranjestad",
21
+ "AZ"=>"Baku",
22
+ "BA"=>"Sarajevo",
23
+ "BB"=>"Bridgetown",
24
+ "BD"=>"Dhaka",
25
+ "BE"=>"Brussels",
26
+ "BF"=>"Ouagadougou",
27
+ "BG"=>"Sofia",
28
+ "BH"=>"Manama",
29
+ "BI"=>"Bujumbura",
30
+ "BJ"=>"Porto-Novo",
31
+ "BL"=>"Gustavia",
32
+ "BM"=>"Hamilton",
33
+ "BN"=>"Bandar Seri Begawan",
34
+ "BO"=>"La Paz",
35
+ "BR"=>"Brasilia",
36
+ "BS"=>"Nassau",
37
+ "BT"=>"Thimphu",
38
+ "BV"=>nil,
39
+ "BW"=>"Gaborone",
40
+ "BY"=>"Minsk",
41
+ "BZ"=>"Belmopan",
42
+ "CA"=>"Ottawa",
43
+ "CC"=>"West Island",
44
+ "CD"=>"Kinshasa",
45
+ "CF"=>"Bangui",
46
+ "CG"=>"Brazzaville",
47
+ "CH"=>"Bern",
48
+ "CI"=>"Yamoussoukro",
49
+ "CK"=>"Avarua",
50
+ "CL"=>"Santiago",
51
+ "CM"=>"Yaounde",
52
+ "CN"=>"Beijing",
53
+ "CO"=>"Bogota",
54
+ "CR"=>"San Jose",
55
+ "CU"=>"Havana",
56
+ "CV"=>"Praia",
57
+ "CX"=>"The Settlement",
58
+ "CY"=>"Nicosia",
59
+ "CZ"=>"Prague",
60
+ "DE"=>"Berlin",
61
+ "DJ"=>"Djibouti",
62
+ "DK"=>"Copenhagen",
63
+ "DM"=>"Roseau",
64
+ "DO"=>"Santo Domingo",
65
+ "DZ"=>"Algiers",
66
+ "EC"=>"Quito",
67
+ "EE"=>"Tallinn",
68
+ "EG"=>"Cairo",
69
+ "EH"=>nil,
70
+ "ER"=>"Asmara",
71
+ "ES"=>"Madrid",
72
+ "ET"=>"Addis Ababa",
73
+ "FI"=>"Helsinki",
74
+ "FJ"=>"Suva",
75
+ "FK"=>"Stanley",
76
+ "FM"=>"Palikir",
77
+ "FO"=>"Torshavn",
78
+ "FR"=>"Paris",
79
+ "GA"=>"Libreville",
80
+ "GB"=>"London",
81
+ "GD"=>"Saint George's",
82
+ "GE"=>"T'bilisi",
83
+ "GG"=>"Saint Peter Port",
84
+ "GH"=>"Accra",
85
+ "GI"=>"Gibraltar",
86
+ "GL"=>"Nuuk",
87
+ "GM"=>"Banjul",
88
+ "GN"=>"Conakry",
89
+ "GQ"=>"Malabo",
90
+ "GR"=>"Athens",
91
+ "GT"=>"Guatemala City",
92
+ "GU"=>"Hagatna",
93
+ "GW"=>"Bissau",
94
+ "GY"=>"Georgetown",
95
+ "HK"=>"Hong Kong",
96
+ "HM"=>nil,
97
+ "HN"=>"Tegucigalpa",
98
+ "HR"=>"Zagreb",
99
+ "HT"=>"Port-au-Prince",
100
+ "HU"=>"Budapest",
101
+ "ID"=>"Jakarta",
102
+ "IE"=>"Dublin",
103
+ "IL"=>"Jerusalem",
104
+ "IM"=>"Douglas",
105
+ "IN"=>"New Delhi",
106
+ "IO"=>nil,
107
+ "IQ"=>"Baghdad",
108
+ "IR"=>"Tehran",
109
+ "IS"=>"Reykjavik",
110
+ "IT"=>"Rome",
111
+ "JE"=>"Saint Helier",
112
+ "JM"=>"Kingston",
113
+ "JO"=>"Amman",
114
+ "JP"=>"Tokyo",
115
+ "KE"=>"Nairobi",
116
+ "KG"=>"Bishkek",
117
+ "KH"=>"Phnom Penh",
118
+ "KI"=>"Tarawa",
119
+ "KM"=>"Moroni",
120
+ "KN"=>"Basseterre",
121
+ "KP"=>"Pyongyang",
122
+ "KR"=>"Seoul",
123
+ "KW"=>"Kuwait City",
124
+ "KY"=>"George Town",
125
+ "KZ"=>"Astana",
126
+ "LA"=>"Vientiane",
127
+ "LB"=>"Beirut",
128
+ "LC"=>"Castries",
129
+ "LI"=>"Vaduz",
130
+ "LK"=>"Colombo",
131
+ "LR"=>"Monrovia",
132
+ "LS"=>"Maseru",
133
+ "LT"=>"Vilnius",
134
+ "LU"=>"Luxembourg",
135
+ "LV"=>"Riga",
136
+ "LY"=>"Tripoli",
137
+ "MA"=>"Rabat",
138
+ "MC"=>"Monaco",
139
+ "MD"=>"Chisinau",
140
+ "ME"=>"Podgorica",
141
+ "MF"=>"Marigot",
142
+ "MG"=>"Antananarivo",
143
+ "MH"=>"Majuro",
144
+ "MK"=>"Skopje",
145
+ "ML"=>"Bamako",
146
+ "MM"=>"Rangoon",
147
+ "MN"=>"Ulaanbaatar",
148
+ "MO"=>nil,
149
+ "MP"=>"Saipan",
150
+ "MR"=>"Nouakchott",
151
+ "MS"=>"Plymouth",
152
+ "MT"=>"Valletta",
153
+ "MU"=>"Port Louis",
154
+ "MV"=>"Male",
155
+ "MW"=>"Lilongwe",
156
+ "MX"=>"Mexico City",
157
+ "MY"=>"Kuala Lumpur",
158
+ "MZ"=>"Maputo",
159
+ "NA"=>"Windhoek",
160
+ "NC"=>"Noumea",
161
+ "NE"=>"Niamey",
162
+ "NF"=>"Kingston",
163
+ "NG"=>"Abuja",
164
+ "NI"=>"Managua",
165
+ "NL"=>"Amsterdam",
166
+ "NO"=>"Oslo",
167
+ "NP"=>"Kathmandu",
168
+ "NR"=>nil,
169
+ "NU"=>"Alofi",
170
+ "NZ"=>"Wellington",
171
+ "OM"=>"Muscat",
172
+ "PA"=>"Panama City",
173
+ "PE"=>"Lima",
174
+ "PF"=>"Papeete",
175
+ "PG"=>"Port Moresby",
176
+ "PH"=>"Manila",
177
+ "PK"=>"Islamabad",
178
+ "PL"=>"Warsaw",
179
+ "PM"=>"Saint-Pierre",
180
+ "PN"=>"Adamstown",
181
+ "PR"=>"San Juan",
182
+ "PS"=>nil,
183
+ "PT"=>"Lisbon",
184
+ "PW"=>"Melekeok",
185
+ "PY"=>"Asuncion",
186
+ "QA"=>"Doha",
187
+ "RO"=>"Bucharest",
188
+ "RS"=>"Belgrade",
189
+ "RU"=>"Moscow",
190
+ "RW"=>"Kigali",
191
+ "SA"=>"Riyadh",
192
+ "SB"=>"Honiara",
193
+ "SC"=>"Victoria",
194
+ "SD"=>"Khartoum",
195
+ "SE"=>"Stockholm",
196
+ "SG"=>"Singapore",
197
+ "SH"=>"Jamestown",
198
+ "SI"=>"Ljubljana",
199
+ "SJ"=>"Longyearbyen",
200
+ "SK"=>"Bratislava",
201
+ "SL"=>"Freetown",
202
+ "SM"=>"San Marino",
203
+ "SN"=>"Dakar",
204
+ "SO"=>"Mogadishu",
205
+ "SR"=>"Paramaribo",
206
+ "ST"=>"Sao Tome",
207
+ "SV"=>"San Salvador",
208
+ "SY"=>"Damascus",
209
+ "SZ"=>"Mbabane",
210
+ "TC"=>"Grand Turk",
211
+ "TD"=>"N'Djamena",
212
+ "TF"=>nil,
213
+ "TG"=>"Lome",
214
+ "TH"=>"Bangkok",
215
+ "TJ"=>"Dushanbe",
216
+ "TK"=>nil,
217
+ "TL"=>"Dili",
218
+ "TM"=>"Ashgabat",
219
+ "TN"=>"Tunis",
220
+ "TO"=>"Nuku'alofa",
221
+ "TR"=>"Ankara",
222
+ "TT"=>"Port-of-Spain",
223
+ "TV"=>"Funafuti",
224
+ "TW"=>"Taipei",
225
+ "TZ"=>"Dar es Salaam",
226
+ "UA"=>"Kyiv",
227
+ "UG"=>"Kampala",
228
+ "US"=>"Washington, DC",
229
+ "UY"=>"Montevideo",
230
+ "UZ"=>"Tashkent",
231
+ "VA"=>"Vatican City",
232
+ "VC"=>"Kingstown",
233
+ "VE"=>"Caracas",
234
+ "VG"=>"Road Town",
235
+ "VI"=>"Charlotte Amalie",
236
+ "VN"=>"Hanoi",
237
+ "VU"=>"Port-Vila",
238
+ "WF"=>"Mata-Utu",
239
+ "WS"=>"Apia",
240
+ "YE"=>"Sanaa",
241
+ "YT"=>"Mamoudzou",
242
+ "ZA"=>"Pretoria",
243
+ "ZM"=>"Lusaka",
244
+ "ZW"=>"Harare"}.freeze
245
+
246
+ def call(code:)
247
+ case code
248
+ when 'US', 'CA'
249
+ success('Central Time (US & Canada)')
250
+ else
251
+ success(from_timezone_helper(code))
252
+ end
253
+ end
254
+
255
+ private
256
+
257
+ def from_timezone_helper(code)
258
+ timezones = ActiveSupport::TimeZone.country_zones(code)
259
+ return 'Central Time (US & Canada)' if timezones.empty?
260
+
261
+ timezones.first.name if timezones.size == 1
262
+
263
+ # If there is more than one timezone for the country, then we'll use the capital city
264
+ # to determine the timezone
265
+ # eg GB has London and Edinburgh
266
+ capital_city = CAPITAL_CITIES[code]
267
+ capital_city_time_zone = timezones.find{ |tz| tz.name.match(capital_city) }
268
+ return capital_city_time_zone.name if capital_city_time_zone.present?
269
+
270
+ timezones.first.name
271
+ end
272
+ end
273
+ end
@@ -12,9 +12,11 @@ module Spree
12
12
  first_name: 'Spree',
13
13
  last_name: 'Admin'
14
14
  )
15
-
16
- user.spree_roles << Spree::Role.find_or_create_by(name: :admin)
17
15
  user.save!
16
+
17
+ Spree::Store.all.each do |store|
18
+ store.add_user(user)
19
+ end
18
20
  end
19
21
  end
20
22
  end
@@ -14,9 +14,11 @@ module Spree
14
14
  Roles.call
15
15
 
16
16
  # additional data
17
- DefaultReimbursementTypes.call
17
+ ReturnsEnvironment.call
18
18
  ShippingCategories.call
19
19
  StoreCreditCategories.call
20
+ TaxCategories.call
21
+ DigitalDelivery.call
20
22
 
21
23
  # store & stock location
22
24
  Stores.call
@@ -0,0 +1,20 @@
1
+ module Spree
2
+ module Seeds
3
+ class DigitalDelivery
4
+ prepend Spree::ServiceModule::Base
5
+
6
+ def call
7
+ digital_shipping_category = Spree::ShippingCategory.find_or_create_by!(name: 'Digital')
8
+ zones = Spree::Zone.all
9
+
10
+ digital_shipping_method = Spree::ShippingMethod.find_or_initialize_by(name: Spree.t('digital.digital_delivery'))
11
+
12
+ digital_shipping_method.display_on = 'both'
13
+ digital_shipping_method.shipping_categories = [digital_shipping_category]
14
+ digital_shipping_method.calculator ||= Spree::Calculator::Shipping::DigitalDelivery.create!
15
+ digital_shipping_method.zones = zones
16
+ digital_shipping_method.save!
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,27 @@
1
+ module Spree
2
+ module Seeds
3
+ class ReturnsEnvironment
4
+ prepend Spree::ServiceModule::Base
5
+
6
+ def call
7
+ Spree::RefundReason.find_or_create_by!(name: 'Return processing', mutable: false)
8
+ [
9
+ 'Better price available',
10
+ 'Missed estimated delivery date',
11
+ 'Missing parts or accessories',
12
+ 'Damaged/Defective',
13
+ 'Different from what was ordered',
14
+ 'Different from description',
15
+ 'No longer needed/wanted',
16
+ 'Accidental order',
17
+ 'Unauthorized purchase',
18
+ ].each do |name|
19
+ Spree::ReturnAuthorizationReason.find_or_create_by!(name: name)
20
+ end
21
+ Spree::ReimbursementType.find_or_create_by!(name: 'Store Credit', type: 'Spree::ReimbursementType::StoreCredit')
22
+ Spree::ReimbursementType.find_or_create_by!(name: 'Exchange', type: 'Spree::ReimbursementType::Exchange')
23
+ Spree::ReimbursementType.find_or_create_by!(name: 'Original payment', type: 'Spree::ReimbursementType::OriginalPayment')
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,12 @@
1
+ module Spree
2
+ module Seeds
3
+ class TaxCategories
4
+ prepend Spree::ServiceModule::Base
5
+
6
+ def call
7
+ Spree::TaxCategory.find_or_create_by(name: 'Default', is_default: true)
8
+ Spree::TaxCategory.find_or_create_by(name: 'Non-taxable')
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,38 @@
1
+ module Spree
2
+ module Stores
3
+ class SettingsDefaultsByCountry
4
+ prepend Spree::ServiceModule::Base
5
+
6
+ IMPERIAL = %w[US GB LR MM].freeze
7
+
8
+ def call(code:)
9
+ default_unit_system = unit_system(code)
10
+
11
+ success(
12
+ unit_system: default_unit_system,
13
+ weight_unit: weight_unit(default_unit_system),
14
+ timezone: timezone(code)
15
+ )
16
+ end
17
+
18
+ private
19
+
20
+ def unit_system(code)
21
+ IMPERIAL.include?(code) ? :imperial : :metric
22
+ end
23
+
24
+ def weight_unit(unit_system)
25
+ unit_system.to_s == 'metric' ? 'kg' : 'lb'
26
+ end
27
+
28
+ def timezone(code)
29
+ case code
30
+ when 'US', 'CA'
31
+ 'Central Time (US & Canada)'
32
+ else
33
+ Spree::CountryToTimezone.call(code: code).value
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -16,7 +16,19 @@ module Spree
16
16
 
17
17
  record_class = records.first.class
18
18
 
19
- taggings_to_upsert = records.pluck(:id).map do |record_id|
19
+ taggings_to_upsert = taggings_attributes(tags, records, context: context, record_class: record_class)
20
+
21
+ return if taggings_to_upsert.empty?
22
+
23
+ ActsAsTaggableOn::Tagging.insert_all(taggings_to_upsert)
24
+
25
+ record_class.where(id: records.pluck(:id)).touch_all
26
+ end
27
+
28
+ private
29
+
30
+ def taggings_attributes(tags, records, context:, record_class:)
31
+ records.pluck(:id).map do |record_id|
20
32
  tags.map do |tag|
21
33
  {
22
34
  taggable_id: record_id,
@@ -26,12 +38,6 @@ module Spree
26
38
  }
27
39
  end
28
40
  end.flatten.compact
29
-
30
- return if taggings_to_upsert.empty?
31
-
32
- ActsAsTaggableOn::Tagging.insert_all(taggings_to_upsert)
33
-
34
- record_class.where(id: records.pluck(:id)).touch_all
35
41
  end
36
42
  end
37
43
  end
@@ -0,0 +1,12 @@
1
+ <h1>
2
+ <%= Spree.t('invitation_mailer.greeting', user_name: @invitation.inviter.first_name) %>
3
+ </h1>
4
+ <p>
5
+ <%= Spree.t('invitation_mailer.invitation_accepted.body', invitee_name: @invitation.invitee&.name, resource_name: @invitation.resource.name) %>
6
+ </p>
7
+
8
+ <p>
9
+ <%= Spree.t('invitation_mailer.thanks') %><br />
10
+ <%= current_store.name %>
11
+ </p>
12
+
@@ -0,0 +1,21 @@
1
+ <h1>
2
+ <%= Spree.t('invitation_mailer.greeting', user_name: @invitation.invitee&.first_name || @invitation.email) %>
3
+ </h1>
4
+ <p>
5
+ <%= Spree.t('invitation_mailer.invitation_email.body', inviter_name: @invitation.inviter.name, resource_name: @invitation.resource.name) %>
6
+ </p>
7
+ <p>
8
+ <%= Spree.t('invitation_mailer.invitation_email.link_description') %>
9
+ </p>
10
+
11
+ <% if spree.respond_to?(:admin_invitation_url) %>
12
+ <p>
13
+ <%= link_to Spree.t('invitation_mailer.invitation_email.link_text'), spree.admin_invitation_url(@invitation, token: @invitation.token, host: @invitation.store.formatted_url) %>
14
+ </p>
15
+ <% end %>
16
+
17
+ <p>
18
+ <%= Spree.t('invitation_mailer.thanks') %><br />
19
+ <%= current_store.name %>
20
+ </p>
21
+