spree_cm_commissioner 2.8.1.pre.3 → 2.8.2

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 (306) hide show
  1. checksums.yaml +4 -4
  2. data/.env.example +1 -0
  3. data/.gitignore +0 -4
  4. data/Gemfile.lock +1 -1
  5. data/app/controllers/spree/admin/homepage_section_controller.rb +1 -4
  6. data/app/controllers/spree/admin/taxons_controller_decorator.rb +0 -19
  7. data/app/controllers/spree/api/v2/storefront/homepage_sections_controller.rb +0 -1
  8. data/app/controllers/spree/api/v2/storefront/trip_search_controller.rb +0 -1
  9. data/app/controllers/spree/api/v2/tenant/base_controller.rb +0 -4
  10. data/app/controllers/spree/api/v2/tenant/homepage_sections_controller.rb +0 -1
  11. data/app/controllers/spree/api/v2/tenant/products_controller.rb +1 -1
  12. data/app/controllers/spree/api/v2/tenant/taxons_controller.rb +1 -1
  13. data/app/controllers/spree_cm_commissioner/admin/products_controller_decorator.rb +0 -19
  14. data/app/factory/spree_cm_commissioner/event_telegram_message_factory.rb +68 -0
  15. data/app/finders/spree_cm_commissioner/accommodations/find_variant.rb +2 -2
  16. data/app/finders/spree_cm_commissioner/events/find_matches.rb +0 -1
  17. data/app/helpers/spree_cm_commissioner/admin/homepage_segment_helper.rb +0 -2
  18. data/app/jobs/spree_cm_commissioner/event_creation_telegram_alert_sender_job.rb +10 -0
  19. data/app/jobs/spree_cm_commissioner/oauth_access_tokens/cleanup_expired_job.rb +11 -0
  20. data/app/models/concerns/spree_cm_commissioner/homepage_section_bitwise.rb +1 -2
  21. data/app/models/concerns/spree_cm_commissioner/line_item_transitable.rb +8 -0
  22. data/app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb +1 -2
  23. data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +0 -10
  24. data/app/models/concerns/spree_cm_commissioner/product_type.rb +1 -1
  25. data/app/models/concerns/spree_cm_commissioner/service_origin.rb +22 -0
  26. data/app/models/concerns/spree_cm_commissioner/store_preference.rb +1 -0
  27. data/app/models/concerns/spree_cm_commissioner/vehicle_kind.rb +1 -1
  28. data/app/models/spree_cm_commissioner/integration.rb +0 -31
  29. data/app/models/spree_cm_commissioner/integrations/stadium_x_v1.rb +10 -4
  30. data/app/models/spree_cm_commissioner/inventory_item.rb +17 -8
  31. data/app/models/spree_cm_commissioner/maintenance_tasks/cache_invalidation.rb +2 -0
  32. data/app/models/spree_cm_commissioner/order_decorator.rb +0 -1
  33. data/app/models/spree_cm_commissioner/place.rb +0 -2
  34. data/app/models/spree_cm_commissioner/product_decorator.rb +0 -39
  35. data/app/models/spree_cm_commissioner/role_decorator.rb +1 -4
  36. data/app/models/spree_cm_commissioner/route.rb +6 -2
  37. data/app/models/spree_cm_commissioner/seat_layout.rb +0 -2
  38. data/app/models/spree_cm_commissioner/stock_item_decorator.rb +0 -7
  39. data/app/models/spree_cm_commissioner/taxon_decorator.rb +7 -15
  40. data/app/models/spree_cm_commissioner/taxonomy_decorator.rb +1 -10
  41. data/app/models/spree_cm_commissioner/tenant.rb +0 -9
  42. data/app/models/spree_cm_commissioner/trip.rb +6 -2
  43. data/app/models/spree_cm_commissioner/trip_stop.rb +0 -2
  44. data/app/models/spree_cm_commissioner/user_decorator.rb +0 -5
  45. data/app/models/spree_cm_commissioner/variant_decorator.rb +0 -1
  46. data/app/models/spree_cm_commissioner/variant_options.rb +0 -4
  47. data/app/models/spree_cm_commissioner/vehicle.rb +0 -3
  48. data/app/models/spree_cm_commissioner/vehicle_type.rb +0 -1
  49. data/app/models/spree_cm_commissioner/vendor_decorator.rb +0 -21
  50. data/app/models/spree_cm_commissioner/vendor_place.rb +0 -2
  51. data/app/overrides/spree/admin/stores/_form/store_preferences.html.erb.deface +9 -0
  52. data/app/queries/spree_cm_commissioner/multi_leg_trips_query.rb +26 -44
  53. data/app/queries/spree_cm_commissioner/single_leg_trips_query.rb +36 -31
  54. data/app/queries/spree_cm_commissioner/trip_query.rb +2 -4
  55. data/app/serializers/spree/v2/storefront/homepage_section_serializer.rb +1 -1
  56. data/app/serializers/spree/v2/storefront/product_serializer_decorator.rb +1 -1
  57. data/app/serializers/spree/v2/storefront/role_serializer.rb +1 -1
  58. data/app/serializers/spree/v2/storefront/taxon_serializer_decorator.rb +1 -2
  59. data/app/serializers/spree/v2/tenant/homepage_section_serializer.rb +1 -1
  60. data/app/serializers/spree/v2/tenant/role_serializer.rb +1 -1
  61. data/app/serializers/spree_cm_commissioner/v2/storefront/trip_result_serializer.rb +7 -2
  62. data/app/services/spree_cm_commissioner/integrations/base/sync_manager.rb +2 -1
  63. data/app/services/spree_cm_commissioner/integrations/base/sync_result.rb +0 -11
  64. data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/external_client/client.rb +15 -14
  65. data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/polling/sync_matches.rb +4 -7
  66. data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/polling/sync_zones.rb +3 -6
  67. data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/sync_manager.rb +3 -0
  68. data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/sync_strategies/full_sync_strategy.rb +3 -1
  69. data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/sync_strategies/incremental_sync_strategy.rb +3 -1
  70. data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/sync_strategies/webhook_sync_strategy.rb +2 -1
  71. data/app/services/spree_cm_commissioner/oauth_access_tokens/cleanup_expired.rb +53 -0
  72. data/app/services/spree_cm_commissioner/order_holds/hold.rb +0 -17
  73. data/app/services/spree_cm_commissioner/order_holds/release.rb +0 -17
  74. data/app/services/spree_cm_commissioner/pricing_models/preview.rb +15 -6
  75. data/app/services/spree_cm_commissioner/routes/create.rb +0 -5
  76. data/app/services/spree_cm_commissioner/telegram_alerts/event_creation.rb +35 -0
  77. data/app/services/spree_cm_commissioner/trips/create_multi_leg.rb +5 -16
  78. data/app/services/spree_cm_commissioner/trips/create_single_leg.rb +0 -1
  79. data/app/views/spree/admin/homepage_section/_form.html.erb +0 -5
  80. data/app/views/spree/admin/integrations/_form.html.erb +0 -12
  81. data/app/views/spree/admin/integrations/index.html.erb +1 -1
  82. data/config/initializers/spree_permitted_attributes.rb +1 -8
  83. data/config/locales/en.yml +0 -13
  84. data/config/locales/km.yml +0 -7
  85. data/config/routes.rb +0 -26
  86. data/lib/spree_cm_commissioner/test_helper/factories/integration_factory.rb +0 -11
  87. data/lib/spree_cm_commissioner/trip_result.rb +48 -21
  88. data/lib/spree_cm_commissioner/version.rb +1 -1
  89. data/lib/spree_cm_commissioner.rb +1 -7
  90. metadata +10 -220
  91. data/app/controllers/spree/api/v2/storefront/preview_products_controller.rb +0 -48
  92. data/app/controllers/spree/api/v2/storefront/preview_sections_controller.rb +0 -27
  93. data/app/controllers/spree/api/v2/storefront/preview_taxons_controller.rb +0 -18
  94. data/app/controllers/spree/api/v2/storefront/products_controller_decorator.rb +0 -15
  95. data/app/controllers/spree/api/v2/storefront/taxons_controller_decorator.rb +0 -15
  96. data/app/controllers/spree/api/v2/storefront/transit/item_availabilities_controller.rb +0 -66
  97. data/app/controllers/spree/api/v2/tenant/free_vote_claims_controller.rb +0 -37
  98. data/app/controllers/spree/api/v2/tenant/preview_products_controller.rb +0 -47
  99. data/app/controllers/spree/api/v2/tenant/preview_sections_controller.rb +0 -26
  100. data/app/controllers/spree/api/v2/tenant/preview_shows_controller.rb +0 -19
  101. data/app/controllers/spree/api/v2/tenant/preview_taxons_controller.rb +0 -19
  102. data/app/controllers/spree/api/v2/tenant/show_contestants_controller.rb +0 -51
  103. data/app/controllers/spree/api/v2/tenant/show_people_controller.rb +0 -49
  104. data/app/controllers/spree/api/v2/tenant/show_person_assignments_controller.rb +0 -36
  105. data/app/controllers/spree/api/v2/tenant/shows_controller.rb +0 -34
  106. data/app/controllers/spree/api/v2/tenant/votes_controller.rb +0 -94
  107. data/app/controllers/spree/api/v2/tenant/voting_contestants_controller.rb +0 -40
  108. data/app/controllers/spree/api/v2/tenant/voting_credit_transactions_controller.rb +0 -41
  109. data/app/controllers/spree/api/v2/tenant/voting_credits_controller.rb +0 -31
  110. data/app/jobs/spree_cm_commissioner/audit_event_job.rb +0 -29
  111. data/app/jobs/spree_cm_commissioner/cleanup_expired_access_tokens_job.rb +0 -9
  112. data/app/jobs/spree_cm_commissioner/vote_fraud_event_job.rb +0 -9
  113. data/app/jobs/spree_cm_commissioner/voting_credit_allocation_job.rb +0 -10
  114. data/app/jobs/spree_cm_commissioner/voting_credit_de_allocation_job.rb +0 -10
  115. data/app/models/concerns/spree_cm_commissioner/audit_wrapper.rb +0 -139
  116. data/app/models/concerns/spree_cm_commissioner/integrations/inventory_sync_cachable.rb +0 -9
  117. data/app/models/concerns/spree_cm_commissioner/variant_metadata.rb +0 -24
  118. data/app/models/spree_cm_commissioner/audit_event.rb +0 -11
  119. data/app/models/spree_cm_commissioner/currency_rate.rb +0 -15
  120. data/app/models/spree_cm_commissioner/integrations/book_me_bus_v1.rb +0 -56
  121. data/app/models/spree_cm_commissioner/integrations/larryta.rb +0 -81
  122. data/app/models/spree_cm_commissioner/integrations/vireak_buntham.rb +0 -82
  123. data/app/models/spree_cm_commissioner/maintenance_tasks/voting_session.rb +0 -34
  124. data/app/models/spree_cm_commissioner/preview_role.rb +0 -8
  125. data/app/models/spree_cm_commissioner/role_user_decorator.rb +0 -8
  126. data/app/models/spree_cm_commissioner/show.rb +0 -157
  127. data/app/models/spree_cm_commissioner/show_contestant.rb +0 -34
  128. data/app/models/spree_cm_commissioner/show_contestant_image.rb +0 -11
  129. data/app/models/spree_cm_commissioner/show_contestant_video.rb +0 -15
  130. data/app/models/spree_cm_commissioner/show_episode.rb +0 -135
  131. data/app/models/spree_cm_commissioner/show_person.rb +0 -15
  132. data/app/models/spree_cm_commissioner/show_person_assignment.rb +0 -20
  133. data/app/models/spree_cm_commissioner/show_person_image.rb +0 -11
  134. data/app/models/spree_cm_commissioner/vote.rb +0 -16
  135. data/app/models/spree_cm_commissioner/vote_fraud_event.rb +0 -19
  136. data/app/models/spree_cm_commissioner/voting_contestant.rb +0 -34
  137. data/app/models/spree_cm_commissioner/voting_credit.rb +0 -72
  138. data/app/models/spree_cm_commissioner/voting_credit_transaction.rb +0 -55
  139. data/app/models/spree_cm_commissioner/voting_session.rb +0 -194
  140. data/app/overrides/spree/admin/products/_form/preview_checkbox.html.erb.deface +0 -9
  141. data/app/overrides/spree/admin/taxons/_form/preview_checkbox.html.erb.deface +0 -7
  142. data/app/serializables/spree_cm_commissioner/item_availability_sync.rb +0 -10
  143. data/app/serializers/spree/v2/tenant/show_contestant_serializer.rb +0 -21
  144. data/app/serializers/spree/v2/tenant/show_episode_serializer.rb +0 -17
  145. data/app/serializers/spree/v2/tenant/show_person_assignment_serializer.rb +0 -16
  146. data/app/serializers/spree/v2/tenant/show_person_serializer.rb +0 -13
  147. data/app/serializers/spree/v2/tenant/show_serializer.rb +0 -26
  148. data/app/serializers/spree/v2/tenant/video_serializer.rb +0 -9
  149. data/app/serializers/spree/v2/tenant/vote_serializer.rb +0 -14
  150. data/app/serializers/spree/v2/tenant/voting_contestant_serializer.rb +0 -18
  151. data/app/serializers/spree/v2/tenant/voting_credit_serializer.rb +0 -10
  152. data/app/serializers/spree/v2/tenant/voting_credit_transaction_serializer.rb +0 -14
  153. data/app/serializers/spree/v2/tenant/voting_session_serializer.rb +0 -15
  154. data/app/serializers/spree_cm_commissioner/v2/storefront/item_availability_sync_serializer.rb +0 -10
  155. data/app/services/spree_cm_commissioner/audit_logger.rb +0 -59
  156. data/app/services/spree_cm_commissioner/cleanup_expired_access_tokens.rb +0 -52
  157. data/app/services/spree_cm_commissioner/currency_converter/create.rb +0 -27
  158. data/app/services/spree_cm_commissioner/currency_rates/manage.rb +0 -99
  159. data/app/services/spree_cm_commissioner/fraud_check.rb +0 -279
  160. data/app/services/spree_cm_commissioner/google_maps_geocoder.rb +0 -41
  161. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/external_client/client.rb +0 -261
  162. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/external_client/connection.rb +0 -147
  163. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/inventory/external_inventory_item_status.rb +0 -52
  164. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/inventory/external_inventory_items.rb +0 -91
  165. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/inventory/unstock_inventory.rb +0 -140
  166. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_inventory.rb +0 -52
  167. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_item_availability.rb +0 -249
  168. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_locations.rb +0 -103
  169. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_product.rb +0 -66
  170. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_route_stops.rb +0 -113
  171. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_routes.rb +0 -128
  172. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_seat_layout.rb +0 -342
  173. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_service_calendars.rb +0 -59
  174. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_trip_stop.rb +0 -179
  175. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_trips.rb +0 -597
  176. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_variant.rb +0 -58
  177. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_vehicle_types.rb +0 -87
  178. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/time_parser.rb +0 -19
  179. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/base.rb +0 -40
  180. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/branch.rb +0 -65
  181. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/direction.rb +0 -51
  182. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/inventory_item_status.rb +0 -148
  183. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/location.rb +0 -55
  184. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/operator.rb +0 -17
  185. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/reservation_cart.rb +0 -85
  186. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/seat.rb +0 -128
  187. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/seat_layout.rb +0 -363
  188. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/stop.rb +0 -84
  189. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/trip.rb +0 -199
  190. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/wallet_payment.rb +0 -40
  191. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/sync_manager.rb +0 -22
  192. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/sync_strategies/full_sync_strategy.rb +0 -117
  193. data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/sync_strategies/incremental_sync_strategy.rb +0 -64
  194. data/app/services/spree_cm_commissioner/integrations/larryta/external_client/client.rb +0 -344
  195. data/app/services/spree_cm_commissioner/integrations/larryta/external_client/connection.rb +0 -74
  196. data/app/services/spree_cm_commissioner/integrations/larryta/inventory/external_inventory_item_status.rb +0 -53
  197. data/app/services/spree_cm_commissioner/integrations/larryta/inventory/external_inventory_items.rb +0 -106
  198. data/app/services/spree_cm_commissioner/integrations/larryta/inventory/hold_seats.rb +0 -143
  199. data/app/services/spree_cm_commissioner/integrations/larryta/inventory/release_seats.rb +0 -90
  200. data/app/services/spree_cm_commissioner/integrations/larryta/inventory/unstock_inventory.rb +0 -113
  201. data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_item_availability.rb +0 -261
  202. data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_product.rb +0 -72
  203. data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_routes.rb +0 -142
  204. data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_seat_layout.rb +0 -255
  205. data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_stock_item.rb +0 -55
  206. data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_trip_stop.rb +0 -167
  207. data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_trips.rb +0 -320
  208. data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_variant.rb +0 -63
  209. data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_vehicle_type.rb +0 -79
  210. data/app/services/spree_cm_commissioner/integrations/larryta/resources/base.rb +0 -39
  211. data/app/services/spree_cm_commissioner/integrations/larryta/resources/booking.rb +0 -113
  212. data/app/services/spree_cm_commissioner/integrations/larryta/resources/booking_session.rb +0 -43
  213. data/app/services/spree_cm_commissioner/integrations/larryta/resources/booking_transaction.rb +0 -236
  214. data/app/services/spree_cm_commissioner/integrations/larryta/resources/direction.rb +0 -71
  215. data/app/services/spree_cm_commissioner/integrations/larryta/resources/passenger.rb +0 -48
  216. data/app/services/spree_cm_commissioner/integrations/larryta/resources/schedule.rb +0 -150
  217. data/app/services/spree_cm_commissioner/integrations/larryta/resources/seat.rb +0 -31
  218. data/app/services/spree_cm_commissioner/integrations/larryta/resources/seat_availability.rb +0 -49
  219. data/app/services/spree_cm_commissioner/integrations/larryta/resources/seat_layout.rb +0 -211
  220. data/app/services/spree_cm_commissioner/integrations/larryta/sync_manager.rb +0 -17
  221. data/app/services/spree_cm_commissioner/integrations/larryta/sync_strategies/full_sync_strategy.rb +0 -79
  222. data/app/services/spree_cm_commissioner/integrations/larryta/sync_strategies/incremental_sync_strategy.rb +0 -58
  223. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/external_client/client.rb +0 -206
  224. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/external_client/connection.rb +0 -59
  225. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/inventory/external_inventory_item_status.rb +0 -48
  226. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/inventory/external_inventory_items.rb +0 -97
  227. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/inventory/unstock_inventory.rb +0 -208
  228. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_item_availability.rb +0 -270
  229. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_locations.rb +0 -96
  230. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_nationality_pricing.rb +0 -76
  231. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_product.rb +0 -69
  232. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_routes.rb +0 -110
  233. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_seat_layout.rb +0 -207
  234. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_stock_item.rb +0 -43
  235. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_trip_stop.rb +0 -185
  236. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_trips.rb +0 -300
  237. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_variant.rb +0 -56
  238. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_vehicle_type.rb +0 -51
  239. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/base.rb +0 -32
  240. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/booking.rb +0 -48
  241. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/booking_transaction.rb +0 -46
  242. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/cell.rb +0 -53
  243. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/confirm_booking_request.rb +0 -43
  244. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/location.rb +0 -37
  245. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/schedule.rb +0 -138
  246. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/seat.rb +0 -48
  247. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/seat_layout.rb +0 -79
  248. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/sync_manager.rb +0 -17
  249. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/sync_strategies/full_sync_strategy.rb +0 -87
  250. data/app/services/spree_cm_commissioner/integrations/vireak_buntham/sync_strategies/incremental_sync_strategy.rb +0 -53
  251. data/app/services/spree_cm_commissioner/inventory_items/generate_permanent_item.rb +0 -48
  252. data/app/services/spree_cm_commissioner/place_resolver.rb +0 -95
  253. data/app/services/spree_cm_commissioner/show_contestants/normalize_video_highlights.rb +0 -56
  254. data/app/services/spree_cm_commissioner/url_embed/youtube_embed.rb +0 -49
  255. data/app/services/spree_cm_commissioner/vote_counters/audit_counters.rb +0 -43
  256. data/app/services/spree_cm_commissioner/vote_counters/base.rb +0 -31
  257. data/app/services/spree_cm_commissioner/vote_counters/increment.rb +0 -44
  258. data/app/services/spree_cm_commissioner/vote_counters/per_contestant_counter.rb +0 -66
  259. data/app/services/spree_cm_commissioner/vote_counters/rebuild_from_db.rb +0 -70
  260. data/app/services/spree_cm_commissioner/vote_credit_deductor.rb +0 -68
  261. data/app/services/spree_cm_commissioner/vote_package/create.rb +0 -145
  262. data/app/services/spree_cm_commissioner/vote_package/update.rb +0 -91
  263. data/app/services/spree_cm_commissioner/vote_processor.rb +0 -144
  264. data/app/services/spree_cm_commissioner/voting_contestants/advancer.rb +0 -334
  265. data/app/services/spree_cm_commissioner/voting_contestants/assigner.rb +0 -32
  266. data/app/services/spree_cm_commissioner/voting_contestants/bulk_updater.rb +0 -104
  267. data/app/services/spree_cm_commissioner/voting_credits/allocate.rb +0 -77
  268. data/app/services/spree_cm_commissioner/voting_credits/claim_free_votes.rb +0 -119
  269. data/app/services/spree_cm_commissioner/voting_credits/credit_calculator.rb +0 -35
  270. data/app/services/spree_cm_commissioner/voting_credits/de_allocate.rb +0 -87
  271. data/app/views/spree/admin/integrations/_book_me_bus_v1_fields.html.erb +0 -47
  272. data/app/views/spree/admin/integrations/_larryta_fields.html.erb +0 -58
  273. data/app/views/spree/admin/integrations/_vireak_buntham_fields.html.erb +0 -75
  274. data/db/migrate/20260309230148_create_cm_show_people.rb +0 -14
  275. data/db/migrate/20260309230149_create_cm_show_people_assignments.rb +0 -16
  276. data/db/migrate/20260310082711_create_cm_show_contestants.rb +0 -28
  277. data/db/migrate/20260310082720_create_cm_voting_sessions.rb +0 -21
  278. data/db/migrate/20260310082721_create_cm_voting_contestants.rb +0 -23
  279. data/db/migrate/20260310082734_add_voting_fields_to_spree_taxons.rb +0 -9
  280. data/db/migrate/20260310082735_add_type_to_spree_products.rb +0 -6
  281. data/db/migrate/20260310082749_create_cm_voting_credits.rb +0 -27
  282. data/db/migrate/20260326080200_create_cm_voting_credit_transactions.rb +0 -27
  283. data/db/migrate/20260327143200_create_cm_audit_events.rb +0 -21
  284. data/db/migrate/20260330160000_create_cm_votes.rb +0 -25
  285. data/db/migrate/20260401072500_add_advanced_from_to_cm_voting_contestants.rb +0 -7
  286. data/db/migrate/20260402000001_add_voting_credit_scope_to_spree_taxons.rb +0 -6
  287. data/db/migrate/20260402000002_rename_scopeable_to_votable_in_cm_voting_credits.rb +0 -12
  288. data/db/migrate/20260403070000_add_name_to_cm_voting_sessions.rb +0 -5
  289. data/db/migrate/20260406000001_add_vendor_id_to_voting_tables.rb +0 -6
  290. data/db/migrate/20260406000001_rename_votes_remaining_to_amount_in_cm_voting_credits.rb +0 -11
  291. data/db/migrate/20260408085255_add_show_id_and_vendor_id_to_cm_voting_sessions.rb +0 -9
  292. data/db/migrate/20260410045815_create_cm_currency_rates.rb +0 -23
  293. data/db/migrate/20260411102139_add_metadata_to_cm_inventory_items.rb +0 -6
  294. data/db/migrate/20260420000001_rename_type_to_credit_type_in_cm_voting_credits.rb +0 -25
  295. data/db/migrate/20260422000001_create_cm_vote_fraud_events.rb +0 -23
  296. data/db/migrate/20260423000001_add_preview_to_taxons_products_and_sections.rb +0 -11
  297. data/db/migrate/20260423000002_create_preview_roles.rb +0 -24
  298. data/db/migrate/20260515120000_add_public_metadata_to_cm_voting_sessions.rb +0 -5
  299. data/db/migrate/20260520000001_optimize_cm_votes_indexes.rb +0 -22
  300. data/docs/sql/jsonb_query_guide.md +0 -57
  301. data/lib/spree_cm_commissioner/test_helper/factories/show_episode_factory.rb +0 -12
  302. data/lib/spree_cm_commissioner/test_helper/factories/show_factory.rb +0 -96
  303. data/lib/spree_cm_commissioner/test_helper/factories/vote_credit_factory.rb +0 -37
  304. data/lib/spree_cm_commissioner/test_helper/factories/vote_factory.rb +0 -28
  305. data/lib/spree_cm_commissioner/test_helper/factories/voting_credit_transaction_factory.rb +0 -11
  306. data/lib/spree_cm_commissioner/test_helper/factories/voting_session_factory.rb +0 -11
