spree_core 5.1.8 → 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 (389) 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 +2 -7
  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 +17 -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 +228 -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/sorters/spree/posts/sort.rb +40 -0
  349. data/app/views/spree/shared/_payment.html.erb +3 -3
  350. data/config/locales/en.yml +56 -2
  351. data/db/migrate/20250605131334_add_missing_fields_to_users.rb +23 -13
  352. data/db/migrate/20250728095629_create_spree_metafields.rb +27 -0
  353. data/db/migrate/20250730102644_add_missing_unique_indexes_to_spree_option_types_and_values.rb +40 -0
  354. data/db/migrate/20250730154601_add_unique_index_on_spree_properties_name.rb +24 -0
  355. data/db/migrate/20250811112056_create_spree_policies.rb +22 -0
  356. data/db/migrate/20250821211705_fix_unique_index_on_spree_order_promotions.rb +20 -0
  357. data/db/migrate/20250825175217_add_missing_page_builder_indexes.rb +7 -0
  358. data/db/migrate/20250826093602_create_spree_newsletter_subscribers.rb +12 -0
  359. data/db/migrate/20250902143122_fix_policies_store_association.rb +18 -0
  360. data/db/migrate/20250911205659_add_missing_index_on_spree_products_promotionable.rb +5 -0
  361. data/db/migrate/20250913130044_add_page_links_counter_cache_to_spree_stores.rb +10 -0
  362. data/db/migrate/20250914101955_add_missing_indexes_on_spree_adjustments.rb +6 -0
  363. data/db/migrate/20250915093930_add_metadata_to_spree_newsletter_subscribers.rb +20 -0
  364. data/db/migrate/20250923141845_create_spree_imports.rb +47 -0
  365. data/lib/generators/spree/cursor_rules/cursor_rules_generator.rb +19 -0
  366. data/lib/generators/spree/cursor_rules/templates/spree_rules.mdc +387 -0
  367. data/lib/generators/spree/dummy/dummy_generator.rb +0 -1
  368. data/lib/generators/spree/install/templates/config/initializers/spree.rb +5 -0
  369. data/lib/spree/core/configuration.rb +1 -0
  370. data/lib/spree/core/dependencies.rb +3 -0
  371. data/lib/spree/core/engine.rb +57 -2
  372. data/lib/spree/core/version.rb +1 -1
  373. data/lib/spree/core.rb +3 -1
  374. data/lib/spree/permitted_attributes.rb +18 -3
  375. data/lib/spree/testing_support/capybara_config.rb +9 -3
  376. data/lib/spree/testing_support/factories/export_factory.rb +5 -17
  377. data/lib/spree/testing_support/factories/import_factory.rb +20 -0
  378. data/lib/spree/testing_support/factories/import_mapping_factory.rb +7 -0
  379. data/lib/spree/testing_support/factories/import_row_factory.rb +7 -0
  380. data/lib/spree/testing_support/factories/metafield_definition_factory.rb +72 -0
  381. data/lib/spree/testing_support/factories/metafield_factory.rb +68 -0
  382. data/lib/spree/testing_support/factories/newsletter_subscriber_factory.rb +18 -0
  383. data/lib/spree/testing_support/factories/policy_factory.rb +8 -0
  384. data/lib/spree/testing_support/factories/post_factory.rb +8 -0
  385. data/lib/spree/testing_support/store.rb +11 -0
  386. data/lib/tasks/core.rake +128 -0
  387. metadata +279 -6
  388. data/app/models/action_text/rich_text_decorator.rb +0 -11
  389. data/app/presenters/spree/csv/product_presenter.rb +0 -63
@@ -41,6 +41,7 @@ module Spree
41
41
  # order
42
42
  order_approve_service: 'Spree::Orders::Approve',
43
43
  order_cancel_service: 'Spree::Orders::Cancel',
44
+ order_updater: 'Spree::OrderUpdater',
44
45
 
45
46
  # shipment
46
47
  shipment_change_state_service: 'Spree::Shipments::ChangeState',
@@ -56,6 +57,7 @@ module Spree
56
57
  collection_sorter: 'Spree::BaseSorter',
57
58
  order_sorter: 'Spree::BaseSorter',
58
59
  products_sorter: 'Spree::Products::Sort',
60
+ posts_sorter: 'Spree::Posts::Sort',
59
61
 
60
62
  # paginator
61
63
  collection_paginator: 'Spree::Shared::Paginate',
