spree_core 5.1.8 → 5.2.0.rc2

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 (393) 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/jobs/spree/images/save_from_url_job.rb +70 -0
  218. data/app/jobs/spree/imports/create_rows_job.rb +72 -0
  219. data/app/jobs/spree/imports/process_rows_job.rb +19 -0
  220. data/app/models/concerns/spree/adjustment_source.rb +3 -3
  221. data/app/models/concerns/spree/admin_user_methods.rb +52 -0
  222. data/app/models/concerns/spree/display_on.rb +7 -1
  223. data/app/models/concerns/spree/has_image_alt_text.rb +18 -0
  224. data/app/models/concerns/spree/has_one_link.rb +1 -1
  225. data/app/models/concerns/spree/has_page_links.rb +1 -1
  226. data/app/models/concerns/spree/linkable.rb +9 -0
  227. data/app/models/concerns/spree/metadata.rb +2 -0
  228. data/app/models/concerns/spree/metafields.rb +94 -0
  229. data/app/models/concerns/spree/named_type.rb +1 -1
  230. data/app/models/concerns/spree/user_methods.rb +20 -7
  231. data/app/models/concerns/spree/user_payment_source.rb +1 -1
  232. data/app/models/concerns/spree/user_roles.rb +3 -2
  233. data/app/models/spree/ability.rb +4 -0
  234. data/app/models/spree/address.rb +3 -1
  235. data/app/models/spree/adjustable/adjuster/tax.rb +2 -2
  236. data/app/models/spree/adjustable/adjustments_updater.rb +26 -3
  237. data/app/models/spree/adjustment.rb +4 -1
  238. data/app/models/spree/asset.rb +16 -0
  239. data/app/models/spree/base.rb +1 -1
  240. data/app/models/spree/credit_card.rb +1 -0
  241. data/app/models/spree/current.rb +5 -1
  242. data/app/models/spree/custom_domain.rb +5 -0
  243. data/app/models/spree/customer_return.rb +1 -0
  244. data/app/models/spree/export.rb +39 -2
  245. data/app/models/spree/exports/customers.rb +17 -0
  246. data/app/models/spree/exports/gift_cards.rb +13 -0
  247. data/app/models/spree/exports/newsletter_subscribers.rb +13 -0
  248. data/app/models/spree/exports/orders.rb +6 -4
  249. data/app/models/spree/exports/products.rb +9 -3
  250. data/app/models/spree/gift_card.rb +7 -1
  251. data/app/models/spree/gift_card_batch.rb +0 -1
  252. data/app/models/spree/import.rb +279 -0
  253. data/app/models/spree/import_mapping.rb +46 -0
  254. data/app/models/spree/import_row.rb +108 -0
  255. data/app/models/spree/import_schema.rb +25 -0
  256. data/app/models/spree/import_schemas/products.rb +45 -0
  257. data/app/models/spree/imports/products.rb +9 -0
  258. data/app/models/spree/invitation.rb +1 -1
  259. data/app/models/spree/legacy_user.rb +0 -1
  260. data/app/models/spree/line_item.rb +9 -8
  261. data/app/models/spree/metafield.rb +53 -0
  262. data/app/models/spree/metafield_definition.rb +91 -0
  263. data/app/models/spree/metafields/boolean.rb +15 -0
  264. data/app/models/spree/metafields/json.rb +27 -0
  265. data/app/models/spree/metafields/long_text.rb +7 -0
  266. data/app/models/spree/metafields/number.rb +15 -0
  267. data/app/models/spree/metafields/rich_text.rb +18 -0
  268. data/app/models/spree/metafields/short_text.rb +7 -0
  269. data/app/models/spree/newsletter_subscriber/emails.rb +12 -0
  270. data/app/models/spree/newsletter_subscriber.rb +64 -0
  271. data/app/models/spree/option_type.rb +2 -0
  272. data/app/models/spree/option_value.rb +1 -0
  273. data/app/models/spree/order/checkout.rb +7 -0
  274. data/app/models/spree/order.rb +8 -3
  275. data/app/models/spree/order_merger.rb +2 -4
  276. data/app/models/spree/order_promotion.rb +3 -0
  277. data/app/models/spree/order_updater.rb +2 -2
  278. data/app/models/spree/page.rb +5 -1
  279. data/app/models/spree/page_block.rb +4 -0
  280. data/app/models/spree/page_blocks/image.rb +3 -0
  281. data/app/models/spree/page_blocks/metafields.rb +18 -0
  282. data/app/models/spree/page_blocks/products/brand.rb +15 -0
  283. data/app/models/spree/page_blocks/products/buy_buttons.rb +5 -1
  284. data/app/models/spree/page_blocks/products/description.rb +18 -0
  285. data/app/models/spree/page_blocks/products/price.rb +1 -1
  286. data/app/models/spree/page_blocks/products/quantity_selector.rb +6 -2
  287. data/app/models/spree/page_blocks/products/title.rb +5 -1
  288. data/app/models/spree/page_blocks/products/variant_picker.rb +1 -1
  289. data/app/models/spree/page_section.rb +2 -2
  290. data/app/models/spree/page_sections/breadcrumbs.rb +12 -0
  291. data/app/models/spree/page_sections/footer.rb +20 -13
  292. data/app/models/spree/page_sections/image_banner.rb +6 -1
  293. data/app/models/spree/page_sections/image_with_text.rb +5 -0
  294. data/app/models/spree/page_sections/newsletter.rb +7 -0
  295. data/app/models/spree/page_sections/product_details.rb +38 -1
  296. data/app/models/spree/pages/account.rb +4 -0
  297. data/app/models/spree/pages/cart.rb +10 -0
  298. data/app/models/spree/pages/checkout.rb +6 -0
  299. data/app/models/spree/pages/custom.rb +4 -0
  300. data/app/models/spree/pages/homepage.rb +4 -0
  301. data/app/models/spree/pages/login.rb +4 -0
  302. data/app/models/spree/pages/password.rb +2 -0
  303. data/app/models/spree/pages/post_list.rb +4 -0
  304. data/app/models/spree/pages/product_details.rb +1 -0
  305. data/app/models/spree/pages/shop_all.rb +4 -0
  306. data/app/models/spree/pages/wishlist.rb +4 -0
  307. data/app/models/spree/payment.rb +1 -0
  308. data/app/models/spree/payment_method.rb +4 -5
  309. data/app/models/spree/payment_source.rb +1 -0
  310. data/app/models/spree/policy.rb +70 -0
  311. data/app/models/spree/post.rb +4 -2
  312. data/app/models/spree/post_category.rb +1 -0
  313. data/app/models/spree/product.rb +16 -9
  314. data/app/models/spree/promotion/actions/free_shipping.rb +3 -3
  315. data/app/models/spree/promotion.rb +24 -8
  316. data/app/models/spree/promotion_action.rb +1 -1
  317. data/app/models/spree/promotion_handler/cart.rb +1 -1
  318. data/app/models/spree/promotion_handler/coupon.rb +1 -1
  319. data/app/models/spree/promotion_rule.rb +1 -1
  320. data/app/models/spree/property.rb +18 -0
  321. data/app/models/spree/refund.rb +2 -1
  322. data/app/models/spree/role_user.rb +1 -1
  323. data/app/models/spree/shipment.rb +1 -0
  324. data/app/models/spree/shipping_method.rb +1 -0
  325. data/app/models/spree/stock_item.rb +1 -0
  326. data/app/models/spree/stock_transfer.rb +1 -0
  327. data/app/models/spree/store.rb +45 -3
  328. data/app/models/spree/store_credit.rb +2 -1
  329. data/app/models/spree/tax_category.rb +1 -1
  330. data/app/models/spree/tax_rate.rb +18 -3
  331. data/app/models/spree/taxon.rb +12 -2
  332. data/app/models/spree/taxonomy.rb +11 -0
  333. data/app/models/spree/theme.rb +1 -1
  334. data/app/models/spree/variant.rb +16 -0
  335. data/app/presenters/spree/csv/customer_presenter.rb +59 -0
  336. data/app/presenters/spree/csv/gift_card_presenter.rb +49 -0
  337. data/app/presenters/spree/csv/metafields_helper.rb +17 -0
  338. data/app/presenters/spree/csv/newsletter_subscriber_presenter.rb +39 -0
  339. data/app/presenters/spree/csv/order_line_item_presenter.rb +12 -5
  340. data/app/presenters/spree/csv/product_variant_presenter.rb +9 -5
  341. data/app/services/spree/cart/recalculate.rb +6 -4
  342. data/app/services/spree/cart/remove_line_item.rb +1 -2
  343. data/app/services/spree/imports/row_processors/base.rb +19 -0
  344. data/app/services/spree/imports/row_processors/product_variant.rb +238 -0
  345. data/app/services/spree/line_items/destroy.rb +1 -1
  346. data/app/services/spree/newsletter/subscribe.rb +43 -0
  347. data/app/services/spree/newsletter/verify.rb +30 -0
  348. data/app/services/spree/seeds/admin_user.rb +5 -5
  349. data/app/sorters/spree/posts/sort.rb +40 -0
  350. data/app/views/spree/shared/_payment.html.erb +3 -3
  351. data/config/locales/en.yml +56 -2
  352. data/db/migrate/20250605131334_add_missing_fields_to_users.rb +23 -13
  353. data/db/migrate/20250728095629_create_spree_metafields.rb +27 -0
  354. data/db/migrate/20250730102644_add_missing_unique_indexes_to_spree_option_types_and_values.rb +40 -0
  355. data/db/migrate/20250730154601_add_unique_index_on_spree_properties_name.rb +24 -0
  356. data/db/migrate/20250811112056_create_spree_policies.rb +22 -0
  357. data/db/migrate/20250821211705_fix_unique_index_on_spree_order_promotions.rb +20 -0
  358. data/db/migrate/20250825175217_add_missing_page_builder_indexes.rb +7 -0
  359. data/db/migrate/20250826093602_create_spree_newsletter_subscribers.rb +12 -0
  360. data/db/migrate/20250902143122_fix_policies_store_association.rb +18 -0
  361. data/db/migrate/20250911205659_add_missing_index_on_spree_products_promotionable.rb +5 -0
  362. data/db/migrate/20250913130044_add_page_links_counter_cache_to_spree_stores.rb +10 -0
  363. data/db/migrate/20250914101955_add_missing_indexes_on_spree_adjustments.rb +6 -0
  364. data/db/migrate/20250915093930_add_metadata_to_spree_newsletter_subscribers.rb +20 -0
  365. data/db/migrate/20250923141845_create_spree_imports.rb +47 -0
  366. data/lib/generators/spree/authentication/devise/devise_generator.rb +24 -0
  367. data/lib/generators/spree/cursor_rules/cursor_rules_generator.rb +19 -0
  368. data/lib/generators/spree/cursor_rules/templates/spree_rules.mdc +387 -0
  369. data/lib/generators/spree/dummy/dummy_generator.rb +0 -1
  370. data/lib/generators/spree/install/install_generator.rb +7 -2
  371. data/lib/generators/spree/install/templates/config/initializers/spree.rb +6 -2
  372. data/lib/spree/core/configuration.rb +1 -0
  373. data/lib/spree/core/dependencies.rb +3 -0
  374. data/lib/spree/core/engine.rb +57 -2
  375. data/lib/spree/core/version.rb +1 -1
  376. data/lib/spree/core.rb +3 -1
  377. data/lib/spree/permitted_attributes.rb +18 -3
  378. data/lib/spree/testing_support/capybara_config.rb +9 -3
  379. data/lib/spree/testing_support/common_rake.rb +1 -0
  380. data/lib/spree/testing_support/factories/export_factory.rb +5 -17
  381. data/lib/spree/testing_support/factories/import_factory.rb +20 -0
  382. data/lib/spree/testing_support/factories/import_mapping_factory.rb +7 -0
  383. data/lib/spree/testing_support/factories/import_row_factory.rb +7 -0
  384. data/lib/spree/testing_support/factories/metafield_definition_factory.rb +72 -0
  385. data/lib/spree/testing_support/factories/metafield_factory.rb +68 -0
  386. data/lib/spree/testing_support/factories/newsletter_subscriber_factory.rb +18 -0
  387. data/lib/spree/testing_support/factories/policy_factory.rb +8 -0
  388. data/lib/spree/testing_support/factories/post_factory.rb +8 -0
  389. data/lib/spree/testing_support/store.rb +11 -0
  390. data/lib/tasks/core.rake +128 -0
  391. metadata +279 -6
  392. data/app/models/action_text/rich_text_decorator.rb +0 -11
  393. data/app/presenters/spree/csv/product_presenter.rb +0 -63
