spree_cm_commissioner 2.0.3.pre.pre4 → 2.0.3.pre.pre5

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 (202) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test_and_build_gem.yml +16 -2
  3. data/.gitignore +2 -1
  4. data/Gemfile.lock +28 -1
  5. data/Rakefile +33 -4
  6. data/app/assets/stylesheets/spree_cm_commissioner/backend/calendar.scss +8 -11
  7. data/app/controllers/spree/admin/inventory_items_controller.rb +83 -0
  8. data/app/controllers/spree/admin/stock_managements_controller.rb +63 -1
  9. data/app/controllers/spree/api/v2/operator/event_charts_controller.rb +8 -2
  10. data/app/controllers/spree/api/v2/storefront/accommodations/variants_controller.rb +42 -0
  11. data/app/controllers/spree/api/v2/storefront/accommodations_controller.rb +14 -31
  12. data/app/controllers/spree/api/v2/storefront/queue_cart/line_items_controller.rb +2 -2
  13. data/app/controllers/spree/api/v2/storefront/trip_search_controller.rb +60 -0
  14. data/app/finders/spree_cm_commissioner/accommodations/find.rb +37 -0
  15. data/app/finders/spree_cm_commissioner/accommodations/find_variant.rb +32 -0
  16. data/app/interactors/spree_cm_commissioner/ensure_correct_product_type.rb +40 -0
  17. data/app/interactors/spree_cm_commissioner/inventory_item_syncer.rb +25 -0
  18. data/app/interactors/spree_cm_commissioner/stock/inventory_item_resetter.rb +44 -0
  19. data/app/interactors/spree_cm_commissioner/stock/inventory_items_adjuster.rb +13 -0
  20. data/app/interactors/spree_cm_commissioner/stock/inventory_items_generator.rb +15 -0
  21. data/app/interactors/spree_cm_commissioner/stock/permanent_inventory_items_generator.rb +75 -0
  22. data/app/interactors/spree_cm_commissioner/stock/stock_movement_creator.rb +32 -0
  23. data/app/interactors/spree_cm_commissioner/taxi_trip_creator.rb +66 -0
  24. data/app/interactors/spree_cm_commissioner/transit/draft_order_creator.rb +119 -0
  25. data/app/interactors/spree_cm_commissioner/variant_block_updater.rb +62 -0
  26. data/app/interactors/spree_cm_commissioner/vehicle_updater.rb +41 -0
  27. data/app/jobs/spree_cm_commissioner/application_job.rb +20 -0
  28. data/app/jobs/spree_cm_commissioner/application_unique_job.rb +20 -0
  29. data/app/jobs/spree_cm_commissioner/ensure_correct_product_type_job.rb +7 -0
  30. data/app/jobs/spree_cm_commissioner/inventory_item_syncer_job.rb +7 -0
  31. data/app/jobs/spree_cm_commissioner/stock/inventory_items_adjuster_job.rb +11 -0
  32. data/app/jobs/spree_cm_commissioner/stock/inventory_items_generator_job.rb +11 -0
  33. data/app/jobs/spree_cm_commissioner/stock/permanent_inventory_items_generator_job.rb +9 -0
  34. data/app/models/concerns/spree_cm_commissioner/line_item_durationable.rb +18 -15
  35. data/app/models/concerns/spree_cm_commissioner/line_item_guests_concern.rb +29 -15
  36. data/app/models/concerns/spree_cm_commissioner/line_item_transitable.rb +89 -0
  37. data/app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb +2 -12
  38. data/app/models/concerns/spree_cm_commissioner/order_seatable.rb +44 -0
  39. data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +39 -0
  40. data/app/models/concerns/spree_cm_commissioner/product_delegation.rb +1 -3
  41. data/app/models/concerns/spree_cm_commissioner/product_type.rb +10 -0
  42. data/app/models/concerns/spree_cm_commissioner/route_type.rb +1 -1
  43. data/app/models/concerns/spree_cm_commissioner/taxon_kind.rb +1 -1
  44. data/app/models/concerns/spree_cm_commissioner/vehicle_type.rb +11 -0
  45. data/app/models/spree_cm_commissioner/address_decorator.rb +22 -2
  46. data/app/models/spree_cm_commissioner/block.rb +43 -0
  47. data/app/models/spree_cm_commissioner/guest.rb +35 -0
  48. data/app/models/spree_cm_commissioner/inventory.rb +11 -0
  49. data/app/models/spree_cm_commissioner/inventory_item.rb +69 -0
  50. data/app/models/spree_cm_commissioner/line_item_decorator.rb +47 -78
  51. data/app/models/spree_cm_commissioner/notification_taxon.rb +1 -1
  52. data/app/models/spree_cm_commissioner/option_type_decorator.rb +1 -11
  53. data/app/models/spree_cm_commissioner/order_decorator.rb +31 -1
  54. data/app/models/spree_cm_commissioner/place.rb +1 -4
  55. data/app/models/spree_cm_commissioner/price_decorator.rb +9 -0
  56. data/app/models/spree_cm_commissioner/product_decorator.rb +10 -6
  57. data/app/models/spree_cm_commissioner/redis_stock/cached_inventory_items_builder.rb +41 -0
  58. data/app/models/spree_cm_commissioner/redis_stock/inventory_updater.rb +126 -0
  59. data/app/models/spree_cm_commissioner/redis_stock/line_items_cached_inventory_items_builder.rb +36 -0
  60. data/app/models/spree_cm_commissioner/redis_stock/variant_cached_inventory_items_builder.rb +25 -0
  61. data/app/models/spree_cm_commissioner/reserved_block.rb +30 -0
  62. data/app/models/spree_cm_commissioner/saved_guest.rb +13 -0
  63. data/app/models/spree_cm_commissioner/seat_layout.rb +20 -0
  64. data/app/models/spree_cm_commissioner/seat_section.rb +16 -0
  65. data/app/models/spree_cm_commissioner/seats/blocks_canceler.rb +30 -0
  66. data/app/models/spree_cm_commissioner/seats/blocks_holder.rb +53 -0
  67. data/app/models/spree_cm_commissioner/seats/blocks_reserver.rb +49 -0
  68. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_on_hold_by_other_guest.rb +4 -0
  69. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_reserved_by_other_guest.rb +4 -0
  70. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_reserved_by_same_guest.rb +4 -0
  71. data/app/models/spree_cm_commissioner/seats/errors/unable_to_save_reserved_block_record.rb +4 -0
  72. data/app/models/spree_cm_commissioner/service_calendar.rb +0 -2
  73. data/app/models/spree_cm_commissioner/state_decorator.rb +0 -1
  74. data/app/models/spree_cm_commissioner/stock/availability_checker.rb +26 -25
  75. data/app/models/spree_cm_commissioner/stock/availability_validator_decorator.rb +2 -1
  76. data/app/models/spree_cm_commissioner/stock/line_item_availability_checker.rb +3 -3
  77. data/app/models/spree_cm_commissioner/stock/order_availability_checker.rb +44 -0
  78. data/app/models/spree_cm_commissioner/stock_item_decorator.rb +17 -0
  79. data/app/models/spree_cm_commissioner/taxon_decorator.rb +0 -1
  80. data/app/models/spree_cm_commissioner/taxonomy_decorator.rb +0 -6
  81. data/app/models/spree_cm_commissioner/trip.rb +17 -10
  82. data/app/models/spree_cm_commissioner/trip_connection.rb +5 -5
  83. data/app/models/spree_cm_commissioner/trip_stop.rb +10 -21
  84. data/app/models/spree_cm_commissioner/variant_block.rb +17 -0
  85. data/app/models/spree_cm_commissioner/variant_decorator.rb +37 -47
  86. data/app/models/spree_cm_commissioner/variant_options.rb +0 -23
  87. data/app/models/spree_cm_commissioner/vehicle.rb +11 -16
  88. data/app/models/spree_cm_commissioner/vendor_decorator.rb +11 -14
  89. data/app/models/spree_cm_commissioner/vendor_place.rb +13 -3
  90. data/app/queries/spree_cm_commissioner/trip_query.rb +110 -131
  91. data/app/request_schemas/spree_cm_commissioner/accommodation_request_schema.rb +3 -0
  92. data/app/request_schemas/spree_cm_commissioner/application_request_schema.rb +1 -1
  93. data/app/request_schemas/spree_cm_commissioner/trip_search_request_schema.rb +20 -0
  94. data/app/request_schemas/spree_cm_commissioner/variant_request_schema.rb +19 -0
  95. data/app/serializers/spree/v2/storefront/accommodation_serializer.rb +2 -0
  96. data/app/serializers/spree/v2/storefront/amenity_serializer.rb +15 -0
  97. data/app/serializers/spree/v2/storefront/line_item_serializer_decorator.rb +1 -0
  98. data/app/serializers/spree/v2/storefront/trip_query_result_serializer.rb +14 -0
  99. data/app/serializers/spree/v2/storefront/trip_result_serializer.rb +16 -0
  100. data/app/serializers/spree/v2/storefront/trip_vehicle_serializer.rb +11 -0
  101. data/app/serializers/spree/v2/storefront/trip_vendor_serializer.rb +13 -0
  102. data/app/views/spree/admin/inventory_items/show.html.erb +72 -0
  103. data/app/views/spree/admin/stock_managements/_variant_stock_items.html.erb +7 -2
  104. data/app/views/spree/admin/stock_managements/calendar.html.erb +56 -0
  105. data/app/views/spree/admin/stock_managements/index.html.erb +55 -6
  106. data/config/initializers/paper_trail.rb +1 -0
  107. data/config/initializers/spree_permitted_attributes.rb +5 -0
  108. data/config/routes.rb +24 -2
  109. data/db/migrate/20240202080634_update_counter_cache_of_vehicle_type.rb +3 -1
  110. data/db/migrate/20250122000000_move_route_type_from_vehicles_to_trips.rb +7 -0
  111. data/db/migrate/20250304293518_create_cm_inventory_items.rb +21 -0
  112. data/db/migrate/20250429094228_add_lock_version_to_cm_inventory_items.rb +5 -0
  113. data/db/migrate/20250502025848_add_index_to_spree_products.rb +5 -0
  114. data/db/migrate/20250502030001_add_product_type_to_spree_variants.rb +5 -0
  115. data/db/migrate/20250502030002_add_product_type_to_spree_line_items.rb +5 -0
  116. data/db/migrate/20250603035256_add_inventory_item_to_spree_prices.rb +7 -0
  117. data/db/migrate/20250619073724_drop_table_cm_line_item_seats.rb +5 -0
  118. data/db/migrate/20250619073812_drop_table_cm_vehicle_seats.rb +5 -0
  119. data/db/migrate/20250619073844_drop_table_cm_vehicle_types.rb +9 -0
  120. data/db/migrate/20250619073957_drop_table_cm_option_value_vehicle_types.rb +5 -0
  121. data/db/migrate/20250619082354_remove_unnecessary_fields_from_cm_places.rb +9 -0
  122. data/db/migrate/20250619082736_remove_route_type_from_spree_products.rb +5 -0
  123. data/db/migrate/20250619083055_remove_unnecessary_fields_from_spree_taxons.rb +5 -0
  124. data/db/migrate/20250620083055_remove_variant_id_from_cm_trips.rb +5 -0
  125. data/db/migrate/20250620090000_update_cm_trip_connections_to_use_cm_trips.rb +6 -0
  126. data/db/migrate/20250620090001_create_cm_seat_layouts.rb +17 -0
  127. data/db/migrate/20250620090002_create_cm_seat_sections.rb +18 -0
  128. data/db/migrate/20250620090003_create_cm_blocks.rb +18 -0
  129. data/db/migrate/20250624091005_create_cm_reserved_blocks.rb +29 -0
  130. data/db/migrate/20250626083642_create_cm_variant_blocks.rb +24 -0
  131. data/db/migrate/20250627023314_add_block_id_to_cm_guests.rb +13 -0
  132. data/db/migrate/20250716022821_add_location_reference_to_cm_vendor_places.rb +5 -0
  133. data/db/migrate/20250716031743_drop_table_cm_vendor_stops.rb +5 -0
  134. data/db/migrate/20250717023824_add_vendor_reference_to_cm_trips.rb +5 -0
  135. data/db/migrate/20250717041414_add_location_place_reference_to_cm_trip_stops.rb +5 -0
  136. data/db/migrate/20250717042539_rename_cm_trip_stops_stop_id_column_to_stop_place_id.rb +7 -0
  137. data/db/migrate/20250717042707_rename_cm_trips_origin_and_destination_to_origin_place_and_destination_place.rb +11 -0
  138. data/db/migrate/20250721080738_add_vehicle_type_to_cm_vehicles.rb +7 -0
  139. data/db/migrate/20250725092713_add_block_type_to_cm_blocks.rb +5 -0
  140. data/db/migrate/20250731062816_add_departure_time_and_arrival_time_to_trip_stop.rb +6 -0
  141. data/db/migrate/20250807033035_create_spree_cm_commissioner_saved_guests.rb +23 -0
  142. data/db/migrate/20250808054835_add_saved_guest_reference_to_cm_blocks.rb +5 -0
  143. data/docker-compose.yml +1 -1
  144. data/lib/cm_app_logger.rb +11 -4
  145. data/lib/generators/spree_cm_commissioner/install/install_generator.rb +14 -11
  146. data/lib/generators/spree_cm_commissioner/install/templates/app/javascript/{spree_cm_commissioner → spree_dashboard/spree_cm_commissioner}/utilities.js +4 -0
  147. data/lib/spree_cm_commissioner/cached_inventory_item.rb +23 -0
  148. data/lib/spree_cm_commissioner/calendar_event.rb +11 -1
  149. data/lib/spree_cm_commissioner/test_helper/factories/block_factory.rb +16 -0
  150. data/lib/spree_cm_commissioner/test_helper/factories/guest_factory.rb +10 -0
  151. data/lib/spree_cm_commissioner/test_helper/factories/homepage_section_relatable_factory.rb +1 -1
  152. data/lib/spree_cm_commissioner/test_helper/factories/inventory_item_factory.rb +9 -0
  153. data/lib/spree_cm_commissioner/test_helper/factories/line_item_factory.rb +1 -1
  154. data/lib/spree_cm_commissioner/test_helper/factories/option_type_factory.rb +6 -30
  155. data/lib/spree_cm_commissioner/test_helper/factories/order_factory.rb +0 -36
  156. data/lib/spree_cm_commissioner/test_helper/factories/product_factory.rb +18 -34
  157. data/lib/spree_cm_commissioner/test_helper/factories/reserved_block_factory.rb +27 -0
  158. data/lib/spree_cm_commissioner/test_helper/factories/seat_layout_factory.rb +11 -0
  159. data/lib/spree_cm_commissioner/test_helper/factories/seat_section_factory.rb +16 -0
  160. data/lib/spree_cm_commissioner/test_helper/factories/stock_location_factory.rb +2 -2
  161. data/lib/spree_cm_commissioner/test_helper/factories/trip_connection_factory.rb +6 -0
  162. data/lib/spree_cm_commissioner/test_helper/factories/trip_factory.rb +11 -3
  163. data/lib/spree_cm_commissioner/test_helper/factories/trip_stop_factory.rb +13 -0
  164. data/lib/spree_cm_commissioner/test_helper/factories/variant_block_factory.rb +7 -0
  165. data/lib/spree_cm_commissioner/test_helper/factories/variant_factory.rb +41 -19
  166. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_factory.rb +1 -1
  167. data/lib/spree_cm_commissioner/test_helper/factories/vendor_factory.rb +6 -1
  168. data/lib/spree_cm_commissioner/test_helper/factories/vendor_place_factory.rb +13 -1
  169. data/lib/spree_cm_commissioner/transit/leg.rb +23 -0
  170. data/lib/spree_cm_commissioner/transit/seat_selection.rb +19 -0
  171. data/lib/spree_cm_commissioner/trip_query_result.rb +16 -0
  172. data/lib/spree_cm_commissioner/trip_result.rb +12 -10
  173. data/lib/spree_cm_commissioner/version.rb +1 -1
  174. data/lib/spree_cm_commissioner.rb +37 -1
  175. data/lib/tasks/create_default_non_permanent_inventory_items.rake +16 -0
  176. data/lib/tasks/ensure_correct_product_type.rake +7 -0
  177. data/lib/tasks/generate_inventory_items.rake +7 -0
  178. data/spree_cm_commissioner.gemspec +7 -0
  179. metadata +161 -26
  180. data/app/controllers/concerns/spree_cm_commissioner/transit/taxon_bitwise.rb +0 -44
  181. data/app/finders/spree_cm_commissioner/line_items/find_by_variant_decorator.rb +0 -20
  182. data/app/models/spree_cm_commissioner/branch.rb +0 -12
  183. data/app/models/spree_cm_commissioner/line_item_seat.rb +0 -10
  184. data/app/models/spree_cm_commissioner/option_value_vehicle_type.rb +0 -8
  185. data/app/models/spree_cm_commissioner/stop.rb +0 -23
  186. data/app/models/spree_cm_commissioner/vehicle_seat.rb +0 -11
  187. data/app/models/spree_cm_commissioner/vehicle_type.rb +0 -76
  188. data/app/models/spree_cm_commissioner/vendor_stop.rb +0 -10
  189. data/app/queries/spree_cm_commissioner/trip_search_query.rb +0 -76
  190. data/app/queries/spree_cm_commissioner/variant_availability/non_permanent_stock_query.rb +0 -45
  191. data/app/queries/spree_cm_commissioner/variant_availability/permanent_stock_query.rb +0 -55
  192. data/app/queries/spree_cm_commissioner/vendor_stop_place_query.rb +0 -54
  193. data/app/services/spree_cm_commissioner/vehicle_option_value_creator.rb +0 -11
  194. data/lib/spree_cm_commissioner/test_helper/factories/branch_factory.rb +0 -12
  195. data/lib/spree_cm_commissioner/test_helper/factories/departure_time_option_type_factory.rb +0 -8
  196. data/lib/spree_cm_commissioner/test_helper/factories/duration_option_type_factory.rb +0 -8
  197. data/lib/spree_cm_commissioner/test_helper/factories/line_item_seat_factory.rb +0 -7
  198. data/lib/spree_cm_commissioner/test_helper/factories/stop_factory.rb +0 -14
  199. data/lib/spree_cm_commissioner/test_helper/factories/transit_place_factory.rb +0 -8
  200. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_option_type_factory.rb +0 -8
  201. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_type_factory.rb +0 -96
  202. data/lib/spree_cm_commissioner/trip_seat_layout_result.rb +0 -11
