spree_core 5.1.7 → 5.2.0.rc1

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 (400) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/payment_icons/ach.svg +1 -0
  3. data/app/assets/images/payment_icons/achdirectdebit.svg +1 -0
  4. data/app/assets/images/payment_icons/ada.svg +1 -0
  5. data/app/assets/images/payment_icons/adyen.svg +1 -0
  6. data/app/assets/images/payment_icons/affinbank.svg +1 -0
  7. data/app/assets/images/payment_icons/affirm.svg +1 -0
  8. data/app/assets/images/payment_icons/afterpay.svg +1 -0
  9. data/app/assets/images/payment_icons/airtel_money.svg +1 -0
  10. data/app/assets/images/payment_icons/airteltigo_mobile_money.svg +1 -0
  11. data/app/assets/images/payment_icons/alandsbanken.svg +1 -0
  12. data/app/assets/images/payment_icons/alipay.svg +1 -0
  13. data/app/assets/images/payment_icons/alipay_hk.svg +1 -0
  14. data/app/assets/images/payment_icons/alliancebank.svg +1 -0
  15. data/app/assets/images/payment_icons/alma.svg +1 -0
  16. data/app/assets/images/payment_icons/amazon.svg +1 -0
  17. data/app/assets/images/payment_icons/ambank.svg +1 -0
  18. data/app/assets/images/payment_icons/american_express.svg +1 -0
  19. data/app/assets/images/payment_icons/apecoin.svg +1 -0
  20. data/app/assets/images/payment_icons/apple_pay.svg +1 -0
  21. data/app/assets/images/payment_icons/arbitrum.svg +1 -0
  22. data/app/assets/images/payment_icons/atome.svg +1 -0
  23. data/app/assets/images/payment_icons/authorizenet.svg +1 -0
  24. data/app/assets/images/payment_icons/avalanche.svg +1 -0
  25. data/app/assets/images/payment_icons/bacs.svg +1 -0
  26. data/app/assets/images/payment_icons/bancontact.svg +1 -0
  27. data/app/assets/images/payment_icons/bangkokbank.svg +1 -0
  28. data/app/assets/images/payment_icons/bankislam.svg +1 -0
  29. data/app/assets/images/payment_icons/bankmuamalat.svg +1 -0
  30. data/app/assets/images/payment_icons/bankofamerica.svg +1 -0
  31. data/app/assets/images/payment_icons/bankrakyat.svg +1 -0
  32. data/app/assets/images/payment_icons/base.svg +1 -0
  33. data/app/assets/images/payment_icons/becs.svg +1 -0
  34. data/app/assets/images/payment_icons/benefit.svg +1 -0
  35. data/app/assets/images/payment_icons/billie.svg +1 -0
  36. data/app/assets/images/payment_icons/bitcoin.svg +1 -0
  37. data/app/assets/images/payment_icons/bitcoin_cash.svg +1 -0
  38. data/app/assets/images/payment_icons/bizum.svg +1 -0
  39. data/app/assets/images/payment_icons/blik.svg +1 -0
  40. data/app/assets/images/payment_icons/bnbchain.svg +1 -0
  41. data/app/assets/images/payment_icons/bogus.svg +1 -0
  42. data/app/assets/images/payment_icons/bogus_app_coin.svg +1 -0
  43. data/app/assets/images/payment_icons/boleto.svg +1 -0
  44. data/app/assets/images/payment_icons/boost.svg +1 -0
  45. data/app/assets/images/payment_icons/braintree.svg +1 -0
  46. data/app/assets/images/payment_icons/buckaroopaybybank.svg +1 -0
  47. data/app/assets/images/payment_icons/busd.svg +1 -0
  48. data/app/assets/images/payment_icons/cartes_bancaires.svg +1 -0
  49. data/app/assets/images/payment_icons/cash.svg +1 -0
  50. data/app/assets/images/payment_icons/cashappafterpay.svg +1 -0
  51. data/app/assets/images/payment_icons/cashapppay.svg +1 -0
  52. data/app/assets/images/payment_icons/checkout_finance.svg +1 -0
  53. data/app/assets/images/payment_icons/chinabank.svg +1 -0
  54. data/app/assets/images/payment_icons/clearpay.svg +1 -0
  55. data/app/assets/images/payment_icons/collector_bank.svg +1 -0
  56. data/app/assets/images/payment_icons/dai.svg +1 -0
  57. data/app/assets/images/payment_icons/dana.svg +1 -0
  58. data/app/assets/images/payment_icons/dankort.svg +1 -0
  59. data/app/assets/images/payment_icons/danske_bank.svg +1 -0
  60. data/app/assets/images/payment_icons/deutschebank.svg +1 -0
  61. data/app/assets/images/payment_icons/diners_club.svg +1 -0
  62. data/app/assets/images/payment_icons/directbanktransferlatinamerica.svg +1 -0
  63. data/app/assets/images/payment_icons/discover.svg +1 -0
  64. data/app/assets/images/payment_icons/dogecoin.svg +1 -0
  65. data/app/assets/images/payment_icons/duitnow.svg +1 -0
  66. data/app/assets/images/payment_icons/eft_secure.svg +1 -0
  67. data/app/assets/images/payment_icons/eftpos_au.svg +1 -0
  68. data/app/assets/images/payment_icons/eftposau.svg +1 -0
  69. data/app/assets/images/payment_icons/elo.svg +1 -0
  70. data/app/assets/images/payment_icons/eos.svg +1 -0
  71. data/app/assets/images/payment_icons/eps.svg +1 -0
  72. data/app/assets/images/payment_icons/ethereum.svg +1 -0
  73. data/app/assets/images/payment_icons/eurobonuscheckout.svg +1 -0
  74. data/app/assets/images/payment_icons/ezcash.svg +1 -0
  75. data/app/assets/images/payment_icons/fantom.svg +1 -0
  76. data/app/assets/images/payment_icons/fpx.svg +1 -0
  77. data/app/assets/images/payment_icons/gcash.svg +1 -0
  78. data/app/assets/images/payment_icons/generic.svg +1 -0
  79. data/app/assets/images/payment_icons/genericbank.svg +1 -0
  80. data/app/assets/images/payment_icons/gift-card.svg +1 -0
  81. data/app/assets/images/payment_icons/giropay.svg +1 -0
  82. data/app/assets/images/payment_icons/glbepaypal.svg +1 -0
  83. data/app/assets/images/payment_icons/gmobanktransfer.svg +1 -0
  84. data/app/assets/images/payment_icons/gnosis.svg +1 -0
  85. data/app/assets/images/payment_icons/google_pay.svg +1 -0
  86. data/app/assets/images/payment_icons/google_wallet.svg +1 -0
  87. data/app/assets/images/payment_icons/gopay.svg +1 -0
  88. data/app/assets/images/payment_icons/grabpay.svg +1 -0
  89. data/app/assets/images/payment_icons/gusd.svg +1 -0
  90. data/app/assets/images/payment_icons/handelsbanken.svg +1 -0
  91. data/app/assets/images/payment_icons/hongleongbank.svg +1 -0
  92. data/app/assets/images/payment_icons/hypercard.svg +1 -0
  93. data/app/assets/images/payment_icons/hypercash.svg +1 -0
  94. data/app/assets/images/payment_icons/ideal.svg +1 -0
  95. data/app/assets/images/payment_icons/in3viaideal.svg +1 -0
  96. data/app/assets/images/payment_icons/inbank.svg +1 -0
  97. data/app/assets/images/payment_icons/jcb.svg +1 -0
  98. data/app/assets/images/payment_icons/kakao_pay.svg +1 -0
  99. data/app/assets/images/payment_icons/kasikornbank.svg +1 -0
  100. data/app/assets/images/payment_icons/klarna-pay-later.svg +1 -0
  101. data/app/assets/images/payment_icons/klarna-pay-now.svg +1 -0
  102. data/app/assets/images/payment_icons/klarna-slice-it.svg +1 -0
  103. data/app/assets/images/payment_icons/klarna.svg +1 -0
  104. data/app/assets/images/payment_icons/knet.svg +1 -0
  105. data/app/assets/images/payment_icons/krungthaibank.svg +1 -0
  106. data/app/assets/images/payment_icons/landbank.svg +1 -0
  107. data/app/assets/images/payment_icons/laybuybyklarna.svg +1 -0
  108. data/app/assets/images/payment_icons/litecoin.svg +1 -0
  109. data/app/assets/images/payment_icons/lunchcheck.svg +1 -0
  110. data/app/assets/images/payment_icons/mach.svg +1 -0
  111. data/app/assets/images/payment_icons/mada.svg +1 -0
  112. data/app/assets/images/payment_icons/maestro.svg +1 -0
  113. data/app/assets/images/payment_icons/master.svg +1 -0
  114. data/app/assets/images/payment_icons/mayabank.svg +1 -0
  115. data/app/assets/images/payment_icons/maybank.svg +1 -0
  116. data/app/assets/images/payment_icons/maybankm2u.svg +1 -0
  117. data/app/assets/images/payment_icons/maybankqrpay.svg +1 -0
  118. data/app/assets/images/payment_icons/mbway.svg +1 -0
  119. data/app/assets/images/payment_icons/mcash.svg +1 -0
  120. data/app/assets/images/payment_icons/medicinosbankas.svg +1 -0
  121. data/app/assets/images/payment_icons/mercadopago.svg +1 -0
  122. data/app/assets/images/payment_icons/metrobank.svg +1 -0
  123. data/app/assets/images/payment_icons/mobilepay.svg +1 -0
  124. data/app/assets/images/payment_icons/momopay.svg +1 -0
  125. data/app/assets/images/payment_icons/monero.svg +1 -0
  126. data/app/assets/images/payment_icons/mtn_mobile_money.svg +1 -0
  127. data/app/assets/images/payment_icons/mybank.svg +1 -0
  128. data/app/assets/images/payment_icons/naver_pay.svg +1 -0
  129. data/app/assets/images/payment_icons/nelo.svg +1 -0
  130. data/app/assets/images/payment_icons/netbanking.svg +1 -0
  131. data/app/assets/images/payment_icons/novalnetdirectdebitach.svg +1 -0
  132. data/app/assets/images/payment_icons/nubank.svg +1 -0
  133. data/app/assets/images/payment_icons/ocbcbank.svg +1 -0
  134. data/app/assets/images/payment_icons/offlinebanktransferlatinamerica.svg +1 -0
  135. data/app/assets/images/payment_icons/ola_money.svg +1 -0
  136. data/app/assets/images/payment_icons/oney.svg +1 -0
  137. data/app/assets/images/payment_icons/onlinebanking.svg +1 -0
  138. data/app/assets/images/payment_icons/onlinebanktransfer.svg +1 -0
  139. data/app/assets/images/payment_icons/orangemobilemoney.svg +1 -0
  140. data/app/assets/images/payment_icons/otpbank.svg +1 -0
  141. data/app/assets/images/payment_icons/oxxo.svg +1 -0
  142. data/app/assets/images/payment_icons/paybybank.svg +1 -0
  143. data/app/assets/images/payment_icons/paybybankmollie.svg +1 -0
  144. data/app/assets/images/payment_icons/paybybankus.svg +1 -0
  145. data/app/assets/images/payment_icons/paycash.svg +1 -0
  146. data/app/assets/images/payment_icons/payco.svg +1 -0
  147. data/app/assets/images/payment_icons/payeverpaybybank.svg +1 -0
  148. data/app/assets/images/payment_icons/payme.svg +1 -0
  149. data/app/assets/images/payment_icons/paynow.svg +1 -0
  150. data/app/assets/images/payment_icons/paynowmbank.svg +1 -0
  151. data/app/assets/images/payment_icons/paypal.svg +1 -0
  152. data/app/assets/images/payment_icons/paypo.svg +1 -0
  153. data/app/assets/images/payment_icons/payrexxbanktransfer.svg +1 -0
  154. data/app/assets/images/payment_icons/payrexxpaybybank.svg +1 -0
  155. data/app/assets/images/payment_icons/paysafecash.svg +1 -0
  156. data/app/assets/images/payment_icons/pix.svg +1 -0
  157. data/app/assets/images/payment_icons/polygon.svg +1 -0
  158. data/app/assets/images/payment_icons/przelewy24.svg +1 -0
  159. data/app/assets/images/payment_icons/publicbank.svg +1 -0
  160. data/app/assets/images/payment_icons/publicbank_pbe.svg +1 -0
  161. data/app/assets/images/payment_icons/qr_promptpay.svg +1 -0
  162. data/app/assets/images/payment_icons/rabobank.svg +1 -0
  163. data/app/assets/images/payment_icons/revolut.svg +1 -0
  164. data/app/assets/images/payment_icons/rhbbank.svg +1 -0
  165. data/app/assets/images/payment_icons/riverty.svg +1 -0
  166. data/app/assets/images/payment_icons/safetypaybanktransfer.svg +1 -0
  167. data/app/assets/images/payment_icons/samsung_pay.svg +1 -0
  168. data/app/assets/images/payment_icons/satispay.svg +1 -0
  169. data/app/assets/images/payment_icons/scalapay.svg +1 -0
  170. data/app/assets/images/payment_icons/scotiabank.svg +1 -0
  171. data/app/assets/images/payment_icons/seabankid.svg +1 -0
  172. data/app/assets/images/payment_icons/seabankph.svg +1 -0
  173. data/app/assets/images/payment_icons/sepa_bank_transfer.svg +1 -0
  174. data/app/assets/images/payment_icons/sepadirectdebit.svg +1 -0
  175. data/app/assets/images/payment_icons/seveneleven.svg +1 -0
  176. data/app/assets/images/payment_icons/shib.svg +1 -0
  177. data/app/assets/images/payment_icons/shopcash.svg +1 -0
  178. data/app/assets/images/payment_icons/siauliubankas.svg +1 -0
  179. data/app/assets/images/payment_icons/skeps.svg +1 -0
  180. data/app/assets/images/payment_icons/snap_checkout.svg +1 -0
  181. data/app/assets/images/payment_icons/sofort.svg +1 -0
  182. data/app/assets/images/payment_icons/softbank.svg +1 -0
  183. data/app/assets/images/payment_icons/spei.svg +1 -0
  184. data/app/assets/images/payment_icons/storecredit.svg +1 -0
  185. data/app/assets/images/payment_icons/stripe.svg +1 -0
  186. data/app/assets/images/payment_icons/sveacheckout.svg +1 -0
  187. data/app/assets/images/payment_icons/swedbank.svg +1 -0
  188. data/app/assets/images/payment_icons/swish.svg +1 -0
  189. data/app/assets/images/payment_icons/tbibank.svg +1 -0
  190. data/app/assets/images/payment_icons/thanachartbank.svg +1 -0
  191. data/app/assets/images/payment_icons/tnmmoney.svg +1 -0
  192. data/app/assets/images/payment_icons/touchngo.svg +1 -0
  193. data/app/assets/images/payment_icons/trustly.svg +1 -0
  194. data/app/assets/images/payment_icons/twint.svg +1 -0
  195. data/app/assets/images/payment_icons/uaevisa.svg +1 -0
  196. data/app/assets/images/payment_icons/unionpay.svg +1 -0
  197. data/app/assets/images/payment_icons/unzerbanktransfer.svg +1 -0
  198. data/app/assets/images/payment_icons/upi.svg +1 -0
  199. data/app/assets/images/payment_icons/usbank.svg +1 -0
  200. data/app/assets/images/payment_icons/usdc.svg +1 -0
  201. data/app/assets/images/payment_icons/usdt.svg +1 -0
  202. data/app/assets/images/payment_icons/venmo.svg +1 -0
  203. data/app/assets/images/payment_icons/vipps.svg +1 -0
  204. data/app/assets/images/payment_icons/visa.svg +1 -0
  205. data/app/assets/images/payment_icons/volksbank.svg +1 -0
  206. data/app/assets/images/payment_icons/waavepaybybank.svg +1 -0
  207. data/app/assets/images/payment_icons/walley.svg +1 -0
  208. data/app/assets/images/payment_icons/wbtc.svg +1 -0
  209. data/app/assets/images/payment_icons/wechatpay.svg +1 -0
  210. data/app/assets/images/payment_icons/whishcheckout.svg +1 -0
  211. data/app/assets/images/payment_icons/wingbank.svg +1 -0
  212. data/app/assets/images/payment_icons/xrp.svg +1 -0
  213. data/app/assets/images/payment_icons/zip.svg +1 -0
  214. data/app/finders/spree/posts/find.rb +137 -0
  215. data/app/helpers/spree/addresses_helper.rb +9 -3
  216. data/app/helpers/spree/base_helper.rb +8 -4
  217. data/app/helpers/spree/currency_helper.rb +21 -6
  218. data/app/jobs/spree/images/save_from_url_job.rb +70 -0
  219. data/app/jobs/spree/imports/create_rows_job.rb +72 -0
  220. data/app/jobs/spree/imports/process_rows_job.rb +19 -0
  221. data/app/models/concerns/spree/adjustment_source.rb +3 -3
  222. data/app/models/concerns/spree/admin_user_methods.rb +52 -0
  223. data/app/models/concerns/spree/display_on.rb +7 -1
  224. data/app/models/concerns/spree/has_image_alt_text.rb +18 -0
  225. data/app/models/concerns/spree/has_one_link.rb +1 -1
  226. data/app/models/concerns/spree/has_page_links.rb +1 -1
  227. data/app/models/concerns/spree/linkable.rb +9 -0
  228. data/app/models/concerns/spree/metadata.rb +2 -0
  229. data/app/models/concerns/spree/metafields.rb +94 -0
  230. data/app/models/concerns/spree/named_type.rb +1 -1
  231. data/app/models/concerns/spree/user_methods.rb +26 -9
  232. data/app/models/concerns/spree/user_payment_source.rb +1 -1
  233. data/app/models/concerns/spree/user_roles.rb +3 -2
  234. data/app/models/spree/ability.rb +4 -0
  235. data/app/models/spree/address.rb +6 -2
  236. data/app/models/spree/adjustable/adjuster/tax.rb +2 -2
  237. data/app/models/spree/adjustable/adjustments_updater.rb +26 -3
  238. data/app/models/spree/adjustment.rb +4 -1
  239. data/app/models/spree/asset.rb +16 -0
  240. data/app/models/spree/base.rb +1 -1
  241. data/app/models/spree/calculator.rb +1 -1
  242. data/app/models/spree/credit_card.rb +1 -0
  243. data/app/models/spree/current.rb +5 -1
  244. data/app/models/spree/custom_domain.rb +5 -0
  245. data/app/models/spree/customer_return.rb +1 -0
  246. data/app/models/spree/export.rb +39 -2
  247. data/app/models/spree/exports/customers.rb +17 -0
  248. data/app/models/spree/exports/gift_cards.rb +13 -0
  249. data/app/models/spree/exports/newsletter_subscribers.rb +13 -0
  250. data/app/models/spree/exports/orders.rb +6 -4
  251. data/app/models/spree/exports/products.rb +9 -3
  252. data/app/models/spree/gateway/bogus.rb +4 -0
  253. data/app/models/spree/gateway/custom_payment_source_method.rb +4 -0
  254. data/app/models/spree/gift_card.rb +9 -1
  255. data/app/models/spree/gift_card_batch.rb +0 -1
  256. data/app/models/spree/import.rb +279 -0
  257. data/app/models/spree/import_mapping.rb +46 -0
  258. data/app/models/spree/import_row.rb +108 -0
  259. data/app/models/spree/import_schema.rb +25 -0
  260. data/app/models/spree/import_schemas/products.rb +45 -0
  261. data/app/models/spree/imports/products.rb +9 -0
  262. data/app/models/spree/invitation.rb +1 -1
  263. data/app/models/spree/legacy_user.rb +0 -1
  264. data/app/models/spree/line_item.rb +3 -8
  265. data/app/models/spree/metafield.rb +53 -0
  266. data/app/models/spree/metafield_definition.rb +91 -0
  267. data/app/models/spree/metafields/boolean.rb +15 -0
  268. data/app/models/spree/metafields/json.rb +27 -0
  269. data/app/models/spree/metafields/long_text.rb +7 -0
  270. data/app/models/spree/metafields/number.rb +15 -0
  271. data/app/models/spree/metafields/rich_text.rb +18 -0
  272. data/app/models/spree/metafields/short_text.rb +7 -0
  273. data/app/models/spree/newsletter_subscriber/emails.rb +12 -0
  274. data/app/models/spree/newsletter_subscriber.rb +64 -0
  275. data/app/models/spree/option_type.rb +2 -0
  276. data/app/models/spree/option_value.rb +1 -0
  277. data/app/models/spree/order/checkout.rb +7 -0
  278. data/app/models/spree/order/payments.rb +1 -1
  279. data/app/models/spree/order.rb +14 -11
  280. data/app/models/spree/order_merger.rb +2 -4
  281. data/app/models/spree/order_promotion.rb +3 -0
  282. data/app/models/spree/order_updater.rb +2 -2
  283. data/app/models/spree/page.rb +5 -1
  284. data/app/models/spree/page_block.rb +4 -0
  285. data/app/models/spree/page_blocks/image.rb +3 -0
  286. data/app/models/spree/page_blocks/metafields.rb +18 -0
  287. data/app/models/spree/page_blocks/products/brand.rb +15 -0
  288. data/app/models/spree/page_blocks/products/buy_buttons.rb +5 -1
  289. data/app/models/spree/page_blocks/products/description.rb +18 -0
  290. data/app/models/spree/page_blocks/products/price.rb +1 -1
  291. data/app/models/spree/page_blocks/products/quantity_selector.rb +6 -2
  292. data/app/models/spree/page_blocks/products/title.rb +5 -1
  293. data/app/models/spree/page_blocks/products/variant_picker.rb +1 -1
  294. data/app/models/spree/page_section.rb +2 -2
  295. data/app/models/spree/page_sections/breadcrumbs.rb +12 -0
  296. data/app/models/spree/page_sections/footer.rb +20 -13
  297. data/app/models/spree/page_sections/image_banner.rb +6 -1
  298. data/app/models/spree/page_sections/image_with_text.rb +5 -0
  299. data/app/models/spree/page_sections/newsletter.rb +7 -0
  300. data/app/models/spree/page_sections/product_details.rb +38 -1
  301. data/app/models/spree/pages/account.rb +4 -0
  302. data/app/models/spree/pages/cart.rb +10 -0
  303. data/app/models/spree/pages/checkout.rb +6 -0
  304. data/app/models/spree/pages/custom.rb +4 -0
  305. data/app/models/spree/pages/homepage.rb +4 -0
  306. data/app/models/spree/pages/login.rb +4 -0
  307. data/app/models/spree/pages/password.rb +2 -0
  308. data/app/models/spree/pages/post_list.rb +5 -1
  309. data/app/models/spree/pages/product_details.rb +1 -0
  310. data/app/models/spree/pages/search_results.rb +1 -1
  311. data/app/models/spree/pages/shop_all.rb +5 -1
  312. data/app/models/spree/pages/wishlist.rb +4 -0
  313. data/app/models/spree/payment.rb +1 -0
  314. data/app/models/spree/payment_method.rb +8 -5
  315. data/app/models/spree/payment_source.rb +1 -0
  316. data/app/models/spree/policy.rb +70 -0
  317. data/app/models/spree/post.rb +4 -2
  318. data/app/models/spree/post_category.rb +1 -0
  319. data/app/models/spree/product.rb +16 -9
  320. data/app/models/spree/promotion/actions/free_shipping.rb +3 -3
  321. data/app/models/spree/promotion.rb +24 -8
  322. data/app/models/spree/promotion_action.rb +1 -1
  323. data/app/models/spree/promotion_handler/cart.rb +1 -1
  324. data/app/models/spree/promotion_handler/coupon.rb +1 -1
  325. data/app/models/spree/promotion_rule.rb +1 -1
  326. data/app/models/spree/property.rb +18 -0
  327. data/app/models/spree/refund.rb +2 -1
  328. data/app/models/spree/role_user.rb +1 -1
  329. data/app/models/spree/shipment.rb +1 -0
  330. data/app/models/spree/shipping_method.rb +1 -0
  331. data/app/models/spree/stock_item.rb +1 -0
  332. data/app/models/spree/stock_transfer.rb +1 -0
  333. data/app/models/spree/store.rb +45 -3
  334. data/app/models/spree/store_credit.rb +2 -1
  335. data/app/models/spree/tax_category.rb +1 -1
  336. data/app/models/spree/tax_rate.rb +18 -3
  337. data/app/models/spree/taxon.rb +12 -2
  338. data/app/models/spree/taxonomy.rb +11 -0
  339. data/app/models/spree/theme.rb +1 -1
  340. data/app/models/spree/variant.rb +17 -0
  341. data/app/presenters/spree/csv/customer_presenter.rb +59 -0
  342. data/app/presenters/spree/csv/gift_card_presenter.rb +49 -0
  343. data/app/presenters/spree/csv/metafields_helper.rb +17 -0
  344. data/app/presenters/spree/csv/newsletter_subscriber_presenter.rb +39 -0
  345. data/app/presenters/spree/csv/order_line_item_presenter.rb +12 -5
  346. data/app/presenters/spree/csv/product_variant_presenter.rb +9 -5
  347. data/app/services/spree/addresses/update.rb +8 -1
  348. data/app/services/spree/cart/recalculate.rb +6 -4
  349. data/app/services/spree/cart/remove_line_item.rb +1 -2
  350. data/app/services/spree/imports/row_processors/base.rb +19 -0
  351. data/app/services/spree/imports/row_processors/product_variant.rb +228 -0
  352. data/app/services/spree/line_items/destroy.rb +1 -1
  353. data/app/services/spree/newsletter/subscribe.rb +43 -0
  354. data/app/services/spree/newsletter/verify.rb +30 -0
  355. data/app/services/spree/orders/create_user_account.rb +5 -1
  356. data/app/services/spree/products/prepare_nested_attributes.rb +44 -0
  357. data/app/sorters/spree/posts/sort.rb +40 -0
  358. data/app/{services → validators}/spree/addresses/phone_validator.rb +1 -1
  359. data/app/views/spree/shared/_payment.html.erb +11 -9
  360. data/config/locales/en.yml +56 -2
  361. data/db/migrate/20250605131334_add_missing_fields_to_users.rb +23 -13
  362. data/db/migrate/20250728095629_create_spree_metafields.rb +27 -0
  363. data/db/migrate/20250730102644_add_missing_unique_indexes_to_spree_option_types_and_values.rb +40 -0
  364. data/db/migrate/20250730154601_add_unique_index_on_spree_properties_name.rb +24 -0
  365. data/db/migrate/20250811112056_create_spree_policies.rb +22 -0
  366. data/db/migrate/20250821211705_fix_unique_index_on_spree_order_promotions.rb +20 -0
  367. data/db/migrate/20250825175217_add_missing_page_builder_indexes.rb +7 -0
  368. data/db/migrate/20250826093602_create_spree_newsletter_subscribers.rb +12 -0
  369. data/db/migrate/20250902143122_fix_policies_store_association.rb +18 -0
  370. data/db/migrate/20250911205659_add_missing_index_on_spree_products_promotionable.rb +5 -0
  371. data/db/migrate/20250913130044_add_page_links_counter_cache_to_spree_stores.rb +10 -0
  372. data/db/migrate/20250914101955_add_missing_indexes_on_spree_adjustments.rb +6 -0
  373. data/db/migrate/20250915093930_add_metadata_to_spree_newsletter_subscribers.rb +20 -0
  374. data/db/migrate/20250923141845_create_spree_imports.rb +47 -0
  375. data/lib/generators/spree/cursor_rules/cursor_rules_generator.rb +19 -0
  376. data/lib/generators/spree/cursor_rules/templates/spree_rules.mdc +387 -0
  377. data/lib/generators/spree/dummy/dummy_generator.rb +0 -1
  378. data/lib/generators/spree/install/templates/config/initializers/spree.rb +5 -0
  379. data/lib/spree/core/configuration.rb +1 -0
  380. data/lib/spree/core/dependencies.rb +3 -0
  381. data/lib/spree/core/engine.rb +57 -2
  382. data/lib/spree/core/version.rb +1 -1
  383. data/lib/spree/core.rb +3 -1
  384. data/lib/spree/permitted_attributes.rb +18 -3
  385. data/lib/spree/testing_support/capybara_config.rb +9 -3
  386. data/lib/spree/testing_support/common_rake.rb +5 -5
  387. data/lib/spree/testing_support/factories/export_factory.rb +5 -17
  388. data/lib/spree/testing_support/factories/import_factory.rb +20 -0
  389. data/lib/spree/testing_support/factories/import_mapping_factory.rb +7 -0
  390. data/lib/spree/testing_support/factories/import_row_factory.rb +7 -0
  391. data/lib/spree/testing_support/factories/metafield_definition_factory.rb +72 -0
  392. data/lib/spree/testing_support/factories/metafield_factory.rb +68 -0
  393. data/lib/spree/testing_support/factories/newsletter_subscriber_factory.rb +18 -0
  394. data/lib/spree/testing_support/factories/policy_factory.rb +8 -0
  395. data/lib/spree/testing_support/factories/post_factory.rb +8 -0
  396. data/lib/spree/testing_support/store.rb +11 -0
  397. data/lib/tasks/core.rake +130 -3
  398. metadata +280 -7
  399. data/app/models/action_text/rich_text_decorator.rb +0 -11
  400. data/app/presenters/spree/csv/product_presenter.rb +0 -63
