spree_cm_commissioner 2.0.3.pre.pre5 → 2.0.3.pre.pre.pre7

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 (215) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test_and_build_gem.yml +2 -16
  3. data/.gitignore +1 -2
  4. data/Gemfile.lock +4 -39
  5. data/Rakefile +4 -33
  6. data/app/assets/stylesheets/spree_cm_commissioner/backend/calendar.scss +11 -8
  7. data/app/controllers/concerns/spree_cm_commissioner/transit/taxon_bitwise.rb +44 -0
  8. data/app/controllers/spree/admin/stock_managements_controller.rb +1 -63
  9. data/app/controllers/spree/api/v2/operator/event_charts_controller.rb +2 -8
  10. data/app/controllers/spree/api/v2/storefront/accommodations_controller.rb +31 -14
  11. data/app/controllers/spree/api/v2/storefront/dynamic_fields_controller.rb +42 -0
  12. data/app/controllers/spree/api/v2/storefront/guests_controller.rb +2 -0
  13. data/app/controllers/spree/api/v2/storefront/queue_cart/line_items_controller.rb +2 -2
  14. data/app/controllers/spree_cm_commissioner/admin/products_controller_decorator.rb +14 -0
  15. data/app/finders/spree_cm_commissioner/line_items/find_by_variant_decorator.rb +20 -0
  16. data/app/interactors/spree_cm_commissioner/create_vendor.rb +11 -1
  17. data/app/jobs/spree_cm_commissioner/application_job.rb +0 -20
  18. data/app/jobs/spree_cm_commissioner/application_unique_job.rb +0 -20
  19. data/app/models/concerns/spree_cm_commissioner/line_item_durationable.rb +15 -18
  20. data/app/models/concerns/spree_cm_commissioner/line_item_guests_concern.rb +15 -29
  21. data/app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb +12 -2
  22. data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +0 -39
  23. data/app/models/concerns/spree_cm_commissioner/product_delegation.rb +3 -1
  24. data/app/models/concerns/spree_cm_commissioner/product_type.rb +0 -10
  25. data/app/models/concerns/spree_cm_commissioner/route_type.rb +1 -1
  26. data/app/models/concerns/spree_cm_commissioner/taxon_kind.rb +1 -1
  27. data/app/models/spree_cm_commissioner/address_decorator.rb +2 -22
  28. data/app/models/spree_cm_commissioner/branch.rb +12 -0
  29. data/app/models/spree_cm_commissioner/guest.rb +85 -71
  30. data/app/models/spree_cm_commissioner/guest_dynamic_field.rb +37 -27
  31. data/app/models/spree_cm_commissioner/line_item_decorator.rb +78 -47
  32. data/app/models/spree_cm_commissioner/line_item_seat.rb +10 -0
  33. data/app/models/spree_cm_commissioner/notification_taxon.rb +1 -1
  34. data/app/models/spree_cm_commissioner/option_type_decorator.rb +11 -1
  35. data/app/models/spree_cm_commissioner/option_value_vehicle_type.rb +8 -0
  36. data/app/models/spree_cm_commissioner/order_decorator.rb +1 -31
  37. data/app/models/spree_cm_commissioner/place.rb +4 -1
  38. data/app/models/spree_cm_commissioner/product_decorator.rb +35 -10
  39. data/app/models/spree_cm_commissioner/service_calendar.rb +2 -0
  40. data/app/models/spree_cm_commissioner/state_decorator.rb +1 -0
  41. data/app/models/spree_cm_commissioner/stock/availability_checker.rb +25 -26
  42. data/app/models/spree_cm_commissioner/stock/availability_validator_decorator.rb +1 -2
  43. data/app/models/spree_cm_commissioner/stock/line_item_availability_checker.rb +3 -3
  44. data/app/models/spree_cm_commissioner/stock_item_decorator.rb +0 -17
  45. data/app/models/spree_cm_commissioner/stop.rb +23 -0
  46. data/app/models/spree_cm_commissioner/taxon_decorator.rb +1 -0
  47. data/app/models/spree_cm_commissioner/taxonomy_decorator.rb +6 -0
  48. data/app/models/spree_cm_commissioner/trip.rb +10 -17
  49. data/app/models/spree_cm_commissioner/trip_connection.rb +5 -5
  50. data/app/models/spree_cm_commissioner/trip_stop.rb +21 -10
  51. data/app/models/spree_cm_commissioner/user_decorator.rb +1 -1
  52. data/app/models/spree_cm_commissioner/variant_decorator.rb +47 -37
  53. data/app/models/spree_cm_commissioner/variant_options.rb +23 -0
  54. data/app/models/spree_cm_commissioner/vehicle.rb +16 -11
  55. data/app/models/spree_cm_commissioner/vehicle_seat.rb +11 -0
  56. data/app/models/spree_cm_commissioner/vehicle_type.rb +76 -0
  57. data/app/models/spree_cm_commissioner/vendor_decorator.rb +14 -11
  58. data/app/models/spree_cm_commissioner/vendor_place.rb +3 -13
  59. data/app/models/spree_cm_commissioner/vendor_stop.rb +10 -0
  60. data/app/overrides/spree/admin/products/_form/industry_taxons.html.erb.deface +26 -0
  61. data/app/overrides/spree/admin/products/_form/taxons.html.erb.deface +26 -0
  62. data/app/queries/spree_cm_commissioner/trip_query.rb +131 -110
  63. data/app/queries/spree_cm_commissioner/trip_search_query.rb +76 -0
  64. data/app/queries/spree_cm_commissioner/variant_availability/non_permanent_stock_query.rb +45 -0
  65. data/app/queries/spree_cm_commissioner/variant_availability/permanent_stock_query.rb +55 -0
  66. data/app/queries/spree_cm_commissioner/vendor_stop_place_query.rb +54 -0
  67. data/app/request_schemas/spree_cm_commissioner/accommodation_request_schema.rb +0 -3
  68. data/app/request_schemas/spree_cm_commissioner/application_request_schema.rb +1 -1
  69. data/app/serializers/spree/v2/storefront/accommodation_serializer.rb +0 -2
  70. data/app/serializers/spree/v2/storefront/line_item_serializer_decorator.rb +0 -1
  71. data/app/serializers/spree/v2/storefront/product_serializer_decorator.rb +2 -0
  72. data/app/serializers/spree_cm_commissioner/v2/storefront/guest_serializer.rb +1 -3
  73. data/app/services/spree_cm_commissioner/vehicle_option_value_creator.rb +11 -0
  74. data/app/views/spree/admin/stock_managements/_variant_stock_items.html.erb +2 -7
  75. data/app/views/spree/admin/stock_managements/index.html.erb +6 -55
  76. data/config/initializers/spree_permitted_attributes.rb +0 -5
  77. data/config/routes.rb +3 -24
  78. data/db/migrate/20240202080634_update_counter_cache_of_vehicle_type.rb +1 -3
  79. data/db/migrate/20250812015522_remove_unique_indexes_from_cm_user_identity_providers.rb +8 -0
  80. data/db/migrate/20250812121745_add_data_fill_stage_phase_to_cm_guests.rb +5 -0
  81. data/db/migrate/20250814073854_add_call_to_action_to_spree_products.rb +5 -0
  82. data/docker-compose.yml +1 -1
  83. data/lib/cm_app_logger.rb +4 -11
  84. data/lib/generators/spree_cm_commissioner/install/install_generator.rb +11 -14
  85. data/lib/generators/spree_cm_commissioner/install/templates/app/javascript/{spree_dashboard/spree_cm_commissioner → spree_cm_commissioner}/utilities.js +0 -4
  86. data/lib/spree_cm_commissioner/calendar_event.rb +1 -11
  87. data/lib/spree_cm_commissioner/test_helper/factories/branch_factory.rb +12 -0
  88. data/lib/spree_cm_commissioner/test_helper/factories/departure_time_option_type_factory.rb +8 -0
  89. data/lib/spree_cm_commissioner/test_helper/factories/duration_option_type_factory.rb +8 -0
  90. data/lib/spree_cm_commissioner/test_helper/factories/guest_factory.rb +0 -10
  91. data/lib/spree_cm_commissioner/test_helper/factories/homepage_section_relatable_factory.rb +1 -1
  92. data/lib/spree_cm_commissioner/test_helper/factories/line_item_factory.rb +1 -1
  93. data/lib/spree_cm_commissioner/test_helper/factories/line_item_seat_factory.rb +7 -0
  94. data/lib/spree_cm_commissioner/test_helper/factories/option_type_factory.rb +30 -6
  95. data/lib/spree_cm_commissioner/test_helper/factories/order_factory.rb +36 -0
  96. data/lib/spree_cm_commissioner/test_helper/factories/product_factory.rb +34 -18
  97. data/lib/spree_cm_commissioner/test_helper/factories/stock_location_factory.rb +2 -2
  98. data/lib/spree_cm_commissioner/test_helper/factories/stop_factory.rb +14 -0
  99. data/lib/spree_cm_commissioner/test_helper/factories/transit_place_factory.rb +8 -0
  100. data/lib/spree_cm_commissioner/test_helper/factories/trip_factory.rb +3 -11
  101. data/lib/spree_cm_commissioner/test_helper/factories/variant_factory.rb +19 -41
  102. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_factory.rb +1 -1
  103. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_option_type_factory.rb +8 -0
  104. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_type_factory.rb +96 -0
  105. data/lib/spree_cm_commissioner/test_helper/factories/vendor_factory.rb +1 -6
  106. data/lib/spree_cm_commissioner/test_helper/factories/vendor_place_factory.rb +1 -13
  107. data/lib/spree_cm_commissioner/trip_query_result.rb +0 -16
  108. data/lib/spree_cm_commissioner/trip_result.rb +10 -12
  109. data/lib/spree_cm_commissioner/trip_seat_layout_result.rb +11 -0
  110. data/lib/spree_cm_commissioner/version.rb +1 -1
  111. data/lib/spree_cm_commissioner.rb +1 -37
  112. data/spree_cm_commissioner.gemspec +0 -7
  113. metadata +32 -161
  114. data/app/controllers/spree/admin/inventory_items_controller.rb +0 -83
  115. data/app/controllers/spree/api/v2/storefront/accommodations/variants_controller.rb +0 -42
  116. data/app/controllers/spree/api/v2/storefront/trip_search_controller.rb +0 -60
  117. data/app/finders/spree_cm_commissioner/accommodations/find.rb +0 -37
  118. data/app/finders/spree_cm_commissioner/accommodations/find_variant.rb +0 -32
  119. data/app/interactors/spree_cm_commissioner/ensure_correct_product_type.rb +0 -40
  120. data/app/interactors/spree_cm_commissioner/inventory_item_syncer.rb +0 -25
  121. data/app/interactors/spree_cm_commissioner/stock/inventory_item_resetter.rb +0 -44
  122. data/app/interactors/spree_cm_commissioner/stock/inventory_items_adjuster.rb +0 -13
  123. data/app/interactors/spree_cm_commissioner/stock/inventory_items_generator.rb +0 -15
  124. data/app/interactors/spree_cm_commissioner/stock/permanent_inventory_items_generator.rb +0 -75
  125. data/app/interactors/spree_cm_commissioner/stock/stock_movement_creator.rb +0 -32
  126. data/app/interactors/spree_cm_commissioner/taxi_trip_creator.rb +0 -66
  127. data/app/interactors/spree_cm_commissioner/transit/draft_order_creator.rb +0 -119
  128. data/app/interactors/spree_cm_commissioner/variant_block_updater.rb +0 -62
  129. data/app/interactors/spree_cm_commissioner/vehicle_updater.rb +0 -41
  130. data/app/jobs/spree_cm_commissioner/ensure_correct_product_type_job.rb +0 -7
  131. data/app/jobs/spree_cm_commissioner/inventory_item_syncer_job.rb +0 -7
  132. data/app/jobs/spree_cm_commissioner/stock/inventory_items_adjuster_job.rb +0 -11
  133. data/app/jobs/spree_cm_commissioner/stock/inventory_items_generator_job.rb +0 -11
  134. data/app/jobs/spree_cm_commissioner/stock/permanent_inventory_items_generator_job.rb +0 -9
  135. data/app/models/concerns/spree_cm_commissioner/line_item_transitable.rb +0 -89
  136. data/app/models/concerns/spree_cm_commissioner/order_seatable.rb +0 -44
  137. data/app/models/concerns/spree_cm_commissioner/vehicle_type.rb +0 -11
  138. data/app/models/spree_cm_commissioner/block.rb +0 -43
  139. data/app/models/spree_cm_commissioner/inventory.rb +0 -11
  140. data/app/models/spree_cm_commissioner/inventory_item.rb +0 -69
  141. data/app/models/spree_cm_commissioner/price_decorator.rb +0 -9
  142. data/app/models/spree_cm_commissioner/redis_stock/cached_inventory_items_builder.rb +0 -41
  143. data/app/models/spree_cm_commissioner/redis_stock/inventory_updater.rb +0 -126
  144. data/app/models/spree_cm_commissioner/redis_stock/line_items_cached_inventory_items_builder.rb +0 -36
  145. data/app/models/spree_cm_commissioner/redis_stock/variant_cached_inventory_items_builder.rb +0 -25
  146. data/app/models/spree_cm_commissioner/reserved_block.rb +0 -30
  147. data/app/models/spree_cm_commissioner/saved_guest.rb +0 -13
  148. data/app/models/spree_cm_commissioner/seat_layout.rb +0 -20
  149. data/app/models/spree_cm_commissioner/seat_section.rb +0 -16
  150. data/app/models/spree_cm_commissioner/seats/blocks_canceler.rb +0 -30
  151. data/app/models/spree_cm_commissioner/seats/blocks_holder.rb +0 -53
  152. data/app/models/spree_cm_commissioner/seats/blocks_reserver.rb +0 -49
  153. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_on_hold_by_other_guest.rb +0 -4
  154. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_reserved_by_other_guest.rb +0 -4
  155. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_reserved_by_same_guest.rb +0 -4
  156. data/app/models/spree_cm_commissioner/seats/errors/unable_to_save_reserved_block_record.rb +0 -4
  157. data/app/models/spree_cm_commissioner/stock/order_availability_checker.rb +0 -44
  158. data/app/models/spree_cm_commissioner/variant_block.rb +0 -17
  159. data/app/request_schemas/spree_cm_commissioner/trip_search_request_schema.rb +0 -20
  160. data/app/request_schemas/spree_cm_commissioner/variant_request_schema.rb +0 -19
  161. data/app/serializers/spree/v2/storefront/amenity_serializer.rb +0 -15
  162. data/app/serializers/spree/v2/storefront/trip_query_result_serializer.rb +0 -14
  163. data/app/serializers/spree/v2/storefront/trip_result_serializer.rb +0 -16
  164. data/app/serializers/spree/v2/storefront/trip_vehicle_serializer.rb +0 -11
  165. data/app/serializers/spree/v2/storefront/trip_vendor_serializer.rb +0 -13
  166. data/app/views/spree/admin/inventory_items/show.html.erb +0 -72
  167. data/app/views/spree/admin/stock_managements/calendar.html.erb +0 -56
  168. data/config/initializers/paper_trail.rb +0 -1
  169. data/db/migrate/20250122000000_move_route_type_from_vehicles_to_trips.rb +0 -7
  170. data/db/migrate/20250304293518_create_cm_inventory_items.rb +0 -21
  171. data/db/migrate/20250429094228_add_lock_version_to_cm_inventory_items.rb +0 -5
  172. data/db/migrate/20250502025848_add_index_to_spree_products.rb +0 -5
  173. data/db/migrate/20250502030001_add_product_type_to_spree_variants.rb +0 -5
  174. data/db/migrate/20250502030002_add_product_type_to_spree_line_items.rb +0 -5
  175. data/db/migrate/20250603035256_add_inventory_item_to_spree_prices.rb +0 -7
  176. data/db/migrate/20250619073724_drop_table_cm_line_item_seats.rb +0 -5
  177. data/db/migrate/20250619073812_drop_table_cm_vehicle_seats.rb +0 -5
  178. data/db/migrate/20250619073844_drop_table_cm_vehicle_types.rb +0 -9
  179. data/db/migrate/20250619073957_drop_table_cm_option_value_vehicle_types.rb +0 -5
  180. data/db/migrate/20250619082354_remove_unnecessary_fields_from_cm_places.rb +0 -9
  181. data/db/migrate/20250619082736_remove_route_type_from_spree_products.rb +0 -5
  182. data/db/migrate/20250619083055_remove_unnecessary_fields_from_spree_taxons.rb +0 -5
  183. data/db/migrate/20250620083055_remove_variant_id_from_cm_trips.rb +0 -5
  184. data/db/migrate/20250620090000_update_cm_trip_connections_to_use_cm_trips.rb +0 -6
  185. data/db/migrate/20250620090001_create_cm_seat_layouts.rb +0 -17
  186. data/db/migrate/20250620090002_create_cm_seat_sections.rb +0 -18
  187. data/db/migrate/20250620090003_create_cm_blocks.rb +0 -18
  188. data/db/migrate/20250624091005_create_cm_reserved_blocks.rb +0 -29
  189. data/db/migrate/20250626083642_create_cm_variant_blocks.rb +0 -24
  190. data/db/migrate/20250627023314_add_block_id_to_cm_guests.rb +0 -13
  191. data/db/migrate/20250716022821_add_location_reference_to_cm_vendor_places.rb +0 -5
  192. data/db/migrate/20250716031743_drop_table_cm_vendor_stops.rb +0 -5
  193. data/db/migrate/20250717023824_add_vendor_reference_to_cm_trips.rb +0 -5
  194. data/db/migrate/20250717041414_add_location_place_reference_to_cm_trip_stops.rb +0 -5
  195. data/db/migrate/20250717042539_rename_cm_trip_stops_stop_id_column_to_stop_place_id.rb +0 -7
  196. data/db/migrate/20250717042707_rename_cm_trips_origin_and_destination_to_origin_place_and_destination_place.rb +0 -11
  197. data/db/migrate/20250721080738_add_vehicle_type_to_cm_vehicles.rb +0 -7
  198. data/db/migrate/20250725092713_add_block_type_to_cm_blocks.rb +0 -5
  199. data/db/migrate/20250731062816_add_departure_time_and_arrival_time_to_trip_stop.rb +0 -6
  200. data/db/migrate/20250807033035_create_spree_cm_commissioner_saved_guests.rb +0 -23
  201. data/db/migrate/20250808054835_add_saved_guest_reference_to_cm_blocks.rb +0 -5
  202. data/lib/spree_cm_commissioner/cached_inventory_item.rb +0 -23
  203. data/lib/spree_cm_commissioner/test_helper/factories/block_factory.rb +0 -16
  204. data/lib/spree_cm_commissioner/test_helper/factories/inventory_item_factory.rb +0 -9
  205. data/lib/spree_cm_commissioner/test_helper/factories/reserved_block_factory.rb +0 -27
  206. data/lib/spree_cm_commissioner/test_helper/factories/seat_layout_factory.rb +0 -11
  207. data/lib/spree_cm_commissioner/test_helper/factories/seat_section_factory.rb +0 -16
  208. data/lib/spree_cm_commissioner/test_helper/factories/trip_connection_factory.rb +0 -6
  209. data/lib/spree_cm_commissioner/test_helper/factories/trip_stop_factory.rb +0 -13
  210. data/lib/spree_cm_commissioner/test_helper/factories/variant_block_factory.rb +0 -7
  211. data/lib/spree_cm_commissioner/transit/leg.rb +0 -23
  212. data/lib/spree_cm_commissioner/transit/seat_selection.rb +0 -19
  213. data/lib/tasks/create_default_non_permanent_inventory_items.rake +0 -16
  214. data/lib/tasks/ensure_correct_product_type.rake +0 -7
  215. data/lib/tasks/generate_inventory_items.rake +0 -7
