spree_cm_commissioner 2.5.0.pre.pre7 → 2.5.0.pre.pre8

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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test_and_build_gem.yml +1 -1
  3. data/.tool-versions +1 -1
  4. data/Gemfile.lock +1 -1
  5. data/app/controllers/spree/api/v2/storefront/popular_route_places_controller.rb +7 -1
  6. data/app/controllers/spree/api/v2/storefront/route_places_controller.rb +9 -9
  7. data/app/finders/spree_cm_commissioner/places/find_with_route.rb +10 -10
  8. data/app/finders/spree_cm_commissioner/routes/find_popular.rb +10 -14
  9. data/app/interactors/spree_cm_commissioner/stock/inventory_item_resetter.rb +1 -1
  10. data/app/jobs/spree_cm_commissioner/stock/inventory_items_adjuster_job.rb +3 -3
  11. data/app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb +3 -15
  12. data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +0 -2
  13. data/app/models/concerns/spree_cm_commissioner/store_metadata.rb +2 -14
  14. data/app/models/concerns/spree_cm_commissioner/tenant_preference.rb +3 -0
  15. data/app/models/concerns/spree_cm_commissioner/variant_options_concern.rb +7 -1
  16. data/app/models/spree_cm_commissioner/guest.rb +0 -13
  17. data/app/models/spree_cm_commissioner/inventory_item.rb +1 -5
  18. data/app/models/spree_cm_commissioner/line_item_decorator.rb +1 -13
  19. data/app/models/spree_cm_commissioner/option_type_decorator.rb +0 -8
  20. data/app/models/spree_cm_commissioner/option_value_decorator.rb +0 -34
  21. data/app/models/spree_cm_commissioner/order_decorator.rb +0 -1
  22. data/app/models/spree_cm_commissioner/product_decorator.rb +2 -3
  23. data/app/models/spree_cm_commissioner/redis_stock/cached_inventory_items_builder.rb +2 -2
  24. data/app/models/spree_cm_commissioner/redis_stock/inventory_updater.rb +2 -2
  25. data/app/models/spree_cm_commissioner/taxon_decorator.rb +0 -1
  26. data/app/models/spree_cm_commissioner/taxonomy_decorator.rb +1 -13
  27. data/app/models/spree_cm_commissioner/variant_decorator.rb +4 -7
  28. data/app/models/spree_cm_commissioner/vendor_decorator.rb +0 -4
  29. data/app/presenters/spree/variants/{visible_options_presenter.rb → visable_options_presenter.rb} +4 -2
  30. data/app/request_schemas/spree_cm_commissioner/popular_route_places_request_schema.rb +12 -0
  31. data/app/request_schemas/spree_cm_commissioner/route_places_request_schema.rb +5 -0
  32. data/app/views/spree/admin/tenants/_form.html.erb +18 -0
  33. data/app/views/spree/admin/tenants/form/_footer.html.erb +31 -0
  34. data/app/views/spree/admin/tenants/form/_social.html.erb +31 -0
  35. data/app/views/spree/order_mailer/confirm_email.html.erb +1 -1
  36. data/app/views/spree_cm_commissioner/layouts/order_mailer.html.erb +1 -1
  37. data/app/views/spree_cm_commissioner/order_mailer/tenant/_footer.html.erb +13 -6
  38. data/app/views/spree_cm_commissioner/order_mailer/tenant/_support_contact.html.erb +23 -24
  39. data/config/locales/en.yml +0 -8
  40. data/config/locales/km.yml +0 -8
  41. data/config/routes.rb +0 -8
  42. data/db/migrate/20251209022924_add_contact_fields_to_cm_tenants.rb +9 -0
  43. data/lib/cm_app_logger.rb +3 -21
  44. data/lib/spree_cm_commissioner/version.rb +1 -1
  45. data/lib/spree_cm_commissioner.rb +7 -8
  46. metadata +7 -57
  47. data/app/controllers/spree/admin/integration_mappings_controller.rb +0 -21
  48. data/app/controllers/spree/admin/integration_sessions_controller.rb +0 -21
  49. data/app/controllers/spree/admin/integrations_controller.rb +0 -83
  50. data/app/controllers/spree/api/v2/storefront/event_matches_controller.rb +0 -15
  51. data/app/errors/spree_cm_commissioner/integrations/external_client_error.rb +0 -10
  52. data/app/errors/spree_cm_commissioner/integrations/sync_error.rb +0 -4
  53. data/app/finders/spree_cm_commissioner/events/find_matches.rb +0 -15
  54. data/app/helpers/spree_cm_commissioner/external_integrations_helper.rb +0 -58
  55. data/app/jobs/spree_cm_commissioner/integrations/base_job.rb +0 -39
  56. data/app/jobs/spree_cm_commissioner/integrations/polling_job.rb +0 -53
  57. data/app/jobs/spree_cm_commissioner/integrations/polling_scheduler_job.rb +0 -30
  58. data/app/jobs/spree_cm_commissioner/telegram_alerts/integration_sync_failure_job.rb +0 -17
  59. data/app/models/concerns/spree_cm_commissioner/integrations/integration_mappable.rb +0 -61
  60. data/app/models/concerns/spree_cm_commissioner/line_item_integration.rb +0 -36
  61. data/app/models/concerns/spree_cm_commissioner/order_integration.rb +0 -33
  62. data/app/models/spree_cm_commissioner/integration.rb +0 -29
  63. data/app/models/spree_cm_commissioner/integration_mapping.rb +0 -41
  64. data/app/models/spree_cm_commissioner/integration_sync_session.rb +0 -15
  65. data/app/models/spree_cm_commissioner/integrations/stadium_x_v1.rb +0 -37
  66. data/app/overrides/spree/admin/shared/sub_menu/_integrations/external_integrations.html.erb.deface +0 -6
  67. data/app/services/spree_cm_commissioner/integrations/base/sync_manager.rb +0 -69
  68. data/app/services/spree_cm_commissioner/integrations/base/sync_result.rb +0 -183
  69. data/app/services/spree_cm_commissioner/integrations/polling.rb +0 -70
  70. data/app/services/spree_cm_commissioner/integrations/polling_scheduler.rb +0 -79
  71. data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/external_client/client.rb +0 -152
  72. data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/inventory/unstock_inventory.rb +0 -83
  73. data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/polling/sync_matches.rb +0 -113
  74. data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/polling/sync_zones.rb +0 -215
  75. data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/resources/base.rb +0 -20
  76. data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/resources/league.rb +0 -19
  77. data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/resources/match.rb +0 -95
  78. data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/resources/ticket.rb +0 -81
  79. data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/resources/ticket_image.rb +0 -19
  80. data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/resources/zone.rb +0 -90
  81. data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/sync_manager.rb +0 -35
  82. data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/sync_strategies/full_sync_strategy.rb +0 -38
  83. data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/sync_strategies/incremental_sync_strategy.rb +0 -44
  84. data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/sync_strategies/webhook_sync_strategy.rb +0 -16
  85. data/app/services/spree_cm_commissioner/telegram_alerts/integration_sync_failure.rb +0 -49
  86. data/app/views/spree/admin/integration_mappings/_integration_mappings.html.erb +0 -107
  87. data/app/views/spree/admin/integration_mappings/index.html.erb +0 -33
  88. data/app/views/spree/admin/integration_sessions/_integration_sync_sessions.html.erb +0 -116
  89. data/app/views/spree/admin/integration_sessions/index.html.erb +0 -42
  90. data/app/views/spree/admin/integrations/_form.html.erb +0 -104
  91. data/app/views/spree/admin/integrations/_stadium_x_v1_fields.html.erb +0 -29
  92. data/app/views/spree/admin/integrations/edit.html.erb +0 -45
  93. data/app/views/spree/admin/integrations/index.html.erb +0 -75
  94. data/app/views/spree/admin/integrations/new.html.erb +0 -25
  95. data/db/migrate/20251017094845_create_cm_integrations.rb +0 -22
  96. data/db/migrate/20251017101555_create_cm_integration_sync_sessions.rb +0 -68
  97. data/db/migrate/20251017101605_create_cm_integration_mappings.rb +0 -52
  98. data/lib/spree_cm_commissioner/test_helper/factories/integration_factory.rb +0 -25
  99. data/lib/spree_cm_commissioner/test_helper/factories/integration_mapping_factory.rb +0 -14
  100. data/lib/spree_cm_commissioner/test_helper/factories/integration_sync_session_factory.rb +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cd65c0e3f9c574eac1886f0dd7872516ee4b06ce9de12c91cd56e9101ea37914
