ba_spree 1.1.0 → 1.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 82aeb70ed5e30afcc4c5849eb6daf41f9a311b649e9e3f86adb0ff519feee6c9
4
- data.tar.gz: 771f95d599301938053a772c997baca793f9237451568b1072ed127be2770f17
3
+ metadata.gz: 7ff58a21f768530a02800b2fc55181f69d07e8abf91b2e2da5b0a9064e412b7e
4
+ data.tar.gz: d16fd26564e35a8a448420fd8f7dc585111c11f4fbb3e5204a73c299bfb9c9ee
5
5
  SHA512:
6
- metadata.gz: 1e15809db814b48a2211a17dce5ac0e3e2fcd6dd40aaf0dcf0d7a96f0c43664a71eb33ff718eded86546cef5a6384706a35bc0a2c1361eea5219e12c178720c2
7
- data.tar.gz: 0a2c180bdf9a3e648affd0f56fe915f87a8ee7c2b790e30d04a80298fbfc52c4f907a511d30ecd0283330bc96e953abad0be333a0625d65e54263bcefa91b75f
6
+ metadata.gz: bc60da4dd93ffcf3d0d15e823f5f6f264a3368c4614b2c2bcde5527cf4bf0146b45cabfe4277d0e57478a5fdeac1ca131f011e6a3bc924627eba02553b6e7ed5
7
+ data.tar.gz: dc7bd940663133de589568351e00d546587163bdebe19eb81a2872df644238e2cae1fe3420153bd2ccf7f3f8c4365947487e7a299027464d70f6d8ae10384f54
data/README.md CHANGED
@@ -69,7 +69,7 @@ are specific to your shop, so set them yourself.
69
69
 
70
70
  ## What you get
71
71
 
72
- ba_spree itself is a thin wrapper. The substance is these 20 engines, all
72
+ ba_spree itself is a thin wrapper. The substance is these 23 engines, all
73
73
  pulled in by a single `gem 'ba_spree'`.
74
74
 
75
75
  ### Japanese commerce conventions
@@ -99,6 +99,9 @@ pulled in by a single `gem 'ba_spree'`.
99
99
  | `spree_auto_capture_digital` | Auto-capture orders containing only digital products |
100
100
  | `spree_digital_payment_notice` | Show payment notices for orders containing digital products |
101
101
  | `spree_checkout_signup_promotion` | Prompt sign-up / login at the checkout address step |
102
+ | `spree_order_total_discount` | Percentage discount on the order total |
103
+ | `spree_common_shipping_method_splitter` | Ship items in one package when their shipping categories share a shipping method |
104
+ | `spree_promotion_action_create_line_items` | Stop customers adding, changing or removing the items a promotion adds to the cart |
102
105
 
103
106
  ### Analytics
104
107
 
@@ -11,6 +11,9 @@ module BaSpree
11
11
  # @gem-override spree_storefront-5.3.6/app/controllers/spree/checkout_controller.rb#load_order
12
12
  # reason: ゲストチェックアウト対応のため super なしで丸ごと再実装。本家のゲスト処理を
13
13
  # handle_guest_checkout / create_guest_order に抽出している (commit d0dbe2b4)
14
+ # #1352: 抽出時に落ちていた本家の `elsif !current_store.prefers_guest_checkout?` →
15
+ # `require_user(redirect_path: spree_signup_path)` の分岐を復元した。
16
+ # これが無いと guest_checkout を OFF にしてもゲストのカートがチェックアウトへ進めてしまう。
14
17
  # @see https://github.com/be-agile/giga-repeat/commit/d0dbe2b4524e22c1cf974bbd4829c587ef7cd254
15
18
  def load_order
16
19
  return @order if @order.present?
@@ -35,6 +38,11 @@ module BaSpree
35
38
  elsif try_spree_current_user.nil? && !allow_access_to_complete_order_with_new_user?
36
39
  handle_guest_checkout
37
40
  end