@@ -1,10 +1,10 @@
1
1
  module SpreeCmCommissioner
2
2
  class Route < Base
3
3
  include SpreeCmCommissioner::RouteType
4
- include SpreeCmCommissioner::Integrations::IntegrationMappable
5
4
  include SpreeCmCommissioner::StoreMetadata
5
+ include SpreeCmCommissioner::ServiceOrigin
6
6
 
7
- belongs_to :vendor, class_name: 'Spree::Vendor', optional: false
7
+ belongs_to :vendor, class_name: 'Spree::Vendor', inverse_of: :routes, optional: false
8
8
  belongs_to :tenant, class_name: 'SpreeCmCommissioner::Tenant', optional: true
9
9
 
10
10
  belongs_to :service_origin, class_name: 'Spree::Taxon', optional: true
@@ -67,6 +67,10 @@ module SpreeCmCommissioner
67
67
 
68
68
  private
69
69
 
70
+ def resolve_service_origin_id
71
+ vendor&.service_origin_id
72
+ end
73
+
70
74
  def validate_route_stops
71
75
  return if route_stops.valid?
72
76
 
@@ -1,7 +1,5 @@
1
1
  module SpreeCmCommissioner
2
2
  class SeatLayout < Base
3
- include SpreeCmCommissioner::Integrations::IntegrationMappable
4
-
5
3
  has_many :seat_sections, class_name: 'SpreeCmCommissioner::SeatSection', dependent: :destroy