@@ -1,6 +1,7 @@
1
1
  module SpreeCmCommissioner
2
2
  module VariantDecorator
3
- def self.prepended(base)
3
+ def self.prepended(base) # rubocop:disable Metrics/AbcSize
4
+ base.include SpreeCmCommissioner::ProductType
4
5
  base.include SpreeCmCommissioner::ProductDelegation
5
6
  base.include SpreeCmCommissioner::VariantOptionsConcern
6
7
  base.include SpreeCmCommissioner::KycBitwise
@@ -20,24 +21,21 @@ module SpreeCmCommissioner
20
21
  base.has_many :video_on_demands, class_name: 'SpreeCmCommissioner::VideoOnDemand', dependent: :destroy
21
22
  base.has_many :complete_line_items, -> { complete }, class_name: 'Spree::LineItem'
22
23
 
24
+ base.has_many :variant_blocks, class_name: 'SpreeCmCommissioner::VariantBlock', dependent: :destroy
25
+ base.has_many :blocks, class_name: 'SpreeCmCommissioner::Block', through: :variant_blocks
26
+
23
27
  base.has_many :variant_guest_card_class, class_name: 'SpreeCmCommissioner::VariantGuestCardClass'
24
28
  base.has_many :guest_card_classes, class_name: 'SpreeCmCommissioner::GuestCardClass', through: :variant_guest_card_class