4
- data.tar.gz: 223b2e1bc19876a282cf764cbfd45da3aeb3e13b671a9bafeaf697bed5938380
3
+ metadata.gz: 538969bdcdc4e74a70c795d9355b5c49357852b362d0534d208098434dcc8558
4
+ data.tar.gz: 14329cc3a2c2e8b0ae754057f65c6175c16e6f3251b9d16cd589efe64460ebde
5
5
  SHA512:
6
- metadata.gz: 959b4855a961019439474b8dc5fb987650e65ecb96c6e3b9a12355d3487d6d067c5824317cc825c882c858cee64c23e21695448999c3caf6b852e7c7d73fbfdc
7
- data.tar.gz: c3fe124a224836d629669bf723d80162253e1e732512870d1ddfbaf8bd2c115bb081eb058e7f9dc2acc1bdbe23b425bf9ad19ad2134d31c523c11163016eee0f
6
+ metadata.gz: 8f989e81e1e4fc89004874ac6fe64535b450aeff5d709127e125339c0a71f5f4fd35eb344722354950fb72c28dbd751325b4b9c44ac3acb73c3ea6473626bdca
7
+ data.tar.gz: 624b7a73bf7ac18e24a60de96e284a6c1f336d3efbc3d818cbcdb0bda0e1839a9107e9264af5924c934d0e383bac7093db07b88e3ab0543bf0e6512a1f46d3d0
@@ -10,7 +10,7 @@ on:
10
10
  - reopened