6
4
 
7
5
  has_many :blocks, class_name: 'SpreeCmCommissioner::Block'
@@ -6,9 +6,6 @@ module SpreeCmCommissioner
6
6
 
7
7
  base.after_commit :create_inventory_items, on: :create
8
8
  base.after_commit :adjust_inventory_items_async, on: :destroy
9
-
10
- # Create maintaining task to purge product related caches
11
- base.after_commit { SpreeCmCommissioner::MaintenanceTasks::CacheInvalidation.pending.create_or_find_by(maintainable: variant.product) }
12
9
  end
13
10
 
14
11
  def update_vendor_total_inventory
@@ -18,10 +15,6 @@ module SpreeCmCommissioner
18
15
  private
19
16
 
20
17
  def create_inventory_items
21
- # Skip automatic inventory generation when variant has manual_generate_inventory_items set to true
22
- # Use case: For variants where inventory items need to be manually created/managed (e.g., external integrations)
23
- return if variant.manual_generate_inventory_items?
24
-
25
18
  SpreeCmCommissioner::InventoryItems::GenerateInventoryItemsJob.perform_later(variant_id: variant.id)
26
19
  end
27
20
 
@@ -74,6 +74,7 @@ module SpreeCmCommissioner
74
74
  base.has_many :taxon_option_values, class_name: 'SpreeCmCommissioner::TaxonOptionValue'