25
29
 
30
+ base.has_many :inventory_items, class_name: 'SpreeCmCommissioner::InventoryItem'
31
+
26
32
  base.scope :subscribable, -> { active.joins(:product).where(product: { subscribable: true, status: :active }) }
27
- base.has_one :trip,
28
- class_name: 'SpreeCmCommissioner::Trip'
29
- base.has_many :trip_stops, class_name: 'SpreeCmCommissioner::TripStop', dependent: :destroy, foreign_key: :trip_id
30
- base.accepts_nested_attributes_for :option_values
31
- base.after_commit :sync_trip, if: :transit?
32
- base.accepts_nested_attributes_for :trip_stops, allow_destroy: true
33
- base.after_commit :create_trip_stops, if: :transit?
34
- end
33
+ base.scope :with_permanent_stock, -> { where(product_type: base::PERMANENT_STOCK_PRODUCT_TYPES) }
34
+ base.scope :with_non_permanent_stock, -> { where.not(product_type: base::PERMANENT_STOCK_PRODUCT_TYPES) }
35
35
 
36
- def create_trip_stops
37
- return if is_master?
36
+ base.accepts_nested_attributes_for :option_values
38
37
 
39
- trip_stops.find_or_create_by(stop_type: :boarding, stop_id: options.origin)
40
- trip_stops.find_or_create_by(stop_type: :drop_off, stop_id: options.destination)
38
+ base.before_save -> { self.product_type = product.product_type }, if: -> { product_type.nil? }
41
39
  end