@@ -4,10 +4,13 @@ module SpreeCmCommissioner
4
4
  belongs_to :dynamic_field, class_name: 'SpreeCmCommissioner::DynamicField', optional: false
5
5
  belongs_to :dynamic_field_option, class_name: 'SpreeCmCommissioner::DynamicFieldOption', optional: true
6
6
 
7
- validates :value, presence: true
8
7
  validate :validate_value_format, if: -> { value.present? && dynamic_field.present? }
9
8
  validate :validate_option_reference, if: -> { dynamic_field_option.present? }
9
+ validate :validate_phase_sequence
10
10
  validate :check_required_fields_based_on_phase
11
+ validate :reject_empty_string_for_text_fields
12
+
13
+ after_commit :sync_guest_data_fill_stage_phase
11
14
 
12
15
  private
13
16
 
@@ -15,6 +18,8 @@ module SpreeCmCommissioner
15
18
  return if dynamic_field.blank?
16
19
 
17
20
  case dynamic_field.data_type.to_s
21
+ when 'text', 'textarea'
22
+ errors.add(:value, "can't be blank") if value.is_a?(String) && value.strip == ''
18
23
  when 'number'
19
24
  errors.add(:value, 'must be a number') unless value.to_s.match?(/\A\d+\z/)
20
25
  when 'boolean'