75
75
 
76
76
  base.after_commit :send_transaction_email_to_organizers, on: :create
77
+ base.after_commit :send_event_creation_telegram_alert, on: :create
77
78
 
78
79
  base.has_many :taxon_places, class_name: 'SpreeCmCommissioner::TaxonPlace', dependent: :destroy
79
80
  base.has_many :places, through: :taxon_places
@@ -82,21 +83,7 @@ module SpreeCmCommissioner
82
83
 
83
84
  base.has_many :import_orders, as: :importable, class_name: 'SpreeCmCommissioner::Imports::ImportOrder', dependent: :destroy
84
85
 
85
- base.scope :shows, -> { where(taxonomy_id: Spree::Taxonomy.shows.id, depth: 1) }
86
- base.scope :events, -> { where(taxonomy_id: Spree::Taxonomy.events.id, depth: 1) }
87
86
  base.has_many :agencies, class_name: 'SpreeCmCommissioner::Agency', foreign_key: :agency_category_id
88
- base.has_many :preview_roles, class_name: 'SpreeCmCommissioner::PreviewRole', as: :previewable
89
-
90
- base.scope :visible_to, lambda { |user|
91
- publicly_available = where(preview: false)
92
-
93
- if user
94
- allowed_ids = user.preview_roles.where(previewable_type: polymorphic_name).select(:previewable_id)
95
- publicly_available.or(where(preview: true, id: allowed_ids))
96
- else
97
- publicly_available
98
- end
99
- }
100
87
 
