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
@@ -5,6 +5,7 @@ module Spree
5
5
  include Spree::Core::NumberGenerator.new(prefix: 'H', length: 11)
6
6
  include Spree::NumberIdentifier
7
7
  include Spree::NumberAsParam
8
+ include Spree::Metafields
8
9
  include Spree::Metadata
9
10
  if defined?(Spree::Security::Shipments)
10
11
  include Spree::Security::Shipments
@@ -2,6 +2,7 @@ module Spree
2
2
  class ShippingMethod < Spree.base_class
3
3
  acts_as_paranoid
4
4
  include Spree::CalculatedAdjustments
5
+ include Spree::Metafields
5
6
  include Spree::Metadata
6
7
  include Spree::DisplayOn
7
8
  if defined?(Spree::Webhooks::HasWebhooks)
@@ -2,6 +2,7 @@ module Spree
2
2
  class StockItem < Spree.base_class
3
3
  acts_as_paranoid
4
4
 
5
+ include Spree::Metafields
5
6
  include Spree::Metadata
6
7
  include Spree::StockItem::Webhooks
7
8
 
@@ -3,6 +3,7 @@ module Spree
3
3
  include Spree::Core::NumberGenerator.new(prefix: 'T')
4
4
  include Spree::NumberIdentifier
5
5
  include Spree::NumberAsParam
6
+ include Spree::Metafields
6
7
  include Spree::Metadata
7
8
  if defined?(Spree::Webhooks::HasWebhooks)
8
9
  include Spree::Webhooks::HasWebhooks
@@ -8,12 +8,14 @@ module Spree
8
8
 
9
9
  include FriendlyId
10
10
  include Spree::TranslatableResource
11
+ include Spree::Metafields
11
12
  include Spree::Metadata
12
13
  include Spree::Stores::Setup
13
14
  include Spree::Stores::Socials
14
15
  include Spree::Webhooks::HasWebhooks if defined?(Spree::Webhooks::HasWebhooks)
15
16
  include Spree::Security::Stores if defined?(Spree::Security::Stores)
16
17
  include Spree::UserManagement
18
+ include Spree::HasPageLinks
17
19
 
18
20
  #
19
21
  # Magic methods
@@ -111,6 +113,8 @@ module Spree
111
113
 
112
114
  has_many :gift_cards, class_name: 'Spree::GiftCard', dependent: :destroy
113
115
 
116
+ has_many :policies, class_name: 'Spree::Policy', dependent: :destroy, as: :owner
117
+
114
118
  #
115
119
  # Page Builder associations
116
120
  #
@@ -123,6 +127,7 @@ module Spree
123
127
  inverse_of: :store,
124
128
  dependent: :destroy
125
129
  has_one :default_theme, -> { without_previews.where(default: true) }, class_name: 'Spree::Theme', inverse_of: :store
130
+ alias theme default_theme
126
131
  has_many :theme_pages, class_name: 'Spree::Page', through: :themes, source: :pages
127
132
  has_many :theme_page_previews, class_name: 'Spree::Page', through: :theme_pages, source: :previews
128
133
  has_many :pages, -> { without_previews.custom }, class_name: 'Spree::Pages::Custom', dependent: :destroy, as: :pageable
@@ -185,6 +190,7 @@ module Spree
185
190
  after_create :import_products_from_store, if: -> { import_products_from_store_id.present? }
186
191
  after_create :import_payment_methods_from_store, if: -> { import_payment_methods_from_store_id.present? }
187
192
  after_create :create_default_theme
193
+ after_create :create_default_policies
188
194
  before_destroy :validate_not_last, unless: :skip_validate_not_last
189
195
  before_destroy :pass_default_flag_to_other_store
190
196
  after_commit :clear_cache
@@ -203,7 +209,11 @@ module Spree
203
209
  delegate :iso, to: :default_country, prefix: true, allow_nil: true
204
210
 