42
40
 
43
41
  def delivery_required?
@@ -53,8 +51,20 @@ module SpreeCmCommissioner
53
51
  super || product.discontinued?
54
52
  end
55
53
 
56
- def permanent_stock?
57
- accommodation?
54
+ def default_inventory_item_exist?
55
+ inventory_items.exists?(inventory_date: nil)
56
+ end
57
+
58
+ def create_default_non_permanent_inventory_item!(quantity_available: nil, max_capacity: nil)
59
+ return if product_type.blank? # handle in case product not exist for variant.
60
+ return unless should_track_inventory?
61
+ return if default_inventory_item_exist?
62
+
63
+ inventory_items.create!(
64
+ product_type: product_type,
65
+ quantity_available: [0, quantity_available || total_on_hand].max,
66
+ max_capacity: [0, max_capacity || total_on_hand].max
67
+ )
58
68
  end
59
69
 
60
70
  # override
@@ -72,30 +82,26 @@ module SpreeCmCommissioner
72
82
  "#{display_sku} - #{display_price}"
73
83
  end
74
84
 
75
- def transit?
76
- product.product_type == 'transit'
77
- end
78
-
79
85
  # override
80
- def in_stock?
81
- available_quantity.positive?
86
+ def in_stock?(options = {})
87
+ SpreeCmCommissioner::Stock::AvailabilityChecker.new(self, options).can_supply?
82
88
  end
83
89
 
84
- private
90
+ def price_for_date(currency:, date:)
91
+ currency = currency.upcase
85
92
 
86
- def total_purchases
87
- Spree::LineItem.complete.where(variant_id: id).sum(:quantity).to_i
93
+ prices.joins(:inventory_item)
94
+ .find_by(
95
+ currency: currency,
96
+ inventory_item: { inventory_date: date }
97
+ )
88
98
  end
89
99
 
90
- def available_quantity
91
- stock_count = stock_items.sum(&:count_on_hand)
92
- return stock_count if delivery_required?
93
-
94
- stock_count - total_purchases
95
- end
100
+ private
96
101
 
97
102
  def update_vendor_price
98
- return unless vendor.present? && product&.product_type == vendor&.primary_product_type
103
+ return unless vendor.present? && product_type == vendor&.primary_product_type
104
+ return if price.blank?
99
105
 
100
106
  vendor.update(min_price: price) if vendor.min_price.nil? || price < vendor.min_price
101
107
  vendor.update(max_price: price) if vendor.max_price.nil? || price > vendor.max_price
@@ -119,22 +125,6 @@ module SpreeCmCommissioner
119
125
  end
120
126
  end
121
127
  end
122
-
123
- def sync_trip
124
- return unless product.product_type == 'transit'
125
-
126
- trip = SpreeCmCommissioner::Trip.find_or_initialize_by(variant_id: id)
127
-
128
- trip.assign_attributes(
129
- product_id: product_id,
130
- origin_id: options.origin,
131
- destination_id: options.destination,
132
- departure_time: options.departure_time,
133
- duration: options.total_duration_in_seconds,
134
- vehicle_id: options.vehicle
135
- )
136
- trip.save
137
- end
138
128
  end
139
129
  end
140
130
 
@@ -143,28 +143,5 @@ module SpreeCmCommissioner
143
143
  def number_of_guests
144
144
  number_of_adults + number_of_kids
145
145
  end
146
-
147
- def origin
148
- @origin ||= option_value_name_for(option_type_name: 'origin')&.to_i
149
- end
150
-
151
- def destination
152
- @destination ||= option_value_name_for(option_type_name: 'destination')&.to_i
153
- end
154
-
155
- def vehicle
156
- @vehicle ||= option_value_name_for(option_type_name: 'vehicle')&.to_i
157
- end
158
-
159
- def allow_seat_selection
160
- @allow_seat_selection ||= option_value_name_for(option_type_name: 'allow-seat-selection')&.to_i
161
- end
162
-
163
- def departure_time
164
- @departure_time ||= begin
165
- time = option_value_name_for(option_type_name: 'departure-time')
166
- Time.zone.parse(time) if time.present?
167
- end
168
- end
169
146
  end