11
11
  branches:
12
12
  - develop
13
- - 3114-external-integration-milestone
13
+ - milestone-77-scalable-design
14
14
  push:
15
15
  tags:
16
16
  - "*"
data/.tool-versions CHANGED
@@ -1 +1 @@
1
- ruby 3.2.0
1
+ ruby 3.3.5
data/Gemfile.lock CHANGED
@@ -34,7 +34,7 @@ GIT
34
34
  PATH
35
35
  remote: .
36
36
  specs:
37
- spree_cm_commissioner (2.5.0.pre.pre7)
37
+ spree_cm_commissioner (2.5.0.pre.pre8)
38
38
  activerecord-multi-tenant
39
39
  activerecord_json_validator (~> 2.1, >= 2.1.3)
40
40
  aws-sdk-cloudfront
@@ -19,7 +19,8 @@ module Spree
19
19
  # override
20
20
  def collection
21
21
  @collection ||= collection_finder.new.execute(
22
- route_type: params[:route_type]
22
+ route_type: params[:route_type],
23
+ query: params[:query]
23
24
  )
24
25
  end
25
26
 
@@ -51,6 +52,11 @@ module Spree
51
52
  )
52
53
  end
53
54
 
55
+ # override
56
+ def required_schema
57
+ SpreeCmCommissioner::PopularRoutePlacesRequestSchema
58
+ end
59
+
54
60
  def include_vendors?
55
61
  resource_includes.include?(:vendors) || false
56
62
  end
@@ -3,22 +3,22 @@
3
3
  # GET /api/v2/storefront/route_places
4
4
  #
5
5
  # Finds places (origins or destinations) that are connected to a given place through existing routes.
6
- # Optionally filters results by keyword or route_type. Supports two modes:
6
+ # Optionally filters results by query or route_type. Supports two modes:
7
7
  #
8
8
  # Usage 1: Connected places (requires place_id)
9
9
  # - Finds places connected to a specific place via routes
10
10
  # - Returns origins/destinations that have routes with the specified place
11
11
  #
12
- # Usage 2: Keyword search (requires query, place_id optional)
13
- # - Searches all route places by keyword
14
- # - Returns all origins/destinations matching the keyword
12
+ # Usage 2: query search (requires query, place_id optional)
13
+ # - Searches all route places by query
14
+ # - Returns all origins/destinations matching the query
15
15
  #
16
16
  # Query Parameters:
17
17
  # - place_type: [String] Required. Type of route place: 'origin' or 'destination'
18
18
  # * 'origin': returns origins that have routes TO the specified place (if place_id provided)
19
19
  # * 'destination': returns destinations that have routes FROM the specified place (if place_id provided)
20
20
  # - place_id: [Integer] Optional. The place ID to find connected places for
21
- # - query: [String] Optional. Keyword to filter place names (case-insensitive)
21
+ # - query: [String] Optional. query to filter place names (case-insensitive)
22
22
  # - include: Optional comma-separated list (e.g., 'vendors,nearby_places')
23
23
  #
24
24
  # Response: Collection of places serialized with PlaceSerializer
@@ -27,15 +27,15 @@
27
27
  # - Returns empty collection if place_type is invalid
28
28
  # - If place_id provided: returns places connected to that place
29
29
  # - If place_id blank: returns all origins/destinations
30
- # - Filters results by keyword or route_type if provided
30
+ # - Filters results by query or route_type if provided
31
31
  #
32
32
  # @example Mode 1: Find destinations connected to origin place ID 123
33
33
  # GET /api/v2/storefront/route_places?place_id=123&place_type=destination
34
34
  #
35
- # @example Mode 2: Search all destination places by keyword
35
+ # @example Mode 2: Search all destination places by query
36
36
  # GET /api/v2/storefront/route_places?place_type=destination&query=Phnom
37
37
  #
38
- # @example Combined: Find origins connected to place 456, filtered by keyword
38
+ # @example Combined: Find origins connected to place 456, filtered by query
39
39
  # GET /api/v2/storefront/route_places?place_id=456&place_type=origin&query=Siem
40
40
  module Spree
41
41
  module Api
@@ -49,7 +49,7 @@ module Spree
49
49
  @collection ||= collection_finder.new(
50
50
  place_type: params[:place_type],
51
51
  place_id: params[:place_id],
52
- keyword: params[:query],
52
+ query: params[:query],
53
53
  route_type: params[:route_type]
54
54
  ).execute
55
55
  end
@@ -2,14 +2,14 @@
2
2
  #
3
3
  # @param place_type [String] Required. 'origin' or 'destination'
4
4
  # @param place_id [Integer] Optional. Filter by connected place ID
