spree_cm_commissioner 1.21.0 → 2.0.1.pre.pre

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 (190) 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/organizer/invite_guests_controller.rb +1 -1
  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/factory/spree_cm_commissioner/invite_guest_claimed_telegram_message_factory.rb +84 -37
  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/pin_code_sender.rb +1 -0
  19. data/app/interactors/spree_cm_commissioner/sms.rb +1 -1
  20. data/app/interactors/spree_cm_commissioner/stock/inventory_item_resetter.rb +44 -0
  21. data/app/interactors/spree_cm_commissioner/stock/inventory_items_adjuster.rb +13 -0
  22. data/app/interactors/spree_cm_commissioner/stock/inventory_items_generator.rb +15 -0
  23. data/app/interactors/spree_cm_commissioner/stock/permanent_inventory_items_generator.rb +75 -0
  24. data/app/interactors/spree_cm_commissioner/stock/stock_movement_creator.rb +32 -0
  25. data/app/interactors/spree_cm_commissioner/user_id_token_authenticator.rb +3 -7
  26. data/app/interactors/spree_cm_commissioner/user_id_token_checker.rb +3 -11
  27. data/app/interactors/spree_cm_commissioner/user_identity_checker.rb +6 -12
  28. data/app/interactors/spree_cm_commissioner/user_registration_with_id_token.rb +1 -7
  29. data/app/jobs/spree_cm_commissioner/application_job.rb +20 -0
  30. data/app/jobs/spree_cm_commissioner/application_unique_job.rb +20 -0
  31. data/app/jobs/spree_cm_commissioner/ensure_correct_product_type_job.rb +7 -0
  32. data/app/jobs/spree_cm_commissioner/inventory_item_syncer_job.rb +7 -0
  33. data/app/jobs/spree_cm_commissioner/sms_pin_code_job.rb +1 -1
  34. data/app/jobs/spree_cm_commissioner/stock/inventory_items_adjuster_job.rb +11 -0
  35. data/app/jobs/spree_cm_commissioner/stock/inventory_items_generator_job.rb +11 -0
  36. data/app/jobs/spree_cm_commissioner/stock/permanent_inventory_items_generator_job.rb +9 -0
  37. data/app/models/concerns/spree_cm_commissioner/line_item_durationable.rb +9 -15
  38. data/app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb +1 -12
  39. data/app/models/concerns/spree_cm_commissioner/order_seatable.rb +44 -0
  40. data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +39 -0
  41. data/app/models/concerns/spree_cm_commissioner/product_delegation.rb +1 -3
  42. data/app/models/concerns/spree_cm_commissioner/product_type.rb +10 -0
  43. data/app/models/concerns/spree_cm_commissioner/taxon_kind.rb +1 -1
  44. data/app/models/spree_cm_commissioner/block.rb +23 -0
  45. data/app/models/spree_cm_commissioner/guest.rb +18 -0
  46. data/app/models/spree_cm_commissioner/inventory.rb +11 -0
  47. data/app/models/spree_cm_commissioner/inventory_item.rb +69 -0
  48. data/app/models/spree_cm_commissioner/line_item_decorator.rb +46 -78
  49. data/app/models/spree_cm_commissioner/notification_taxon.rb +1 -1
  50. data/app/models/spree_cm_commissioner/option_type_decorator.rb +1 -11
  51. data/app/models/spree_cm_commissioner/order_decorator.rb +30 -1
  52. data/app/models/spree_cm_commissioner/place.rb +1 -4
  53. data/app/models/spree_cm_commissioner/price_decorator.rb +9 -0
  54. data/app/models/spree_cm_commissioner/product_decorator.rb +10 -6
  55. data/app/models/spree_cm_commissioner/redis_stock/cached_inventory_items_builder.rb +41 -0
  56. data/app/models/spree_cm_commissioner/redis_stock/inventory_updater.rb +126 -0
  57. data/app/models/spree_cm_commissioner/redis_stock/line_items_cached_inventory_items_builder.rb +36 -0
  58. data/app/models/spree_cm_commissioner/redis_stock/variant_cached_inventory_items_builder.rb +25 -0
  59. data/app/models/spree_cm_commissioner/reserved_block.rb +30 -0
  60. data/app/models/spree_cm_commissioner/seat_layout.rb +20 -0
  61. data/app/models/spree_cm_commissioner/seat_section.rb +16 -0
  62. data/app/models/spree_cm_commissioner/seats/blocks_canceler.rb +30 -0
  63. data/app/models/spree_cm_commissioner/seats/blocks_holder.rb +53 -0
  64. data/app/models/spree_cm_commissioner/seats/blocks_reserver.rb +49 -0
  65. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_on_hold_by_other_guest.rb +4 -0
  66. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_reserved_by_other_guest.rb +4 -0
  67. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_reserved_by_same_guest.rb +4 -0
  68. data/app/models/spree_cm_commissioner/seats/errors/unable_to_save_reserved_block_record.rb +4 -0
  69. data/app/models/spree_cm_commissioner/service_calendar.rb +0 -2
  70. data/app/models/spree_cm_commissioner/state_decorator.rb +0 -1
  71. data/app/models/spree_cm_commissioner/stock/availability_checker.rb +26 -25
  72. data/app/models/spree_cm_commissioner/stock/availability_validator_decorator.rb +2 -1
  73. data/app/models/spree_cm_commissioner/stock/line_item_availability_checker.rb +3 -3
  74. data/app/models/spree_cm_commissioner/stock/order_availability_checker.rb +44 -0
  75. data/app/models/spree_cm_commissioner/stock_item_decorator.rb +17 -0
  76. data/app/models/spree_cm_commissioner/taxon_decorator.rb +0 -1
  77. data/app/models/spree_cm_commissioner/taxonomy_decorator.rb +0 -6
  78. data/app/models/spree_cm_commissioner/trip.rb +8 -10
  79. data/app/models/spree_cm_commissioner/trip_connection.rb +5 -5
  80. data/app/models/spree_cm_commissioner/trip_stop.rb +6 -25
  81. data/app/models/spree_cm_commissioner/user_identity_provider.rb +4 -26
  82. data/app/models/spree_cm_commissioner/variant_block.rb +9 -0
  83. data/app/models/spree_cm_commissioner/variant_decorator.rb +37 -47
  84. data/app/models/spree_cm_commissioner/variant_options.rb +0 -23
  85. data/app/models/spree_cm_commissioner/vehicle.rb +9 -14
  86. data/app/models/spree_cm_commissioner/vendor_decorator.rb +11 -14
  87. data/app/models/spree_cm_commissioner/vendor_place.rb +9 -3
  88. data/app/queries/spree_cm_commissioner/trip_query.rb +70 -44
  89. data/app/request_schemas/spree_cm_commissioner/accommodation_request_schema.rb +3 -0
  90. data/app/request_schemas/spree_cm_commissioner/application_request_schema.rb +1 -1
  91. data/app/request_schemas/spree_cm_commissioner/variant_request_schema.rb +19 -0
  92. data/app/serializers/spree/v2/storefront/accommodation_serializer.rb +2 -0
  93. data/app/serializers/spree/v2/storefront/line_item_serializer_decorator.rb +1 -0
  94. data/app/serializers/spree/v2/tenant/user_serializer.rb +0 -1
  95. data/app/services/spree_cm_commissioner/user_authenticator.rb +1 -1
  96. data/app/views/spree/admin/inventory_items/show.html.erb +72 -0
  97. data/app/views/spree/admin/stock_managements/_variant_stock_items.html.erb +7 -2
  98. data/app/views/spree/admin/stock_managements/calendar.html.erb +56 -0
  99. data/app/views/spree/admin/stock_managements/index.html.erb +55 -6
  100. data/config/initializers/paper_trail.rb +1 -0
  101. data/config/initializers/spree_permitted_attributes.rb +5 -0
  102. data/config/routes.rb +21 -2
  103. data/db/migrate/20240202080634_update_counter_cache_of_vehicle_type.rb +3 -1
  104. data/db/migrate/20250304293518_create_cm_inventory_items.rb +21 -0
  105. data/db/migrate/20250429094228_add_lock_version_to_cm_inventory_items.rb +5 -0
  106. data/db/migrate/20250502025848_add_index_to_spree_products.rb +5 -0
  107. data/db/migrate/20250502030001_add_product_type_to_spree_variants.rb +5 -0
  108. data/db/migrate/20250502030002_add_product_type_to_spree_line_items.rb +5 -0
  109. data/db/migrate/20250603035256_add_inventory_item_to_spree_prices.rb +7 -0
  110. data/db/migrate/20250619073724_drop_table_cm_line_item_seats.rb +5 -0
  111. data/db/migrate/20250619073812_drop_table_cm_vehicle_seats.rb +5 -0
  112. data/db/migrate/20250619073844_drop_table_cm_vehicle_types.rb +9 -0
  113. data/db/migrate/20250619073957_drop_table_cm_option_value_vehicle_types.rb +5 -0
  114. data/db/migrate/20250619082354_remove_unnecessary_fields_from_cm_places.rb +9 -0
  115. data/db/migrate/20250619082736_remove_route_type_from_spree_products.rb +5 -0
  116. data/db/migrate/20250619083055_remove_unnecessary_fields_from_spree_taxons.rb +5 -0
  117. data/db/migrate/20250620083055_remove_variant_id_from_cm_trips.rb +5 -0
  118. data/db/migrate/20250620090000_update_cm_trip_connections_to_use_cm_trips.rb +6 -0
  119. data/db/migrate/20250620090001_create_cm_seat_layouts.rb +17 -0
  120. data/db/migrate/20250620090002_create_cm_seat_sections.rb +18 -0
  121. data/db/migrate/20250620090003_create_cm_blocks.rb +18 -0
  122. data/db/migrate/20250624091005_create_cm_reserved_blocks.rb +29 -0
  123. data/db/migrate/20250626083642_create_cm_variant_blocks.rb +24 -0
  124. data/db/migrate/20250627023314_add_block_id_to_cm_guests.rb +13 -0
  125. data/db/migrate/20250716022821_add_location_reference_to_cm_vendor_places.rb +5 -0
  126. data/db/migrate/20250716031743_drop_table_cm_vendor_stops.rb +5 -0
  127. data/db/migrate/20250717023824_add_vendor_reference_to_cm_trips.rb +5 -0
  128. data/db/migrate/20250717041414_add_location_place_reference_to_cm_trip_stops.rb +5 -0
  129. data/db/migrate/20250717042539_rename_cm_trip_stops_stop_id_column_to_stop_place_id.rb +7 -0
  130. data/db/migrate/20250717042707_rename_cm_trips_origin_and_destination_to_origin_place_and_destination_place.rb +11 -0
  131. data/docker-compose.yml +1 -1
  132. data/lib/cm_app_logger.rb +11 -4
  133. data/lib/generators/spree_cm_commissioner/install/install_generator.rb +14 -11
  134. data/lib/generators/spree_cm_commissioner/install/templates/app/javascript/{spree_cm_commissioner → spree_dashboard/spree_cm_commissioner}/utilities.js +4 -0
  135. data/lib/spree_cm_commissioner/cached_inventory_item.rb +23 -0
  136. data/lib/spree_cm_commissioner/calendar_event.rb +11 -1
  137. data/lib/spree_cm_commissioner/test_helper/factories/block_factory.rb +15 -0
  138. data/lib/spree_cm_commissioner/test_helper/factories/guest_factory.rb +10 -0
  139. data/lib/spree_cm_commissioner/test_helper/factories/homepage_section_relatable_factory.rb +1 -1
  140. data/lib/spree_cm_commissioner/test_helper/factories/inventory_item_factory.rb +9 -0
  141. data/lib/spree_cm_commissioner/test_helper/factories/line_item_factory.rb +1 -1
  142. data/lib/spree_cm_commissioner/test_helper/factories/option_type_factory.rb +6 -30
  143. data/lib/spree_cm_commissioner/test_helper/factories/order_factory.rb +0 -36
  144. data/lib/spree_cm_commissioner/test_helper/factories/product_factory.rb +18 -34
  145. data/lib/spree_cm_commissioner/test_helper/factories/reserved_block_factory.rb +27 -0
  146. data/lib/spree_cm_commissioner/test_helper/factories/seat_layout_factory.rb +11 -0
  147. data/lib/spree_cm_commissioner/test_helper/factories/seat_section_factory.rb +16 -0
  148. data/lib/spree_cm_commissioner/test_helper/factories/stock_location_factory.rb +2 -2
  149. data/lib/spree_cm_commissioner/test_helper/factories/trip_connection_factory.rb +6 -0
  150. data/lib/spree_cm_commissioner/test_helper/factories/trip_factory.rb +11 -3
  151. data/lib/spree_cm_commissioner/test_helper/factories/trip_stop_factory.rb +10 -0
  152. data/lib/spree_cm_commissioner/test_helper/factories/user_identity_provider_factory.rb +1 -1
  153. data/lib/spree_cm_commissioner/test_helper/factories/variant_block_factory.rb +7 -0
  154. data/lib/spree_cm_commissioner/test_helper/factories/variant_factory.rb +41 -19
  155. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_factory.rb +1 -1
  156. data/lib/spree_cm_commissioner/test_helper/factories/vendor_factory.rb +6 -1
  157. data/lib/spree_cm_commissioner/test_helper/factories/vendor_place_factory.rb +13 -1
  158. data/lib/spree_cm_commissioner/trip_query_result.rb +8 -0
  159. data/lib/spree_cm_commissioner/trip_result.rb +5 -3
  160. data/lib/spree_cm_commissioner/version.rb +1 -1
  161. data/lib/spree_cm_commissioner.rb +35 -1
  162. data/lib/tasks/create_default_non_permanent_inventory_items.rake +16 -0
  163. data/lib/tasks/ensure_correct_product_type.rake +7 -0
  164. data/lib/tasks/generate_inventory_items.rake +7 -0
  165. data/spree_cm_commissioner.gemspec +7 -0
  166. metadata +140 -28
  167. data/app/controllers/concerns/spree_cm_commissioner/transit/taxon_bitwise.rb +0 -44
  168. data/app/finders/spree_cm_commissioner/line_items/find_by_variant_decorator.rb +0 -20
  169. data/app/models/spree_cm_commissioner/branch.rb +0 -12
  170. data/app/models/spree_cm_commissioner/line_item_seat.rb +0 -10
  171. data/app/models/spree_cm_commissioner/option_value_vehicle_type.rb +0 -8
  172. data/app/models/spree_cm_commissioner/stop.rb +0 -23
  173. data/app/models/spree_cm_commissioner/vehicle_seat.rb +0 -11
  174. data/app/models/spree_cm_commissioner/vehicle_type.rb +0 -76
  175. data/app/models/spree_cm_commissioner/vendor_stop.rb +0 -10
  176. data/app/queries/spree_cm_commissioner/trip_search_query.rb +0 -76
  177. data/app/queries/spree_cm_commissioner/variant_availability/non_permanent_stock_query.rb +0 -45
  178. data/app/queries/spree_cm_commissioner/variant_availability/permanent_stock_query.rb +0 -55
  179. data/app/queries/spree_cm_commissioner/vendor_stop_place_query.rb +0 -54
  180. data/app/services/spree_cm_commissioner/vehicle_option_value_creator.rb +0 -11
  181. data/db/migrate/20250715103333_remove_indexes_from_cm_user_identity_providers.rb +0 -13
  182. data/lib/spree_cm_commissioner/test_helper/factories/branch_factory.rb +0 -12
  183. data/lib/spree_cm_commissioner/test_helper/factories/departure_time_option_type_factory.rb +0 -8
  184. data/lib/spree_cm_commissioner/test_helper/factories/duration_option_type_factory.rb +0 -8
  185. data/lib/spree_cm_commissioner/test_helper/factories/line_item_seat_factory.rb +0 -7
  186. data/lib/spree_cm_commissioner/test_helper/factories/stop_factory.rb +0 -14
  187. data/lib/spree_cm_commissioner/test_helper/factories/transit_place_factory.rb +0 -8
  188. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_option_type_factory.rb +0 -8
  189. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_type_factory.rb +0 -96
  190. data/lib/spree_cm_commissioner/trip_seat_layout_result.rb +0 -11