41
+ elsif !current_store.prefers_guest_checkout?
42
+ # 本家にある分岐。ユーザーが紐付いていない(=純粋なゲストの)カートは、
43
+ # ゲスト購入が無効なストアではログインを要求する。
44
+ # @see https://github.com/be-agile/giga-repeat/issues/1352
45
+ require_user(redirect_path: spree_signup_path)
38
46
  end
39
47
 
40
48
  # completed orders shouldn't be updated anymore
@@ -0,0 +1,28 @@
1
+ module BaSpree
2
+ # storefront API の商品取得を、HTML 側と同じ公開状態の判定に揃える。
3
+ #
4
+ # 本家の scope は for_store + accessible_by(:show) だけで、ゲストに適用される
5
+ # Spree::PermissionSets::DefaultCustomer が `can :read, Spree::Product` を条件なしで
6
+ # 与えるため、公開状態の絞り込みが効いていない。結果、slug か id を指定すれば
7
+ # draft(非公開) / archived(取扱対象外) / 論理削除済みの商品が取得できていた。
8
+ #
9
+ # 一覧も同じ scope を通るので、filter[show_discontinued] / filter[show_deleted] を
10
+ # 渡してフィルタを外す経路もここで塞がる(for_user が付ける status = 'active' は
11
+ # finder の include_discontinued では外れず、not_deleted は生 SQL の where なので
12
+ # with_deleted の unscope でも消えない)。
13
+ #
14
+ # prepend 先は storefront のコントローラに限定する。Spree::Api::V2::ResourceController に
15
+ # 当てると、それを継承する Spree::Api::V2::Platform::ResourceController 経由で
16
+ # Platform API 全体が Spree::Variant 等に for_user を呼んで NoMethodError になる。
17
+ #
18
+ # @see https://github.com/be-agile/giga-repeat/issues/1352
19
+ module StorefrontApiProductsControllerDecorator
20
+ protected
21
+
22
+ def scope(skip_cancancan: false)
23
+ super.for_user(spree_current_user)
24
+ end
25
+ end
26
+ end
27
+
28
+ Spree::Api::V2::Storefront::ProductsController.prepend(BaSpree::StorefrontApiProductsControllerDecorator)
@@ -0,0 +1,27 @@
1
+ module BaSpree
2
+ # storefront API のバリエーション取得も、商品と同じ公開状態の判定に揃える
3
+ # (draft / archived / 論理削除済みの商品の SKU・価格が取得できていた)。
4
+ #
5
+ # scope の返り値は Spree::Variant のリレーションで、for_user は Spree::Product の
6
+ # スコープのため後ろにチェーンできない。商品を引く側に挟む必要があるので、
7
+ # 本家のメソッドを丸ごと再実装している。
8
+ module StorefrontApiVariantsControllerDecorator
9
+ private
10
+
11
+ # @gem-override spree_api-5.3.6/app/controllers/spree/api/v2/storefront/variants_controller.rb#scope
12
+ # reason: 本家の product_scope に for_user を挟むため。for_user は Spree::Product の
13
+ # スコープで、本家の返り値(Spree::Variant のリレーション)にはチェーンできない。
14
+ # @see https://github.com/be-agile/giga-repeat/issues/1352
15
+ def scope(skip_cancancan: false)
16
+ product_scope = Spree::Product.for_store(current_store)
17
+ product_scope = product_scope.accessible_by(current_ability, :show) unless skip_cancancan
18
+ product_scope = product_scope.for_user(spree_current_user)
19
+ product_scope = product_scope.i18n if model_class.include?(Spree::TranslatableResource)
20
+
21
+ product = product_scope.friendly.find(params[:id])
22
+ product.variants_including_master
23
+ end
24
+ end
25
+ end
26
+
27
+ Spree::Api::V2::Storefront::VariantsController.prepend(BaSpree::StorefrontApiVariantsControllerDecorator)
@@ -0,0 +1,19 @@
1
+ module BaSpree
2
+ module Products
3
+ module FindDecorator
4
+ private
5
+
6
+ # @gem-override spree_core-5.3.6/app/finders/spree/products/find.rb#ordered
7
+ # reason: 「関連性」の並び順で、親カテゴリの一覧に子カテゴリの商品が混ざって並ばないよう、
8
+ # カテゴリツリーの縦型探索順に並べる。
9
+ # @see https://github.com/be-agile/giga-repeat/issues/1503
10
+ def ordered(products)
11
+ return super unless %w[default manual].include?(sort_by) && taxons?
12
+
13
+ products.ascend_by_taxons_tree_position(taxons)
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ Spree::Products::Find.prepend(BaSpree::Products::FindDecorator)
@@ -1,5 +1,26 @@
1
1
  module Spree