5
- # @param keyword [String] Optional. Filter by place name (case-insensitive)
5
+ # @param query [String] Optional. Filter by place name (case-insensitive)
6
6
  # @param route_type [Symbol, String] Optional. Filter by route type from associated trips (e.g., :ferry, :bus)
7
7
  #
8
8
  # @return [ActiveRecord::Relation<SpreeCmCommissioner::Place>]
9
9
  #
10
10
  # Modes:
11
11
  # - place_id only: returns connected places (origins TO or destinations FROM given place)
12
- # - keyword only: filters by name
12
+ # - query only: filters by name
13
13
  # - route_type only: filters by trip route types on those routes
14
14
  # - combinations: connected places filtered by name and/or route type
15
15
  # - neither: all origins/destinations in routes
@@ -17,17 +17,17 @@
17
17
  # @example Origins with ferry trips to place 123
18
18
  # FindWithRoute.new(place_type: 'origin', place_id: 123, route_type: :ferry).execute
19
19
  #
20
- # @example Destinations filtered by keyword and route type
21
- # FindWithRoute.new(place_type: 'destination', keyword: 'Phnom', route_type: :bus).execute
20
+ # @example Destinations filtered by query and route type
21
+ # FindWithRoute.new(place_type: 'destination', query: 'Phnom', route_type: :bus).execute
22
22
  module SpreeCmCommissioner
23
23
  module Places
24
24
  class FindWithRoute
25
- attr_reader :place_type, :place_id, :keyword, :route_type
25
+ attr_reader :place_type, :place_id, :query, :route_type
26
26
 
27
- def initialize(place_type:, place_id: nil, keyword: nil, route_type: nil)
27
+ def initialize(place_type:, place_id: nil, query: nil, route_type: nil)
28
28
  @place_type = place_type
29
29
  @place_id = place_id
30
- @keyword = keyword
30
+ @query = query
31
31
  @route_type = route_type
32
32
  end
33
33
 
@@ -36,7 +36,7 @@ module SpreeCmCommissioner
36
36
  return SpreeCmCommissioner::Place.none if place_id.present? && !SpreeCmCommissioner::Place.exists?(place_id)
37
37
 
38
38
  result = scope
39
- result = apply_keyword_filter(result) if keyword.present?
39
+ result = apply_query_filter(result) if query.present?
40
40
  result = apply_route_type_filter(result) if route_type.present?
41
41
  result
42
42
  end
@@ -57,8 +57,8 @@ module SpreeCmCommissioner
57
57
  end
58
58
  end
59
59
 
60
- def apply_keyword_filter(result)
61
- result.where('cm_places.name ILIKE ?', "%#{keyword}%")
60
+ def apply_query_filter(result)
61
+ result.where('cm_places.name ILIKE ?', "%#{query}%")
62
62
  end
63
63
 
64
64
  def apply_route_type_filter(result)
@@ -24,26 +24,22 @@
24
24
  module SpreeCmCommissioner
25
25
  module Routes
26
26
  class FindPopular
27
- def execute(route_type: nil)
28
- scope(route_type: route_type)
27
+ def execute(route_type: nil, query: nil)
28
+ scope(route_type: route_type, query: query)
29
29
  end
30
30
 
31
31
  private
32
32
 
33
- def scope(route_type: nil)
34
- result = SpreeCmCommissioner::Route
35
- .includes(:origin_place, :destination_place)
33
+ def scope(route_type:, query:)
34
+ includes_associations = %i[origin_place destination_place]
35
+ includes_associations << :trips if route_type.present?
36
+ result = SpreeCmCommissioner::Route.includes(*includes_associations)
36
37
 
37
- if route_type.present?
38
- # Filter routes that have trips with the specified route_type
39
- route_scope = SpreeCmCommissioner::Route
40
- .joins(:trips)
41
- .where(cm_trips: { route_type: route_type.to_sym })
42
- result = result.where(id: route_scope.select(:id))
43
- end
38
+ result = result.joins(:trips).where(cm_trips: { route_type: route_type.to_sym }) if route_type.present?
44
39
 
45
- result.order(Arel.sql('COALESCE(fulfilled_order_count, 0) DESC'))
46
- .order(Arel.sql('COALESCE(order_count, 0) DESC'))
40
+ result = result.where('cm_routes.route_name ILIKE ?', "%#{query}%") if query.present?
41
+
42
+ result.distinct.order(fulfilled_order_count: :desc, order_count: :desc)
47
43
  end
48
44
  end
49
45
  end
@@ -35,7 +35,7 @@ module SpreeCmCommissioner
35
35
  end
36
36
 
37
37
  def clear_inventory_cache
38
- SpreeCmCommissioner.inventory_redis_pool.with do |redis|
38
+ SpreeCmCommissioner.redis_pool.with do |redis|
39
39
  redis.del(inventory_item.redis_key)
40
40
  end
41
41
  end
@@ -1,10 +1,10 @@
1
1
  module SpreeCmCommissioner
2
2
  module Stock