@@ -40,44 +45,49 @@ module SpreeCmCommissioner
40
45
  errors.add(:dynamic_field_option, 'must belong to the same dynamic field')
41
46
  end
42
47
 
43
- def before_checkin_phase?
44
- guest.present? && guest.line_item.present? && guest.check_in.nil?
45
- end
48
+ def validate_phase_sequence
49
+ return if dynamic_field.blank? || guest.blank?
46
50
 
47
- def after_purchase_phase?
48
- guest.present? && guest.line_item.present? && guest.line_item.completed? && guest.check_in.nil?
51
+ case dynamic_field.data_fill_stage.to_sym
52
+ when :post_registration
53
+ errors.add(:base, 'Must complete pre_registration fields first') unless guest.pre_registration_completed?
54
+ when :during_check_in
55
+ unless guest.post_registration_completed? || !guest.post_registration_fields?
56
+ errors.add(:base, 'Must complete post_registration fields first')
57
+ end
58
+ end
49
59
  end
50
60
 
51
- def during_checkin_phase?
52
- guest.present? && guest.check_in.present?
53
- end
61
+ def field_required_in_current_phase?
62
+ return false if dynamic_field.blank? || guest.blank?
54
63
 
55
- def pre_registration_required?
56
- dynamic_field.data_fill_stage.to_sym == :pre_registration &&
64
+ case dynamic_field.data_fill_stage.to_sym
65
+ when :pre_registration, :post_registration
57
66
  guest.line_item.order.completed? && guest.check_in.blank?