@@ -0,0 +1,91 @@
1
+ module Spree
2
+ class MetafieldDefinition < Spree.base_class
3
+ include Spree::DisplayOn
4
+
5
+ DISPLAY = [:both, :back_end]
6
+
7
+ #
8
+ # Associations
9
+ #
10
+ has_many :metafields, class_name: 'Spree::Metafield', dependent: :destroy
11
+
12
+ #
13
+ # Validations
14
+ #
15
+ validates :namespace, :key, :name, :resource_type, presence: true
16
+ validates :metafield_type, presence: true, inclusion: { in: :valid_available_types }
17
+ validates :resource_type, presence: true, inclusion: { in: :valid_available_resources }
18
+ validates :key, uniqueness: { scope: spree_base_uniqueness_scope + [:resource_type, :namespace] }
19
+
20
+ #
21
+ # Scopes
22
+ #
23
+ scope :for_resource_type, ->(resource_type) { where(resource_type: resource_type) }
24
+ scope :multi_search, ->(search) do
25
+ return all if search.blank?
26
+
27
+ search_term = "%#{search.downcase}%"
28
+ namespace_condition = arel_table[:namespace].lower.matches(search_term)
29
+ key_condition = arel_table[:key].lower.matches(search_term)
30
+ name_condition = arel_table[:name].lower.matches(search_term)
31
+
32
+ where(namespace_condition.or(key_condition).or(name_condition))
33
+ end
34
+
35
+ #
36
+ # Callbacks
37
+ #
38
+ normalizes :key, with: ->(value) { value.to_s.parameterize.underscore.strip }
39
+ normalizes :namespace, with: ->(value) { value.to_s.parameterize.underscore.strip }
40
+ before_validation :set_default_type, if: -> { metafield_type.blank? }, on: :create
41
+ before_validation :set_name_from_key, if: -> { name.blank? }, on: :create
42
+
43
+ #
44
+ # Ransack
45
+ #
46
+ self.whitelisted_ransackable_attributes = %w[key namespace name resource_type display_on]
47
+ self.whitelisted_ransackable_scopes = %w[multi_search]
48
+
49
+ # Returns the full key with namespace
50
+ # @return [String] eg. custom.id
51
+ def full_key
52
+ "#{namespace}.#{key}"
53
+ end
54
+
55
+ # Returns the CSV header name for this metafield
56
+ # @return [String] eg. metafield.custom.id
57
+ def csv_header_name
58
+ "metafield.#{full_key}"
59
+ end
60
+
61
+ # Returns the available types
62
+ # @return [Array<Class>]
63
+ def self.available_types
64
+ Rails.application.config.spree.metafield_types
65
+ end
66
+
67
+ # Returns the available resources
68
+ # @return [Array<Class>]
69
+ def self.available_resources
70
+ Rails.application.config.spree.metafield_enabled_resources
71
+ end
72
+
73
+ private
74
+
75
+ def valid_available_types
76
+ self.class.available_types.map(&:to_s)
77
+ end
78
+
79
+ def valid_available_resources
80
+ self.class.available_resources.map(&:to_s)
81
+ end
82
+
83
+ def set_default_type
84
+ self.metafield_type ||= Rails.application.config.spree.metafield_types.first.to_s
85
+ end
86
+
87
+ def set_name_from_key
88
+ self.name ||= key.titleize
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,15 @@
1
+ module Spree
2
+ module Metafields
3
+ class Boolean < Spree::Metafield
4
+ normalizes :value, with: ->(value) { value.to_b.to_s }
5
+
6
+ def csv_value
7
+ value.to_b ? Spree.t(:say_yes) : Spree.t(:say_no)
8
+ end
9
+
10
+ def serialize_value
11
+ value.to_b
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,27 @@
1
+ module Spree
2
+ module Metafields
3
+ class Json < Spree::Metafield
4
+ validate :value_must_be_valid_json
5
+
6
+ def serialize_value
7
+ JSON.parse(value)
8
+ rescue JSON::ParserError
9
+ value
10
+ end
11
+
12
+ def csv_value
13
+ value.to_s
14
+ end
15
+
16
+ private
17
+
18
+ def value_must_be_valid_json
19
+ return if value.blank?
20
+
21
+ JSON.parse(value)
22
+ rescue JSON::ParserError => e
23
+ errors.add(:value, "must be valid JSON: #{e.message}")
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,7 @@
1
+ module Spree
2
+ module Metafields
3
+ class LongText < Spree::Metafield
4
+ normalizes :value, with: ->(value) { value.to_s.strip }
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,15 @@
1
+ module Spree
2
+ module Metafields
3
+ class Number < Spree::Metafield
4
+ validates :value, numericality: true
5
+
6
+ def serialize_value
7
+ value.to_d
8
+ end
9
+
10
+ def csv_value
11
+ value.to_d.to_s
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ module Spree
2
+ module Metafields
3
+ class RichText < Spree::Metafield
4
+ # Avoid collision with the `value` column used by other metafield types
5
+ self.ignored_columns = %w[value]
6
+
7
+ has_rich_text :value
8
+
9
+ def serialize_value
10
+ value&.body&.to_s
11
+ end
12
+
13
+ def csv_value
14
+ value&.body&.to_plain_text || ''
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,7 @@
1
+ module Spree
2
+ module Metafields
3
+ class ShortText < Spree::Metafield
4
+ normalizes :value, with: ->(value) { value.to_s.strip }
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ module Spree
2
+ class NewsletterSubscriber < Spree.base_class
3
+ module Emails
4
+ extend ActiveSupport::Concern
5
+
6
+ def deliver_newsletter_email_verification
7
+ # you can overwrite this method in your application / extension to send out the confirmation email
8
+ # or use `spree_emails` gem
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,64 @@
1
+ require_dependency 'spree/newsletter_subscriber/emails'
2
+
3
+ module Spree
4
+ class NewsletterSubscriber < Spree.base_class
5
+ include Spree::NewsletterSubscriber::Emails
6
+ include Spree::Metafields
7
+
8
+ has_secure_token :verification_token
9
+
10
+ #
11
+ # Associations
12
+ #
13
+ belongs_to :user, optional: true, class_name: Spree.user_class&.name
14
+
15
+ #
16
+ # Validations
17
+ #
18
+ validates :email,
19
+ presence: true,
20
+ format: { with: URI::MailTo::EMAIL_REGEXP },
21
+ uniqueness: { case_sensitive: false, scope: spree_base_uniqueness_scope }
22
+
23
+ #
24
+ # Scopes
25
+ #
26
+ scope :verified, -> { where.not(verified_at: nil) }
27
+ scope :unverified, -> { where(verified_at: nil) }
28
+
29
+ #
30
+ # Callbacks
31
+ #
32
+ normalizes :email, with: ->(email) { email.to_s.strip.downcase.presence }
33
+
34
+ #
35
+ # Ransack filtering
36
+ #
37
+ self.whitelisted_ransackable_attributes = %w[email verified_at]
38
+ self.whitelisted_ransackable_scopes = %w[verified unverified]
39
+
40
+ def accepts_email_marketing
41
+ return user.accepts_email_marketing if user.present?
42
+
43
+ verified?
44
+ end
45
+
46
+ def verified?
47
+ verified_at.present?
48
+ end
49
+
50
+ def to_csv(_store = nil)
51
+ Spree::CSV::NewsletterSubscriberPresenter.new(self).call
52
+ end
53
+
54
+ def self.subscribe(email:, user: nil)
55
+ Spree::Newsletter::Subscribe.new(email: email, current_user: user).call
56
+ end
57
+
58
+ def self.verify(token:)
59
+ subscriber = unverified.find_by!(verification_token: token)
60
+
61
+ Spree::Newsletter::Verify.new(subscriber: subscriber).call
62
+ end
63
+ end
64
+ end
@@ -4,6 +4,7 @@ module Spree
4
4
 