205
211
  def self.current(url = nil)
206
- Spree::Dependencies.current_store_finder.constantize.new(url: url).execute || Spree::Current.store
212
+ if url.present?
213
+ Spree::Dependencies.current_store_finder.constantize.new(url: url).execute
214
+ else
215
+ Spree::Current.store
216
+ end
207
217
  end
208
218
 
209
219
  # FIXME: we need to drop `or_initialize` in v5
@@ -320,15 +330,20 @@ module Spree
320
330
  formatted_custom_domain || formatted_url
321
331
  end
322
332
 
333
+ # Returns the countries available for checkout for the store or creates a new one if it doesn't exist
334
+ # @return [Array<Spree::Country>]
323
335
  def countries_available_for_checkout
324
336
  @countries_available_for_checkout ||= Rails.cache.fetch(countries_available_for_checkout_cache_key) do
325
- checkout_zone.try(:country_list) || Spree::Country.all
337
+ (checkout_zone.try(:country_list) || Spree::Country.all).to_a
326
338
  end
327
339
  end
328
340
 
341
+ # Returns the states available for checkout for the store or creates a new one if it doesn't exist
342
+ # @param country [Spree::Country] the country to get the states for
343
+ # @return [Array<Spree::State>]
329
344
  def states_available_for_checkout(country)
330
345
  Rails.cache.fetch(states_available_for_checkout_cache_key(country)) do
331
- checkout_zone.try(:state_list_for, country) || country.states
346
+ (checkout_zone.try(:state_list_for, country) || country.states).to_a
332
347
  end
333
348
  end
334
349
 
@@ -403,6 +418,21 @@ module Spree
403
418
  StorePaymentMethod.insert_all(payment_method_ids.map { |payment_method_id| { store_id: id, payment_method_id: payment_method_id } })
404
419
  end
405
420
 
421
+ %w[customer_terms_of_service customer_privacy_policy customer_returns_policy customer_shipping_policy].each do |policy_method|
422
+ define_method policy_method do
423
+ Spree::Deprecation.warn("Store##{policy_method} is deprecated and will be removed in Spree 6.0. Please use Store#policies instead.")
424
+
425
+ ActionText::RichText.find_by(name: policy_method, record: self)
426
+ end
427
+ end
428
+
429
+ # Returns all active webhooks subscribers for the store
430
+ #
431
+ # @return [Array<Spree::Webhooks::Subscriber>]
432
+ def active_webhooks_subscribers
433
+ @active_webhooks_subscribers ||= Spree::Webhooks::Subscriber.active
434
+ end
435
+
406
436
  private
407
437
 
408
438
  def countries_available_for_checkout_cache_key
@@ -496,6 +526,18 @@ module Spree
496
526
  post_categories.find_or_create_by(title: Spree.t('default_post_categories.news'))
497
527
  end
498
528
 
529
+ def create_default_policies
530
+ policies.find_or_create_by(name: Spree.t('terms_of_service'))
531
+ policies.find_or_create_by(name: Spree.t('privacy_policy'))
532
+ policies.find_or_create_by(name: Spree.t('returns_policy'))
533
+ policies.find_or_create_by(name: Spree.t('shipping_policy'))
534
+
535
+ # Create checkout links to the policies
536
+ policies.each do |policy|
537
+ links.find_or_create_by(linkable: policy)
538
+ end
539
+ end
540
+
499
541
  # code is slug, so we don't want to generate new slug when code changes
500
542
  # we use friendlyId only for history feature
501
543
  def should_generate_new_friendly_id?
@@ -1,6 +1,7 @@
1
1
  module Spree
2
2
  class StoreCredit < Spree.base_class
3
3
  include Spree::SingleStoreResource
4
+ include Spree::Metafields
4
5
  include Spree::Metadata
5
6
  if defined?(Spree::Webhooks::HasWebhooks)
6
7
  include Spree::Webhooks::HasWebhooks