2
2
  module BaseHelperDecorator
3
+ # Issue #1153: ストアフロントのフラグメントキャッシュのキーは、本家では
4
+ # locale / currency / ログイン中か否か / role_users しか持たず、ユーザごとの差が入らない。
5
+ # このままカテゴリ・商品・価格をユーザごとに絞ると、別のユーザ向けに生成された HTML が
6
+ # そのまま出るため、顧客グループID(ソート済み)を署名として足して分離する。
7
+ # spree_storefront_base_cache_key の中身でもあるため、ナビ・一覧・絞り込みサイドバーが
8
+ # これ1箇所で分離される。Issue #1219 で残っていた「一覧の価格が別グループのユーザに
9
+ # 見える」経路の修正も兼ねる。
10
+ # 本家と同じく defined?(try_spree_current_user) のガードを維持する
11
+ # (Spree::BaseHelper は Spree::MailHelper と Spree::VariantPresenter にも include され、
12
+ # そこでは try_spree_current_user が未定義のため)。
13
+ # @see https://github.com/be-agile/giga-repeat/issues/1153
14
+ # メモ化には本家と別の ivar を使う。本家も @spree_base_cache_key に ||= するため、同じ
15
+ # ivar を使うと「||= が左辺を先に読む」という評価順序に依存することになり、本家の実装が
16
+ # 変わったときに顧客グループIDだけが無音で落ちる(別グループ向けの HTML が出る)。
17
+ def spree_base_cache_key
18
+ @ba_spree_base_cache_key ||= [
19
+ *super,
20
+ (defined?(try_spree_current_user) && try_spree_current_user.try(:customer_group_ids)&.sort)
21
+ ].compact
22
+ end
23
+
3
24
  CHILD_TAXONS_SECTION_DEFAULT_PREFERENCES = {
4
25
  heading_size: 'medium',
5
26
  heading_alignment: 'center'
@@ -24,6 +24,20 @@ module BaSpree
24
24
 
25
25
  # ProductProperty -> metafields 移行用の読み書きヘルパー(Spree 5.4 の Property 削除対応)
26
26
  base.include Spree::ProductPropertyMetafields
27
+
28
+ # 指定カテゴリ群の中で、カテゴリツリーを縦型探索した順(lft) → カテゴリ内の商品の並び順(position) に並べる。
29
+ # 複数のカテゴリに属する商品は、最初に出てくる位置で並ぶ。
30
+ # taxon は、絞り込みに使う spree_products_taxons の行からたどり、指定カテゴリ群の行だけで MIN をとる。
31
+ base.add_search_scope :ascend_by_taxons_tree_position do |taxon_ids|
32
+ # position(INT)の上の桁に lft を置いた1つの整数にする
33
+ tree_position_sql = "MIN(#{Spree::Taxon.table_name}.lft * #{2**32} + #{Spree::Classification.table_name}.position)"
34
+
35
+ joins(classifications: :taxon).
36
+ where(Spree::Classification.table_name => { taxon_id: taxon_ids }).
37
+ select("#{Spree::Product.table_name}.*", "#{tree_position_sql} AS taxon_tree_position").
38
+ group("#{Spree::Product.table_name}.id").
39
+ order(Arel.sql("#{tree_position_sql} ASC"))
40
+ end
27
41
  end
28
42
 
29
43
  def set_slug
@@ -18,7 +18,12 @@ module Spree
18
18
  end
19
19
  end
20
20
 
21
+ # 注文に紐づいたプロモーションは、条件を外れたときに取り消す(deactivate)ため除外しない
21
22
  def exclude_promotion_ids
23
+ unmatched_product_rule_promotion_ids - order.promotion_ids
24
+ end
25
+
26
+ def unmatched_product_rule_promotion_ids
22
27
  cart_product_ids = order.line_items.joins(:variant).pluck('spree_variants.product_id').uniq
23
28
  # Find all promotions with Product rules
24
29
  all_product_rule_promotions = Spree::Promotion
@@ -1,6 +1,8 @@
1
1
  <%# @gem-override spree_storefront-5.3.6/app/views/themes/default/spree/orders/_summary.html.erb %>
2
- <%# reason: カートサマリの小計・割引・合計表示を adjustments ベースに組み替え、買い物を続けるボタンを追加している %>
2
+ <%# reason: カートサマリの小計・割引・合計表示を adjustments ベースに組み替え、買い物を続けるボタンを追加している。空のクイックチェックアウト欄を出さず、スマホでボタンを横幅いっぱいにしている %>
3
+ <%# (「レジに進む」を押したらカートをローディング状態にして連打を防ぐ) %>
3
4
  <%# @see https://github.com/be-agile/giga-repeat/issues/698 %>
5
+ <%# @see https://github.com/be-agile/giga-repeat/issues/1390 %>
4
6
  <%= turbo_frame_tag :cart_summary do %>
5
7
  <% if order.line_items.any? %>
6
8
  <div class="cart-summary-container p-4">
@@ -53,7 +55,9 @@
53
55
 
54
56
 
55
57
  <div class="flex <%= !turbo_frame_request? && !turbo_stream_request? ? 'flex-row' : 'flex-col' %> gap-4 mt-4 w-full justify-end items-end">
56
- <% if quick_checkout_enabled?(@order) %>
58
+ <%# quick_checkout_enabled? は注文の条件しか見ないので、Apple Pay 等のボタンのパーシャルが1つも登録されていないと
59
+ 中身が空の w-full の欄だけが出て、隣の「レジに進む」等のボタンの幅を半分奪う。パーシャルがあるときだけ出す %>
60
+ <% if quick_checkout_enabled?(@order) && Spree.storefront.partials.quick_checkout.any? %>
57
61
  <div class="min-h-[46px] w-full has-[turbo-frame]:block group no-separator">
58
62
  <% if !turbo_frame_request? && !turbo_stream_request? %>
59
63
  <%= render partial: 'spree/checkout/quick_checkout', locals: { height: 46, theme: 'black', button_width: 320, container_class: "w-full flex justify-end" } %>
@@ -62,21 +66,28 @@
62
66
  <% end %>
63
67
  </div>
64
68
  <% end %>
65
- <div style="display: flex; flex-direction: column; align-items: center; gap: 1rem;<%= ' width: 100%;' if turbo_frame_request? || turbo_stream_request? %>">
69
+ <%# 幅を指定しないと中身に合わせて縮み、日本語は1文字ごとに改行できるのでボタンが極端に細くなる。
70
+ スマホではボタンを横幅いっぱいに広げ、PC では幅 320px(lg:w-80)でページなら右寄せ・スライドオーバーなら中央にする。
71
+ ba_spree のビューは storefront の Tailwind のビルド対象外なので、クラスは本家のビューで使われていてビルドに含まれるものだけを使う %>
72
+ <div class="<%= turbo_frame_request? || turbo_stream_request? ? 'lg:items-center' : 'lg:items-end' %>" style="display: flex; flex-direction: column; gap: 1rem; width: 100%;">
73
+ <%# レジに進むと確認画面まで自動で進める(spree_checkout_auto_advance)分だけ待ち時間が長いので、数量の変更時と同じく
74
+ カートを操作できなくしてローディングを出す(連打も防ぐ)。ブラウザの戻るで復元されたときは元に戻す (#1390) %>
66
75
  <%= link_to Spree.t(:checkout), spree.checkout_path(order.token),
67
76
  class: 'btn-primary block w-full lg:w-80 text-center !no-underline !mt-0',
68
- data: { 'turbo': 'false', 'cart-target': 'checkoutButton' } %>
77
+ data: { 'turbo': 'false', 'cart-target': 'checkoutButton', action: 'click->cart#disableCart pageshow@window->cart#enableCart' } %>
69
78
 
70
79
  <% # Continue Shopping button %>
71
80
  <% if turbo_frame_request? || turbo_stream_request? %>
72
81
  <%# Modal context: close the slideover %>
73
82
  <%= button_tag Spree.t(:continue_shopping),
74
83
  type: 'button',
84
+ class: 'lg:w-80',
75
85
  style: 'display: inline-block; text-align: center; text-decoration: none; background-color: white; padding: 0.75rem 1.25rem; font-weight: 600; font-size: 0.875rem; line-height: 1.25rem; text-transform: uppercase; letter-spacing: 0.05em; cursor: pointer; border-radius: var(--button-border-radius); border: var(--button-border-width) solid var(--button-background-color, var(--button)); color: var(--button-background-color, var(--button));',
76
86
  data: { action: 'slideover#toggle' } %>
77
87
  <% else %>
78
88
  <%# Full-page cart context: redirect to products %>
79
89
  <%= link_to Spree.t(:continue_shopping), spree.products_path,
90
+ class: 'lg:w-80',
80
91
  style: 'display: inline-block; text-align: center; text-decoration: none; background-color: white; padding: 0.75rem 1.25rem; font-weight: 600; font-size: 0.875rem; line-height: 1.25rem; text-transform: uppercase; letter-spacing: 0.05em; cursor: pointer; border-radius: var(--button-border-radius); border: var(--button-border-width) solid var(--button-background-color, var(--button)); color: var(--button-background-color, var(--button));',
81
92
  data: { 'turbo-frame': '_top' } %>
82
93
  <% end %>
@@ -1,3 +1,3 @@
1
1
  module BaSpree
2
- VERSION = "1.1.0"
2
+ VERSION = "1.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ba_spree
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - be agile Co., Ltd.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-09-30 00:00:00.000000000 Z
11
+ date: 2026-10-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: spree
@@ -402,6 +402,20 @@ dependencies:
402
402
  - - ">="
403
403
  - !ruby/object:Gem::Version
404
404
  version: '0'
405
+ - !ruby/object:Gem::Dependency
406
+ name: spree_promotion_action_create_line_items
407
+ requirement: !ruby/object:Gem::Requirement
408
+ requirements:
409
+ - - ">="
410
+ - !ruby/object:Gem::Version
411
+ version: '0'
412
+ type: :runtime
413
+ prerelease: false
414
+ version_requirements: !ruby/object:Gem::Requirement
415
+ requirements:
416
+ - - ">="
417
+ - !ruby/object:Gem::Version
418
+ version: '0'
405
419
  - !ruby/object:Gem::Dependency
406
420
  name: gem_override_marker
407
421
  requirement: !ruby/object:Gem::Requirement
@@ -431,6 +445,8 @@ files:
431
445
  - app/assets/stylesheets/spree/admin/custom.scss
432
446
  - app/controllers/ba_spree/checkout_controller_decorator.rb
433
447
  - app/controllers/ba_spree/store_controller_decorator.rb
448
+ - app/controllers/ba_spree/storefront_api_products_controller_decorator.rb
449
+ - app/controllers/ba_spree/storefront_api_variants_controller_decorator.rb
434
450
  - app/controllers/concerns/ba_spree/theme_concern_decorator.rb
435
451
  - app/controllers/spree/admin/assets_controller_decorator.rb
436
452
  - app/controllers/spree/admin/products_controller_decorator.rb
@@ -444,6 +460,7 @@ files:
444
460
  - app/decorators/spree/money_decorator.rb
445
461
  - app/decorators/spree/order_email_subscriber_decorator.rb
446
462
  - app/decorators/spree/page_sections/featured_posts_decorator.rb
463
+ - app/finders/ba_spree/products/find_decorator.rb
447
464
  - app/helpers/currency_rounding_helper.rb
448
465
  - app/helpers/spree/admin/filter_params_preservation.rb
449
466
  - app/helpers/spree/admin/navigation_helper_decorator.rb