3
3
  class InventoryItemsAdjusterJob < ApplicationUniqueJob
4
- def perform(options = {})
5
- variant = Spree::Variant.find(options[:variant_id])
4
+ def perform(variant_id:, quantity:)
5
+ variant = Spree::Variant.find(variant_id)
6
6
 
7
- SpreeCmCommissioner::Stock::InventoryItemsAdjuster.call(variant: variant, quantity: options[:quantity])
7
+ SpreeCmCommissioner::Stock::InventoryItemsAdjuster.call(variant: variant, quantity: quantity)
8
8
  end
9
9
  end
10
10
  end
@@ -45,8 +45,7 @@ module SpreeCmCommissioner
45
45
  'color' => 'color',
46
46
  'ticket-type' => 'string',
47
47
  'seat-type' => 'string',
48
- 'intercity-taxi' => 'string',
49
- 'rules' => 'string'
48
+ 'intercity-taxi' => 'string'
50
49
  }.freeze
51
50
 
52
51
  included do
@@ -57,7 +56,7 @@ module SpreeCmCommissioner
57
56
 
58
57
  validate :ensure_name_is_not_changed, on: :update
59
58
 
60
- before_validation :set_reserved_options_attributes, if: :reserved_option?
59
+ before_validation :set_reverved_options_attributes, if: :reserved_option?
61
60
 
62
61
  after_save :sort_date_time_option_values, if: -> { attr_type == 'date' || attr_type == 'time' }
63
62
  after_save :update_variants_metadata, if: :saved_change_to_name?
@@ -69,17 +68,6 @@ module SpreeCmCommissioner
69
68
  end
70
69
  end
71
70
 
72
- class_methods do
73
- def rules_option_type = find_by(name: 'rules')
74
-
75
- def ticket_type
76
- Spree::OptionType.find_or_create_by!(name: 'ticket-type') do |ot|
77
- ot.presentation = 'Ticket Type'
78
- ot.kind = :variant
79
- end
80
- end
81
- end
82
-
83
71
  def reserved_option?
84
72
  return name_was.in?(RESERVED_OPTIONS.keys) if name_changed?
85
73
 
@@ -90,7 +78,7 @@ module SpreeCmCommissioner
90
78
  name == 'ticket-type'
91
79
  end
92
80
 
93
- def set_reserved_options_attributes
81
+ def set_reverved_options_attributes
94
82
  self.attr_type = RESERVED_OPTIONS[name]
95
83
  self.kind = :variant
96
84
  end
@@ -143,7 +143,6 @@ module SpreeCmCommissioner
143
143
  # The payment will be reversed in vPago gem, and `Spree::Checkout::Complete` will be called, which checks `order.reload.complete?`.
144
144
  # This is critical because if the order state is complete, the payment will be marked as paid.
145
145
 
146
- unstock_inventory_from_external_system!
147
146
  reserve_blocks!
148
147
  unstock_inventory_in_redis!
149
148
 
@@ -162,7 +161,6 @@ module SpreeCmCommissioner
162
161
 
163
162
  def restock_inventory!
164
163
  ActiveRecord::Base.transaction do
165
- restock_inventory_from_external_system!
166
164
  cancel_blocks!
167
165
  restock_inventory_in_redis!
168
166
  end
@@ -13,7 +13,6 @@
13
13
  # - integer
14
14
  # - array
15
15
  # - datetime
16
- # - hash
17
16
  #
18
17
  # Example usage:
19
18
  # ```
@@ -23,7 +22,6 @@
23
22
  # store_public_metadata :completed, :boolean, default: true
24
23
  # store_public_metadata :count, :integer, default: 5
25
24
  # store_public_metadata :tags, :array, default: []
26
- # store_public_metadata :tags, :hash
27
25
  # store_private_metadata :app_token, :string, default: "XYZ"
28
26
  # store_public_metadata :scheduled_at, :datetime, default: Time.now
29
27
  # end
@@ -94,7 +92,7 @@ module SpreeCmCommissioner
94
92
  # - Return default if nil
95
93
  # - Cast to correct type
96
94
  # - Add `?` predicate for booleans
97
- def define_metadata_reader(column_name, key, type, default) # rubocop:disable Metrics/CyclomaticComplexity
95
+ def define_metadata_reader(column_name, key, type, default)
98
96
  define_method(key) do
99
97
  metadata = send(column_name) || {}
100
98
  raw_value = metadata[key.to_s]
@@ -111,8 +109,6 @@ module SpreeCmCommissioner
111
109
  Array(raw_value)
112
110
  when :datetime
113
111
  Time.zone.parse(raw_value.to_s)
114
- when :hash
115
- raw_value.is_a?(Hash) ? raw_value : {}
116
112
  else
117
113
  raw_value
118
114
  end
@@ -122,7 +118,7 @@ module SpreeCmCommissioner
122
118
  end
123
119
 
124
120
  # Validates only new assignments (raw JSON values) for type safety