5
5
  include Spree::ParameterizableName
6
6
  include Spree::UniqueName
7
+ include Spree::Metafields
7
8
  include Spree::Metadata
8
9
  include Spree::TranslatableResource
9
10
  if defined?(Spree::Webhooks::HasWebhooks)
@@ -61,6 +62,7 @@ module Spree
61
62
 
62
63
  # legacy, name itself is now parameterized before saving
63
64
  def filter_param
65
+ Spree::Deprecation.warn('Spree::OptionType#filter_param is deprecated and will be removed in Spree 6. Please use Spree::OptionType#name instead.')
64
66
  name.parameterize
65
67
  end
66
68
 
@@ -1,6 +1,7 @@
1
1
  module Spree
2
2
  class OptionValue < Spree.base_class
3
3
  include Spree::ParameterizableName
4
+ include Spree::Metafields
4
5
  include Spree::Metadata
5
6
  include Spree::TranslatableResource
6
7
  if defined?(Spree::Webhooks::HasWebhooks)
@@ -122,6 +122,7 @@ module Spree
122
122
  after_transition to: :complete, do: :redeem_gift_card
123
123
  after_transition to: :resumed, do: :after_resume
124
124
  after_transition to: :canceled, do: :after_cancel
125
+ after_transition to: :complete, do: :subscribe_to_newsletter
125
126
 