@@ -19,7 +20,7 @@ module Spree
19
20
  belongs_to :store, class_name: 'Spree::Store'
20
21
  belongs_to :user, class_name: "::#{Spree.user_class}", foreign_key: 'user_id'
21
22
  belongs_to :category, class_name: 'Spree::StoreCreditCategory', optional: true
22
- belongs_to :created_by, class_name: "::#{Spree.admin_user_class}", foreign_key: 'created_by_id', optional: true
23
+ belongs_to :created_by, class_name: Spree.admin_user_class.to_s, foreign_key: 'created_by_id', optional: true
23
24
  belongs_to :credit_type, class_name: 'Spree::StoreCreditType', foreign_key: 'type_id', optional: true
24
25
  belongs_to :originator, polymorphic: true, optional: true
25
26
 
@@ -5,7 +5,7 @@ module Spree
5
5
  end
6
6
 
7
7
  acts_as_paranoid
8
- validates :name, presence: true, uniqueness: { case_sensitive: false, scope: spree_base_uniqueness_scope.push(:deleted_at) }
8
+ validates :name, presence: true, uniqueness: { case_sensitive: false, scope: spree_base_uniqueness_scope + [:deleted_at] }
9
9
 
10
10
  has_many :tax_rates, dependent: :destroy, inverse_of: :tax_category
11
11
  has_many :products, dependent: :nullify
@@ -4,6 +4,7 @@ module Spree
4
4
 
5
5
  include Spree::CalculatedAdjustments
6
6
  include Spree::AdjustmentSource
7
+ include Spree::Metafields
7
8
  include Spree::Metadata
8
9
  if defined?(Spree::Webhooks::HasWebhooks)
9
10
  include Spree::Webhooks::HasWebhooks
@@ -71,15 +72,21 @@ module Spree
71
72
  # Deletes all tax adjustments, then applies all applicable rates
72
73
  # to relevant items.
73
74
  def self.adjust(order, items)
75
+ return if items.none?
76
+
74
77
  rates = match(order.tax_zone)
75
78
  tax_category_ids = rates.map(&:tax_category_id)
76
79
 
77
80
  # using destroy_all to ensure adjustment destroy callback fires.
78
81
  Spree::Adjustment.where(adjustable: items).tax.destroy_all
79
82
 
80
- relevant_items = items.select do |item|
81
- tax_category_ids.include?(item.tax_category_id)
82
- end
83
+ relevant_items = if tax_category_ids.any?
84
+ items.select do |item|
85
+ tax_category_ids.include?(item.tax_category_id)
86
+ end
87
+ else
88
+ []
89
+ end
83
90
 
84
91
  relevant_items.each do |item|
85
92
  relevant_rates = rates.select do |rate|
@@ -115,6 +122,14 @@ module Spree
115
122
  compute(item)
116
123
  end
117
124
 
125
+ def included?
126
+ included_in_price
127
+ end
128
+
129
+ def additional?
130
+ !included_in_price
131
+ end
132
+
118
133
  private
119
134
 
120
135
  def label
@@ -16,8 +16,10 @@ module Spree
16
16
 
17
17
  include Spree::TranslatableResource
18
18
  include Spree::TranslatableResourceSlug
19
+ include Spree::Metafields
19
20
  include Spree::Metadata
20
21
  include Spree::MemoizedData
22
+ include Spree::Linkable
21
23
  if defined?(Spree::Webhooks::HasWebhooks)
22
24
  include Spree::Webhooks::HasWebhooks
23
25
  end
@@ -46,8 +48,6 @@ module Spree
46
48
  has_many :promotion_rule_taxons, class_name: 'Spree::PromotionRuleTaxon', dependent: :destroy
47
49
  has_many :promotion_rules, through: :promotion_rule_taxons, class_name: 'Spree::PromotionRule'
48
50
 