125
- def define_metadata_validation(column_name, key, type) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity,Metrics/AbcSize
121
+ def define_metadata_validation(column_name, key, type) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
126
122
  case type
127
123
  when :boolean
128
124
  validates key, inclusion: { in: [true, false] }, allow_nil: true
@@ -164,14 +160,6 @@ module SpreeCmCommissioner
164
160
  errors.add(key, 'is not a valid datetime')
165
161
  end
166
162
  end
167
- when :hash
168
- validate do
169
- metadata = send(column_name) || {}
170
- raw_value = metadata[key.to_s]
171
- next if raw_value.nil?
172
-
173
- errors.add(key, 'must be a hash') unless raw_value.is_a?(Hash)
174
- end
175
163
  end
176
164
  end
177
165
  end
@@ -12,6 +12,9 @@ module SpreeCmCommissioner
12
12
  preference :brand_primary_color, :string, default: ''
13
13
  preference :redirect_target_host, :string, default: ''
14
14
  preference :redirect_excluded_paths, :string, default: ''
15
+ preference :facebook, :string, default: ''
16
+ preference :twitter, :string, default: ''
17
+ preference :instagram, :string, default: ''
15
18
  end
16
19
  end
17
20
  end
@@ -35,6 +35,12 @@ module SpreeCmCommissioner
35
35
  to: :options
36
36
  end
37
37
 
38
+ # Override variant.rb to return cached formatted options text, avoiding repeated database queries.
39
+ # Falls back to database queries & computing the format if preload data is unavailable.
40
+ def options_text
41
+ @options_text ||= public_metadata[:preload_options_text].presence || Spree::Variants::VisableOptionsPresenter.new(self).to_sentence
42
+ end
43
+
38
44
  def options
39
45
  @options ||= VariantOptions.new(self)
40
46
  end
@@ -105,7 +111,7 @@ module SpreeCmCommissioner
105
111
  # Precomputes the human-readable format (e.g., "Red, 256GB") to avoid
106
112
  # repeated formatting and association queries.
107
113
  # Example: {"color" => "red", "storage" => "256GB"} - option_type_name => option_value_name pairs
108
- self.public_metadata[:preload_options_text] = Spree::Variants::VisibleOptionsPresenter.new(self).to_sentence
114
+ self.public_metadata[:preload_options_text] = Spree::Variants::VisableOptionsPresenter.new(self).to_sentence
109
115
  end
110
116
 
111
117
  def set_options_to_public_metadata!
@@ -3,8 +3,6 @@ module SpreeCmCommissioner
3
3
  class Guest < SpreeCmCommissioner::Base # rubocop:disable Metrics/ClassLength
4
4
  include SpreeCmCommissioner::KycBitwise
5
5
  include SpreeCmCommissioner::PhoneNumberSanitizer
6
- include SpreeCmCommissioner::StoreMetadata
7
- include SpreeCmCommissioner::Integrations::IntegrationMappable
8
6
 
9
7
  delegate :kyc, to: :line_item, allow_nil: true
10
8
  delegate :allowed_upload_later?, to: :line_item, allow_nil: true
@@ -214,20 +212,9 @@ module SpreeCmCommissioner
214
212
  end
215
213
 
216
214
  def qr_data
217
- return external_qr_data if external_qr_data.present?
218
-
219
215
  token
220
216
  end
221
217
 
222
- # QR data for check-in. If external_wins? is true, use their QR data (they have their own check-in system).
223
- # Otherwise, use our system's QR data. Only applicable to models with QR support (e.g., line_item, guest).
224
- def external_qr_data
225
- return nil if line_item.nil? || !line_item.integration?
226
-
227
- mapping = external_wins_integration_mappings.first
228
- mapping.external_qr_data if mapping.present?
229
- end
230
-
231
218
  def current_age
232
219
  return nil if dob.nil?
233
220
 
@@ -56,12 +56,8 @@ module SpreeCmCommissioner
56
56
  "inventory:#{id}"
57
57
  end
58
58
 
59
- def quantity_in_redis
60
- SpreeCmCommissioner.inventory_redis_pool.with { |redis| redis.get(redis_key).to_i }
61
- end
62
-
63
59
  def adjust_quantity_in_redis(quantity)
64
- SpreeCmCommissioner.inventory_redis_pool.with do |redis|
60
+ SpreeCmCommissioner.redis_pool.with do |redis|
65
61
  # Always update Redis cache, even if it doesn't exist yet.
66
62
  # This prevents admin adjustments from being lost when cache is later initialized.
67
63
  script = <<~LUA
@@ -72,12 +72,10 @@ module SpreeCmCommissioner
72
72
  def self.include_modules(base)
73
73
  base.include Spree::Core::NumberGenerator.new(prefix: 'L')
74
74
  base.include SpreeCmCommissioner::StoreMetadata
75
- base.include SpreeCmCommissioner::LineItemIntegration
76
75
  base.include SpreeCmCommissioner::LineItemDurationable
77
76
  base.include SpreeCmCommissioner::LineItemsFilterScope