126
127
  after_transition from: any - :cart, to: any - [:confirm, :complete] do |order|
127
128
  order.update_totals
@@ -132,6 +133,12 @@ module Spree
132
133
  alias_method :save_state, :save
133
134
  end
134
135
 
136
+ def subscribe_to_newsletter
137
+ return unless accept_marketing?
138
+
139
+ Spree::NewsletterSubscriber.subscribe(email: email, user: user)
140
+ end
141
+
135
142
  def self.go_to_state(name, options = {})
136
143
  self.checkout_steps[name] = options
137
144
  self.previous_states.each { |state| add_transition({ from: state, to: name }.merge(options)) }
@@ -20,7 +20,7 @@ module Spree
20
20
  # :allow_checkout_on_gateway_error is set to false
21
21
  #
22
22
  def process_payments!
23
- process_payments_with(:process!)
23
+ with_lock { process_payments_with(:process!) }
24
24
  end
25
25
 
26
26
  def authorize_payments!
@@ -29,6 +29,7 @@ module Spree
29
29
  include Spree::NumberAsParam
30
30
  include Spree::SingleStoreResource
31
31
  include Spree::MemoizedData
32
+ include Spree::Metafields
32
33
  include Spree::Metadata
33
34
  include Spree::MultiSearchable
34
35
  if defined?(Spree::Security::Orders)