49
- has_many :page_links, as: :linkable, class_name: 'Spree::PageLink', dependent: :destroy
50
-
51
51
  #
52
52
  # Attachments
53
53
  #
@@ -118,6 +118,16 @@ module Spree
118
118
  end
119
119
  end
120
120
 
121
+ scope :with_matching_name, ->(name_to_match) do
122
+ value = name_to_match.to_s.strip.downcase
123
+
124
+ if Spree.use_translations?
125
+ i18n { name.lower.eq(value) }
126
+ else
127
+ where(arel_table[:name].lower.eq(value))
128
+ end
129
+ end
130
+
121
131
  #
122
132
  # Ransack
123
133
  #
@@ -1,6 +1,7 @@
1
1
  module Spree
2
2
  class Taxonomy < Spree.base_class
3
3
  include Spree::TranslatableResource
4
+ include Spree::Metafields
4
5
  include Spree::Metadata
5
6
  include Spree::SingleStoreResource
6
7
  if defined?(Spree::Webhooks::HasWebhooks)
@@ -24,6 +25,16 @@ module Spree
24
25
 
25
26
  default_scope { order("#{table_name}.position, #{table_name}.created_at") }
26
27
 
28
+ scope :with_matching_name, ->(name_to_match) do
29
+ value = name_to_match.to_s.strip.downcase
30
+
31
+ if Spree.use_translations?
32
+ i18n { name.lower.eq(value) }
33
+ else
34
+ where(arel_table[:name].lower.eq(value))
35
+ end
36
+ end
37
+
27
38
  self.whitelisted_ransackable_attributes = %w[name]
28
39
  self.whitelisted_ransackable_associations = %w[root]
29
40
 
@@ -21,7 +21,7 @@ module Spree
21
21
  has_many :previews, class_name: 'Spree::Theme', foreign_key: :parent_id, dependent: :destroy_async
22
22
  has_many :pages, -> { without_previews }, class_name: 'Spree::Page', dependent: :destroy, as: :pageable
23
23
  has_many :page_previews, -> { only_previews }, class_name: 'Spree::Page', dependent: :destroy_async, as: :pageable
24
- has_many :layout_sections, class_name: 'Spree::PageSection', dependent: :destroy, as: :pageable
24
+ has_many :layout_sections, -> { order(position: :asc) }, class_name: 'Spree::PageSection', dependent: :destroy, as: :pageable
25
25
  alias sections layout_sections
26
26
 
27
27
  #
@@ -4,6 +4,7 @@ module Spree
4
4
  acts_as_list scope: :product
5
5
 
6
6
  include Spree::MemoizedData
7
+ include Spree::Metafields
7
8
  include Spree::Metadata
8
9
  include Spree::Variant::Webhooks
9
10
 
@@ -393,6 +394,22 @@ module Spree
393
394
  price_in(currency).try(:compare_at_amount)
394
395
  end
395
396
 
397
+ def set_price(currency, amount, compare_at_amount = nil)
398
+ price = prices.find_or_initialize_by(currency: currency)
399
+ price.amount = amount
400
+ price.compare_at_amount = compare_at_amount if compare_at_amount.present?
401
+ price.save!
402
+ end
403
+
404
+ def set_stock(count_on_hand, backorderable = nil, stock_location = nil)
405
+ stock_location ||= Spree::Store.current.default_stock_location
406
+ stock_items.find_or_initialize_by(stock_location: stock_location) do |stock_item|
407
+ stock_item.count_on_hand = count_on_hand
408
+ stock_item.backorderable = backorderable if backorderable.present?
409
+ stock_item.save!
410
+ end
411
+ end
412
+
396
413
  def price_modifier_amount_in(currency, options = {})
397
414
  return 0 unless options.present?
398
415
 