@@ -19,11 +19,18 @@ end
19
19
 
20
20
  Capybara.register_driver :selenium_chrome_headless do |app|
21
21
  options = ::Selenium::WebDriver::Chrome::Options.new
22
- options.add_argument '--headless'
22
+
23
+ options.add_argument '--headless=new'
23
24
  options.add_argument '--disable-gpu'
24
- options.add_argument '--window-size=1440,900'
25
+
26
+ # Larger window size helps with dialog rendering in headless mode
27
+ options.add_argument '--window-size=1920,1080'
25
28
  options.add_argument '--disable-search-engine-choice-screen'
26
29
 
30
+ # Required for running in Docker containers (CircleCI)
31
+ options.add_argument '--no-sandbox'
32
+ options.add_argument '--disable-dev-shm-usage'
33
+
27
34
  # Disable timers being throttled in background pages/tabs. Useful for parallel test runs.
28
35
  options.add_argument '--disable-background-timer-throttling'
29
36
 
@@ -34,6 +41,5 @@ Capybara.register_driver :selenium_chrome_headless do |app|
34
41
  # This disables non-foreground tabs from getting a lower process priority. Useful for parallel test runs.
35
42
  options.add_argument '--disable-renderer-backgrounding'
36
43
 
37
-
38
44
  Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