@@ -228,7 +229,7 @@ module Spree
228
229
  conditions << multi_search_condition(Spree::Address, :lastname, full_name.last)
229
230
  end
230
231
 
231
- left_joins(:bill_address).where(email: sanitized_query).or(where(conditions.reduce(:or)))
232
+ left_joins(:bill_address).where(arel_table[:email].lower.eq(query.downcase)).or(where(conditions.reduce(:or)))
232
233
  end
233
234
 
234
235
  # Use this method in other gems that wish to register their own custom logic
@@ -268,16 +269,14 @@ module Spree
268
269
  end
269
270
 
270
271
  def order_refunded?
271
- (payment_state == 'void' && refunds.sum(:amount).positive?) || refunds.sum(:amount) == total
272
+ (payment_state.in?(%w[void failed]) && refunds.sum(:amount).positive?) ||
273
+ refunds.sum(:amount) == total_minus_store_credits - additional_tax_total.abs
272
274
  end
273
275
 
274
276
  def partially_refunded?
275
- return false if refunds.empty?
277
+ return false if refunds.empty? || payment_state.in?(%w[void failed])
276
278
 
277
- # we must deduct not returned amount, otherwise it can look like order has not been fully refunded
278
- amount_not_refunded = additional_tax_total.abs + total_applied_store_credit
279
-
280
- refunds.sum(:amount) < total - amount_not_refunded
279
+ refunds.sum(:amount) < total_minus_store_credits - additional_tax_total.abs
281
280
  end