@@ -2,54 +2,57 @@ module SpreeCmCommissioner
2
2
  class TripQuery
3
3
  include SpreeCmCommissioner::Transit::TripHelper
4
4
 
5
- attr_reader :origin_id, :destination_id, :travel_date, :params
5
+ attr_reader :origin_id, :destination_id, :date, :params
6
6
 
7
- def initialize(origin_id:, destination_id:, travel_date:, params: {})
7
+ def initialize(origin_id:, destination_id:, date:, params: {})
8
8
  @origin_id = origin_id
9
9
  @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
10
+ @date = date.to_date == Time.zone.now.to_date ? Time.zone.now : Time.zone.parse(date.to_s)
12
11
  @params = params
13
12
  end
14
13
 
15
14
  def call
16
- return [] if travel_date.to_date < Date.current
15
+ return [] if date.to_date < Date.current
17
16
 
18
17
  direct_results = direct_trips.map { |trip| SpreeCmCommissioner::TripQueryResult.new([trip]) }
19
18
  connected_results = connected_trips || []
20
19
  direct_results + connected_results
21
20
  end
22
21
 
23
- def direct_trips
24
- result = Spree::Variant
25
- .select('spree_variants.id AS variant_id,
22
+ def direct_trips # rubocop:disable Metrics/MethodLength
23
+ result = Spree::Product
24
+ .select('
26
25
  vendors.id AS vendor_id,
27
26
  vendors.name AS vendor_name,
28
- routes.name AS route_name,
29
- routes.short_name AS short_name,
27
+ spree_products.name AS route_name,
28
+ spree_products.short_name AS short_name,
30
29
  boarding.stop_id AS origin_id,
31
30
  drop_off.stop_id AS destination_id,
32
31
  boarding.stop_name AS origin,
33
32
  drop_off.stop_name AS destination,
33
+ spree_products.id AS trip_id,
34
34
  trips.departure_time AS departure_time,
35
35
  trips.duration AS duration,
36
- trips.vehicle_id AS vehicle_id'
36
+ trips.vehicle_id AS vehicle_id,
37
+ COALESCE(iv.quantity_available, 0) AS quantity_available,
38
+ COALESCE(iv.max_capacity, 0) AS max_capacity'
37
39
  )
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')
40
+ .joins('INNER JOIN cm_trips AS trips ON trips.product_id = spree_products.id')
41
+ .joins('INNER JOIN cm_trip_stops AS boarding ON boarding.trip_id = trips.id AND boarding.stop_type = 0')
42
+ .joins('INNER JOIN cm_trip_stops AS drop_off ON drop_off.trip_id = trips.id AND drop_off.stop_type = 1')
43
+ .joins('INNER JOIN spree_vendors AS vendors ON vendors.id = spree_products.vendor_id')
44
+ .joins("LEFT JOIN (#{product_inventory_totals.to_sql}) iv ON spree_products.id = iv.product_id")
45
+
43
46
  result = result.where(vendors: { id: params[:vendor_id] }) if params[:vendor_id].present?
44
47
  result = result.where('boarding.stop_id = ? AND drop_off.stop_id = ?', origin_id, destination_id)
45
48
  .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')
49
+ date.strftime('%H:%M:%S'),
50
+ date.end_of_day.strftime('%H:%M:%S')
48
51
  )