67
+ when :during_check_in
68
+ guest.check_in.present?
69
+ else
70
+ false
71
+ end
58
72
  end
59
73
 
60
- def post_registration_required?
61
- dynamic_field.data_fill_stage.to_sym == :post_registration &&
62
- guest.line_item.order.completed? && guest.check_in.blank?
74
+ def check_required_fields_based_on_phase
75
+ return if dynamic_field.blank? || value.present?
76
+ return unless field_required_in_current_phase?
77
+
78
+ errors.add(:value, I18n.t("guest_dynamic_field.errors.#{dynamic_field.data_fill_stage}_required"))
63
79
  end
64
80
 
65
- def during_check_in_required?
66
- dynamic_field.data_fill_stage.to_sym == :during_check_in &&
67
- guest.check_in.present?
81
+ def sync_guest_data_fill_stage_phase
82
+ guest&.save_and_move_to_next_stage
68
83
  end
69
84
 
70
- def check_required_fields_based_on_phase
71
- return if dynamic_field.blank? || value.present?
85
+ def reject_empty_string_for_text_fields
86
+ return if dynamic_field.blank?
87
+ return unless %w[text textarea].include?(dynamic_field.data_type.to_s)
88
+ return unless value.is_a?(String)
72
89
 
73
- case dynamic_field.data_fill_stage.to_sym
74
- when :pre_registration
75
- errors.add(:value, I18n.t('guest_dynamic_field.errors.pre_registration_required')) if pre_registration_required?
76
- when :post_registration
77
- errors.add(:value, I18n.t('guest_dynamic_field.errors.post_registration_required')) if post_registration_required?
78
- when :during_check_in
79
- errors.add(:value, I18n.t('guest_dynamic_field.errors.during_check_in_required')) if during_check_in_required?
80
- end
90
+ errors.add(:value, "can't be blank") if value.strip == ''
81
91
  end
82
92
  end
83
93
  end
@@ -1,6 +1,6 @@
1
1
  module SpreeCmCommissioner
2
2
  module LineItemDecorator
3
- def self.prepended(base) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize
3
+ def self.prepended(base) # rubocop:disable Metrics/MethodLength
4
4
  include_modules(base)
5
5
 
6
6
  base.belongs_to :accepter, class_name: 'Spree::User', optional: true