282
281
 
283
282
  # Indicates whether or not the user is allowed to proceed to checkout.
@@ -301,7 +300,7 @@ module Spree
301
300
  # If true, causes the confirmation step to happen during the checkout process
302
301
  def confirmation_required?
303
302
  Spree::Config[:always_include_confirm_step] ||
304
- payments.valid.map(&:payment_method).compact.any?(&:payment_profiles_supported?) ||
303
+ payments.valid.map(&:payment_method).compact.any?(&:confirmation_required?) ||
305
304
  # Little hacky fix for #4117
306
305
  # If this wasn't here, order would transition to address state on confirm failure
307
306
  # because there would be no valid payments any more.
@@ -350,7 +349,7 @@ module Spree
350
349
  end
351
350
 
352
351
  def updater
353
- @updater ||= OrderUpdater.new(self)
352
+ @updater ||= Spree::Dependencies.order_updater.constantize.new(self)
354
353
  end
355
354
 
356
355
  def update_with_updater!
@@ -454,7 +453,7 @@ module Spree
454
453
 
455
454
  def full_name
456
455
  @full_name ||= if user.present? && user.name.present?
457
- user.name.full
456
+ user.full_name
458
457
  else
459
458
  billing_address&.full_name || email
460
459
  end
@@ -849,9 +848,13 @@ module Spree
849
848
  end