39
45
  end
@@ -30,6 +30,7 @@ namespace :common do
30
30
  Spree::DummyGenerator.start dummy_app_args
31
31
 
32
32
  unless skip_javascript
33
+ system('bundle add sprockets-rails') # we need this until we will remove bootstrap/popper_js gems
33
34
  system('bundle exec rails importmap:install turbo:install stimulus:install')
34
35
  end
35
36
 
@@ -1,24 +1,8 @@
1
- # == Schema Information
2
- #
3
- # Table name: spree_exports
4
- #
5
- # id :uuid not null, primary key
6
- # format :integer not null
7
- # number :string(32) not null
8
- # search_params :jsonb
9
- # type :string not null
10
- # created_at :datetime not null
11
- # updated_at :datetime not null
12
- # project_id :uuid not null
13
- # store_id :uuid not null
14
- # user_id :uuid
15
- # vendor_id :uuid
16
- #
17
1
  FactoryBot.define do
18
2
  factory :export, class: 'Spree::Export' do
19
3
  store { create(:store) }
20
4
  user { create(:admin_user) }
21
- type { 'Spree::Export::Products' }
5
+ type { 'Spree::Exports::Products' }
22
6
  format { 'csv' }
23
7
 
24
8
  factory :product_export, class: 'Spree::Exports::Products', parent: :export do