@@ -102,6 +104,7 @@ module Spree
102
104
  completed_order_finder: 'Spree::Orders::FindComplete',
103
105
  credit_card_finder: 'Spree::CreditCards::Find',
104
106
  products_finder: 'Spree::Products::Find',
107
+ posts_finder: 'Spree::Posts::Find',
105
108
  taxon_finder: 'Spree::Taxons::Find',
106
109
  line_item_by_variant_finder: 'Spree::LineItems::FindByVariant',
107
110
  variant_finder: 'Spree::Variants::Find'
@@ -15,6 +15,7 @@ module Spree
15
15
  :line_item_comparison_hooks,
16
16
  :data_feed_types,
17
17
  :export_types,
18
+ :import_types,
18
19
  :taxon_rules,
19
20
  :themes,
20
21
  :theme_layout_sections,
@@ -23,6 +24,8 @@ module Spree
23
24
  :page_blocks,
24
25
  :reports,
25
26
  :translatable_resources,
27
+ :metafield_types,
28
+ :metafield_enabled_resources,
26
29
  :analytics_events,
27
30
  :analytics_event_handlers,
28
31
  :integrations)
@@ -150,7 +153,14 @@ module Spree
150
153
 
151
154
  Rails.application.config.spree.export_types = [
152
155
  Spree::Exports::Products,
153
- Spree::Exports::Orders
156
+ Spree::Exports::Orders,
157
+ Spree::Exports::Customers,
158
+ Spree::Exports::GiftCards,
159
+ Spree::Exports::NewsletterSubscribers
160
+ ]
161
+
162
+ Rails.application.config.spree.import_types = [
163
+ Spree::Imports::Products,
154
164
  ]
155
165
 
156
166
  Rails.application.config.spree.taxon_rules = [
@@ -189,6 +199,7 @@ module Spree
189
199
  ]
190
200
 
191
201
  Rails.application.config.spree.page_sections = [
202
+ Spree::PageSections::Breadcrumbs,
192
203
  Spree::PageSections::FeaturedPosts,
193
204
  Spree::PageSections::TaxonGrid,
194
205
  Spree::PageSections::ImageWithText,
@@ -245,7 +256,51 @@ module Spree
245
256
  Spree::Property,
246
257
  Spree::Taxon,
247
258
  Spree::Taxonomy,
248
- Spree::Store
259
+ Spree::Store,
260
+ Spree::Policy
261
+ ]
262
+
263
+ Rails.application.config.spree.metafield_types = [
264
+ Spree::Metafields::ShortText,
265
+ Spree::Metafields::LongText,
266
+ Spree::Metafields::RichText,
267
+ Spree::Metafields::Number,
268
+ Spree::Metafields::Boolean,
269
+ Spree::Metafields::Json
270
+ ]
271
+
272
+ Rails.application.config.spree.metafield_enabled_resources = [
273
+ Spree::Address,
274
+ Spree::Asset,
275
+ Spree::CreditCard,
276
+ Spree::CustomDomain,
277
+ Spree::CustomerReturn,
278
+ Spree::GiftCard,
279
+ Spree::Image,
280
+ Spree::LineItem,
281
+ Spree::NewsletterSubscriber,
282
+ Spree::OptionType,
283
+ Spree::OptionValue,
284
+ Spree::Order,
285
+ Spree::Payment,
286
+ Spree::PaymentMethod,
287
+ Spree::PaymentSource,
288
+ Spree::Post,
289
+ Spree::PostCategory,
290
+ Spree::Product,
291
+ Spree::Promotion,
292
+ Spree::Refund,
293
+ Spree::Shipment,
294
+ Spree::ShippingMethod,
295
+ Spree::StockItem,
296
+ Spree::StockTransfer,
297
+ Spree::Store,
298
+ Spree::StoreCredit,
299
+ Spree::TaxRate,
300
+ Spree::Taxon,
301
+ Spree::Taxonomy,
302
+ Spree::Variant,
303
+ Spree.user_class
249
304
  ]
250
305
 