101
88
  # Create maintaining task to purge taxon related caches
102
89
  base.after_save { SpreeCmCommissioner::MaintenanceTasks::CacheInvalidation.pending.create_or_find_by(maintainable: self) }
@@ -109,7 +96,6 @@ module SpreeCmCommissioner
109
96
  .joins('INNER JOIN cm_homepage_sections ON cm_homepage_section_relatables.homepage_section_id = cm_homepage_sections.id')
110
97
  .where(cm_homepage_sections: { tenant_id: nil, active: true })
111
98
  .where(kind: :event)
112
- .where(preview: false)
113
99
  end
114
100
 
115
101
  def base.find_event(id)
@@ -154,6 +140,12 @@ module SpreeCmCommissioner
154
140
  SpreeCmCommissioner::OrganizersTransactionalEmailNotifier.call(event_id: id)
155
141
  end
156
142
 
143
+ def send_event_creation_telegram_alert
144
+ return unless kind == 'event' && depth == 1
145
+
146
+ SpreeCmCommissioner::EventCreationTelegramAlertSenderJob.perform_later(event_id: id)
147
+ end
148
+
157
149
  def sync_event_dates_to_line_items
158
150
  return unless event? && depth == 1
159
151
 
@@ -1,6 +1,6 @@
1
1
  module SpreeCmCommissioner
2
2
  module TaxonomyDecorator
3
- def self.prepended(base) # rubocop:disable Metrics/MethodLength
3
+ def self.prepended(base)
4
4
  base.include SpreeCmCommissioner::TaxonKind
5
5
 
6
6
  base.belongs_to :vendor, class_name: 'Spree::Vendor', optional: true
@@ -15,15 +15,6 @@ module SpreeCmCommissioner
15
15
  end
16
16
  end
17
17
 
18
- def base.shows
19
- ActiveRecord::Base.connected_to(role: :writing) do
20
- shows = Spree::Taxonomy.find_or_create_by(name: 'Shows', store: Spree::Store.default)
21
- shows.kind = :event
22
- shows.save if shows.changed?
23
- shows
24
- end
25
- end
26
-
27
18
  def base.businesses
28
19
  ActiveRecord::Base.connected_to(role: :writing) do
29
20
  businesses = Spree::Taxonomy.find_or_create_by(name: 'Businesses', store: Spree::Store.default)
@@ -24,8 +24,6 @@ module SpreeCmCommissioner
24
24
 
25
25
  before_validation :generate_slug, if: -> { slug.blank? && name.present? }
26
26
 
27
- validate :single_active_vendor
28
-
29
27
  def active_vendor
30
28
  vendors.where(state: :active).first
31
29
  end
@@ -45,12 +43,5 @@ module SpreeCmCommissioner
45
43
  def generate_slug
46
44
  self.slug = name.parameterize if slug.blank?
47
45
  end
48
-
49
- # Add Guardrails to ensure data integrity and make system predictable.
50
- def single_active_vendor
51
- return unless vendors.where(state: :active).count > 1
52
-
53
- errors.add(:base, 'must have at most one active vendor')
54
- end
55
46
  end
56
47
  end
@@ -2,7 +2,7 @@ module SpreeCmCommissioner
2
2
  class Trip < Base
3
3
  include SpreeCmCommissioner::StoreMetadata
4
4
  include SpreeCmCommissioner::RouteType
5
- include SpreeCmCommissioner::Integrations::IntegrationMappable
5
+ include SpreeCmCommissioner::ServiceOrigin
6
6
 
7
7
  attr_accessor :hours, :minutes, :seconds
8
8
 
@@ -26,7 +26,7 @@ module SpreeCmCommissioner
26
26
  after_commit :update_route_price_range, on: %i[create update]
27
27
 
28
28
  belongs_to :vendor, class_name: 'Spree::Vendor', inverse_of: :trips, optional: false
29
- belongs_to :product, class_name: 'Spree::Product', inverse_of: :trip, optional: true
29
+ belongs_to :product, class_name: 'Spree::Product', inverse_of: :trip, optional: false
30
30
 
31
31
  belongs_to :service_origin, class_name: 'Spree::Taxon', optional: true
32
32
 
@@ -134,6 +134,10 @@ module SpreeCmCommissioner
134
134
 
135
135
  private
136
136
 
137
+ def resolve_service_origin_id
138
+ route&.service_origin_id || vendor&.service_origin_id
139
+ end
140
+
137
141
  def duplicate_seat_layout_from_vehicle
138
142
  # Duplicate the vehicle's seat layout into this trip. Copies nested
139
143
  # seat sections and blocks while excluding identifying columns and
@@ -1,7 +1,5 @@
1
1
  module SpreeCmCommissioner
2
2
  class TripStop < Base
3
- include SpreeCmCommissioner::Integrations::IntegrationMappable
4
-
5
3
  acts_as_list column: :sequence, scope: :trip_id
6
4
 
7
5
  belongs_to :trip, class_name: 'SpreeCmCommissioner::Trip', optional: false
@@ -19,8 +19,6 @@ module SpreeCmCommissioner
19
19
  base.has_many :payments, as: :payable, class_name: 'Spree::Payment', dependent: :nullify
20
20
  base.has_many :role_permissions, through: :spree_roles, class_name: 'SpreeCmCommissioner::RolePermission'
21
21
  base.has_many :permissions, through: :role_permissions, class_name: 'SpreeCmCommissioner::Permission'
22
- base.has_many :preview_spree_roles, -> { where(role_type: :preview) }, through: :role_users, source: :role, class_name: 'Spree::Role'
23
- base.has_many :preview_roles, through: :preview_spree_roles, class_name: 'SpreeCmCommissioner::PreviewRole'
24
22
  base.has_many :line_items, through: :orders, source: :line_items
25
23
  base.has_many :check_ins, foreign_key: 'check_in_by_id', class_name: 'SpreeCmCommissioner::CheckIn'
26
24
  base.has_many :user_events, class_name: 'SpreeCmCommissioner::UserEvent'
@@ -37,9 +35,6 @@ module SpreeCmCommissioner
37
35
  base.has_many :user_agencies, class_name: 'SpreeCmCommissioner::UserAgency'
38
36
  base.has_many :user_places, class_name: 'SpreeCmCommissioner::UserPlace'
39
37
  base.has_many :places, through: :user_places, class_name: 'SpreeCmCommissioner::Place'
40
- base.has_many :voting_credits, class_name: 'SpreeCmCommissioner::VotingCredit', dependent: :destroy
41
- base.has_many :votes, class_name: 'SpreeCmCommissioner::Vote', dependent: :destroy
42
- base.has_many :voting_credit_transactions, through: :voting_credits, class_name: 'SpreeCmCommissioner::VotingCreditTransaction'
43
38
 
44
39
  base.has_one :profile, as: :viewable, dependent: :destroy, class_name: 'SpreeCmCommissioner::UserProfile'
45
40
  base.has_one :customer, class_name: 'SpreeCmCommissioner::Customer'
@@ -6,7 +6,6 @@ module SpreeCmCommissioner
6
6
  base.include SpreeCmCommissioner::VariantOptionsConcern
7
7
  base.include SpreeCmCommissioner::KycBitwise
8
8
  base.include SpreeCmCommissioner::Integrations::IntegrationMappable
9
- base.include SpreeCmCommissioner::VariantMetadata
10
9
 