@@ -28,5 +12,9 @@ FactoryBot.define do
28
12
  factory :order_export, class: 'Spree::Exports::Orders', parent: :export do
29
13
  type { 'Spree::Exports::Orders' }
30
14
  end
15
+
16
+ factory :customer_export, class: 'Spree::Exports::Customers', parent: :export do
17
+ type { 'Spree::Exports::Customers' }
18
+ end
31
19
  end
32
20
  end
@@ -0,0 +1,20 @@
1
+ FactoryBot.define do
2
+ factory :import, class: 'Spree::Import' do
3
+ owner { Spree::Store.default || create(:store) }
4
+ user { create(:admin_user) }
5
+ type { 'Spree::Imports::Products' }
6
+
7
+ factory :product_import, class: 'Spree::Imports::Products', parent: :import do
8
+ type { 'Spree::Imports::Products' }
9
+ # attachment { Rack::Test::UploadedFile.new(Spree::Core::Engine.root.join('spec', 'fixtures', 'files', 'products_import.csv'), 'text/csv') }
10
+
11
+ after(:create) do |import|
12
+ import.attachment.attach(
13
+ io: File.open(Spree::Core::Engine.root.join('spec', 'fixtures', 'files', 'products_import.csv')),
14
+ filename: 'products_import.csv',
15
+ content_type: 'text/csv'
16
+ )
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ FactoryBot.define do
2
+ factory :import_mapping, class: 'Spree::ImportMapping' do
3
+ import { create(:product_import) }
4
+ schema_field { 'name' }
5
+ file_column { 'name' }
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ FactoryBot.define do
2
+ factory :import_row, class: 'Spree::ImportRow' do
3
+ import { create(:product_import) }
4
+ data { { 'slug' => 'test-product', 'name' => 'Test Product', 'price' => '10.00' }.to_json }
5
+ row_number { import.rows_count + 1 }
6
+ end
7
+ end
@@ -0,0 +1,72 @@
1
+ FactoryBot.define do
2
+ factory :metafield_definition, class: 'Spree::MetafieldDefinition' do
3
+ namespace { 'custom' }
4
+ sequence(:key) { |n| "custom_field_#{n}" }
5
+ name { 'Custom Field' }
6
+ metafield_type { 'Spree::Metafields::ShortText' }
7
+ resource_type { 'Spree::Product' }
8
+ display_on { 'both' }
9
+
10
+ trait :front_end_only do
11
+ display_on { 'front_end' }
12
+ end
13
+
14
+ trait :back_end_only do
15
+ display_on { 'back_end' }
16
+ end
17
+
18
+ trait :short_text_field do
19
+ metafield_type { 'Spree::Metafields::ShortText' }
20
+ key { 'title' }
21
+ name { 'Title' }
22
+ end
23
+
24
+ trait :long_text_field do
25
+ metafield_type { 'Spree::Metafields::LongText' }
26
+ key { 'description' }
27
+ name { 'Description' }
28
+ end
29
+
30
+ trait :rich_text_field do
31
+ metafield_type { 'Spree::Metafields::RichText' }
32
+ key { 'content' }
33
+ name { 'Content' }
34
+ end
35
+
36
+ trait :number_field do
37
+ metafield_type { 'Spree::Metafields::Number' }
38
+ key { 'priority' }
39
+ name { 'Priority' }
40
+ end
41
+
42
+ trait :boolean_field do
43
+ metafield_type { 'Spree::Metafields::Boolean' }
44
+ key { 'featured' }
45
+ name { 'Featured' }
46
+ end
47
+
48
+ trait :json_field do
49
+ metafield_type { 'Spree::Metafields::Json' }
50
+ key { 'metadata' }
51
+ name { 'Metadata' }
52
+ end
53
+
54
+ trait :for_variant do
55
+ resource_type { 'Spree::Variant' }
56
+ key { 'variant_custom' }
57
+ name { 'Variant Custom Field' }
58
+ end
59
+
60
+ trait :for_order do
61
+ resource_type { 'Spree::Order' }
62
+ key { 'order_notes' }
63
+ name { 'Order Notes' }
64
+ end
65
+
66
+ trait :for_user do
67
+ resource_type { Spree.user_class.name }
68
+ key { 'user_preference' }
69
+ name { 'User Preference' }
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,68 @@
1
+ FactoryBot.define do
2
+ factory :metafield, class: 'Spree::Metafield' do
3
+ value { 'test_value' }
4
+ type { 'Spree::Metafields::ShortText' }
5
+
6
+ association :resource, factory: :product
7
+ association :metafield_definition
8
+
9
+ trait :front_end_only do
10
+ association :metafield_definition, :front_end_only
11
+ end
12
+
13
+ trait :back_end_only do
14
+ association :metafield_definition, :back_end_only
15
+ end
16
+
17
+ trait :short_text do
18
+ type { 'Spree::Metafields::ShortText' }
19
+ association :metafield_definition, :short_text_field
20
+ value { 'Short text value' }
21
+ end
22
+
23
+ trait :long_text do
24
+ type { 'Spree::Metafields::LongText' }
25
+ association :metafield_definition, :long_text_field
26
+ value { 'This is a longer text value with more detailed information.' }
27
+ end
28
+
29
+ trait :number do
30
+ type { 'Spree::Metafields::Number' }
31
+ association :metafield_definition, :number_field
32
+ value { 42 }
33
+ end
34
+
35
+ trait :rich_text do
36
+ type { 'Spree::Metafields::RichText' }
37
+ association :metafield_definition, :rich_text_field
38
+ value { '<p>Rich text with <strong>formatting</strong></p>' }
39
+ end
40
+
41
+ trait :boolean do
42
+ type { 'Spree::Metafields::Boolean' }
43
+ association :metafield_definition, :boolean_field
44
+ value { true }
45
+ end
46
+
47
+ trait :json do
48
+ type { 'Spree::Metafields::Json' }
49
+ association :metafield_definition, :json_field
50
+ value { '{"key": "value"}' }
51
+ end
52
+
53
+ trait :for_variant do
54
+ association :resource, factory: :variant
55
+ association :metafield_definition, :for_variant
56
+ end
57
+
58
+ trait :for_order do
59
+ association :resource, factory: :order
60
+ association :metafield_definition, :for_order
61
+ end
62
+
63
+ trait :for_user do
64
+ association :resource, factory: :user
65
+ association :metafield_definition, :for_user
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,18 @@
1
+ FactoryBot.define do
2
+ factory :newsletter_subscriber, class: Spree::NewsletterSubscriber do
3
+ email { FFaker::Internet.unique.email }
4
+ verified_at { nil }
5
+
6
+ trait :with_user do
7
+ association :user, factory: :user
8
+ end
9
+
10
+ trait :verified do
11
+ verified_at { Time.current }
12
+ end
13
+
14
+ trait :unverified do
15
+ verified_at { nil }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,8 @@
1
+ FactoryBot.define do
2
+ factory :policy, class: 'Spree::Policy' do
3
+ owner { Spree::Store.default }
4
+ slug { 'my-policy' }
5
+ name { 'My Policy' }
6
+ body { 'This is the my policy' }
7
+ end
8
+ end
@@ -10,5 +10,13 @@ FactoryBot.define do
10
10
  trait :with_image do