251
306
  Rails.application.config.spree.analytics_events = {
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- VERSION = '5.1.8'.freeze
2
+ VERSION = '5.2.0.rc1'.freeze
3
3
 
4
4
  def self.version
5
5
  VERSION
data/lib/spree/core.rb CHANGED
@@ -6,10 +6,10 @@ require 'active_model/railtie'
6
6
  require 'active_record/railtie'
7
7
  require 'active_storage/engine'
8
8
  require 'action_text/engine'
9
+ require 'action_cable/engine'
9
10
 
10
11
  require 'mail'
11
12
  require 'action_mailer/railtie'
12
- require 'sprockets/railtie'
13
13
 
14
14
  require 'active_merchant'
15
15
  require 'acts_as_list'
@@ -98,6 +98,8 @@ module Spree
98
98
  @@queues ||= OpenStruct.new(
99
99
  default: :default,
100
100
  exports: :default,
101
+ images: :default,
102
+ imports: :default,
101
103
  reports: :default,
102
104
  variants: :default,
103
105
  taxons: :default,
@@ -15,12 +15,16 @@ module Spree
15
15
  :gift_card_attributes,
16
16
  :gift_card_batch_attributes,
17
17
  :image_attributes,
18
+ :import_attributes,
19
+ :import_mapping_attributes,
18
20
  :integration_attributes,
19
21
  :inventory_unit_attributes,
20
22
  :invitation_attributes,
21
23
  :line_item_attributes,
22
24
  :menu_attributes,
23
25
  :menu_item_attributes,
26
+ :metafield_attributes,
27
+ :metafield_definition_attributes,
24
28
  :option_type_attributes,
25
29
  :option_value_attributes,
26
30
  :page_attributes,
@@ -29,6 +33,7 @@ module Spree
29
33
  :page_section_attributes,
30
34
  :payment_attributes,
31
35
  :payment_method_attributes,
36
+ :policy_attributes,
32
37
  :post_attributes,
33
38
  :post_category_attributes,
34
39
  :product_attributes,
@@ -83,7 +88,7 @@ module Spree
83
88
 
84
89
  @@checkout_attributes = [
85
90
  :coupon_code, :email, :shipping_method_id, :special_instructions, :use_billing, :use_shipping,
86
- :user_id, :bill_address_id, :ship_address_id, :accept_marketing, :signup_for_an_account
91
+ :user_id, :bill_address_id, :ship_address_id, :accept_marketing, :signup_for_an_account, :currency
87
92
  ]
88
93
 
89
94
  @@classification_attributes = [
@@ -107,12 +112,16 @@ module Spree
107
112
 
108
113
  @@export_attributes = [:type, :format, :record_selection, :search_params]
109
114
 
110
- @@gift_card_attributes = [:code, :amount, :expires_at, :user_id]
115
+ @@gift_card_attributes = [:code, :amount, :expires_at, :user_id, :currency]
111
116
 
112
- @@gift_card_batch_attributes = [:prefix, :codes_count, :amount, :expires_at]
117
+ @@gift_card_batch_attributes = [:prefix, :codes_count, :amount, :expires_at, :currency]
113
118
 
114
119
  @@image_attributes = [:alt, :attachment, :position, :viewable_type, :viewable_id]
115
120
 
121
+ @@import_attributes = [:type, :attachment, :delimiter]
122
+
123
+ @@import_mapping_attributes = [:file_column]
124
+
116
125
  @@integration_attributes = [:type, :active]
117
126
 
118
127
  @@inventory_unit_attributes = [:shipment, :shipment_id, :variant_id]
@@ -126,6 +135,10 @@ module Spree
126
135
  @@menu_item_attributes = [:name, :subtitle, :destination, :new_window, :item_type,
127
136
  :linked_resource_type, :linked_resource_id, :code, :menu_id]
128
137
 
138
+ @@metafield_attributes = [:id, :value, :type, :metafield_definition_id, :_destroy]
139
+
140
+ @@metafield_definition_attributes = [:key, :name, :namespace, :metafield_type, :resource_type, :display_on]
141
+
129
142
  @@option_type_attributes = [:name, :presentation, :position, :filterable,
130
143
  option_values_attributes: [:id, :name, :presentation, :position, :_destroy]]
131
144
 
@@ -143,6 +156,8 @@ module Spree
143
156
 
144
157
  @@payment_method_attributes = [:name, :type, :description, :active, :display_on, :auto_capture, :position]
145
158
 
159
+ @@policy_attributes = [:name, :slug, :body]
160
+
146
161
  @@post_attributes = [:title, :meta_title, :meta_description, :slug, :author_id, :post_category_id, :published_at, :content, :excerpt, :image, tag_list: []]
147
162
 
148
163
  @@post_category_attributes = [:title, :slug, :description]
@@ -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
@@ -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