11
10
  base.after_commit :update_vendor_price
12
11
  base.validate :validate_option_types
@@ -146,10 +146,6 @@ module SpreeCmCommissioner
146
146
  @seat_type ||= option_value_name_for(option_type_name: 'seat-type')
147
147
  end
148
148
 
149
- def vote_package_amount
150
- @vote_package_amount ||= option_value_name_for(option_type_name: 'vote-package')&.to_i
151
- end
152
-
153
149
  # can consider as customers.
154
150
  def number_of_guests
155
151
  number_of_adults + number_of_kids
@@ -1,7 +1,6 @@
1
1
  module SpreeCmCommissioner
2
2
  class Vehicle < Base
3
3
  include SpreeCmCommissioner::VehicleKind
4
- include SpreeCmCommissioner::Integrations::IntegrationMappable
5
4
 
6
5
  belongs_to :vendor, class_name: 'Spree::Vendor'
7
6
  belongs_to :vehicle_type, class_name: 'SpreeCmCommissioner::VehicleType'
@@ -14,8 +13,6 @@ module SpreeCmCommissioner
14
13
  validates :name, presence: true
15
14
  validates :license_plate, uniqueness: true, allow_blank: true
16
15
 
17
- has_one :seat_layout, through: :vehicle_type
18
-
19
16
  self.whitelisted_ransackable_attributes = %w[name license_plate kind]
20
17
 
21
18
  def display_name
@@ -2,7 +2,6 @@ module SpreeCmCommissioner
2
2
  class VehicleType < Base
3
3
  include SpreeCmCommissioner::StoreMetadata
4
4
  include SpreeCmCommissioner::VehicleKind
5
- include SpreeCmCommissioner::Integrations::IntegrationMappable
6
5
 
7
6
  # This model has no seat_layout column (polymorphic association), so we store the preload_seat_layout_id ID in public_metadata.
8
7
  # This lets us check if a seat layout exists without triggering a database query.
@@ -30,14 +30,9 @@ module SpreeCmCommissioner
30
30
  base.has_many :nearby_places, -> { order(position: :asc) }, class_name: 'SpreeCmCommissioner::VendorPlace', dependent: :destroy
31
31
 
32
32
  base.has_many :stock_items, through: :variants, class_name: 'Spree::StockItem'
33
- base.has_many :currency_rates, class_name: 'SpreeCmCommissioner::CurrencyRate', dependent: :destroy
34
33
 
35
34
  base.has_many :taxon_vendors, class_name: 'SpreeCmCommissioner::TaxonVendor'
36
35
  base.has_many :taxons, through: :taxon_vendors
37
- base.has_many :shows, -> { where(spree_taxons: { type: 'SpreeCmCommissioner::Show' }) },
38
- through: :taxon_vendors, source: :taxon, class_name: 'SpreeCmCommissioner::Show'
39
-
40
- base.has_many :voting_sessions, class_name: 'SpreeCmCommissioner::VotingSession', dependent: :destroy
41
36
 
42
37
  base.has_many :promoted_option_types, -> { where(promoted: true).order(:position) },
43
38
  through: :vendor_option_types, source: :option_type
@@ -102,7 +97,6 @@ module SpreeCmCommissioner
102
97
  base.has_many :boarding_trip_stops, through: :trips, class_name: 'SpreeCmCommissioner::TripStop', source: :boarding_trip_stops
103
98
  base.has_many :drop_off_trip_stops, through: :trips, class_name: 'SpreeCmCommissioner::TripStop', source: :drop_off_trip_stops
104
99
  base.has_many :pricing_models, class_name: 'SpreeCmCommissioner::PricingModel', foreign_key: :vendor_id, dependent: :destroy
105
- base.has_many :orders, -> { distinct }, through: :variants, source: :orders
106
100
 
107
101
  base.has_many :agency_categories, -> { where(kind: :agency_category) }, class_name: 'Spree::Taxon', foreign_key: :vendor_id
108
102
 
@@ -245,21 +239,6 @@ module SpreeCmCommissioner
245
239
  end
246
240
 
247
241
  delegate :present?, to: :tenant, prefix: true
248
-
249
- # Returns the exchange rate between two currencies
250
- # If no direct rate exists, calculates the inverse rate from the reverse pair
251
- # Returns 1.0 for identical currencies, nil if no rate is found
252
- def exchange_rate(from_currency, to_currency)
253
- return 1.0 if from_currency == to_currency
254
-
255
- pair = currency_rates.by_pair(from_currency, to_currency).first
256
- return pair.rate if pair.present?
257
-
258
- reverse_pair = currency_rates.by_pair(to_currency, from_currency).first
259
- return (1.0 / reverse_pair.rate).round(6) if reverse_pair.present?
260
-
261
- nil
262
- end
263
242
  end
264
243
  end
265
244
 
@@ -1,7 +1,5 @@
1
1
  module SpreeCmCommissioner
2
2
  class VendorPlace < Base
3
- include SpreeCmCommissioner::Integrations::IntegrationMappable
4
-
5
3
  enum place_type: { venue: 0, branch: 1, stop: 2, location: 3 }
6
4
  acts_as_list scope: :vendor
7
5
 
@@ -46,6 +46,15 @@
46
46
  <% end %>
47
47
  </div>
48
48
 
49
+ <!-- Telegram New Event Alert Chat ID -->
50
+ <div class="col-6">
51
+ <%= f.field_container :preferred_telegram_new_event_alert_chat_id do %>
52
+ <%= f.label :preferred_telegram_new_event_alert_chat_id, Spree.t(:telegram_new_event_alert_chat_id) %>
53
+ <%= f.text_field :preferred_telegram_new_event_alert_chat_id, class: 'form-control' %>
54
+ <%= f.error_message_on :preferred_telegram_new_event_alert_chat_id %>
55
+ <% end %>
56
+ </div>
57
+
49
58
  <!-- Assetlinks -->
50
59
  <div class="col-12">
51
60
  <%= f.field_container :preferred_assetlinks do %>
@@ -43,7 +43,7 @@ module SpreeCmCommissioner
43
43
  @date = normalize_date(date)
44
44
  @vendor_id = vendor_id
45
45
  @tenant_id = tenant_id
46
- @number_of_guests = number_of_guests || 1
46
+ @number_of_guests = Integer(number_of_guests || 1)
47
47
  @route_type = route_type
48
48
  @options = options
49
49
  end
@@ -106,7 +106,12 @@ module SpreeCmCommissioner
106
106
 
107
107
  INNER JOIN spree_prices prices
108
108
  ON prices.variant_id = master.id
109
+ AND prices.inventory_item_id IS NULL
109
110
  AND prices.deleted_at IS NULL
111
+
112
+ LEFT JOIN spree_prices AS date_prices
113
+ ON date_prices.inventory_item_id = cm_inventory_items.id
114
+ AND date_prices.deleted_at IS NULL
110
115
  SQL
111
116
  .where(parent: { origin_place_id: origin_id, destination_place_id: destination_id })
112
117
 
@@ -114,14 +119,6 @@ module SpreeCmCommissioner
114
119
  scope = scope.where(parent: { route_type: SpreeCmCommissioner::Trip.route_types[route_type] }) if route_type.present?
115
120
  scope = scope.where(parent: { vendor_id: vendor_id }) if vendor_id.present?
116
121
 