@@ -10,32 +10,31 @@ module SpreeCmCommissioner
10
10
  base.has_one :google_wallet, class_name: 'SpreeCmCommissioner::GoogleWallet', through: :product
11
11
 
12
12
  base.has_many :option_types, through: :product
13
-
14
- base.has_many :inventory_items, lambda { |line_item|
15
- where(inventory_date: nil).or(where(inventory_date: line_item.date_range))
16
- }, through: :variant
17
-
18
13
  base.has_many :taxons, class_name: 'Spree::Taxon', through: :product
19
14
  base.has_many :guests, class_name: 'SpreeCmCommissioner::Guest', dependent: :destroy
20
- base.has_many :guests_with_blocks, -> { where.not(block_id: nil) }, class_name: 'SpreeCmCommissioner::Guest'
21
- base.has_many :reserved_blocks, through: :guests, class_name: 'SpreeCmCommissioner::ReservedBlock'
22
15
  base.has_many :pending_guests, pending_guests_query, class_name: 'SpreeCmCommissioner::Guest', dependent: :destroy
23
16
  base.has_many :product_completion_steps, class_name: 'SpreeCmCommissioner::ProductCompletionStep', through: :product
17
+ base.has_many :line_item_seats, class_name: 'SpreeCmCommissioner::LineItemSeat', dependent: :destroy
24
18
 
25
19
  base.before_save :update_vendor_id
20
+ base.before_save :update_quantity, if: :transit?
21
+
22
+ base.validate :validate_seats_reservation, if: :transit?
26
23
 
27
24
  base.before_create :add_due_date, if: :subscription?
28
- base.before_save -> { self.product_type = variant.product_type }, if: -> { product_type.nil? }
29
25
 
30
26
  base.validate :ensure_not_exceed_max_quantity_per_order, if: -> { variant&.max_quantity_per_order.present? }
31
27
 
32
28
  base.whitelisted_ransackable_associations |= %w[guests order]
33
29
  base.whitelisted_ransackable_attributes |= %w[number to_date from_date vendor_id]
34
30
 
35
- base.delegate :delivery_required?, :high_demand,
31
+ base.delegate :delivery_required?, :permanent_stock?, :high_demand, :transit?,
36
32
  to: :variant
33
+ base.delegate :discontinue_on, :product_type, :accommodation?, :service?, :ecommerce?, :need_confirmation,
34
+ to: :product
37
35
 
38
36
  base.accepts_nested_attributes_for :guests, allow_destroy: true
37
+ base.accepts_nested_attributes_for :line_item_seats, allow_destroy: true
39
38
 
40
39
  def base.json_api_columns
41
40
  json_api_columns = column_names.reject { |c| c.match(/_id$|id|preferences|(.*)password|(.*)token|(.*)api_key/) }
@@ -43,10 +42,6 @@ module SpreeCmCommissioner
43
42
  json_api_columns << :vendor_id
44
43
  end
45
44
 
46
- def discontinue_on
47
- variant.discontinue_on || product.discontinue_on
48
- end
49
-
50
45
  def base.search_by_qr_data!(data)
51
46
  matches = data.match(/(R\d+)-([A-Za-z0-9_\-]+)-(L\d+)/)&.captures
52
47
 
@@ -65,8 +60,6 @@ module SpreeCmCommissioner
65
60
  base.include SpreeCmCommissioner::LineItemDurationable
66
61
  base.include SpreeCmCommissioner::LineItemsFilterScope
67
62
  base.include SpreeCmCommissioner::LineItemGuestsConcern
68
- base.include SpreeCmCommissioner::LineItemTransitable
69
- base.include SpreeCmCommissioner::ProductType
70
63
  base.include SpreeCmCommissioner::ProductDelegation
71
64
  base.include SpreeCmCommissioner::KycBitwise
72
65
  end
@@ -82,39 +75,24 @@ module SpreeCmCommissioner
82
75
  }
83
76
  end
84
77
 
85
- # override to calculate price per date for permanent stock
86
- def update_price_from_modifier(currency, opts)
87
- self.currency = currency
88
-
89
- # these fields can be null during this process below.
90
- # it is needed for permanent_stock?, date_range to work.
91
- self.product_type = variant.product_type
92
- self.from_date = opts.delete(:from_date)&.to_datetime
93
- self.to_date = opts.delete(:to_date)&.to_datetime
94
-
95
- base_price = variant.price_in(currency)
96
-
97
- self.price = if permanent_stock?
98
- date_range.map do |date|
99
- selected_price = variant.price_for_date(date: date, currency: currency) || base_price
100
- (selected_price.amount || 0) + variant.price_modifier_amount_in(currency, opts.merge(date: date))
101
- end.sum
102
- else
103
- (base_price.amount || 0) + variant.price_modifier_amount_in(currency, opts)
104
- end
78
+ def reservation?
79
+ date_present? && !subscription?
105
80
  end
106
81
 
107
- # override to calculate price per date for permanent stock
108
- def update_price
109
- base_price = variant.price_in(order.currency)
110
- self.price = if permanent_stock?
111
- date_range.map do |date|
112
- selected_price = variant.price_for_date(date: date, currency: order.currency) || base_price
113
- selected_price.amount || 0
114
- end.sum
115
- else
116
- base_price.amount || 0
117
- end
82
+ # date_unit could be number of nights, or days or hours depending on usecases
83
+ # For example:
84
+ # - accomodation uses number of nights.
85
+ # - appointment uses number of hours, etc.
86
+ #
87
+ # override
88
+ def amount
89
+ base_price = price * quantity
90
+
91
+ if permanent_stock? && date_unit.present?
92
+ base_price * date_unit
93
+ else
94
+ base_price
95
+ end
118
96
  end
119
97
 
120
98
  def allowed_self_check_in?
@@ -201,6 +179,8 @@ module SpreeCmCommissioner
201
179
 
202
180
  # override
203
181
  def sufficient_stock?
182
+ return transit_sufficient_stock? if variant.product.product_type == 'transit'
183
+
204
184
  SpreeCmCommissioner::Stock::LineItemAvailabilityChecker.new(self).can_supply?(quantity)
205
185
  end
206
186
 
@@ -219,6 +199,18 @@ module SpreeCmCommissioner
219
199
  errors.add(:quantity, 'exceeded_max_quantity_per_order') if quantity > variant.max_quantity_per_order