@@ -0,0 +1,59 @@
1
+ module Spree
2
+ module CSV
3
+ class CustomerPresenter
4
+ include Spree::CSV::MetafieldsHelper
5
+
6
+ HEADERS = [
7
+ 'First Name',
8
+ 'Last Name',
9
+ 'Email',
10
+ 'Accepts Email Marketing',
11
+ 'Company',
12
+ 'Address 1',
13
+ 'Address 2',
14
+ 'City',
15
+ 'Province',
16
+ 'Province Code',
17
+ 'Country',
18
+ 'Country Code',
19
+ 'Zip',
20
+ 'Phone',
21
+ 'Total Spent',
22
+ 'Total Orders',
23
+ 'Tags'
24
+ ].freeze
25
+
26
+ def initialize(customer)
27
+ @customer = customer
28
+ end
29
+
30
+ attr_accessor :customer
31
+
32
+ def call
33
+ csv = [
34
+ customer.first_name,
35
+ customer.last_name,
36
+ customer.email,
37
+ customer.accepts_email_marketing ? Spree.t(:say_yes) : Spree.t(:say_no),
38
+ customer.address&.company,
39
+ customer.address&.address1,
40
+ customer.address&.address2,
41
+ customer.address&.city,
42
+ customer.address&.state_text,
43
+ customer.address&.state_abbr,
44
+ customer.address&.country&.name,
45
+ customer.address&.country&.iso,
46
+ customer.address&.zipcode,
47
+ customer.phone,
48
+ customer.amount_spent_in(Spree::Store.current.default_currency),
49
+ customer.completed_orders.count,
50
+ customer.tag_list
51
+ ]
52
+
53
+ csv += metafields_for_csv(customer)
54
+
55
+ csv
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,49 @@
1
+ module Spree
2
+ module CSV
3
+ class GiftCardPresenter
4
+ include Spree::CSV::MetafieldsHelper
5
+
6
+ HEADERS = [
7
+ 'Code',
8
+ 'Amount',
9
+ 'Amount Used',
10
+ 'Amount Remaining',
11
+ 'Currency',
12
+ 'Status',
13
+ 'Expires At',
14
+ 'Customer Email',
15
+ 'Customer First Name',
16
+ 'Customer Last Name',
17
+ 'Created At',
18
+ 'Updated At'
19
+ ].freeze
20
+
21
+ def initialize(gift_card)
22
+ @gift_card = gift_card
23
+ end
24
+
25
+ attr_accessor :gift_card
26
+
27
+ def call
28
+ csv = [
29
+ gift_card.display_code,
30
+ gift_card.display_amount,
31
+ gift_card.display_amount_used,
32
+ gift_card.display_amount_remaining,
33
+ gift_card.currency,
34
+ gift_card.display_state,
35
+ gift_card.expires_at&.strftime('%Y-%m-%d'),
36
+ gift_card.user&.email,
37
+ gift_card.user&.first_name,
38
+ gift_card.user&.last_name,
39
+ gift_card.created_at&.strftime('%Y-%m-%d %H:%M:%S'),
40
+ gift_card.updated_at&.strftime('%Y-%m-%d %H:%M:%S')
41
+ ]
42
+
43
+ csv += metafields_for_csv(gift_card)
44
+
45
+ csv
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,17 @@
1
+ module Spree
2
+ module CSV
3
+ module MetafieldsHelper
4
+ private
5
+
6
+ def metafield_definitions_for_csv(resource)
7
+ Spree::MetafieldDefinition.for_resource_type(resource.class.to_s).order(:namespace, :key)
8
+ end
9
+
10
+ def metafields_for_csv(resource)
11
+ Spree::MetafieldDefinition.for_resource_type(resource.class.to_s).order(:namespace, :key).map do |mf_def|
12
+ resource.metafields.find { |mf| mf.metafield_definition_id == mf_def.id }&.csv_value
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,39 @@
1
+ module Spree
2
+ module CSV
3
+ class NewsletterSubscriberPresenter
4
+ include Spree::CSV::MetafieldsHelper
5
+
6
+ HEADERS = [
7
+ 'Email',
8
+ 'Customer Name',
9
+ 'Customer ID',
10
+ 'Verified',
11
+ 'Verified At',
12
+ 'Created At',
13
+ 'Updated At'
14
+ ].freeze
15
+
16
+ def initialize(newsletter_subscriber)
17
+ @newsletter_subscriber = newsletter_subscriber
18
+ end
19
+
20
+ attr_accessor :newsletter_subscriber
21
+
22
+ def call
23
+ csv = [
24
+ newsletter_subscriber.email,
25
+ newsletter_subscriber.user&.full_name,
26
+ newsletter_subscriber.user_id,
27
+ newsletter_subscriber.verified? ? Spree.t(:say_yes) : Spree.t(:say_no),
28
+ newsletter_subscriber.verified_at,
29
+ newsletter_subscriber.created_at,
30
+ newsletter_subscriber.updated_at
31
+ ]
32
+
33
+ csv += metafields_for_csv(newsletter_subscriber)
34
+
35
+ csv
36
+ end
37
+ end
38
+ end
39
+ end
@@ -59,16 +59,17 @@ module Spree
59
59
  'Notes'