117
- if options.key?(:featured)
118
- scope = if ActiveModel::Type::Boolean.new.cast(options[:featured])
119
- scope.where('parent.featured_until >= ?', Time.current)
120
- else
121
- scope.where('parent.featured_until IS NULL OR parent.featured_until < ?', Time.current)
122
- end
123
- end
124
-
125
122
  if tenant_id.present?
126
123
  scope = scope.joins('INNER JOIN spree_vendors v ON v.id = parent.vendor_id')
127
124
  .where(v: { tenant_id: tenant_id })
@@ -140,9 +137,9 @@ module SpreeCmCommissioner
140
137
  SUM(cm_inventory_items.quantity_available) AS quantity_available,
141
138
  SUM(cm_inventory_items.max_capacity) AS max_capacity,
142
139
 
143
- prices.amount,
144
- prices.compare_at_amount,
145
- prices.currency
140
+ COALESCE(MIN(date_prices.amount), MIN(prices.amount)) AS price,
141
+ COALESCE(MIN(date_prices.compare_at_amount), MIN(prices.compare_at_amount)) AS compare_at_price,
142
+ MIN(COALESCE(date_prices.currency, prices.currency)) AS currency
146
143
  SQL
147
144
  # GROUP BY ensures one result row per parent+leg combination, and SUM aggregates inventory
148
145
  # across all variants for that leg. Without aggregation, the single JOIN on spree_variants
@@ -157,10 +154,7 @@ module SpreeCmCommissioner
157
154
  parent.destination_place_id,
158
155
  parent.vendor_id,
159
156
  stop_legs.sequence,
160
- stop_legs.offset_days,
161
- prices.amount,
162
- prices.compare_at_amount,
163
- prices.currency
157
+ stop_legs.offset_days
164
158
  SQL
165
159
  .having('SUM(cm_inventory_items.quantity_available) >= ?', number_of_guests)
166
160
  end
@@ -232,47 +226,35 @@ module SpreeCmCommissioner
232
226
  vendor: trip.vendor,
233
227
  product_id: trip.product_id,
234
228
 
235
- price: trip_row.amount,
229
+ price: trip_row.price,
236
230
  currency: trip_row.currency,
237
- compare_at_amount: trip_row.compare_at_amount,
231
+ compare_at_price: trip_row.compare_at_price,
238
232
 
239
233
  quantity_available: trip_row.quantity_available,
240
234
  max_capacity: trip_row.max_capacity,
241
235
  offset_days: trip_row.offset_days,
242
236
  sequence: trip_row.sequence,
243
237
 
244
- boarding: build_boarding_info_from_record(trip),
245
- drop_off: build_drop_off_info_from_record(trip),
238
+ stops: build_stops_from_record(trip),
246
239
 
247
240
  amenities: trip.vehicle_type&.option_values || []
248
241
  )
249
242
  end
250
243
 
251
- # @return Hash { stop_id, stop_name, departure_time } or nil
252
- def build_boarding_info_from_record(trip)
253
- trip_stop = trip.trip_stops.min_by(&:sequence)&.then do |stop|
254
- stop if stop&.allow_boarding
244
+ # @return [Array<Hash>] All stops ordered by sequence with lat/lon and timing info
245
+ def build_stops_from_record(trip)
246
+ trip.trip_stops.sort_by(&:sequence).map do |stop|
247
+ {
248
+ stop_id: stop.stop_place_id,
249
+ stop_name: stop.stop_name,
250
+ allow_boarding: stop.allow_boarding,
251
+ allow_drop_off: stop.allow_drop_off,
252
+ departure_time: stop.departure_time,
253
+ arrival_time: stop.arrival_time,
254
+ lat: stop.stop_place&.lat,
255
+ lon: stop.stop_place&.lon
256
+ }
255
257
  end
256
-
257
- return nil unless trip_stop
258
-
259
- {
260
- stop_id: trip_stop.stop_place_id,
261
- stop_name: trip_stop.stop_name,
262
- departure_time: trip_stop.departure_time
263
- }
264
- end
265
-
266
- # @return Hash { stop_id, stop_name, arrival_time } or nil
267
- def build_drop_off_info_from_record(trip)
268
- trip_stop = trip.trip_stops.reverse.find(&:allow_drop_off)
269
- return nil unless trip_stop
270
-
271
- {
272
- stop_id: trip_stop.stop_place_id,
273
- stop_name: trip_stop.stop_name,
274
- arrival_time: trip_stop.arrival_time
275
- }
276
258
  end
277
259
  end
278
260
  end
@@ -32,7 +32,7 @@ module SpreeCmCommissioner
32
32
  @date = date.to_date == Time.zone.today ? Time.zone.now : Time.zone.parse(date.to_s)
33
33
  @vendor_id = vendor_id
34
34
  @tenant_id = tenant_id
35
- @number_of_guests = number_of_guests || 1
35
+ @number_of_guests = Integer(number_of_guests || 1)
36
36
  @route_type = route_type
37
37
  @options = options
38
38
  end
@@ -72,8 +72,12 @@ module SpreeCmCommissioner
72
72
  INNER JOIN cm_places AS origin_places ON origin_places.id = cm_trips.origin_place_id
73
73
  INNER JOIN cm_places AS dest_places ON dest_places.id = cm_trips.destination_place_id
74
74
  INNER JOIN spree_variants AS master ON master.product_id = cm_trips.product_id AND master.is_master = true
75
- INNER JOIN spree_prices AS prices ON prices.variant_id = master.id AND prices.deleted_at IS NULL
75
+ INNER JOIN spree_prices AS prices ON prices.variant_id = master.id AND prices.inventory_item_id IS NULL AND prices.deleted_at IS NULL
76
76
  INNER JOIN (#{inventory_subquery.to_sql}) iv ON iv.product_id = cm_trips.product_id
77
+ LEFT JOIN spree_variants AS trip_variant ON trip_variant.product_id = cm_trips.product_id AND trip_variant.is_master = false AND trip_variant.deleted_at IS NULL
78
+ LEFT JOIN cm_inventory_items AS date_iv ON date_iv.variant_id = trip_variant.id AND date_iv.inventory_date = '#{date.to_date}' AND date_iv.quantity_available >= #{number_of_guests}
79
+ LEFT JOIN spree_prices AS date_prices ON date_prices.inventory_item_id = date_iv.id AND date_prices.deleted_at IS NULL
80
+ LEFT JOIN (#{stops_subquery_sql}) all_stops ON all_stops.trip_id = cm_trips.id
77
81
  SQL
78
82
  )
79
83
  .where(<<~SQL.squish, origin: origin_id, destination: destination_id)
@@ -89,46 +93,47 @@ module SpreeCmCommissioner
89
93
  cm_trips.destination_place_id = :destination
90
94
  )
91
95
  SQL
92
- .then { |scope| apply_featured_filter(scope) }
93
- .order('cm_trips.id, boarding.departure_time')
96
+ .order(Arel.sql('cm_trips.id, COALESCE(date_prices.amount, prices.amount) ASC NULLS LAST'))
94
97
  end
95
98
 
96
- def apply_featured_filter(scope)
97
- return scope unless featured_filter_requested?
98
-
99
- if featured?
100
- scope.where('cm_trips.featured_until >= ?', Time.current)
101
- else
102
- scope.where('cm_trips.featured_until IS NULL OR cm_trips.featured_until < ?', Time.current)
103
- end
104
- end
105
-
106
- def featured_filter_requested?
107
- options.respond_to?(:key?) && options.key?(:featured)
108
- end
109
-
110
- def featured?
111
- ActiveModel::Type::Boolean.new.cast(options[:featured])
112
- end
113
-
114
- # SQL to select trip attributes along with boarding/drop-off details, place names, pricing, and inventory
99
+ # SQL to select trip attributes along with place names, pricing, inventory, and ordered stop list
115
100
  def selected_columns_sql