11
11
  image { Rack::Test::UploadedFile.new(Spree::Core::Engine.root.join('spec/fixtures/thinking-cat.jpg'), 'image/jpeg') }
12
12
  end
13
+
14
+ trait :published do
15
+ published_at { Time.current }
16
+ end
17
+
18
+ trait :unpublished do
19
+ published_at { nil }
20
+ end
13
21
  end
14
22
  end
@@ -1,5 +1,16 @@
1
1
  # setup default store, to be always present
2
2
  RSpec.configure do |config|
3
+ config.before(:suite) do
4
+ if defined?(ActiveSupport::SafeBuffer)
5
+ ActiveSupport::SafeBuffer.class_eval do
6
+ # Make Psych serialize SafeBuffer as a plain string
7
+ def encode_with(coder)
8
+ coder.represent_scalar(nil, to_s)
9
+ end
10
+ end
11
+ end
12
+ end
13
+
3
14
  config.before(:all) do
4
15
  unless self.class.metadata[:without_global_store]
5
16
  @default_country = Spree::Country.find_by(iso: 'US') || FactoryBot.create(:country_us)
data/lib/tasks/core.rake CHANGED
@@ -191,6 +191,116 @@ use rake db:load_file[/absolute/path/to/sample/filename.rb]}
191
191
  role_user.update_columns(resource_type: default_store.class.name, resource_id: default_store.id)