49
52
 
50
53
  result.map do |trip|
51
54
  trip_result_options = {
52
- trip_id: trip[:variant_id],
55
+ trip_id: trip[:trip_id],
53
56
  vendor_id: trip[:vendor_id],
54
57
  vendor_name: trip[:vendor_name],
55
58
  route_name: trip[:route_name],
@@ -61,7 +64,9 @@ module SpreeCmCommissioner
61
64
  destination: trip[:destination],
62
65
  vehicle_id: trip[:vehicle_id],
63
66
  departure_time: parse_time(trip[:departure_time]),
64
- duration: trip[:duration]
67
+ duration: trip[:duration],
68
+ quantity_available: trip[:quantity_available].to_i,
69
+ max_capacity: trip[:max_capacity].to_i
65
70
  }
66
71
  SpreeCmCommissioner::TripResult.new(trip_result_options)
67
72
  end
@@ -69,52 +74,69 @@ module SpreeCmCommissioner
69
74
 
70
75
  def connected_trips # rubocop:disable Metrics/MethodLength
71
76
  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'
77
+ .joins("
78
+ INNER JOIN cm_trips trip1 ON trip1.id = cm_trip_connections.from_trip_id
79
+ INNER JOIN cm_trips trip2 ON trip2.id = cm_trip_connections.to_trip_id
80
+ INNER JOIN spree_products AS product1 ON product1.id = trip1.product_id
81
+ INNER JOIN spree_products AS product2 ON product2.id = trip2.product_id
82
+ INNER JOIN cm_trip_stops trip1_origin ON trip1_origin.trip_id = trip1.id AND trip1_origin.stop_type = 0
83
+ INNER JOIN cm_trip_stops trip2_origin ON trip2_origin.trip_id = trip2.id AND trip2_origin.stop_type = 0
84
+ INNER JOIN cm_trip_stops trip2_destination ON trip2_destination.trip_id = trip2.id AND trip2_destination.stop_type = 1
85
+ INNER JOIN spree_vendors AS vendor1 ON vendor1.id = product1.vendor_id
86
+ INNER JOIN spree_vendors AS vendor2 ON vendor2.id = product2.vendor_id
87
+ LEFT JOIN (#{product_inventory_totals.to_sql}) AS iv1 ON iv1.product_id = product1.id
88
+ LEFT JOIN (#{product_inventory_totals.to_sql}) AS iv2 ON iv2.product_id = product2.id"
84
89
  )
85
90
  .select('cm_trip_connections.id AS id,
86
- trip1.variant_id AS trip1_id,
91
+ trip1.id AS trip1_id,
87
92
  trip1.origin_id AS trip1_origin_id,
88
93
  trip1.destination_id AS trip1_destination_id,
89
94
  trip1.departure_time AS trip1_departure_time,
90
95
  trip1.duration AS trip1_duration,
91
- routes1.short_name AS route1_short_name,
92
- routes1.name AS route1_name,
96
+ product1.id AS trip1_id,
97
+ product1.short_name AS route1_short_name,
98
+ product1.name AS route1_name,
93
99
  trip1.vehicle_id AS trip1_vehicle,
94
100
  vendor1.name AS trip1_vendor_name,
95
- trip2.variant_id AS trip2_id,
101
+ trip2.id AS trip2_id,
96
102
  trip2.origin_id AS trip2_origin_id,
97
103
  trip2.destination_id AS trip2_destination_id,
98
104
  trip2.departure_time AS trip2_departure_time,
99
105
  trip2.duration AS trip2_duration,
100
106
  trip2.vehicle_id AS trip2_vehicle,
101
- routes2.short_name AS route2_short_name,
102
- routes2.name AS route2_name,
107
+ product2.id AS trip2_id,
108
+ product2.short_name AS route2_short_name,
109
+ product2.name AS route2_name,
103
110
  trip1_origin.stop_name AS trip1_origin,
104
111
  trip2_origin.stop_name AS trip2_origin,
105
112
  trip2_destination.stop_name AS trip2_destination,
106
- vendor2.name AS trip2_vendor_name'
113
+ vendor2.name AS trip2_vendor_name,
114
+ COALESCE(iv1.quantity_available, 0) as trip1_quantity_available,
115
+ COALESCE(iv2.quantity_available, 0) as trip2_quantity_available,
116
+ COALESCE(iv1.max_capacity, 0) as trip1_max_capacity,
117
+ COALESCE(iv2.max_capacity, 0) as trip2_max_capacity'
107
118
  ).where('trip1_origin.stop_id = ? AND trip2_destination.stop_id = ?', origin_id, destination_id)
108
119
  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')
120
+ result = result.where('trip1.departure_time > ? AND trip1.departure_time <= ?', date.strftime('%H:%M:%S'),
121
+ date.end_of_day.strftime('%H:%M:%S')
111
122
  ).uniq
112
-
113
123
  return [] if result.blank?
114
124
 
115
125
  build_trip_query_result(result)
116
126
  end
117
127
 
128
+ def product_inventory_totals
129
+ Spree::Product
130
+ .select(
131
+ 'spree_products.id AS product_id,
132
+ SUM(cm_inventory_items.max_capacity) AS max_capacity,
133
+ SUM(cm_inventory_items.quantity_available) AS quantity_available'
134
+ )
135
+ .joins(variants: :inventory_items)
136
+ .where(cm_inventory_items: { inventory_date: date.to_date })
137
+ .group('spree_products.id')
138
+ end
139
+
118
140
  private
119
141
 
120
142
  def build_trip_query_result(connections)
@@ -130,7 +152,9 @@ module SpreeCmCommissioner
130
152
  short_name: trip[:route1_short_name],
131
153
  vehicle_id: trip[:trip1_vehicle],
132
154
  origin: trip[:trip1_origin],
133
- destination: trip[:trip2_origin]
155
+ destination: trip[:trip2_origin],
156
+ quantity_available: trip[:trip1_quantity_available].to_i,
157
+ max_capacity: trip[:trip1_max_capacity].to_i
134
158
  }
135
159
  to_trip = {
136
160
  trip_id: trip[:trip2_id],
@@ -143,7 +167,9 @@ module SpreeCmCommissioner
143
167
  short_name: trip[:route2_short_name],
144
168
  vehicle_id: trip[:trip2_vehicle],
145
169
  origin: trip[:trip2_origin],
146
- destination: trip[:trip2_destination]
170
+ destination: trip[:trip2_destination],
171
+ quantity_available: trip[:trip2_quantity_available].to_i,
172
+ max_capacity: trip[:trip2_max_capacity].to_i
147
173
  }
148
174
  data = [SpreeCmCommissioner::TripResult.new(from_trip),
149
175
  SpreeCmCommissioner::TripResult.new(to_trip)
@@ -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,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
@@ -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,
@@ -11,7 +11,6 @@ module Spree
11
11
  has_one :profile, serializer: Spree::V2::Tenant::AssetSerializer
12
12
  has_many :device_tokens, serializer: Spree::V2::Tenant::UserDeviceTokenSerializer
13
13
  has_many :spree_roles, serializer: Spree::V2::Tenant::RoleSerializer
14
- has_many :user_identity_providers, serializer: Spree::V2::Tenant::UserIdentityProviderSerializer
15
14
 
16
15
  attribute :store_credits, &:total_available_store_credit
17
16
 
@@ -32,7 +32,7 @@ module SpreeCmCommissioner
32
32
  options = { login: params[:username], password: params[:password], tenant_id: tenant_id }
33
33
  SpreeCmCommissioner::UserPasswordAuthenticator.call(options)
34
34
  when 'social_auth'
35
- options = { id_token: params[:id_token], tenant_id: tenant_id }
35
+ options = { id_token: params[:id_token] }
36
36
  SpreeCmCommissioner::UserIdTokenAuthenticator.call(options)
37
37
  when 'telegram_web_app_auth'
38
38
  options = { telegram_init_data: params[:telegram_init_data], telegram_bot_username: params[:tg_bot] }
@@ -0,0 +1,72 @@
1
+ <%= turbo_frame_tag "inventory_item" do %>
2
+ <div>
3
+ <h5 class="modal-title">Inventory</h5>
4
+ <p>
5
+ <% if @inventory_item.inventory_date.present? %>
6
+ <span><%= @inventory_item.inventory_date %></span><br>
7
+ <% end %>
8
+ <%= @inventory_item.variant.options_text %>
9
+ </p>
10
+
11
+ <ul class="list-group mb-1">
12
+ <li class="list-group-item d-flex justify-content-between align-items-center">
13
+ Max capacity
14
+ <span class="badge badge-primary badge-pill"><%= @inventory_item.max_capacity %></span>
15
+ </li>
16
+ <li class="list-group-item d-flex justify-content-between align-items-center">
17
+ Quantity available
18
+ <span class="badge badge-primary badge-pill"><%= @inventory_item.quantity_available %></span>
19
+ </li>
20
+ </ul>
21
+
22
+ <small class="text-muted">
23
+ <%= inventory_item_message(@inventory_item, @cached_inventory_item) %>
24
+ </small>
25
+
26
+ <%= link_to_with_icon('arrow-counterclockwise.svg', "Reset Inventory Item", reset_admin_product_variant_inventory_item_path(@product, @inventory_item.variant_id, @inventory_item.id),
27
+ method: :patch,
28
+ remote: false,
29
+ class: 'icon_link btn btn-sm outline text-dark',
30
+ data: { confirm: "Only reset if stock is incorrect. Are you sure?" }, no_text: true
31
+ ) %>
32
+ </div>
33
+
34
+ <hr />
35
+
36
+ <div class="mt-2">
37
+ <h6 class="modal-title mb-1 d-flex flex-row justify-content-between">
38
+ Custom Prices
39
+ <%= link_to_with_icon('delete.svg', Spree.t(:remove),
40
+ delete_prices_admin_product_variant_inventory_item_path(@product, @inventory_item.variant_id, @inventory_item.id),
41
+ method: :delete, remote: false, class: 'icon_link btn btn-sm text-danger', data: { action: :remove, confirm: "Are you sure to remove these prices & use base price?" }, no_text: true
42
+ ) if @prices.any?(&:persisted?) %>
43
+ </h6>
44
+
45
+ <%= form_with url: update_prices_admin_product_variant_inventory_item_path(@product, @inventory_item.variant_id, @inventory_item.id), method: :patch, local: true, html: { class: 'inventory-item-prices-form' } do |form| %>
46
+ <table class="table">
47
+ <tbody>
48
+ <% @prices.each do |price| %>
49
+ <% currency = price.currency %>
50
+ <% default_price = @default_prices[currency] || Spree::Price.new %>
51
+ <tr id="inventory-item_prices_row_<%= currency %>" data-hook="inventory-item_prices_row">
52
+ <td><%= form.label "price_#{currency}", currency, class: 'form-label' %></td>
53
+ <td>
54
+ <%= form.hidden_field "prices[#{currency}][currency]", value: currency %>
55
+ <%= form.text_field "prices[#{currency}][price]", value: price.amount, placeholder: "Default: #{default_price.amount || 'N/A'}", class: 'form-control' %>
56
+ </td>
57
+ <td>
58
+ <%= form.text_field "prices[#{currency}][compare_at_price]", value: price.compare_at_price, placeholder: "Default: #{default_price.compare_at_price || 'N/A'}", class: 'form-control' %>
59
+ </td>
60
+ </tr>
61
+ <% end %>
62
+ </tbody>
63
+ </table>
64
+
65
+ <div class="d-flex flex-row justify-content-end mt-2">
66
+ <div class="form-actions" data-hook="buttons">
67
+ <%= button Spree.t('actions.save'), 'save.svg', 'submit', { class: 'btn-outline-success', data: { disable_with: "#{ Spree.t(:saving) }...", turbo_frame: "_top" } } %>
68
+ </div>
69
+ </div>
70
+ <% end %>
71
+ </div>
72
+ <% end %>
@@ -17,9 +17,11 @@
17
17
  </td>
18
18
  <td class="text-center d-flex flex-column align-items-center justify-content-center">
19
19
  <div style="width: 90px;">
20
- <%= form_tag admin_stock_items_path(variant_id: variant.id, stock_location_id: stock_location.id), method: :post do %>
20
+ <%= form_tag admin_product_stock_managements_path(product_id: params[:product_id], variant_id: variant.id, stock_location_id: stock_location.id), method: :post do %>
21
21
  <div class="input-group input-group-sm">
22
22
  <%= number_field_tag 'stock_movement[quantity]', 0, class: 'form-control text-center p-0' %>
23
+ <%= hidden_field_tag 'stock_movement[originator_id]', spree_current_user.id %>
24
+ <%= hidden_field_tag 'stock_movement[originator_type]', spree_current_user.class.name %>
23
25
  <div class="input-group-append">
24
26
  <%= button_tag(class: 'btn btn-outline-success pl-2 pr-1') do %>
25
27
  <%= svg_icon(name: 'arrow-left-right.svg', classes: "icon", width: 14, height: 14) %>
@@ -32,7 +34,10 @@
32
34
  <td class="text-center">
33
35
  <% if item.persisted? && can?(:update, item) %>
34
36
  <%= form_tag admin_stock_item_path(item), method: :put, class: 'toggle_stock_item_backorderable' do %>
35
- <%= check_box_tag 'stock_item[backorderable]', true, item.backorderable?, class: 'stock_item_backorderable', id: "stock_item_backorderable_#{stock_location.id}" %>
37
+ <%= check_box_tag 'stock_item[backorderable]', true, item.backorderable?,
38
+ class: 'stock_item_backorderable',
39
+ id: "stock_item_backorderable_#{stock_location.id}",
40
+ onclick: "if (!confirm('Are you sure to change backorderable status?')) { this.checked = !this.checked; }" %>
36
41
  <% end %>
37
42
  <% else %>
38
43
  <%= 'N/A' %>
@@ -0,0 +1,56 @@
1
+ <%= turbo_frame_tag "calendar" do %>
2
+ <%= form_with url: admin_product_stock_managements_path, method: :get, class: "mt-4" do %>
3
+ <%= select_year(params[:year]&.to_i || @year, { start_year: 2025, end_year: @year + 3 }, { name: "year", onchange: "this.form.submit()" }) %>
4
+ <% end %>
5
+
6
+ <div class="c-annual-calendar-container mt-2">
7
+ <div class="c-annual-calendar">
8
+ <% (1..12).each do |month| %>
9
+ <%= month_calendar(start_date: Date.new(@year, month, 1), attribute: :from_date, end_attribute: :to_date, events: @events) do |date, events| %>
10
+ <div class="c-annual-day" data-date="<%= date.strftime '%Y-%m-%d' %>">
11
+ <%= date.day %>
12
+ <ul class="p-0 m-0 list-unstyled">
13
+ <% events = events.sort_by { |e| e.options[:inventory_item]&.variant_id.to_i } %>
14
+ <% events.each do |event| %>
15
+ <% inventory_item = event.options[:inventory_item] %>
16
+ <% synced = inventory_item.quantity_available == @cached_inventory_items[inventory_item.id].quantity_available %>
17
+
18
+ <% classes = 'badge ' %>
19
+ <% classes += synced ? 'badge-primary ' : 'badge-danger ' %>
20
+ <% classes += 'badge-success ' if inventory_item.prices.any? %>
21
+
22
+ <li class="<%= classes %>"
23
+ data-toggle="modal"
24
+ data-target="#inventoryItemModal"
25
+ role="button"
26
+ onclick="updateModalTurboFrameSrc('<%= admin_product_variant_inventory_item_path(@product, inventory_item.variant_id, inventory_item.id) %>')">
27
+ <%= inventory_item.quantity_available %>
28
+ <%= inventory_item.prices.first.display_amount if inventory_item.prices.any? %>
29
+ </li>
30
+ <% end %>
31
+ </ul>
32
+ </div>
33
+ <% end %>
34
+ <% end %>
35
+ </div>
36
+ </div>
37
+
38
+ <div class="modal fade" id="inventoryItemModal" tabindex="-1" role="dialog">
39
+ <div class="modal-dialog" role="document">
40
+ <div class="modal-content">
41
+ <div class="modal-body">
42
+ <%= turbo_frame_tag "inventory_item" %>
43
+ </div>
44
+ </div>
45
+ </div>
46
+ </div>
47
+
48
+ <script>
49
+ function updateModalTurboFrameSrc(url) {
50
+ let frame = document.getElementById('inventory_item');
51
+ frame.src = null;
52
+ frame.innerHTML = `<div class="spinner-border mt-2" role="status"></div>`;
53
+ frame.src = url
54
+ }
55
+ </script>
56
+ <% end %>
@@ -19,30 +19,73 @@
19
19
  <% @variants.each do |variant| %>
20
20
  <tr id="<%= spree_dom_id variant %>" data-hook="admin_product_stock_management_index_rows">
21
21
  <td class="image text-center">
22
- <%= small_image(variant) %>
23
- <div class="mt-4">
24
- Reserved Stock: <%= @reserved_stocks[variant.id] || 0 %></strong>
25
- </div>
22
+ <%= small_image(variant) %>
26
23
  </td>
27
24
  <td>
28
25
  <%= variant.sku_and_options_text %>
29
26
  <%= form_tag admin_product_variants_including_master_path(@product, variant, format: :js), method: :put, class: 'toggle_variant_track_inventory mt-2' do %>
30
27
  <div class="checkbox">
31
28
  <%= label_tag "track_inventory_#{ variant.id }", class: 'm-0' do %>
32
- <%= check_box_tag 'track_inventory', 1, variant.track_inventory?, class: 'track_inventory_checkbox', id: "track_inventory_#{ variant.id }" %>
29
+ <%= check_box_tag 'track_inventory', 1, variant.track_inventory?,
30
+ class: 'track_inventory_checkbox',
31
+ id: "track_inventory_#{ variant.id }",
32
+ onclick: "if (!confirm('Are you sure to change track inventory status?')) { this.checked = !this.checked; }" %>
33
33
  <%= Spree.t(:track_inventory) %>
34
34
  <%= hidden_field_tag 'variant[track_inventory]', variant.track_inventory?, class: 'variant_track_inventory', id: "variant_track_inventory_#{variant.id}" %>
35
35
  <% end %>
36
36
  </div>
37
37
  <% end if can?(:update, @product) && can?(:update, variant) %>
38
+
39
+ <% if defined?(@reserved_stocks) %>
40
+ <div>
41
+ <%= svg_icon name: "cart-check.svg", width: '14', height: '14' %>
42
+ <%= label_tag "reserved_stock#{variant.id}", "Reserved Stock: #{@reserved_stocks[variant.id] || 0}", class: "m-0" %>
43
+ <%= link_to_with_icon('capture.svg', "Create Inventory Item", admin_product_stock_management_variant_inventory_items(@product, variant.id),
44
+ method: :post,
45
+ remote: false,
46
+ class: 'icon_link btn btn-sm btn-outline-primary ml-2',
47
+ no_text: true
48
+ ) unless @inventory_items[variant.id].present? %>
49
+ </div>
50
+ <% end %>
51
+
38
52
  <% if variant.permanent_stock? %>
39
53
  <div>
40
54
  <span type="button" data-toggle="popover" data-trigger="hover" data-placement="right" data-content="This product stock will renew every day">
41
55
  <%= svg_icon name: "info-circle-fill.svg", width: '14', height: '14' %>
42
56
  </span>
43
- <%= label_tag "permanent_stock_#{ variant.id }", Spree.t(:permanent_stock) %>
57
+ <%= label_tag "permanent_stock_#{ variant.id }", Spree.t(:permanent_stock), class: "m-0" %>
44
58
  </div>
45
59
  <% end %>
60
+
61
+ <% if defined?(@inventory_items) %>
62
+ <% @inventory_items[variant.id]&.each do |inventory_item| %>
63
+ <div>
64
+ <%= svg_icon name: "handbag.svg", width: '14', height: '14' %>
65
+ <%= label_tag "max_capacity_#{ inventory_item.id }", "Max capacity: #{inventory_item.max_capacity}", class: "m-0" %>
66
+ </div>
67
+ <div>
68
+ <%= svg_icon name: "approve.svg", width: '14', height: '14' %>
69
+ <%= label_tag "quantity_available_#{ inventory_item.id }", "Quantity available: #{inventory_item.quantity_available}", class: "m-0" %>
70
+
71
+ <% synced = inventory_item.quantity_available == @cached_inventory_items[inventory_item.id].quantity_available %>
72
+ <span type="button" data-toggle="popover" data-trigger="hover" data-placement="right" data-content="<%= inventory_item_message(inventory_item, @cached_inventory_items[inventory_item.id]) %>">
73
+ <% if synced %>
74
+ <%= svg_icon name: "cloud-check.svg", width: '14', height: '14', classes: 'text-success' %>
75
+ <% else %>
76
+ <%= svg_icon name: "cloud-slash.svg", width: '14', height: '14', classes: 'text-danger' %>
77
+ <% end %>
78
+ </span>
79
+
80
+ <%= link_to_with_icon('arrow-counterclockwise.svg', "Reset Inventory Item", reset_admin_product_variant_inventory_item_path(@product, inventory_item.variant_id, inventory_item.id),
81
+ method: :patch,
82
+ remote: false,
83
+ class: 'icon_link btn btn-sm outline text-dark',
84
+ data: { confirm: "Only reset if stock is incorrect. Are you sure?" }, no_text: true
85
+ ) %>
86
+ </div>
87
+ <% end %>
88
+ <% end %>
46
89
  </td>
47
90
 
48
91
  <td colspan="3" class="stock_location_info">
@@ -53,3 +96,9 @@
53
96
  </tbody>
54
97
  </table>
55
98
  </div>
99
+
100
+ <%= turbo_frame_tag "calendar", src: calendar_admin_product_stock_managements_path(year: params[:year]) do %>
101
+ <div class="spinner-border mt-2" role="status">
102
+ <span class="sr-only">Loading...</span>
103
+ </div>
104
+ <% end if @product.permanent_stock? %>
@@ -0,0 +1 @@
1
+ PaperTrail.enabled = true
@@ -60,5 +60,10 @@ module Spree
60
60
  age
61
61
  gender
62
62
  ]
63
+
64
+ @@stock_movement_attributes += %i[
65
+ originator_type
66
+ originator_id
67
+ ]
63
68
  end
64
69
  end
data/config/routes.rb CHANGED
@@ -138,7 +138,21 @@ Spree::Core::Engine.add_routes do
138
138
  end
139
139
  end
140
140
 
141
- resources :stock_managements
141
+ resources :stock_managements do
142
+ collection do
143
+ get :calendar
144
+ end
145
+ end
146
+
147
+ resources :variants do
148
+ resources :inventory_items, only: %i[show create] do
149
+ member do
150
+ patch :reset
151
+ patch :update_prices
152
+ delete :delete_prices
153
+ end
154
+ end
155
+ end
142
156
 
143
157
  resources :product_completion_steps do
144
158
  collection do
@@ -531,6 +545,8 @@ Spree::Core::Engine.add_routes do
531
545
  end
532
546
 
533
547
  namespace :storefront do
548
+ resources :inventory_item
549
+
534
550
  resources :waiting_room_sessions, only: :create
535
551
  resources :vattanac_banks, only: %i[create]
536
552
  resource :cart, controller: :cart, only: %i[show create destroy] do
@@ -556,7 +572,10 @@ Spree::Core::Engine.add_routes do
556
572
  resource :cart_guests, only: %i[create destroy]
557
573
  resources :cart_payment_method_groups, only: %i[index]
558
574
 
559
- resources :accommodations, only: %i[index show]
575
+ resources :accommodations, only: %i[index show] do
576
+ resources :variants, only: %i[index show], module: :accommodations
577
+ end
578
+
560
579
  resources :line_items, only: %i[index show]
561
580
  resources :account_checker
562
581
  resource :account_recovers, only: [:update]
@@ -1,5 +1,7 @@
1
1
  class UpdateCounterCacheOfVehicleType < ActiveRecord::Migration[7.0]
2
- def up
2
+ def up
3
+ if defined?(SpreeCmCommissioner::VehicleSeat) && SpreeCmCommissioner::VehicleSeat.respond_to?(:counter_culture_fix_counts)
3
4
  SpreeCmCommissioner::VehicleSeat.counter_culture_fix_counts
4
5
  end
6
+ end
5
7
  end
@@ -0,0 +1,21 @@
1
+ class CreateCmInventoryItems < ActiveRecord::Migration[7.0]
2
+ def up
3
+ create_table :cm_inventory_items, if_not_exists: true do |t|
4
+ t.integer :variant_id
5
+ t.date :inventory_date
6
+ t.integer :max_capacity, default: 0, null: false
7
+ t.integer :quantity_available, default: 0, null: false
8
+ t.integer :product_type, default: 0, null: false
9
+
10
+ t.timestamps
11
+ end
12
+
13
+ add_index :cm_inventory_items, :variant_id, if_not_exists: true
14
+ add_index :cm_inventory_items, :inventory_date, if_not_exists: true
15
+ add_index :cm_inventory_items, [:variant_id, :inventory_date], unique: true, if_not_exists: true
16
+ end
17
+
18
+ def down
19
+ drop_table :cm_inventory_items
20
+ end
21
+ end
@@ -0,0 +1,5 @@
1
+ class AddLockVersionToCmInventoryItems < ActiveRecord::Migration[7.0]
2
+ def change
3
+ add_column :cm_inventory_items, :lock_version, :integer, default: 0, null: false, if_not_exists: true
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddIndexToSpreeProducts < ActiveRecord::Migration[7.0]
2
+ def change
3
+ add_index :spree_products, :product_type unless index_exists?(:spree_products, :product_type)
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class AddProductTypeToSpreeVariants < ActiveRecord::Migration[7.0]
2
+ def change
3
+ add_column :spree_variants, :product_type, :integer, if_not_exists: true
4
+ end
5
+ end