170
147
  end
@@ -1,29 +1,24 @@
1
- require_dependency 'spree_cm_commissioner'
2
-
3
1
  module SpreeCmCommissioner
4
- class Vehicle < SpreeCmCommissioner::Base
5
- include SpreeCmCommissioner::RouteType
2
+ class Vehicle < Base
3
+ include SpreeCmCommissioner::VehicleType
6
4
 
7
- belongs_to :vehicle_type, class_name: 'SpreeCmCommissioner::VehicleType'
8
- has_one :primary_photo, -> { order(position: :asc) }, class_name: 'SpreeCmCommissioner::VehiclePhoto', as: :viewable, dependent: :destroy
9
5
  belongs_to :vendor, class_name: 'Spree::Vendor'
10
6
 
11
- after_commit :create_vehicle_option_value
7
+ has_one :primary_photo, -> { order(position: :asc) }, class_name: 'SpreeCmCommissioner::VehiclePhoto', as: :viewable, dependent: :destroy
8
+ has_one :seat_layout, as: :layoutable, class_name: 'SpreeCmCommissioner::SeatLayout', dependent: :destroy
12
9
 
13
- has_many :vehicle_photo, class_name: 'SpreeCmCommissioner::VehiclePhoto', as: :viewable, dependent: :destroy
14
- has_many :vehicle_seats, class_name: 'SpreeCmCommissioner::VehicleSeat', through: :vehicle_type
10
+ has_many :vehicle_photos, class_name: 'SpreeCmCommissioner::VehiclePhoto', as: :viewable, dependent: :destroy
15
11
 
16
12
  has_many :vehicle_option_types, class_name: 'SpreeCmCommissioner::VehicleOptionType', dependent: :destroy
17
13
  has_many :option_value_vehicles, class_name: 'SpreeCmCommissioner::OptionValueVehicle', dependent: :destroy
18
-
14
+ has_many :option_values, through: :option_value_vehicles, class_name: 'Spree::OptionValue'
19
15
  validates :code, uniqueness: { scope: :vendor_id }, presence: true
20
- validates :license_plate, uniqueness: {}, allow_blank: true
16
+ validates :license_plate, uniqueness: true, allow_blank: true
21
17
 
22
- def create_vehicle_option_value
23
- SpreeCmCommissioner::VehicleOptionValueCreator.call(self)
24
- end
18
+ self.whitelisted_ransackable_attributes = %w[license_plate code vehicle_type]
25
19
 
26
- self.whitelisted_ransackable_attributes = %w[license_plate code]
27
- self.whitelisted_ransackable_associations = %w[vehicle_type]
20
+ def display_name
21
+ "#{code} (#{license_plate})"
22
+ end
28
23
  end
29
24
  end
@@ -36,21 +36,17 @@ module SpreeCmCommissioner
36
36
  base.has_many :vendor_kind_option_values,
37
37
  through: :option_value_vendors, source: :option_value
38
38
 
39
- base.has_many :branches, lambda {
40
- where(cm_vendor_places: { place_type: 0 })
41
- }, through: :vendor_places, class_name: 'SpreeCmCommissioner::VendorPlace'
42
- base.has_many :stops, -> { where(cm_vendor_places: { place_type: 1 }) }, through: :vendor_places, class_name: 'SpreeCmCommissioner::VendorPlace'
43
- base.has_many :locations, -> { where(cm_vendor_places: { place_type: 2 }) },
44
- through: :vendor_places, class_name: 'SpreeCmCommissioner::VendorPlace'
39
+ base.has_many :branches, -> { branch }, class_name: 'SpreeCmCommissioner::VendorPlace'
40
+ base.has_many :stops, -> { stop }, class_name: 'SpreeCmCommissioner::VendorPlace'
41
+ base.has_many :locations, -> { location }, class_name: 'SpreeCmCommissioner::VendorPlace'
42
+
43
+ base.has_many :branch_places, through: :branches, class_name: 'SpreeCmCommissioner::Place', source: :place
44
+ base.has_many :stop_places, through: :stops, class_name: 'SpreeCmCommissioner::Place', source: :place
45
+ base.has_many :location_places, through: :locations, class_name: 'SpreeCmCommissioner::Place', source: :place
45
46
 
46
47
  base.has_many :places,
47
48
  through: :nearby_places, source: :place, class_name: 'SpreeCmCommissioner::Place'
48
49
 
49
- base.has_many :vendor_stops, class_name: 'SpreeCmCommissioner::VendorStop', dependent: :destroy
50
- base.has_many :boarding_points, -> { where(cm_vendor_stops: { stop_type: 0 }) },
51
- through: :vendor_stops, source: :stop, class_name: 'SpreeCmCommissioner::Place'
52
- base.has_many :drop_off_points, -> { where(cm_vendor_stops: { stop_type: 1 }) },
53
- through: :vendor_stops, source: :stop, class_name: 'SpreeCmCommissioner::Place'
54
50
  base.has_many :dynamic_fields, class_name: 'SpreeCmCommissioner::DynamicField', foreign_key: :vendor_id, dependent: :destroy
55
51
 
56
52
  base.has_one :logo, as: :viewable, dependent: :destroy, class_name: 'SpreeCmCommissioner::VendorLogo'
@@ -81,12 +77,13 @@ module SpreeCmCommissioner
81
77
  base.has_many :promotion_categories, class_name: 'Spree::PromotionCategory', foreign_key: :vendor_id, dependent: :destroy
82
78
 
83
79
  base.has_many :homepage_section_relatables,
80
+ as: :relatable,
84
81
  class_name: 'SpreeCmCommissioner::HomepageSectionRelatable',
85
- dependent: :destroy, inverse_of: :relatable
82
+ dependent: :destroy,
83
+ inverse_of: :relatable
86
84
 
87
- base.has_many :vehicle_types, class_name: 'SpreeCmCommissioner::VehicleType', dependent: :destroy
88
85
  base.has_many :vehicles, class_name: 'SpreeCmCommissioner::Vehicle', dependent: :destroy
89
- # base.has_many :vehicles, through: :vehicle_types, class_name: 'SpreeCmCommissioner::Vehicle', dependent: :destroy
86
+ base.has_many :trips, class_name: 'SpreeCmCommissioner::Trip', dependent: :destroy
90
87
 