60
60
  ].freeze
61
61
 
62
- def initialize(order, line_item, index)
62
+ def initialize(order, line_item, index, metafields = [])
63
63
  @order = order
64
64
  @line_item = line_item
65
65
  @index = index
66
+ @metafields = metafields
66
67
  end
67
68
 
68
- attr_accessor :order, :line_item, :index
69
+ attr_accessor :order, :line_item, :index, :metafields
69
70
 
70
71
  def call
71
- [
72
+ csv = [
72
73
  order.number,
73
74
  index.zero? ? order.email : nil,
74
75
  index.zero? ? order.state : nil,
@@ -85,7 +86,7 @@ module Spree
85
86
  index.zero? ? order.total.to_f : nil,
86
87
  index.zero? ? order.shipping_method&.name : nil,
87
88
  index.zero? ? order.total_weight.to_f : nil,
88
- index.zero? && order.payments.valid.any? ? order.payments.valid.first.display_source_name : nil,
89
+ index.zero? ? order.payments.valid&.first&.display_source_name : nil,
89
90
  line_item.product_id,
90
91
  line_item.quantity,
91
92
  line_item.sku,
@@ -94,7 +95,7 @@ module Spree
94
95
  line_item.promo_total.abs,
95
96
  line_item.total,
96
97
  !line_item.product.digital?,
97
- line_item.product.tax_category.present?,
98
+ line_item.product.tax_category_id.present?,
98
99
  line_item.product.try(:vendor_name),
99
100
  taxon_dict(line_item.product.main_taxon)[0],
100
101
  taxon_dict(line_item.product.main_taxon)[1],
@@ -125,6 +126,12 @@ module Spree
125
126
  index.zero? ? order.canceler&.email : nil,
126
127
  index.zero? ? order.special_instructions : nil
127
128
  ]
129
+
130
+ if index.zero?
131
+ csv += metafields
132
+ end
133
+
134
+ csv
128
135
  end
129
136
 
130
137
  private
@@ -47,7 +47,7 @@ module Spree
47
47
  'category3',
48
48
  ].freeze
49
49
 
50
- def initialize(product, variant, index = 0, properties = [], taxons = [], store = nil)
50
+ def initialize(product, variant, index = 0, properties = [], taxons = [], store = nil, metafields = [])
51
51
  @product = product
52
52
  @variant = variant
53
53
  @index = index
@@ -55,9 +55,10 @@ module Spree
55
55
  @taxons = taxons
56
56
  @store = store || product.stores.first
57
57
  @currency = @store.default_currency
58
+ @metafields = metafields
58
59
  end
59
60
 
60
- attr_accessor :product, :variant, :index, :properties, :taxons, :store, :currency
61
+ attr_accessor :product, :variant, :index, :properties, :taxons, :store, :currency, :metafields
61
62
 