850
849
 
851
850
  def to_csv(_store = nil)
851
+ metafields_for_csv ||= Spree::MetafieldDefinition.for_resource_type('Spree::Order').order(:namespace, :key).map do |mf_def|
852
+ metafields.find { |mf| mf.metafield_definition_id == mf_def.id }&.csv_value
853
+ end
854
+
852
855
  csv_lines = []
853
856
  all_line_items.each_with_index do |line_item, index|
854
- csv_lines << Spree::CSV::OrderLineItemPresenter.new(self, line_item, index).call
857
+ csv_lines << Spree::CSV::OrderLineItemPresenter.new(self, line_item, index, metafields_for_csv).call
855
858
  end
856
859
  csv_lines
857
860
  end
@@ -57,7 +57,7 @@ module Spree
57
57
  current_line_item.quantity += other_order_line_item.quantity
58
58
  handle_error(current_line_item) unless current_line_item.save
59
59
  else
60
- other_order_line_item.order_id = order.id
60
+ order.line_items << other_order_line_item
61
61
  other_order_line_item.adjustments.update_all(order_id: order.id)
62
62
  handle_error(other_order_line_item) unless other_order_line_item.save
63
63
  end
@@ -69,9 +69,7 @@ module Spree
69
69
  end
70
70
 
71
71
  def persist_merge
72
- updater.update_item_count
73
- updater.update_item_total
74
- updater.persist_totals
72
+ updater.update
75
73
  end
76
74
 
77
75
  def handle_gift_card(other_order)
@@ -6,6 +6,9 @@ module Spree
6
6
  delegate :name, :description, :code, :public_metadata, to: :promotion
7
7
  delegate :currency, to: :order
8
8
 
9
+ validates :order, :promotion, presence: true
10
+ validates :order, uniqueness: { scope: :promotion }
11
+
9
12
  extend Spree::DisplayMoney
10
13
  money_methods :amount
11
14
 
@@ -69,7 +69,7 @@ module Spree
69
69
  end
70
70
 
71
71
  def update_shipment_total
72
- order.shipment_total = shipments.sum(:cost)
72
+ order.shipment_total = shipments.to_a.sum(&:cost)
73
73
  update_order_total
74
74
  end
75
75
 
@@ -97,7 +97,7 @@ module Spree
97
97
  end
98
98
 
99
99
  def update_item_total
100
- order.item_total = line_items.sum('price * quantity')
100
+ order.item_total = line_items.to_a.sum(&:amount)
101
101
  update_order_total