220
200
  end
221
201
 
202
+ def transit_sufficient_stock?
203
+ return selected_seats_available? if reservation_trip.allow_seat_selection
204
+
205
+ seat_quantity_available?(reservation_trip)
206
+ end
207
+
208
+ def update_quantity
209
+ return if line_item_seats.blank?
210
+
211
+ self.quantity = line_item_seats.size
212
+ end
213
+
222
214
  def update_vendor_id
223
215
  self.vendor_id = variant.vendor_id
224
216
  end
@@ -241,6 +233,45 @@ module SpreeCmCommissioner
241
233
 
242
234
  from_date + variant.month.month + day.days
243
235
  end
236
+
237
+ def validate_seats_reservation
238
+ if reservation_trip.allow_seat_selection && !selected_seats_available?
239
+ errors.add(:base, :some_seats_are_booked, message: 'Some seats are already booked')
240
+ elsif !reservation_trip.allow_seat_selection && !seat_quantity_available?(reservation_trip)
241
+ errors.add(:quantity, :exceeded_available_quantity, message: 'exceeded available quantity')
242
+ end
243
+ end
244
+
245
+ def selected_seats_available?
246
+ selected_seat_ids = line_item_seats.map(&:seat_id)
247
+ !selected_seat_ids_occupied?(selected_seat_ids)
248
+ end
249
+
250
+ def seat_quantity_available?(trip)
251
+ booked_quantity = Spree::LineItem.joins(:order)
252
+ .where(variant_id: variant_id, date: date, spree_orders: { state: 'complete' })
253
+ .where.not(spree_line_items: { id: id })
254
+ .sum(:quantity)
255
+ remaining_quantity = trip.vehicle.number_of_seats - booked_quantity
256
+ remaining_quantity >= quantity
257
+ end
258
+
259
+ def reservation_trip
260
+ return @trip if defined? @trip
261
+
262
+ route = Spree::Variant.find_by(id: variant_id).product
263
+ @trip = route.trip
264
+ end
265
+
266
+ def selected_seat_ids_occupied?(selected_seat_ids)
267
+ # check to see if there are any selected_ids exist in the line_item_seats and belongs to completed order
268
+ SpreeCmCommissioner::LineItemSeat.joins(line_item: :order)
269
+ .where(seat_id: selected_seat_ids, date: date, variant_id: variant_id, spree_orders: { state: 'complete',
270
+ canceled_at: nil
271
+ }
272
+ )
273
+ .present?
274
+ end
244
275
  end
245
276
  end
246
277
 
@@ -0,0 +1,10 @@
1
+ require_dependency 'spree_cm_commissioner'
2
+ module SpreeCmCommissioner
3
+ class LineItemSeat < SpreeCmCommissioner::Base
4
+ belongs_to :line_item, class_name: 'Spree::LineItem'
5
+ belongs_to :seat, class_name: 'SpreeCmCommissioner::VehicleSeat'
6
+ belongs_to :variant, class_name: 'Spree::Variant'
7
+
8
+ validates :date, presence: true
9
+ end
10
+ end
@@ -1,5 +1,5 @@
1
1
  module SpreeCmCommissioner
2
- class NotificationTaxon < Base
2
+ class NotificationTaxon < SpreeCmCommissioner::Base
3
3
  belongs_to :customer_notification, class_name: 'SpreeCmCommissioner::CustomerNotification'
4
4
  belongs_to :taxon, class_name: 'Spree::Taxon'
5
5
  end
@@ -6,7 +6,7 @@ module SpreeCmCommissioner
6
6
  base.include SpreeCmCommissioner::ParameterizeName
7
7
  base.include SpreeCmCommissioner::OptionTypeAttrType
8
8
 
9
- base.enum kind: %i[variant product vendor vehicle]
9
+ base.enum kind: %i[variant product vendor vehicle_type transit]
10
10
 
11
11
  base.validates :name, presence: true
12
12
 
@@ -19,6 +19,16 @@ module SpreeCmCommissioner
19
19
  base.scope :promoted, -> { where(promoted: true) }
20
20
  base.whitelisted_ransackable_attributes = %w[kind]
21
21
 
22
+ def base.amenities
23
+ Spree::OptionType.where(kind: 'vehicle_type', name: 'amenities', presentation: 'Amenities', attr_type: 'amenity').first_or_create
24
+ end
25
+
26
+ def base.vehicle
27
+ Spree::OptionType.where(presentation: 'vehicle', attr_type: 'vehicle_id', kind: 'variant',
28
+ name: 'vehicle'
29
+ ).first_or_create
30
+ end
31
+
22
32
  def base.rules_option_type
23
33
  Spree::OptionType.find_by(name: RULES_OPTION_TYPE_NAME)
24
34
  end
@@ -0,0 +1,8 @@
1
+ require_dependency 'spree_cm_commissioner'
2
+
3
+ module SpreeCmCommissioner
4
+ class OptionValueVehicleType < ApplicationRecord
5
+ belongs_to :vehicle_type, class_name: 'SpreeCmCommissioner::VehicleType', dependent: :destroy
6
+ belongs_to :option_value, class_name: 'Spree::OptionValue', dependent: :destroy
7
+ end
8
+ end
@@ -2,7 +2,6 @@ module SpreeCmCommissioner
2
2
  module OrderDecorator
3
3
  def self.prepended(base) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize
4
4
  base.include SpreeCmCommissioner::PhoneNumberSanitizer
5
- base.include SpreeCmCommissioner::OrderSeatable
6
5
  base.include SpreeCmCommissioner::OrderStateMachine
7
6
 
8
7
  base.scope :subscription, -> { where.not(subscription_id: nil) }
@@ -43,9 +42,6 @@ module SpreeCmCommissioner
43
42
  base.has_many :vendors, through: :products, class_name: 'Spree::Vendor'
44
43
  base.has_many :taxons, through: :products, class_name: 'Spree::Taxon'
45
44
  base.has_many :guests, through: :line_items, class_name: 'SpreeCmCommissioner::Guest'
46
- base.has_many :saved_guests, -> { distinct }, through: :guests, class_name: 'SpreeCmCommissioner::SavedGuest'
47
- base.has_many :blocks, through: :guests, class_name: 'SpreeCmCommissioner::Block', source: :block
48
- base.has_many :reserved_blocks, through: :guests, class_name: 'SpreeCmCommissioner::ReservedBlock'
49
45
  base.has_many :guest_card_classes, class_name: 'SpreeCmCommissioner::GuestCardClass', through: :variants