78
77
  base.include SpreeCmCommissioner::LineItemGuestsConcern
79
78
  base.include SpreeCmCommissioner::LineItemTransitable
80
- base.include SpreeCmCommissioner::Integrations::IntegrationMappable
81
79
  base.include SpreeCmCommissioner::ProductType
82
80
  base.include SpreeCmCommissioner::ProductDelegation
83
81
  base.include SpreeCmCommissioner::KycBitwise
@@ -200,21 +198,11 @@ module SpreeCmCommissioner
200
198
  end
201
199
 
202
200
  def qr_data
203
- return external_qr_data if external_qr_data.present?
204
201
  return nil if order.nil?
205
202
 
206
203
  "#{order.number}-#{order.token}-L#{id}"
207
204
  end
208
205
 
209
- # QR data for check-in. If external_wins? is true, use their QR data (they have their own check-in system).
210
- # Otherwise, use our system's QR data. Only applicable to models with QR support (e.g., line_item, guest).
211
- def external_qr_data
212
- return nil unless integration?
213
-
214
- mapping = external_wins_integration_mappings.first
215
- mapping.external_qr_data if mapping.present?
216
- end
217
-
218
206
  def generate_completion_steps
219
207
  generate_completion_steps!
220
208
  true
@@ -267,7 +255,7 @@ module SpreeCmCommissioner
267
255
  end
268
256
 
269
257
  def update_vendor_id
270
- self.vendor_id = variant&.vendor_id
258
+ self.vendor_id = variant.vendor_id
271
259
  end
272
260
 
273
261
  def subscription?
@@ -22,14 +22,6 @@ module SpreeCmCommissioner
22
22
  def base.rules_option_type
23
23
  Spree::OptionType.find_by(name: RULES_OPTION_TYPE_NAME)
24
24
  end
25
-
26
- # override
27
- def base.color
28
- Spree::OptionType.find_or_create_by!(name: 'color') do |ot|
29
- ot.presentation = 'Color'
30
- ot.kind = :variant
31
- end
32
- end
33
25
  end
34
26
 
35
27
  private
@@ -3,36 +3,6 @@ module SpreeCmCommissioner
3
3
  def self.prepended(base)
4
4
  base.include SpreeCmCommissioner::OptionValueAttrType
5
5
  base.has_many :option_value_vehicles, class_name: 'SpreeCmCommissioner::OptionValueVehicle', foreign_key: :option_value_id, dependent: :destroy
6
-
7
- base.validates :name, presence: true, uniqueness: { scope: :option_type_id, case_sensitive: -> { name_case_sensitive? } }
8
-
9
- # Ticket types: case-SENSITIVE matching (preserve external API casing)
10
- # Other types: case-INSENSITIVE storage (prevent duplicates from varying API casing; presentation keeps original)
11
- def base.find_or_create_by_name!(option_type, name)
12
- name = name.strip
13
- if option_type.ticket_type?
14
- where(option_type_id: option_type.id, name: name).first_or_create! do |ov|
15
- ov.option_type = option_type
16
- ov.name = name
17
- ov.presentation = name
18
- end
19
- else
20
- where(option_type_id: option_type.id).where('LOWER(name) = ?', name.downcase).first_or_create! do |ov|
21
- ov.option_type = option_type
22
- ov.name = name.downcase
23
- ov.presentation = name
24
- end
25
- end
26
- end
27
- end
28
-
29
- # Override Spree's name validation to make it case-sensitive only for ticket-type option values.
30
- # Spree's default is case-insensitive (false), but we enforce case-sensitivity (true) for ticket-types.
31
- # Which means ticket type "STANDARD" and "Standard" are different option values.
32
- def name_case_sensitive?
33
- return true if ticket_type?
34
-
35
- false
36
6
  end
37
7
 
38
8
  def display_icon
@@ -44,9 +14,5 @@ module SpreeCmCommissioner
44
14
  end
45
15
 
46
16
  unless Spree::OptionValue.included_modules.include?(SpreeCmCommissioner::OptionValueDecorator)
47
- # remove all name validations so we can override them in the decorator.
48
- Spree::OptionValue._validators.reject! { |key, _| key == :name }
49
- Spree::OptionValue._validate_callbacks.each { |c| c.filter.attributes.delete(:name) if c.filter.respond_to?(:attributes) }
50
-
51
17
  Spree::OptionValue.prepend SpreeCmCommissioner::OptionValueDecorator
52
18
  end
@@ -3,7 +3,6 @@ module SpreeCmCommissioner
3
3
  def self.prepended(base) # rubocop:disable Metrics/MethodLength
4
4
  base.include SpreeCmCommissioner::StoreMetadata
5
5
  base.include SpreeCmCommissioner::PhoneNumberSanitizer
6
- base.include SpreeCmCommissioner::OrderIntegration
7
6
  base.include SpreeCmCommissioner::OrderSeatable
8
7
  base.include SpreeCmCommissioner::OrderStateMachine