192
192
  end
193
193
  end
194
+
195
+ desc 'Migrate policies to store policies'
196
+ task migrate_policies: :environment do |_t, _args|
197
+ # Helper to consistently derive policy name
198
+ derive_policy_name = lambda do |name_str|
199
+ name_str.to_s.gsub(/customer_/, '').gsub(/_policy$/, '')
200
+ end
201
+
202
+ # Check if migration has already been run
203
+ if Spree::Policy.any?
204
+ puts "Policies already exist. Skipping migration to prevent duplicates."
205
+ exit
206
+ end
207
+
208
+ Spree::Store.all.each do |store|
209
+ %w[customer_terms_of_service customer_privacy_policy customer_returns_policy customer_shipping_policy].each do |policy_slug|
210
+ policy = store.send(policy_slug)
211
+ next unless policy.present?
212
+
213
+ store.policies.create(
214
+ name: Spree.t(derive_policy_name.call(policy_slug)),
215
+ body: policy.body
216
+ )
217
+
218
+ puts "Migrated #{policy_slug} to store #{store.id}"
219
+ end
220
+ end
221
+
222
+ Spree::PageLink.where(linkable_type: 'ActionText::RichText').each do |page_link|
223
+ # Check if this page link is attached to ActionText content
224
+ # Find the ActionText record
225
+ action_text = ActionText::RichText.find_by(id: page_link.linkable_id)
226
+ next unless action_text
227
+
228
+ # Check if the ActionText belongs to a store policy
229
+ if action_text.record_type == 'Spree::Store' && action_text.name.to_s.include?('policy')
230
+ # Find the corresponding policy in the new policies system
231
+ store = action_text.record
232
+ policy_name = derive_policy_name.call(action_text.name)
233
+
234
+ policy = store.policies.find_by(name: Spree.t(policy_name))
235
+
236
+ if policy
237
+ # Update the page link to point to the policy instead
238
+ page_link.update!(
239
+ linked_resource_type: 'Spree::Policy',
240
+ linked_resource_id: policy.id
241
+ )
242
+
243
+ puts "Migrated #{policy_name} to store #{store.id}"
244
+ end
245
+ end
246
+ end
247
+ end
248
+
249
+ desc 'Migrate product properties to metafields'
250
+ task migrate_product_properties_to_metafields: :environment do |_t, _args|
251
+ Spree::Property.find_each do |property|
252
+ metafield_definition = Spree::MetafieldDefinition.find_or_initialize_by(
253
+ namespace: 'properties',
254
+ key: property.name,
255
+ resource_type: 'Spree::Product'
256
+ )
257
+ metafield_definition.assign_attributes(
258
+ metafield_type: property.kind_to_metafield_type,
259
+ display_on: property.display_on
260
+ )
261
+ metafield_definition.save!
262
+
263
+ property.product_properties.includes(:product).find_each do |product_property|
264
+ product_property.product.set_metafield("properties.#{property.name}", product_property.value)
265
+ puts "Migrated #{property.name} to product #{product_property.product.id}"
266
+ end
267
+ end
268
+ end
269
+
270
+ desc 'Migrate product details sections to PDP 2.0 with blocks and metafields'
271
+ task migrate_product_details_pages: :environment do |_t, _args|
272
+ Spree::PageSections::ProductDetails.find_each do |section|
273
+ next if section.blocks.any?
274
+
275
+ if defined?(SpreeMultiTenant)
276
+ SpreeMultiTenant.with_tenant(section.tenant) do
277
+ section.send(:create_blocks)
278
+ end
279
+ else
280
+ section.send(:create_blocks)
281
+ end
282
+ end
283
+
284
+ Spree::Pages::ProductDetails.find_each do |page|
285
+ next if page.sections.exists?(type: 'Spree::PageSections::Breadcrumbs')
286
+
287
+ block = proc do
288
+ breadcrumbs = page.sections.create!(type: 'Spree::PageSections::Breadcrumbs')
289
+ breadcrumbs.move_to_top
290
+
291
+ page_details = page.sections.find_by(type: 'Spree::PageSections::ProductDetails')
292
+ if page_details.present?
293
+ page_details.update!(preferred_top_padding: 0, preferred_top_border_width: 0)
294
+ end
295
+ end
296
+
297
+ if defined?(SpreeMultiTenant)
298
+ SpreeMultiTenant.with_tenant(page.tenant, &block)
299
+ else
300
+ block.call
301
+ end
302
+ end
303
+ end
194
304
  end
195
305
 
196
306
  namespace :core do
@@ -216,4 +326,22 @@ namespace :core do
216
326
  puts '... done'
217
327
  puts "... migrated #{pluralize(total, 'record')}"
218
328
  end
329
+
330
+ desc 'Migrate newsletter subscribers'
331
+ task migrate_newsletter_subscribers: :environment do |_t, _args|
332
+ Spree.user_class.where(accepts_email_marketing: true).in_batches(of: 500) do |user_batch|
333
+ subscriber_attributes = user_batch.pluck(:id, :email, :updated_at).map do |id, email, updated_at|
334
+ {
335
+ email: Spree::NewsletterSubscriber.new(email: email).email, # normalized email
336
+ user_id: id,
337
+ verified_at: updated_at,
338
+ verification_token: nil,
339
+ updated_at: DateTime.current,
340
+ created_at: DateTime.current
341
+ }
342
+ end
343
+
344
+ Spree::NewsletterSubscriber.insert_all(subscriber_attributes.uniq { |attrs| attrs[:email] })
345
+ end
346
+ end
219
347
  end