50
46
 
51
47
  base.delegate :customer, to: :user, allow_nil: true
@@ -62,13 +58,6 @@ module SpreeCmCommissioner
62
58
  end
63
59
  end
64
60
 
65
- # override
66
- # spree use this method to check stock availability & consider whether :order can continue to next state.
67
- def insufficient_stock_lines
68
- checker = SpreeCmCommissioner::Stock::OrderAvailabilityChecker.new(self)
69
- checker.insufficient_stock_lines
70
- end
71
-
72
61
  def ticket_seller_user?
73
62
  return false if user.nil?
74
63
 
@@ -117,14 +106,7 @@ module SpreeCmCommissioner
117
106
  end
118
107
 
119
108
  def mark_as_archive
120
- blocks_canceled = begin
121
- cancel_blocks!
122
- true
123
- rescue StandardError
124
- false
125
- end
126
-
127
- update(archived_at: Time.current) if blocks_canceled
109
+ update(archived_at: Time.current)
128
110
  end
129
111
 
130
112
  # overrided
@@ -217,18 +199,6 @@ module SpreeCmCommissioner
217
199
 
218
200
  private
219
201
 
220
- def unstock_inventory_in_redis!
221
- CmAppLogger.log(label: "#{self.class.name}#unstock_inventory_in_redis!", data: { order_id: id }) do
222
- SpreeCmCommissioner::RedisStock::InventoryUpdater.new(line_item_ids).unstock!
223
- end
224
- end
225
-
226
- def restock_inventory_in_redis!
227
- CmAppLogger.log(label: "#{self.class.name}#restock_inventory_in_redis!", data: { order_id: id }) do
228
- SpreeCmCommissioner::RedisStock::InventoryUpdater.new(line_item_ids).restock!
229
- end
230
- end
231
-
232
202
  # override :spree_api
233
203
  def webhook_payload_body