116
101
  <<~SQL.squish
117
102
  DISTINCT ON (cm_trips.id)
118
103
  cm_trips.*,
119
104
  boarding.departure_time AS boarding_departure_time,
120
- boarding.stop_place_id AS boarding_stop_id,
121
- boarding.stop_name AS boarding_stop_name,
122
- drop_off.stop_name AS drop_off_stop_name,
123
- drop_off.stop_place_id AS drop_off_stop_id,
124
- drop_off.arrival_time AS drop_off_arrival_time,
125
105
  COALESCE(iv.quantity_available, 0) AS quantity_available,
126
106
  COALESCE(iv.max_capacity, 0) AS max_capacity,
127
107
  origin_places.name AS origin_place_name,
128
108
  dest_places.name AS destination_place_name,
129
- prices.amount,
130
- prices.compare_at_amount,
131
- prices.currency
109
+ COALESCE(date_prices.amount, prices.amount) AS price,
110
+ COALESCE(date_prices.compare_at_amount, prices.compare_at_amount) AS compare_at_price,
111
+ COALESCE(date_prices.currency, prices.currency) AS currency,
112
+ all_stops.stops AS stops
113
+ SQL
114
+ end
115
+
116
+ # Subquery to aggregate all stops for each trip into a JSON array, ordered by sequence.
117
+ # Each stop includes place coordinates (lat/lon) joined from cm_places.
118
+ # Returns one row per trip_id with a `stops` JSON column consumed by selected_columns_sql.
119
+ def stops_subquery_sql
120
+ <<~SQL.squish
121
+ SELECT ts.trip_id,
122
+ json_agg(
123
+ json_build_object(
124
+ 'stop_id', ts.stop_place_id,
125
+ 'stop_name', ts.stop_name,
126
+ 'allow_boarding', ts.allow_boarding,
127
+ 'allow_drop_off', ts.allow_drop_off,
128
+ 'departure_time', ts.departure_time AT TIME ZONE 'UTC',
129
+ 'arrival_time', ts.arrival_time AT TIME ZONE 'UTC',
130
+ 'lat', p.lat,
131
+ 'lon', p.lon
132
+ ) ORDER BY ts.sequence
133
+ ) AS stops
134
+ FROM cm_trip_stops ts
135
+ LEFT JOIN cm_places p ON p.id = ts.stop_place_id
136
+ GROUP BY ts.trip_id
132
137
  SQL
133
138
  end
134
139
 
@@ -11,16 +11,14 @@ module SpreeCmCommissioner
11
11
  @number_of_guests = number_of_guests || 1
12
12
  @route_type = route_type
13
13
  @options = options
14
- @page = (options[:page] || 1).to_i
15
- @per_page = options[:per_page]
16
14
  end
17
15
 
18
16
  def call
19
- return Kaminari.paginate_array([]).page(@page).per(@per_page) if date.to_date < Date.current
17
+ return Kaminari.paginate_array([]) if date.to_date < Date.current
20
18
 
21
19
  result = direct_trips
22
20
  result += multi_leg_trips if result.empty? || result.size < 3 || ActiveModel::Type::Boolean.new.cast(@options[:include_multi_leg])
23
- Kaminari.paginate_array(result).page(@page).per(@per_page)
21
+ Kaminari.paginate_array(result)
24
22
  end
25
23
 
26
24
  private
@@ -2,7 +2,7 @@ module Spree
2
2
  module V2
3
3
  module Storefront
4
4
  class HomepageSectionSerializer < BaseSerializer
5
- attributes :id, :title, :segments, :description, :active, :position, :preview, :created_at, :updated_at
5
+ attributes :id, :title, :segments, :description, :active, :position, :created_at, :updated_at
6
6
  has_many :homepage_section_relatables
7
7
  end
8
8
  end
@@ -13,7 +13,7 @@ module Spree
13
13
  base.has_one :venue, serializer: ::SpreeCmCommissioner::V2::Storefront::ProductPlaceSerializer
14
14
 
15
15
  base.attributes :need_confirmation, :product_type, :kyc, :kyc_fields, :allowed_upload_later, :allow_anonymous_booking, :use_video_as_default
16
- base.attributes :reveal_description, :discontinue_on, :public_metadata, :purchasable_on, :preview
16
+ base.attributes :reveal_description, :discontinue_on, :public_metadata, :purchasable_on
17
17
 
18
18
  # Expose only the `event_id` here instead of the full event object.
19
19
  # This lets the client fetch event details separately (usually already cached),
@@ -2,7 +2,7 @@ module Spree
2
2
  module V2
3
3
  module Storefront
4
4
  class RoleSerializer < BaseSerializer
5
- attributes :name, :role_type
5
+ attributes :name
6
6
  end
7
7
  end
8
8
  end
@@ -15,8 +15,7 @@ module Spree
15
15
 
16
16
  base.attributes :custom_redirect_url, :kind, :subtitle, :from_date, :to_date,
17
17
  :background_color, :foreground_color, :show_badge_status,
18
- :purchasable_on, :vendor_id, :available_on, :hide_video_banner,
19
- :preview
18
+ :purchasable_on, :vendor_id, :available_on, :hide_video_banner
20
19
 
21
20
  # To get full seat layout details, call the seat_layouts API with this ID.
22
21
  base.attribute :seat_layout_ids, &:preload_seat_layout_ids
@@ -3,7 +3,7 @@ module Spree
3
3
  module Tenant
4
4
  class HomepageSectionSerializer < BaseSerializer
5
5
  attributes :id, :title, :segments, :description,
6
- :active, :position, :preview, :created_at, :updated_at
6
+ :active, :position, :created_at, :updated_at
7
7
 
8
8
  has_many :homepage_section_relatables, serializer: ::Spree::V2::Tenant::HomepageSectionRelatableSerializer
9
9
  end
@@ -2,7 +2,7 @@ module Spree
2
2
  module V2
3
3
  module Tenant
4
4
  class RoleSerializer < BaseSerializer
5
- attributes :name, :presentation, :role_type
5
+ attributes :name
6
6
  end
7
7
  end
8
8
  end
@@ -15,8 +15,13 @@ module SpreeCmCommissioner
15
15
  expires_in: 30.minutes
16
16
  )
17
17
 
18
- attributes :origin_place, :destination_place, :boarding, :drop_off, :price, :compare_at_amount, :currency, :quantity_available, :max_capacity,
19
- :allow_seat_selection, :departure_time, :route_type, :distance, :display_price, :offset_days
18
+ attributes :origin_place, :destination_place, :stops, :price, :compare_at_price, :currency, :quantity_available, :max_capacity,
19
+ :allow_seat_selection, :departure_time, :route_type, :distance, :offset_days,
20
+ :featured_until, :display_price, :display_compare_at_price
21
+
22
+ # Deprecated for backwards compatibility
23
+ attribute :compare_at_amount, &:compare_at_price
24
+
20
25
  attribute :duration_in_hms, &:duration_in_hms
21
26
  attribute :arrival_time, &:arrival_time
22
27
  belongs_to :vendor, serializer: ::SpreeCmCommissioner::V2::Storefront::TripVendorSerializer