102
102
  end
103
103
 
@@ -1,6 +1,7 @@
1
1
  module Spree
2
2
  class Page < Spree.base_class
3
3
  include Spree::Previewable
4
+ include Spree::Linkable
4
5
 
5
6
  #
6
7
  # Magic methods
@@ -14,7 +15,6 @@ module Spree
14
15
  #
15
16
  belongs_to :pageable, polymorphic: true # this can be either Store or Theme
16
17
  has_many :sections, -> { order(position: :asc) }, class_name: 'Spree::PageSection', dependent: :destroy_async, as: :pageable
17
- has_many :page_links, as: :linkable, class_name: 'Spree::PageLink', dependent: :destroy
18
18
  alias page_sections sections
19
19
 
20
20
  #
@@ -103,6 +103,10 @@ module Spree
103
103
  false
104
104
  end
105
105
 
106
+ def linkable?
107
+ false
108
+ end
109
+
106
110
  def layout_sections?
107
111
  true
108
112
  end
@@ -56,6 +56,10 @@ module Spree
56
56
  name
57
57
  end
58
58
 
59
+ def form_partial_name
60
+ type.demodulize.underscore
61
+ end
62
+
59
63
  def icon_name
60
64
  'fullscreen'
61
65
  end
@@ -1,6 +1,8 @@
1
1
  module Spree
2
2
  module PageBlocks
3
3
  class Image < Spree::PageBlock
4
+ include Spree::HasImageAltText
5
+
4
6
  alias image asset
5
7
 
6
8
  TOP_PADDING_DEFAULT = 20
@@ -8,6 +10,7 @@ module Spree
8
10
 
9
11
  preference :height, :integer, default: 64
10
12
  preference :mobile_height, :integer, default: 32
13
+ preference :image_alt, :string
11
14
 
12
15
  def icon_name
13
16
  'photo'
@@ -0,0 +1,18 @@
1
+ module Spree
2
+ module PageBlocks
3
+ class Metafields < Spree::PageBlock
4
+ RESOURCE_TYPE_DEFAULT = 'Spree::Product'
5
+
6
+ preference :resource_type, :string, default: -> { self.class::RESOURCE_TYPE_DEFAULT if defined?(self.class::RESOURCE_TYPE_DEFAULT) }
7
+ preference :metafield_definition_ids, :array, default: -> { available_metafield_definitions.pluck(:id) }
8
+
9
+ def icon_name
10
+ 'list'
11
+ end
12
+
13
+ def available_metafield_definitions
14
+ @available_metafield_definitions ||= Spree::MetafieldDefinition.where(resource_type: preferred_resource_type).available_on_front_end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ module Spree
2
+ module PageBlocks
3
+ module Products
4
+ class Brand < Spree::PageBlocks::Heading
5
+ preference :text_color, :string
6
+
7
+ SIZE_DEFAULT = 'medium'
8
+
9
+ def display_name
10
+ Spree.t(:brand)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -2,7 +2,7 @@ module Spree
2
2
  module PageBlocks
3
3
  module Products
4
4
  class BuyButtons < Spree::PageBlock
5
- TOP_PADDING_DEFAULT = 20
5
+ TOP_PADDING_DEFAULT = 0
6
6
  BOTTOM_PADDING_DEFAULT = 20
7
7
 
8
8
  preference :text_color, :string
@@ -14,6 +14,10 @@ module Spree
14
14
  def display_name
15
15
  Spree.t('page_blocks.products.buy_buttons.display_name')
16
16
  end
17
+
18
+ def form_partial_name
19
+ 'products/buy_buttons'
20
+ end
17
21
  end
18
22
  end
19
23
  end
@@ -0,0 +1,18 @@
1
+ module Spree
2
+ module PageBlocks
3
+ module Products
4
+ class Description < Spree::PageBlocks::Text
5
+ TOP_PADDING_DEFAULT = 0
6
+ BOTTOM_PADDING_DEFAULT = 20
7
+
8
+ def form_partial_name
9
+ 'products/description'
10
+ end
11
+
12
+ def display_name
13
+ I18n.t('activerecord.attributes.spree/product.description')
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -10,7 +10,7 @@ module Spree
10
10
  end
11
11
 
12
12
  def display_name
13
- 'Price'
13
+ Spree.t(:price)
14
14
  end
15
15
  end
16
16
  end
@@ -2,13 +2,17 @@ module Spree
2
2
  module PageBlocks
3
3
  module Products
4
4
  class QuantitySelector < Spree::PageBlock
5
- TOP_PADDING_DEFAULT = 20
5
+ TOP_PADDING_DEFAULT = 0
6
6
  BOTTOM_PADDING_DEFAULT = 20
7
7
 
8
8
  preference :text_color, :string
9
9
 
10
10
  def icon_name
11
- 'selector'
11
+ 'plus-minus'
12
+ end
13
+
14
+ def form_partial_name
15
+ 'products/quantity_selector'
12
16
  end
13
17
  end
14
18
  end
@@ -7,7 +7,11 @@ module Spree
7
7
  preference :text_color, :string
8
8
 
9
9
  def display_name
10
- section.product_name.presence || 'Title'
10
+ I18n.t('activerecord.attributes.spree/product.name')
11
+ end
12
+
13
+ def icon_name
14
+ 'h-1'
11
15
  end
12
16
  end
13
17
  end
@@ -5,7 +5,7 @@ module Spree
5
5
  preference :text_color, :string
6
6
 
7
7
  def icon_name
8
- 'select'
8
+ 'list-details'
9
9
  end
10
10
  end
11
11
  end
@@ -5,7 +5,7 @@ module Spree
5
5
  # Magic methods
6
6
  #
7
7
  acts_as_paranoid
8
- acts_as_list scope: [:pageable_id, { deleted_at: nil }]
8
+ acts_as_list scope: [:pageable_type, :pageable_id, { deleted_at: nil }]
9
9
 
10
10
  #
11
11
  # Associations
@@ -123,7 +123,7 @@ module Spree
123
123
  end
124
124
 
125
125
  def can_be_sorted?
126
- role == 'content'
126
+ true
127
127
  end
128
128
 
129
129
  def lazy?
@@ -0,0 +1,12 @@
1
+ module Spree
2
+ module PageSections
3
+ class Breadcrumbs < Spree::PageSection
4
+ TOP_PADDING_DEFAULT = 20
5
+ BOTTOM_PADDING_DEFAULT = 20
6
+
7
+ def icon_name
8
+ 'chevron-right'
9
+ end
10
+ end
11
+ end
12
+ end