9
8
  base.include SpreeCmCommissioner::RouteOrderCountable
@@ -8,7 +8,6 @@ module SpreeCmCommissioner
8
8
  base.include SpreeCmCommissioner::TenantUpdatable
9
9
  base.include SpreeCmCommissioner::ServiceType
10
10
  base.include SpreeCmCommissioner::ServiceRecommendations
11
- base.include SpreeCmCommissioner::Integrations::IntegrationMappable
12
11
 
13
12
  base.has_many :variant_kind_option_types, -> { where(kind: :variant).order(:position) },
14
13
  through: :product_option_types, source: :option_type
@@ -90,7 +89,7 @@ module SpreeCmCommissioner
90
89
  request_to_book: 8
91
90
  }
92
91
 
93
- base.belongs_to :tenant, class_name: 'SpreeCmCommissioner::Tenant'
92
+ base.multi_tenant :tenant, class_name: 'SpreeCmCommissioner::Tenant'
94
93
  base.before_save :set_tenant
95
94
  end
96
95
 
@@ -143,7 +142,7 @@ module SpreeCmCommissioner
143
142
  end
144
143
 
145
144
  def set_event_id
146
- self.event_id ||= taxons.select(&:event?).first&.parent_id
145
+ self.event_id = taxons.select(&:event?).first&.parent_id
147
146
  end
148
147
 
149
148
  def update_variants_vendor_id
@@ -12,7 +12,7 @@ module SpreeCmCommissioner
12
12
  keys = inventory_items.map { |item| "inventory:#{item.id}" }
13
13
  return [] unless keys.any?
14
14
 
15
- counts = SpreeCmCommissioner.inventory_redis_pool.with { |redis| redis.mget(*keys) }
15
+ counts = SpreeCmCommissioner.redis_pool.with { |redis| redis.mget(*keys) }
16
16
  inventory_items.map.with_index do |inventory_item, i|
17
17
  ::SpreeCmCommissioner::CachedInventoryItem.new(
18
18
  inventory_key: keys[i],
@@ -32,7 +32,7 @@ module SpreeCmCommissioner
32
32
 
33
33
  # Use atomic SET NX to prevent race condition where multiple concurrent reads
34
34
  # initialize cache with stale values. Only the first thread wins.
35
- SpreeCmCommissioner.inventory_redis_pool.with do |redis|
35
+ SpreeCmCommissioner.redis_pool.with do |redis|
36
36
  redis.eval(set_nx_with_expiry_script, keys: [key], argv: [inventory_item.quantity_available, inventory_item.redis_expired_in])
37
37
  end
38
38
 
@@ -51,13 +51,13 @@ module SpreeCmCommissioner
51
51
  end
52
52
 
53
53
  def unstock(keys, quantities)
54
- SpreeCmCommissioner.inventory_redis_pool.with do |redis|
54
+ SpreeCmCommissioner.redis_pool.with do |redis|
55
55
  redis.eval(unstock_redis_script, keys: keys, argv: quantities)
56
56
  end.positive?
57
57
  end
58
58
 
59
59
  def restock(keys, quantities)
60
- SpreeCmCommissioner.inventory_redis_pool.with do |redis|
60
+ SpreeCmCommissioner.redis_pool.with do |redis|
61
61
  redis.eval(restock_redis_script, keys: keys, argv: quantities)
62
62
  end.positive?
63
63
  end
@@ -5,7 +5,6 @@ module SpreeCmCommissioner
5
5
  base.include SpreeCmCommissioner::TaxonKind
6
6
  base.include SpreeCmCommissioner::ParticipationTypeBitwise
7
7
  base.include SpreeCmCommissioner::EventMetadata
8
- base.include SpreeCmCommissioner::Integrations::IntegrationMappable
9
8
 
10
9
  base.has_many :taxon_vendors, class_name: 'SpreeCmCommissioner::TaxonVendor'
11
10
  base.has_many :vendors, through: :taxon_vendors
@@ -3,21 +3,9 @@ module SpreeCmCommissioner
3
3
  def self.prepended(base)
4
4
  base.include SpreeCmCommissioner::TaxonKind
5
5
 
6
- def base.events
7
- ActiveRecord::Base.connected_to(role: :writing) do
8
- events = Spree::Taxonomy.find_or_create_by(name: 'Events', store: Spree::Store.default)
9
- events.kind = :event
10
- events.save if events.changed?
11
- events
12
- end
13
- end
14
-
15
6
  def base.businesses
16
7
  ActiveRecord::Base.connected_to(role: :writing) do
17
- businesses = Spree::Taxonomy.find_or_create_by(name: 'Businesses', store: Spree::Store.default)
18
- businesses.kind = :category
19
- businesses.save if businesses.changed?
20
- businesses
8
+ Spree::Taxonomy.find_or_create_by(name: 'Businesses', kind: 'category', store: Spree::Store.default)
21
9
  end
22
10
  end
23
11
  end