62
63
  ##
63
64
  # Generates an array representing a CSV row of product variant data.
@@ -71,11 +72,13 @@ module Spree
71
72
  #
72
73
  # @return [Array] An array containing the combined product and variant CSV data.
73
74
  def call
75
+ total_on_hand = variant.total_on_hand
76
+
74
77
  csv = [
75
78
  product.id,
76
79
  variant.sku,
77
80
  index.zero? ? product.name : nil,
78
- index.zero? ? product.slug : nil,
81
+ product.slug,
79
82
  index.zero? ? product.status : nil,
80
83
  index.zero? ? product.try(:vendor_name) : nil,
81
84
  index.zero? ? product.try(:brand_name) : nil,
@@ -86,7 +89,7 @@ module Spree
86
89
  index.zero? ? product.tag_list.to_s : nil,
87
90
  index.zero? ? product.label_list.to_s : nil,
88
91
  variant.amount_in(currency).to_f,
89
- variant.compare_at_price&.to_f,
92
+ variant.compare_at_amount_in(currency).to_f,
90
93
  currency,
91
94
  variant.width,
92
95
  variant.height,
@@ -97,7 +100,7 @@ module Spree
97
100
  variant.available_on&.strftime('%Y-%m-%d %H:%M:%S'),
98
101
  (variant.discontinue_on || product.discontinue_on)&.strftime('%Y-%m-%d %H:%M:%S'),
99
102
  variant.track_inventory?,
100
- variant.total_on_hand == BigDecimal::INFINITY ? '∞' : variant.total_on_hand,
103
+ total_on_hand == BigDecimal::INFINITY ? '∞' : total_on_hand,
101
104
  variant.backorderable?,
102
105
  variant.tax_category&.name,
103
106
  variant.digital?,
@@ -115,6 +118,7 @@ module Spree
115
118
  if index.zero?
116
119
  csv += taxons
117
120
  csv += properties
121
+ csv += metafields
118
122
  end
119
123
 
120
124
  csv
@@ -4,11 +4,13 @@ module Spree
4
4
  prepend Spree::ServiceModule::Base
5
5
 
6
6
  def call(order:, line_item:, line_item_created: false, options: {})
7
- order.remove_gift_card if order.gift_card.present?
8
- order_updater = ::Spree::OrderUpdater.new(order)
7
+ order_updater = order.updater
9
8
 
10
- order.payments.store_credits.checkout.destroy_all
11
- order_updater.update
9
+ order.remove_gift_card if order.gift_card.present?
10
+ order.payments.store_credits.checkout.destroy_all if order.payments.store_credits.checkout.any?
11
+ order_updater.update_item_count
12
+ order_updater.update_totals
13
+ order_updater.persist_totals
12
14
 
13
15
  shipment = options[:shipment]
14
16
  if shipment.present?
@@ -6,12 +6,11 @@ module Spree
6
6
  def call(order:, line_item:, options: nil)
7
7
  options ||= {}
8
8
  ActiveRecord::Base.transaction do
9
- line_item.destroy!
9
+ order.line_items.destroy(line_item)
10
10
  Spree::Dependencies.cart_recalculate_service.constantize.new.call(order: order,
11
11
  line_item: line_item,
12
12
  options: options)
13
13
  end
14
- order.reload
15
14
  success(line_item)
16
15
  end
17
16
  end
@@ -0,0 +1,19 @@
1
+ module Spree
2
+ module Imports
3
+ module RowProcessors
4
+ class Base
5
+ def initialize(row)
6
+ @row = row
7
+ @import = row.import
8
+ @attributes = row.to_schema_hash
9
+ end
10
+
11
+ attr_reader :row, :import, :attributes
12
+
13
+ def process!
14
+ raise NotImplementedError, 'Subclasses must implement the process! method'
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end