234
204
  resource_serializer.new(
@@ -1,5 +1,7 @@
1
+ require_dependency 'spree_cm_commissioner'
2
+
1
3
  module SpreeCmCommissioner
2
- class Place < Base
4
+ class Place < ApplicationRecord
3
5
  acts_as_nested_set
4
6
 
5
7
  validates :reference, presence: true, if: :validate_reference?
@@ -15,6 +17,7 @@ module SpreeCmCommissioner
15
17
  has_many :products, through: :product_places
16
18
 
17
19
  has_many :children, -> { order(:lft) }, class_name: 'SpreeCmCommissioner::Place', foreign_key: :parent_id, dependent: :destroy
20
+ has_many :vendor_stops, class_name: 'SpreeCmCommissioner::VendorStop', dependent: :destroy, foreign_key: :stop_id
18
21
 
19
22
  has_many :taxon_places, class_name: 'SpreeCmCommissioner::TaxonPlace', dependent: :destroy
20
23
  has_many :taxons, through: :taxon_places
@@ -6,6 +6,7 @@ module SpreeCmCommissioner
6
6
  base.include SpreeCmCommissioner::KycBitwise
7
7
  base.include SpreeCmCommissioner::Metafield
8
8
  base.include SpreeCmCommissioner::TenantUpdatable
9
+ base.include SpreeCmCommissioner::RouteType
9
10
 
10
11
  base.has_many :variant_kind_option_types, -> { where(kind: :variant).order(:position) },
11
12
  through: :product_option_types, source: :option_type
@@ -32,7 +33,6 @@ module SpreeCmCommissioner
32
33
  base.has_one :google_wallet, class_name: 'SpreeCmCommissioner::GoogleWallet', dependent: :destroy
33
34
 
34
35
  base.has_many :complete_line_items, through: :classifications, source: :line_items
35
- base.has_many :inventory_items, through: :variants
36
36
  base.has_many :guests, through: :line_items
37
37
 
38
38
  base.has_many :product_places, class_name: 'SpreeCmCommissioner::ProductPlace', dependent: :destroy
@@ -48,6 +48,9 @@ module SpreeCmCommissioner
48
48
 
49
49
  base.belongs_to :event, class_name: 'Spree::Taxon', optional: true
50
50
 
51
+ base.has_many :industry_classifications, -> { joins(:taxon).where(spree_taxons: { kind: :industry }) }, class_name: 'Spree::Classification'
52
+ base.has_many :industry_taxons, through: :industry_classifications, source: :taxon
53
+
51
54
  base.scope :min_price, lambda { |vendor|
52
55
  joins(:prices_including_master)
53
56
  .where(vendor_id: vendor.id, product_type: vendor.primary_product_type)
@@ -64,16 +67,29 @@ module SpreeCmCommissioner
64
67
  base.before_validation :set_event_id
65
68
 
66
69
  base.validate :validate_event_taxons, if: -> { taxons.event.present? }
70
+
67
71
  base.validate :validate_product_date, if: -> { available_on.present? && discontinue_on.present? }
68
- base.validate :product_type_unchanged, on: :update
72
+
69
73
  base.validates :commission_rate, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 100 }, allow_nil: true
70
74
 
71
- base.whitelisted_ransackable_attributes = %w[description name slug discontinue_on status vendor_id short_name]
75
+ base.whitelisted_ransackable_attributes = %w[description name slug discontinue_on status vendor_id short_name route_type]
72
76
 
73
77
  base.after_update :update_variants_vendor_id, if: :saved_change_to_vendor_id?
74
78
  base.after_update :sync_event_id_to_children, if: :saved_change_to_event_id?
75
79
 
76
80
  base.enum purchasable_on: { both: 0, web: 1, app: 2 }
81
+ base.enum call_to_action: { buy_now: 0,
82
+ book_now: 1,
83
+ reserve: 2,
84
+ register: 3,
85
+ apply: 4,
86
+ get_ticket: 5,
87
+ secure_your_seat: 6,
88
+ join_the_event: 7,
89
+ request_to_book: 8
90
+ }
91
+
92
+ base.accepts_nested_attributes_for :trip, allow_destroy: true
77
93
 
78
94
  base.multi_tenant :tenant, class_name: 'SpreeCmCommissioner::Tenant'
79
95
  base.before_save :set_tenant
@@ -83,6 +99,22 @@ module SpreeCmCommissioner
83
99
  "#{Spree::Store.default.formatted_url}/tickets/#{slug}"
84
100
  end
85
101
 
102
+ def action_button
103
+ return :request_to_book if need_confirmation?
104
+ return :reserve if free?
105
+ return call_to_action.to_sym if call_to_action.present?
106
+
107
+ :buy_now
108
+ end
109
+
110
+ def free?
111
+ return false if prices_including_master.empty?
112
+
113
+ prices_including_master.all? do |master_price|
114
+ master_price.price.zero? && (master_price.compare_at_price.nil? || master_price.compare_at_price.zero?)
115
+ end
116
+ end
117
+
86
118
  def dynamic_fields_by_collection_phase
87
119
  {
88
120
  pre_registration: dynamic_fields.pre_registration.order(:position),
@@ -133,13 +165,6 @@ module SpreeCmCommissioner
133
165
 
134
166
  errors.add(:discontinue_on, 'must be after the available on date')
135
167
  end
136
-
137
- def product_type_unchanged
138
- return if product_type_was.nil?
139
- return unless product_type_changed?
140
-
141
- errors.add(:product_type, 'cannot be changed once set')
142
- end
143
168
  end
144
169
  end
145
170
 
@@ -1,3 +1,5 @@
1
+ require_dependency 'spree_cm_commissioner'
2
+
1
3
  module SpreeCmCommissioner
2
4
  class ServiceCalendar < SpreeCmCommissioner::Base
3
5
  # exception_rules = [
@@ -3,6 +3,7 @@ module SpreeCmCommissioner
3
3
  def self.prepended(base)
4
4
  base.whitelisted_ransackable_attributes |= %w[name abbr country_id]
5
5
  base.has_many :vendors, foreign_key: 'default_state_id', class_name: 'Spree::Vendor', inverse_of: :default_state, dependent: :nullify
6
+ base.has_many :stops, class_name: 'SpreeCmCommissioner::Place'
6
7
 
7
8
  def update_total_inventory
8
9
  update(total_inventory: vendors.pluck(:total_inventory).compact.sum)
@@ -1,48 +1,47 @@
1
1
  module SpreeCmCommissioner
2
2
  module Stock
3
3
  class AvailabilityChecker
4
- attr_reader :variant, :options, :error_message
4
+ attr_reader :variant, :error_message
5
5
 
6
- def initialize(variant, options = {})
6
+ def initialize(variant)
7
7
  @variant = variant
8
- @options = options
9
8
  @error_message = nil
10
9
  end
11
10
 
12
- def can_supply?(quantity = 1)
11
+ def can_supply?(quantity = 1, options = {})
13
12
  return false unless variant.available?
14
13
  return true unless variant.should_track_inventory?
15
14
  return true if variant.backorderable?
16
15
  return true if variant.need_confirmation?
17
16
 
18
- variant_available?(quantity)
19
- end
20
-
21
- def variant_available?(quantity = 1)
22
- return false if cached_inventory_items.empty?
23
-
24
- cached_inventory_items.all? do |cached_inventory_item|
25
- cached_inventory_item.active? && cached_inventory_item.quantity_available >= quantity
26
- end
27
- end
28
-
29
- def cached_inventory_items
30
- return @cached_inventory_items if defined?(@cached_inventory_items)
17
+ # when delivery required, shipment will dynamically add / remove unit from stock item.
18
+ # so we can directly check can_supply with stock items directly.
19
+ return variant.stock_items.sum(:count_on_hand) >= quantity if variant.delivery_required?
31
20
 
32
21
  if variant.permanent_stock?
33
- return [] if options[:from_date].blank? || options[:to_date].blank?
34
-
35
- dates = options[:from_date].to_date..options[:to_date].to_date
36
- @cached_inventory_items = builder_klass.new(variant_id: variant.id, dates: dates).call
37
- @cached_inventory_items = [] if @cached_inventory_items.size != dates.count
38
- @cached_inventory_items
22
+ permanent_stock_variant_available?(quantity, options)
39
23
  else
40
- @cached_inventory_items = builder_klass.new(variant_id: variant.id).call
24
+ variant_available?(quantity, options)
41
25
  end
42
26
  end
43
27
 
44
- def builder_klass
45
- ::SpreeCmCommissioner::RedisStock::VariantCachedInventoryItemsBuilder
28
+ def variant_available?(quantity = 1, options = {})
29
+ query = SpreeCmCommissioner::VariantAvailability::NonPermanentStockQuery.new(
30
+ variant: variant,
31
+ except_line_item_id: options[:except_line_item_id]
32
+ )
33
+ result = query.available?(quantity)
34
+ @error_message = query.error_message unless result
35
+ result
36
+ end
37
+
38
+ def permanent_stock_variant_available?(quantity = 1, options = {})
39
+ SpreeCmCommissioner::VariantAvailability::PermanentStockQuery.new(
40
+ variant: variant,
41
+ from_date: options[:from_date].to_date,
42
+ to_date: options[:to_date].to_date,
43
+ except_line_item_id: options[:except_line_item_id]
44
+ ).available?(quantity)
46
45
  end
47
46
  end
48
47
  end
@@ -3,8 +3,7 @@ module SpreeCmCommissioner
3
3
  module AvailabilityValidatorDecorator
4
4
  # override
5
5
  def item_available?(line_item, quantity)
6
- SpreeCmCommissioner::Stock::LineItemAvailabilityChecker.new(line_item)
7
- .can_supply?(quantity)
6
+ SpreeCmCommissioner::Stock::LineItemAvailabilityChecker.new(line_item).can_supply?(quantity)
8
7
  end
9
8
  end
10
9
  end
@@ -8,14 +8,14 @@ module SpreeCmCommissioner
8
8
  end
9
9
 
10
10
  def can_supply?(quantity)
11
- ::SpreeCmCommissioner::Stock::AvailabilityChecker.new(line_item.variant, options)
12
- .can_supply?(quantity)
11
+ AvailabilityChecker.new(line_item.variant).can_supply?(quantity, options)
13
12
  end
14
13
 
15
14
  def options
16
15
  {
17
16
  from_date: line_item.from_date,
18
- to_date: line_item.to_date
17
+ to_date: line_item.to_date,
18
+ except_line_item_id: line_item.id
19
19
  }
20
20
  end
21
21
  end