91
88
  base.validates :account_name, :account_number, presence: true, if: lambda {
92
89
  payment_qrcode.present? && Spree::Store.default.code.include?('billing')
@@ -5,15 +5,25 @@ module SpreeCmCommissioner
5
5
 
6
6
  belongs_to :vendor, class_name: 'Spree::Vendor', optional: false
7
7
  belongs_to :place, class_name: 'SpreeCmCommissioner::Place', optional: false
8
+ belongs_to :location, class_name: 'SpreeCmCommissioner::VendorPlace', optional: true
9
+
10
+ has_many :branches, -> { branch }, class_name: 'SpreeCmCommissioner::VendorPlace', foreign_key: :location_id, dependent: :restrict_with_error
11
+ has_many :stops, -> { stop }, class_name: 'SpreeCmCommissioner::VendorPlace', foreign_key: :location_id, dependent: :restrict_with_error
8
12
 
9
13
  validates :place_type, presence: true
10
14
  validates :place_id, uniqueness: { scope: %i[vendor_id place_type] }
15
+ validates :location, presence: true, if: -> { branch? || stop? }
11
16
 
12
17
  accepts_nested_attributes_for :place, allow_destroy: true
13
18
 
14
- scope :branches, -> { where(place_type: :branch) }
15
- scope :stops, -> { where(place_type: :stop) }
16
- scope :locations, -> { where(place_type: :location) }
19
+ # include place when using these delegate to avoid N+1
20
+ def display_name
21
+ place&.name
22
+ end
23
+
24
+ def self.ransackable_associations(_auth_object = nil)
25
+ ['place']
26
+ end
17
27
 
18
28
  def selected
19
29
  vendor.selected_place_references.include?(place&.reference)
@@ -1,155 +1,134 @@
1
1
  module SpreeCmCommissioner
2
2
  class TripQuery
3
- include SpreeCmCommissioner::Transit::TripHelper
3
+ attr_reader :origin_id, :destination_id, :date
4
4
 
5
- attr_reader :origin_id, :destination_id, :travel_date, :params
6
-
7
- def initialize(origin_id:, destination_id:, travel_date:, params: {})
5
+ def initialize(origin_id:, destination_id:, date:, params: {})
8
6
  @origin_id = origin_id
9
7
  @destination_id = destination_id
10
- @travel_date = travel_date
11
- @travel_date = Time.zone.now if travel_date.to_date == Time.zone.now.to_date
8
+ @date = date.to_date == Time.zone.now.to_date ? Time.zone.now : Time.zone.parse(date.to_s)
12
9
  @params = params
10
+ @page = (params[:page] || 1).to_i
11
+ @per_page = (params[:per_page] || 25).to_i
13
12
  end
14
13
 
15
14
  def call
16
- return [] if travel_date.to_date < Date.current
15
+ return Kaminari.paginate_array([]) if date.to_date < Date.current
16
+
17
+ paginated_relation = direct_trips
18
+ return Kaminari.paginate_array([]) if paginated_relation.empty?
19
+
20
+ results_array = paginated_relation.map do |trip|
21
+ result = build_trip_result(trip)
22
+ SpreeCmCommissioner::TripQueryResult.new([result])
23
+ end
17
24
 
18
- direct_results = direct_trips.map { |trip| SpreeCmCommissioner::TripQueryResult.new([trip]) }
19
- connected_results = connected_trips || []
20
- direct_results + connected_results
25
+ Kaminari.paginate_array(
26
+ results_array,
27
+ total_count: paginated_relation.total_count,
28
+ limit: @per_page,
29
+ offset: paginated_relation.offset_value
30
+ )
21
31
  end
22
32
 
23
33
  def direct_trips
24
- result = Spree::Variant
25
- .select('spree_variants.id AS variant_id,
26
- vendors.id AS vendor_id,
27
- vendors.name AS vendor_name,
28
- routes.name AS route_name,
29
- routes.short_name AS short_name,
30
- boarding.stop_id AS origin_id,
31
- drop_off.stop_id AS destination_id,
32
- boarding.stop_name AS origin,
33
- drop_off.stop_name AS destination,
34
- trips.departure_time AS departure_time,
35
- trips.duration AS duration,
36
- trips.vehicle_id AS vehicle_id'
37
- )
38
- .joins('INNER JOIN cm_trips AS trips ON trips.variant_id = spree_variants.id')
39
- .joins('INNER JOIN cm_trip_stops AS boarding ON boarding.trip_id = spree_variants.id AND boarding.stop_type = 0')
40
- .joins('INNER JOIN cm_trip_stops AS drop_off ON drop_off.trip_id = spree_variants.id AND drop_off.stop_type = 1')
41
- .joins('INNER JOIN spree_vendors AS vendors ON vendors.id = spree_variants.vendor_id')
42
- .joins('INNER JOIN spree_products AS routes ON routes.id = spree_variants.product_id')
43
- result = result.where(vendors: { id: params[:vendor_id] }) if params[:vendor_id].present?
44
- result = result.where('boarding.stop_id = ? AND drop_off.stop_id = ?', origin_id, destination_id)
45
- .where('trips.departure_time > ? AND trips.departure_time <= ?',
46
- travel_date.strftime('%H:%M:%S'),
47
- travel_date.end_of_day.strftime('%H:%M:%S')
48
- )
34
+ @inventory_sql ||= product_inventory_totals
35
+ result = SpreeCmCommissioner::Trip
36
+ .select(<<~SQL.squish)
37
+ cm_trips.*,
38
+ boarding.departure_time AS boarding_departure_time,
39
+ boarding.stop_place_id AS boarding_stop_id, boarding.stop_name AS boarding_stop_name,
40
+ drop_off.stop_name AS drop_off_stop_name, drop_off.stop_place_id AS drop_off_stop_id,
41
+ drop_off.arrival_time AS drop_off_arrival_time,
42
+ COALESCE(iv.quantity_available, 0) AS quantity_available,
43
+ COALESCE(iv.max_capacity, 0) AS max_capacity,
44
+ origin_places.name AS origin_place_name, dest_places.name AS destination_place_name,
45
+ prices.amount AS amount, prices.compare_at_amount AS compare_at_amount,
46
+ prices.currency AS currency
47
+ SQL
48
+ .includes(vendor: :logo, vehicle: :option_values)
49
+ .joins(<<~SQL.squish)
50
+ INNER JOIN cm_trip_stops AS boarding ON boarding.trip_id = cm_trips.id AND boarding.stop_type = 0
51
+ INNER JOIN cm_trip_stops AS drop_off ON drop_off.trip_id = cm_trips.id AND drop_off.stop_type = 1
52
+ INNER JOIN cm_places AS origin_places ON origin_places.id = cm_trips.origin_place_id
53
+ INNER JOIN cm_places AS dest_places ON dest_places.id = cm_trips.destination_place_id
54
+ INNER JOIN spree_products ON spree_products.id = cm_trips.product_id
55
+ INNER JOIN spree_variants AS master ON master.product_id = spree_products.id AND master.is_master = true
56
+ INNER JOIN spree_prices AS prices ON prices.variant_id = master.id AND prices.deleted_at IS NULL
57
+ SQL
58
+ .where('(boarding.location_place_id = ? OR boarding.stop_place_id = ?)
59
+ AND (drop_off.location_place_id = ? OR drop_off.stop_place_id = ?)', origin_id, origin_id, destination_id, destination_id
60
+ )
61
+ .joins("LEFT JOIN (#{@inventory_sql.to_sql}) iv ON cm_trips.product_id = iv.product_id")
49
62
 
50
- result.map do |trip|
51
- trip_result_options = {
52
- trip_id: trip[:variant_id],
53
- vendor_id: trip[:vendor_id],
54
- vendor_name: trip[:vendor_name],
55
- route_name: trip[:route_name],
56
- short_name: trip[:short_name],
57
- detail: trip[:variant_id],
58
- origin_id: trip[:origin_id],
59
- origin: trip[:origin],
60
- destination_id: trip[:destination_id],
61
- destination: trip[:destination],
62
- vehicle_id: trip[:vehicle_id],
63
- departure_time: parse_time(trip[:departure_time]),
64
- duration: trip[:duration]
65
- }
66
- SpreeCmCommissioner::TripResult.new(trip_result_options)
67
- end
63
+ result = result.where(vendor_id: @params[:vendor_id]) if @params[:vendor_id].present?
64
+ result.page(@page).per(@per_page)
65
+ end
66
+
67
+ def product_inventory_totals
68
+ Spree::Product
69
+ .select(
70
+ 'spree_products.id AS product_id,
71
+ SUM(cm_inventory_items.max_capacity) AS max_capacity,
72
+ SUM(cm_inventory_items.quantity_available) AS quantity_available'
73
+ )
74
+ .joins(variants: :inventory_items)
75
+ .where(cm_inventory_items: { inventory_date: date.to_date })
76
+ .group('spree_products.id')
68
77
  end
69
78
 
70
- def connected_trips # rubocop:disable Metrics/MethodLength
71
- result = SpreeCmCommissioner::TripConnection
72
- .joins('
73
- INNER JOIN spree_variants variant1 ON variant1.id = cm_trip_connections.from_trip_id
74
- INNER JOIN spree_variants variant2 ON variant2.id = cm_trip_connections.to_trip_id
75
- INNER JOIN spree_products AS routes1 ON routes1.id = variant1.product_id
76
- INNER JOIN spree_products AS routes2 ON routes2.id = variant2.product_id
77
- INNER JOIN cm_trips AS trip1 ON trip1.variant_id = cm_trip_connections.from_trip_id
78
- INNER JOIN cm_trips AS trip2 ON trip2.variant_id = cm_trip_connections.to_trip_id
79
- INNER JOIN cm_trip_stops trip1_origin ON trip1_origin.trip_id = variant1.id AND trip1_origin.stop_type = 0
80
- INNER JOIN cm_trip_stops trip2_origin ON trip2_origin.trip_id = variant2.id AND trip2_origin.stop_type = 0
81
- INNER JOIN cm_trip_stops trip2_destination ON trip2_destination.trip_id = variant2.id AND trip2_destination.stop_type = 1
82
- INNER JOIN spree_vendors AS vendor1 ON vendor1.id = variant1.vendor_id
83
- INNER JOIN spree_vendors AS vendor2 ON vendor2.id = variant2.vendor_id'
84
- )
85
- .select('cm_trip_connections.id AS id,
86
- trip1.variant_id AS trip1_id,
87
- trip1.origin_id AS trip1_origin_id,
88
- trip1.destination_id AS trip1_destination_id,
89
- trip1.departure_time AS trip1_departure_time,
90
- trip1.duration AS trip1_duration,
91
- routes1.short_name AS route1_short_name,
92
- routes1.name AS route1_name,
93
- trip1.vehicle_id AS trip1_vehicle,
94
- vendor1.name AS trip1_vendor_name,
95
- trip2.variant_id AS trip2_id,
96
- trip2.origin_id AS trip2_origin_id,
97
- trip2.destination_id AS trip2_destination_id,
98
- trip2.departure_time AS trip2_departure_time,
99
- trip2.duration AS trip2_duration,
100
- trip2.vehicle_id AS trip2_vehicle,
101
- routes2.short_name AS route2_short_name,
102
- routes2.name AS route2_name,
103
- trip1_origin.stop_name AS trip1_origin,
104
- trip2_origin.stop_name AS trip2_origin,
105
- trip2_destination.stop_name AS trip2_destination,
106
- vendor2.name AS trip2_vendor_name'
107
- ).where('trip1_origin.stop_id = ? AND trip2_destination.stop_id = ?', origin_id, destination_id)
108
- result = result.where('vendor1.id = ? OR vendor2.id = ?', params[:vendor_id], params[:vendor_id]) if params[:vendor_id].present?
109
- result = result.where('trip1.departure_time > ? AND trip1.departure_time <= ?', travel_date.strftime('%H:%M:%S'),
110
- travel_date.end_of_day.strftime('%H:%M:%S')
111
- ).uniq
79
+ private
112
80
 
113
- return [] if result.blank?
81
+ def cached_inventory_sql
82
+ @inventory_sql ||= product_inventory_totals
83
+ end
114
84
 
115
- build_trip_query_result(result)
85
+ def build_trip_result(trip)
86
+ vehicle = trip&.vehicle
87
+ vendor = trip&.vendor
88
+ trip_result_options = {
89
+ id: trip&.id,
90
+ departure_time: trip&.departure_time,
91
+ duration: trip&.duration,
92
+ allow_seat_selection: trip&.allow_seat_selection,
93
+ origin_place: {
94
+ id: trip&.origin_place_id,
95
+ name: trip&.origin_place_name
96
+ },
97
+ destination_place: {
98
+ id: trip&.destination_place_id,
99
+ name: trip&.destination_place_name
100
+ },
101
+ vehicle_id: trip&.vehicle_id,
102
+ vehicle: vehicle,
103
+ vendor_id: trip&.vendor_id,
104
+ vendor: vendor,
105
+ product_id: trip&.product_id,
106
+ price: trip&.amount,
107
+ currency: trip&.currency,
108
+ compare_at_amount: trip&.compare_at_amount,
109
+ boarding: build_boarding_info(trip),
110
+ drop_off: build_drop_off_info(trip),
111
+ quantity_available: trip&.quantity_available,
112
+ max_capacity: trip&.max_capacity,
113
+ amenities: (trip.vehicle&.option_values || [])
114
+ }
115
+ SpreeCmCommissioner::TripResult.new(trip_result_options)
116
116
  end
117
117
 
118
- private
118
+ def build_boarding_info(trip)
119
+ {
120
+ stop_id: trip&.boarding_stop_id,
121
+ stop_name: trip&.boarding_stop_name,
122
+ departure_time: trip&.boarding_departure_time
123
+ }
124
+ end
119
125
 
120
- def build_trip_query_result(connections)
121
- connections.map do |trip|
122
- from_trip = {
123
- trip_id: trip[:trip1_id],
124
- origin_id: trip[:trip1_origin_id],
125
- destination_id: trip[:trip1_destination_id],
126
- departure_time: parse_time(trip[:trip1_departure_time]),
127
- duration: trip[:trip1_duration],
128
- vendor_name: trip[:trip1_vendor_name],
129
- route_name: trip[:route1_name],
130
- short_name: trip[:route1_short_name],
131
- vehicle_id: trip[:trip1_vehicle],
132
- origin: trip[:trip1_origin],
133
- destination: trip[:trip2_origin]
134
- }
135
- to_trip = {
136
- trip_id: trip[:trip2_id],
137
- origin_id: trip[:trip2_origin_id],
138
- destination_id: trip[:trip2_destination_id],
139
- departure_time: parse_time(trip[:trip2_departure_time]),
140
- duration: trip[:trip2_duration],
141
- vendor_name: trip[:trip2_vendor_name],
142
- route_name: trip[:route2_name],
143
- short_name: trip[:route2_short_name],
144
- vehicle_id: trip[:trip2_vehicle],
145
- origin: trip[:trip2_origin],
146
- destination: trip[:trip2_destination]
147
- }
148
- data = [SpreeCmCommissioner::TripResult.new(from_trip),
149
- SpreeCmCommissioner::TripResult.new(to_trip)
150
- ]
151
- SpreeCmCommissioner::TripQueryResult.new(data, connection_id: trip[:id])
152
- end
126
+ def build_drop_off_info(trip)
127
+ {
128
+ stop_id: trip&.drop_off_stop_id,
129
+ stop_name: trip&.drop_off_stop_name,
130
+ arrival_time: trip&.drop_off_arrival_time
131
+ }
153
132
  end
154
133
  end
155
134
  end
@@ -3,6 +3,9 @@ module SpreeCmCommissioner
3
3
  params do
4
4
  required(:from_date).value(:date)
5
5
  required(:to_date).value(:date)
6
+ required(:province_id).value(:integer)
7
+ required(:adult).value(:integer)
8
+ required(:children).value(:integer)
6
9
  end
7
10
 
8
11
  rule(:from_date, :to_date) do
@@ -11,7 +11,7 @@ module SpreeCmCommissioner
11
11
  end
12
12
 
13
13
  def error_message
14
- errors.map(&:text).join(', ')
14
+ errors.map { |error| "#{error.path.join(', ')}: #{error.text}" }.to_sentence
15
15
  end
16
16
 
17
17
  private
@@ -0,0 +1,20 @@
1
+ module SpreeCmCommissioner
2
+ class TripSearchRequestSchema < ApplicationRequestSchema
3
+ params do
4
+ required(:origin_id).value(:integer)
5
+ required(:destination_id).value(:integer)
6
+ required(:date).value(:date)
7
+ end
8
+
9
+ rule(:date) do
10
+ key.failure(:must_be_in_future) if value < Time.zone.today
11
+ end
12
+
13
+ rule(:origin_id, :destination_id) do
14
+ origin_id = values[:origin_id]
15
+ destination_id = values[:destination_id]
16
+
17
+ key.failure(:must_be_different) if origin_id == destination_id
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ module SpreeCmCommissioner
2
+ class VariantRequestSchema < ApplicationRequestSchema
3
+ params do
4
+ required(:from_date).value(:date)
5
+ required(:to_date).value(:date)
6
+ required(:adult).value(:integer)
7
+ required(:children).value(:integer)
8
+ end
9
+
10
+ rule(:from_date, :to_date) do
11
+ from_date = values[:from_date]
12
+ to_date = values[:to_date]
13
+
14
+ key.failure(:must_be_in_future) if from_date < Time.zone.today
15
+ key.failure(:must_be_later_than_start_date) if from_date > to_date
16
+ key.failure(:stay_is_too_long) if (to_date - from_date).to_i > ENV.fetch('ACCOMMODATION_MAX_STAY_DAYS', 10).to_i
17
+ end
18
+ end
19
+ end
@@ -9,10 +9,12 @@ module Spree
9
9
 
10
10
  attributes :total_inventory, :service_availabilities
11
11
 
12
+ # Deprecated
12
13
  attribute :total_booking do |vendor|
13
14
  vendor.respond_to?(:total_booking) ? vendor.total_booking : 0
14
15
  end
15
16
 
17
+ # Deprecated
16
18
  attribute :remaining do |vendor|
17
19
  vendor.respond_to?(:remaining) ? vendor.remaining : vendor.total_inventory
18
20
  end
@@ -0,0 +1,15 @@
1
+ module Spree
2
+ module V2
3
+ module Storefront
4
+ class AmenitySerializer < BaseSerializer
5
+ set_type :amenity
6
+ attributes :name, :presentation
7
+ attribute :display_icon do |option_value|
8
+ ActionController::Base.helpers.image_url(option_value.display_icon)
9
+ rescue StandardError
10
+ nil
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -4,6 +4,7 @@ module Spree
4
4
  module LineItemSerializerDecorator
5
5
  def self.prepended(base)
6
6
  base.attributes :from_date, :to_date, :need_confirmation, :product_type, :event_status, :amount, :display_amount,
7
+ :checkin_date, :checkout_date,
7
8
  :number, :qr_data,
8
9
  :kyc, :kyc_fields, :remaining_total_guests, :number_of_guests,
9
10
  :completion_steps, :available_social_contact_platforms, :allow_anonymous_booking, :discontinue_on,