spree_cm_commissioner 2.0.3 → 2.1.0.pre.pre1

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 (263) 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/locations_controller.rb +62 -0
  9. data/app/controllers/spree/admin/stock_managements_controller.rb +63 -1
  10. data/app/controllers/spree/api/v2/platform/places_controller.rb +4 -1
  11. data/app/controllers/spree/api/v2/storefront/accommodations/variants_controller.rb +42 -0
  12. data/app/controllers/spree/api/v2/storefront/accommodations_controller.rb +14 -31
  13. data/app/controllers/spree/api/v2/storefront/dynamic_fields_controller.rb +42 -0
  14. data/app/controllers/spree/api/v2/storefront/guests_controller.rb +28 -18
  15. data/app/controllers/spree/api/v2/storefront/inventory_items_controller.rb +57 -0
  16. data/app/controllers/spree/api/v2/storefront/queue_cart/line_items_controller.rb +2 -2
  17. data/app/controllers/spree/api/v2/storefront/transit/draft_orders_controller.rb +46 -0
  18. data/app/controllers/spree/api/v2/storefront/trip_places_controller.rb +29 -0
  19. data/app/controllers/spree/api/v2/storefront/trip_search_controller.rb +62 -0
  20. data/app/controllers/spree/api/v2/storefront/trips_controller.rb +24 -0
  21. data/app/controllers/spree_cm_commissioner/admin/products_controller_decorator.rb +14 -0
  22. data/app/finders/spree_cm_commissioner/accommodations/find.rb +37 -0
  23. data/app/finders/spree_cm_commissioner/accommodations/find_variant.rb +32 -0
  24. data/app/interactors/spree_cm_commissioner/billing_address_creator.rb +33 -0
  25. data/app/interactors/spree_cm_commissioner/create_vendor.rb +11 -1
  26. data/app/interactors/spree_cm_commissioner/customer_notification_sender.rb +7 -2
  27. data/app/interactors/spree_cm_commissioner/ensure_correct_product_type.rb +40 -0
  28. data/app/interactors/spree_cm_commissioner/fetch_facebook_user_data.rb +45 -0
  29. data/app/interactors/spree_cm_commissioner/google_places_fetcher.rb +1 -0
  30. data/app/interactors/spree_cm_commissioner/intercity_taxi_order_creator.rb +106 -0
  31. data/app/interactors/spree_cm_commissioner/inventory_item_syncer.rb +25 -0
  32. data/app/interactors/spree_cm_commissioner/stock/inventory_item_resetter.rb +44 -0
  33. data/app/interactors/spree_cm_commissioner/stock/inventory_items_adjuster.rb +13 -0
  34. data/app/interactors/spree_cm_commissioner/stock/inventory_items_generator.rb +15 -0
  35. data/app/interactors/spree_cm_commissioner/stock/permanent_inventory_items_generator.rb +75 -0
  36. data/app/interactors/spree_cm_commissioner/stock/stock_movement_creator.rb +32 -0
  37. data/app/interactors/spree_cm_commissioner/taxi_trip_creator.rb +66 -0
  38. data/app/interactors/spree_cm_commissioner/transit/draft_order_creator.rb +136 -0
  39. data/app/interactors/spree_cm_commissioner/trip_clone_creator.rb +155 -0
  40. data/app/interactors/spree_cm_commissioner/user_fb_token_authenticator.rb +37 -0
  41. data/app/interactors/spree_cm_commissioner/user_fb_token_checker.rb +20 -0
  42. data/app/interactors/spree_cm_commissioner/user_identity_checker.rb +8 -8
  43. data/app/interactors/spree_cm_commissioner/user_registration_with_fb_token.rb +62 -0
  44. data/app/interactors/spree_cm_commissioner/variant_block_updater.rb +62 -0
  45. data/app/interactors/spree_cm_commissioner/vehicle_updater.rb +41 -0
  46. data/app/jobs/spree_cm_commissioner/application_job.rb +20 -0
  47. data/app/jobs/spree_cm_commissioner/application_unique_job.rb +20 -0
  48. data/app/jobs/spree_cm_commissioner/ensure_correct_product_type_job.rb +7 -0
  49. data/app/jobs/spree_cm_commissioner/inventory_item_syncer_job.rb +7 -0
  50. data/app/jobs/spree_cm_commissioner/stock/inventory_items_adjuster_job.rb +11 -0
  51. data/app/jobs/spree_cm_commissioner/stock/inventory_items_generator_job.rb +11 -0
  52. data/app/jobs/spree_cm_commissioner/stock/permanent_inventory_items_generator_job.rb +9 -0
  53. data/app/models/concerns/spree_cm_commissioner/line_item_durationable.rb +18 -15
  54. data/app/models/concerns/spree_cm_commissioner/line_item_guests_concern.rb +29 -15
  55. data/app/models/concerns/spree_cm_commissioner/line_item_transitable.rb +144 -0
  56. data/app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb +3 -12
  57. data/app/models/concerns/spree_cm_commissioner/order_seatable.rb +44 -0
  58. data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +39 -0
  59. data/app/models/concerns/spree_cm_commissioner/product_delegation.rb +1 -3
  60. data/app/models/concerns/spree_cm_commissioner/product_type.rb +10 -0
  61. data/app/models/concerns/spree_cm_commissioner/route_type.rb +1 -1
  62. data/app/models/concerns/spree_cm_commissioner/taxon_kind.rb +1 -1
  63. data/app/models/concerns/spree_cm_commissioner/user_identity.rb +12 -4
  64. data/app/models/concerns/spree_cm_commissioner/variant_options_concern.rb +1 -0
  65. data/app/models/concerns/spree_cm_commissioner/vehicle_type.rb +11 -0
  66. data/app/models/spree_cm_commissioner/address_decorator.rb +36 -2
  67. data/app/models/spree_cm_commissioner/block.rb +43 -0
  68. data/app/models/spree_cm_commissioner/customer_notification.rb +6 -1
  69. data/app/models/spree_cm_commissioner/dynamic_field.rb +2 -0
  70. data/app/models/spree_cm_commissioner/guest.rb +128 -40
  71. data/app/models/spree_cm_commissioner/guest_dynamic_field.rb +41 -27
  72. data/app/models/spree_cm_commissioner/inventory.rb +11 -0
  73. data/app/models/spree_cm_commissioner/inventory_item.rb +82 -0
  74. data/app/models/spree_cm_commissioner/line_item_decorator.rb +47 -78
  75. data/app/models/spree_cm_commissioner/notification_taxon.rb +1 -1
  76. data/app/models/spree_cm_commissioner/option_type_decorator.rb +1 -11
  77. data/app/models/spree_cm_commissioner/order/address_book_decorator.rb +30 -12
  78. data/app/models/spree_cm_commissioner/order_decorator.rb +38 -1
  79. data/app/models/spree_cm_commissioner/place.rb +3 -4
  80. data/app/models/spree_cm_commissioner/price_decorator.rb +9 -0
  81. data/app/models/spree_cm_commissioner/product_decorator.rb +41 -9
  82. data/app/models/spree_cm_commissioner/redis_stock/cached_inventory_items_builder.rb +41 -0
  83. data/app/models/spree_cm_commissioner/redis_stock/inventory_updater.rb +126 -0
  84. data/app/models/spree_cm_commissioner/redis_stock/line_items_cached_inventory_items_builder.rb +36 -0
  85. data/app/models/spree_cm_commissioner/redis_stock/variant_cached_inventory_items_builder.rb +25 -0
  86. data/app/models/spree_cm_commissioner/reserved_block.rb +31 -0
  87. data/app/models/spree_cm_commissioner/saved_guest.rb +21 -0
  88. data/app/models/spree_cm_commissioner/seat_layout.rb +20 -0
  89. data/app/models/spree_cm_commissioner/seat_section.rb +16 -0
  90. data/app/models/spree_cm_commissioner/seats/blocks_canceler.rb +30 -0
  91. data/app/models/spree_cm_commissioner/seats/blocks_holder.rb +53 -0
  92. data/app/models/spree_cm_commissioner/seats/blocks_reserver.rb +49 -0
  93. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_on_hold_by_other_guest.rb +4 -0
  94. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_reserved_by_other_guest.rb +4 -0
  95. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_reserved_by_same_guest.rb +4 -0
  96. data/app/models/spree_cm_commissioner/seats/errors/unable_to_save_reserved_block_record.rb +4 -0
  97. data/app/models/spree_cm_commissioner/service_calendar.rb +0 -2
  98. data/app/models/spree_cm_commissioner/state_decorator.rb +0 -1
  99. data/app/models/spree_cm_commissioner/stock/availability_checker.rb +26 -25
  100. data/app/models/spree_cm_commissioner/stock/availability_validator_decorator.rb +2 -1
  101. data/app/models/spree_cm_commissioner/stock/line_item_availability_checker.rb +3 -3
  102. data/app/models/spree_cm_commissioner/stock/order_availability_checker.rb +44 -0
  103. data/app/models/spree_cm_commissioner/stock_item_decorator.rb +17 -0
  104. data/app/models/spree_cm_commissioner/taxon_decorator.rb +7 -1
  105. data/app/models/spree_cm_commissioner/taxonomy_decorator.rb +0 -6
  106. data/app/models/spree_cm_commissioner/trip.rb +19 -10
  107. data/app/models/spree_cm_commissioner/trip_connection.rb +5 -5
  108. data/app/models/spree_cm_commissioner/trip_stop.rb +10 -21
  109. data/app/models/spree_cm_commissioner/user_decorator.rb +1 -1
  110. data/app/models/spree_cm_commissioner/variant_block.rb +17 -0
  111. data/app/models/spree_cm_commissioner/variant_decorator.rb +37 -47
  112. data/app/models/spree_cm_commissioner/variant_options.rb +4 -23
  113. data/app/models/spree_cm_commissioner/vehicle.rb +12 -15
  114. data/app/models/spree_cm_commissioner/vendor_decorator.rb +14 -14
  115. data/app/models/spree_cm_commissioner/vendor_place.rb +13 -3
  116. data/app/overrides/spree/admin/products/_form/industry_taxons.html.erb.deface +26 -0
  117. data/app/overrides/spree/admin/products/_form/taxons.html.erb.deface +26 -0
  118. data/app/overrides/spree/admin/shared/sub_menu/_configuration/locations_tab.html.erb.deface +5 -0
  119. data/app/queries/spree_cm_commissioner/trip_query.rb +110 -131
  120. data/app/request_schemas/spree_cm_commissioner/accommodation_request_schema.rb +3 -0
  121. data/app/request_schemas/spree_cm_commissioner/application_request_schema.rb +1 -1
  122. data/app/request_schemas/spree_cm_commissioner/inventory_item_schema.rb +8 -0
  123. data/app/request_schemas/spree_cm_commissioner/trip_search_request_schema.rb +20 -0
  124. data/app/request_schemas/spree_cm_commissioner/variant_request_schema.rb +19 -0
  125. data/app/serializers/spree/v2/storefront/accommodation_serializer.rb +2 -0
  126. data/app/serializers/spree/v2/storefront/cart_serializer_decorator.rb +1 -0
  127. data/app/serializers/spree/v2/storefront/line_item_serializer_decorator.rb +3 -1
  128. data/app/serializers/spree/v2/storefront/product_serializer_decorator.rb +2 -0
  129. data/app/serializers/spree/v2/storefront/user_serializer_decorator.rb +1 -0
  130. data/app/serializers/spree_cm_commissioner/v2/storefront/amenity_serializer.rb +15 -0
  131. data/app/serializers/spree_cm_commissioner/v2/storefront/block_serializer.rb +11 -0
  132. data/app/serializers/spree_cm_commissioner/v2/storefront/guest_serializer.rb +3 -1
  133. data/app/serializers/spree_cm_commissioner/v2/storefront/inventory_item_serializer.rb +42 -0
  134. data/app/serializers/spree_cm_commissioner/v2/storefront/reserved_block_serializer.rb +9 -0
  135. data/app/serializers/spree_cm_commissioner/v2/storefront/saved_guest_serializer.rb +21 -0
  136. data/app/serializers/spree_cm_commissioner/v2/storefront/seat_layout_serializer.rb +12 -0
  137. data/app/serializers/spree_cm_commissioner/v2/storefront/seat_section_serializer.rb +11 -0
  138. data/app/serializers/spree_cm_commissioner/v2/storefront/trip_place_serializer.rb +10 -0
  139. data/app/serializers/spree_cm_commissioner/v2/storefront/trip_query_result_serializer.rb +14 -0
  140. data/app/serializers/spree_cm_commissioner/v2/storefront/trip_result_serializer.rb +17 -0
  141. data/app/serializers/spree_cm_commissioner/v2/storefront/trip_serializer.rb +20 -0
  142. data/app/serializers/spree_cm_commissioner/v2/storefront/trip_stop_serializer.rb +11 -0
  143. data/app/serializers/spree_cm_commissioner/v2/storefront/trip_variant_serializer.rb +12 -0
  144. data/app/serializers/spree_cm_commissioner/v2/storefront/trip_vehicle_serializer.rb +16 -0
  145. data/app/serializers/spree_cm_commissioner/v2/storefront/trip_vendor_serializer.rb +16 -0
  146. data/app/serializers/spree_cm_commissioner/v2/storefront/variant_block_serializer.rb +9 -0
  147. data/app/services/spree_cm_commissioner/transit/legs_builder_service.rb +46 -0
  148. data/app/services/spree_cm_commissioner/user_authenticator.rb +10 -1
  149. data/app/views/shared/_map.html.erb +5 -4
  150. data/app/views/spree/admin/customer_notifications/_form.html.erb +3 -3
  151. data/app/views/spree/admin/inventory_items/show.html.erb +72 -0
  152. data/app/views/spree/admin/locations/_form.html.erb +133 -0
  153. data/app/views/spree/admin/locations/edit.html.erb +11 -0
  154. data/app/views/spree/admin/locations/index.html.erb +67 -0
  155. data/app/views/spree/admin/locations/new.html.erb +11 -0
  156. data/app/views/spree/admin/stock_managements/_variant_stock_items.html.erb +7 -2
  157. data/app/views/spree/admin/stock_managements/calendar.html.erb +56 -0
  158. data/app/views/spree/admin/stock_managements/index.html.erb +55 -6
  159. data/config/initializers/paper_trail.rb +1 -0
  160. data/config/initializers/spree_permitted_attributes.rb +24 -4
  161. data/config/locales/en.yml +2 -0
  162. data/config/routes.rb +33 -2
  163. data/db/migrate/20240202080634_update_counter_cache_of_vehicle_type.rb +3 -1
  164. data/db/migrate/20250122000000_move_route_type_from_vehicles_to_trips.rb +7 -0
  165. data/db/migrate/20250304293518_create_cm_inventory_items.rb +21 -0
  166. data/db/migrate/20250428092706_add_active_to_cm_customer_notifications.rb +7 -0
  167. data/db/migrate/20250428103550_remove_tenant_id_and_vendor_id_from_cm_customer_notifications.rb +9 -0
  168. data/db/migrate/20250429094228_add_lock_version_to_cm_inventory_items.rb +5 -0
  169. data/db/migrate/20250502025848_add_index_to_spree_products.rb +5 -0
  170. data/db/migrate/20250502030001_add_product_type_to_spree_variants.rb +5 -0
  171. data/db/migrate/20250502030002_add_product_type_to_spree_line_items.rb +5 -0
  172. data/db/migrate/20250603035256_add_inventory_item_to_spree_prices.rb +7 -0
  173. data/db/migrate/20250619073724_drop_table_cm_line_item_seats.rb +5 -0
  174. data/db/migrate/20250619073812_drop_table_cm_vehicle_seats.rb +5 -0
  175. data/db/migrate/20250619073844_drop_table_cm_vehicle_types.rb +9 -0
  176. data/db/migrate/20250619073957_drop_table_cm_option_value_vehicle_types.rb +5 -0
  177. data/db/migrate/20250619082354_remove_unnecessary_fields_from_cm_places.rb +9 -0
  178. data/db/migrate/20250619082736_remove_route_type_from_spree_products.rb +5 -0
  179. data/db/migrate/20250619083055_remove_unnecessary_fields_from_spree_taxons.rb +5 -0
  180. data/db/migrate/20250620083055_remove_variant_id_from_cm_trips.rb +5 -0
  181. data/db/migrate/20250620090000_update_cm_trip_connections_to_use_cm_trips.rb +6 -0
  182. data/db/migrate/20250620090001_create_cm_seat_layouts.rb +17 -0
  183. data/db/migrate/20250620090002_create_cm_seat_sections.rb +18 -0
  184. data/db/migrate/20250620090003_create_cm_blocks.rb +18 -0
  185. data/db/migrate/20250624091005_create_cm_reserved_blocks.rb +29 -0
  186. data/db/migrate/20250626083642_create_cm_variant_blocks.rb +24 -0
  187. data/db/migrate/20250627023314_add_block_id_to_cm_guests.rb +13 -0
  188. data/db/migrate/20250716022821_add_location_reference_to_cm_vendor_places.rb +5 -0
  189. data/db/migrate/20250716031743_drop_table_cm_vendor_stops.rb +5 -0
  190. data/db/migrate/20250717023824_add_vendor_reference_to_cm_trips.rb +5 -0
  191. data/db/migrate/20250717041414_add_location_place_reference_to_cm_trip_stops.rb +5 -0
  192. data/db/migrate/20250717042539_rename_cm_trip_stops_stop_id_column_to_stop_place_id.rb +7 -0
  193. data/db/migrate/20250717042707_rename_cm_trips_origin_and_destination_to_origin_place_and_destination_place.rb +11 -0
  194. data/db/migrate/20250721080738_add_vehicle_type_to_cm_vehicles.rb +7 -0
  195. data/db/migrate/20250725092713_add_block_type_to_cm_blocks.rb +5 -0
  196. data/db/migrate/20250731062816_add_departure_time_and_arrival_time_to_trip_stop.rb +6 -0
  197. data/db/migrate/20250807033035_create_spree_cm_commissioner_saved_guests.rb +23 -0
  198. data/db/migrate/20250807040000_generate_pickup_time_integer_option_values.rb +71 -0
  199. data/db/migrate/20250808054835_add_saved_guest_reference_to_cm_blocks.rb +5 -0
  200. data/db/migrate/20250812015522_remove_unique_indexes_from_cm_user_identity_providers.rb +8 -0
  201. data/db/migrate/20250812121745_add_data_fill_stage_phase_to_cm_guests.rb +5 -0
  202. data/db/migrate/20250814073854_add_call_to_action_to_spree_products.rb +5 -0
  203. data/docker-compose.yml +1 -1
  204. data/lib/cm_app_logger.rb +17 -1
  205. data/lib/generators/spree_cm_commissioner/install/install_generator.rb +14 -11
  206. data/lib/generators/spree_cm_commissioner/install/templates/app/javascript/{spree_cm_commissioner → spree_dashboard/spree_cm_commissioner}/utilities.js +4 -0
  207. data/lib/spree_cm_commissioner/cached_inventory_item.rb +23 -0
  208. data/lib/spree_cm_commissioner/calendar_event.rb +11 -1
  209. data/lib/spree_cm_commissioner/test_helper/factories/block_factory.rb +16 -0
  210. data/lib/spree_cm_commissioner/test_helper/factories/guest_factory.rb +10 -0
  211. data/lib/spree_cm_commissioner/test_helper/factories/homepage_section_relatable_factory.rb +1 -1
  212. data/lib/spree_cm_commissioner/test_helper/factories/inventory_item_factory.rb +20 -0
  213. data/lib/spree_cm_commissioner/test_helper/factories/line_item_factory.rb +1 -1
  214. data/lib/spree_cm_commissioner/test_helper/factories/option_type_factory.rb +6 -30
  215. data/lib/spree_cm_commissioner/test_helper/factories/order_factory.rb +0 -36
  216. data/lib/spree_cm_commissioner/test_helper/factories/product_factory.rb +18 -34
  217. data/lib/spree_cm_commissioner/test_helper/factories/reserved_block_factory.rb +27 -0
  218. data/lib/spree_cm_commissioner/test_helper/factories/saved_guest_factory.rb +8 -0
  219. data/lib/spree_cm_commissioner/test_helper/factories/seat_layout_factory.rb +11 -0
  220. data/lib/spree_cm_commissioner/test_helper/factories/seat_section_factory.rb +16 -0
  221. data/lib/spree_cm_commissioner/test_helper/factories/stock_location_factory.rb +2 -2
  222. data/lib/spree_cm_commissioner/test_helper/factories/trip_connection_factory.rb +6 -0
  223. data/lib/spree_cm_commissioner/test_helper/factories/trip_factory.rb +11 -3
  224. data/lib/spree_cm_commissioner/test_helper/factories/trip_stop_factory.rb +13 -0
  225. data/lib/spree_cm_commissioner/test_helper/factories/variant_block_factory.rb +7 -0
  226. data/lib/spree_cm_commissioner/test_helper/factories/variant_factory.rb +41 -19
  227. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_factory.rb +1 -1
  228. data/lib/spree_cm_commissioner/test_helper/factories/vendor_factory.rb +6 -1
  229. data/lib/spree_cm_commissioner/test_helper/factories/vendor_place_factory.rb +13 -1
  230. data/lib/spree_cm_commissioner/transit/leg.rb +37 -0
  231. data/lib/spree_cm_commissioner/transit/seat_selection.rb +27 -0
  232. data/lib/spree_cm_commissioner/trip_query_result.rb +50 -0
  233. data/lib/spree_cm_commissioner/trip_result.rb +19 -10
  234. data/lib/spree_cm_commissioner/version.rb +1 -1
  235. data/lib/spree_cm_commissioner.rb +37 -1
  236. data/lib/tasks/create_default_non_permanent_inventory_items.rake +16 -0
  237. data/lib/tasks/ensure_correct_product_type.rake +7 -0
  238. data/lib/tasks/generate_inventory_items.rake +7 -0
  239. data/spree_cm_commissioner.gemspec +7 -0
  240. metadata +203 -28
  241. data/app/controllers/concerns/spree_cm_commissioner/transit/taxon_bitwise.rb +0 -44
  242. data/app/finders/spree_cm_commissioner/line_items/find_by_variant_decorator.rb +0 -20
  243. data/app/models/spree_cm_commissioner/branch.rb +0 -12
  244. data/app/models/spree_cm_commissioner/line_item_seat.rb +0 -10
  245. data/app/models/spree_cm_commissioner/option_value_vehicle_type.rb +0 -8
  246. data/app/models/spree_cm_commissioner/stop.rb +0 -23
  247. data/app/models/spree_cm_commissioner/vehicle_seat.rb +0 -11
  248. data/app/models/spree_cm_commissioner/vehicle_type.rb +0 -76
  249. data/app/models/spree_cm_commissioner/vendor_stop.rb +0 -10
  250. data/app/queries/spree_cm_commissioner/trip_search_query.rb +0 -76
  251. data/app/queries/spree_cm_commissioner/variant_availability/non_permanent_stock_query.rb +0 -45
  252. data/app/queries/spree_cm_commissioner/variant_availability/permanent_stock_query.rb +0 -55
  253. data/app/queries/spree_cm_commissioner/vendor_stop_place_query.rb +0 -54
  254. data/app/services/spree_cm_commissioner/vehicle_option_value_creator.rb +0 -11
  255. data/lib/spree_cm_commissioner/test_helper/factories/branch_factory.rb +0 -12
  256. data/lib/spree_cm_commissioner/test_helper/factories/departure_time_option_type_factory.rb +0 -8
  257. data/lib/spree_cm_commissioner/test_helper/factories/duration_option_type_factory.rb +0 -8
  258. data/lib/spree_cm_commissioner/test_helper/factories/line_item_seat_factory.rb +0 -7
  259. data/lib/spree_cm_commissioner/test_helper/factories/stop_factory.rb +0 -14
  260. data/lib/spree_cm_commissioner/test_helper/factories/transit_place_factory.rb +0 -8
  261. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_option_type_factory.rb +0 -8
  262. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_type_factory.rb +0 -96
  263. data/lib/spree_cm_commissioner/trip_seat_layout_result.rb +0 -11
@@ -29,9 +29,10 @@ module Spree
29
29
  resource = scope.new(guest_params)
30
30
 
31
31
  if resource.save
32
+ resource.save_and_move_to_next_stage
32
33
  render_serialized_payload(201) { serialize_resource(resource) }
33
34
  else
34
- render_error_payload(resource.errors, 400)
35
+ render_error_payload(resource.errors, 422)
35
36
  end
36
37
  end
37
38
 
@@ -40,23 +41,16 @@ module Spree
40
41
 
41
42
  begin
42
43
  ActiveRecord::Base.transaction do
43
- if guest_params[:guest_dynamic_fields_attributes]
44
- dynamic_field_ids = guest_params[:guest_dynamic_fields_attributes].pluck(:dynamic_field_id)
45
- resource.guest_dynamic_fields.where(dynamic_field_id: dynamic_field_ids).destroy_all
46
-
47
- guest_params[:guest_dynamic_fields_attributes].each do |attr|
48
- field = build_dynamic_field(attr)
49
- field.save!
50
- end
51
- end
44
+ process_dynamic_fields(guest_params[:guest_dynamic_fields_attributes]) if guest_params[:guest_dynamic_fields_attributes]
52
45
 
53
46
  resource.assign_attributes(guest_params.except(:guest_dynamic_fields_attributes))
54
47
  resource.save!
55
48
  end
56
49
 
50
+ resource.save_and_move_to_next_stage
57
51
  render_serialized_payload { serialize_resource(resource) }
58
52
  rescue ActiveRecord::RecordInvalid => e
59
- render_error_payload(e.record.errors, 400)
53
+ render_error_payload(e.record.errors, 422)
60
54
  end
61
55
  end
62
56
 
@@ -95,15 +89,31 @@ module Spree
95
89
  )
96
90
  end
97
91
 
98
- def build_dynamic_field(attr)
99
- field = resource.guest_dynamic_fields.build(attr.except(:id))
100
-
101
- if field.dynamic_field.requires_dynamic_field_options?
102
- option = field.dynamic_field.dynamic_field_options.find_by(id: field.value)
103
- field.dynamic_field_option = option if option
92
+ def process_dynamic_fields(dynamic_fields_attributes)
93
+ dynamic_fields_attributes.each do |attr|
94
+ if attr[:_destroy] == '1' && attr[:id].present?
95
+ field = resource.guest_dynamic_fields.find_by(id: attr[:id])
96
+ field&.destroy!
97
+ elsif attr[:id].present?
98
+ field = resource.guest_dynamic_fields.find_by(id: attr[:id])
99
+ if field
100
+ field.assign_attributes(attr.except(:id, :_destroy))
101
+ associate_dynamic_field_option(field) if field.dynamic_field.present?
102
+ field.save!
103
+ end
104
+ else
105
+ field = resource.guest_dynamic_fields.build(attr.except(:id, :_destroy))
106
+ associate_dynamic_field_option(field) if field.dynamic_field.present?
107
+ field.save!
108
+ end
104
109
  end
110
+ end
111
+
112
+ def associate_dynamic_field_option(field)
113
+ return unless field.dynamic_field&.requires_dynamic_field_options?
105
114
 
106
- field
115
+ option = field.dynamic_field.dynamic_field_options.find_by(id: field.value)
116
+ field.dynamic_field_option = option if option
107
117
  end
108
118
  end
109
119
  end
@@ -0,0 +1,57 @@
1
+ module Spree
2
+ module Api
3
+ module V2
4
+ module Storefront
5
+ class InventoryItemsController < ::Spree::Api::V2::ResourceController
6
+ # GET /api/v2/storefront/inventory_items?
7
+ # - variant_ids[]=[1,2]
8
+ # - inventory_dates[]=[2025-03-06] (optional)
9
+ # - includes[]=reserved_blocks
10
+ def index
11
+ render_serialized_payload do
12
+ collection_serializer.new(
13
+ collection,
14
+ { include: resource_includes, params: serializer_params }
15
+ ).serializable_hash
16
+ end
17
+ end
18
+
19
+ # override
20
+ def collection
21
+ return @collection if defined?(@collection)
22
+
23
+ scope = if include_reserved_blocks?
24
+ SpreeCmCommissioner::InventoryItem.includes(:prices, :reserved_blocks)
25
+ else
26
+ SpreeCmCommissioner::InventoryItem.includes(:prices)
27
+ end
28
+
29
+ @collection = scope.where(variant_id: params[:variant_ids], inventory_date: params[:inventory_dates])
30
+ @collection
31
+ end
32
+
33
+ # override
34
+ def collection_serializer
35
+ SpreeCmCommissioner::V2::Storefront::InventoryItemSerializer
36
+ end
37
+
38
+ # override
39
+ def required_schema
40
+ SpreeCmCommissioner::InventoryItemSchema
41
+ end
42
+
43
+ # override
44
+ def serializer_params
45
+ super.merge(include_reserved_blocks: include_reserved_blocks?)
46
+ end
47
+
48
+ private
49
+
50
+ def include_reserved_blocks?
51
+ resource_includes.include?(:reserved_blocks)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -12,9 +12,9 @@ module Spree
12
12
  spree_authorize! :update, spree_current_order, order_token
13
13
  spree_authorize! :show, @variant
14
14
 
15
- availability_checker = SpreeCmCommissioner::Stock::AvailabilityChecker.new(@variant)
15
+ availability_checker = SpreeCmCommissioner::Stock::AvailabilityChecker.new(@variant, add_item_params[:options])
16
16
 
17
- unless availability_checker.can_supply?(add_item_params[:quantity].to_i, add_item_params[:options])
17
+ unless availability_checker.can_supply?(add_item_params[:quantity].to_i)
18
18
  return render_error_payload(availability_checker.error_message || I18n.t('variant_availability.items_out_of_stock'))
19
19
  end
20
20
 
@@ -0,0 +1,46 @@
1
+ module Spree
2
+ module Api
3
+ module V2
4
+ module Storefront
5
+ module Transit
6
+ class DraftOrdersController < ::Spree::Api::V2::ResourceController
7
+ # Creates a draft transit order.
8
+ # Endpoint: POST /api/v2/storefront/transit/draft_orders
9
+ # Params:
10
+ # - outbound_date: Date of outbound transit (optional)
11
+ # - inbound_date: Date of inbound transit (optional)
12
+ # - outbound_legs: Array of outbound leg details (required)
13
+ # - inbound_legs: Array of inbound leg details (optional)
14
+ def create
15
+ @outbound_legs = params[:outbound_legs].is_a?(Array) && params[:outbound_legs].any? ? build_legs(:outbound, params[:outbound_legs]) : []
16
+ @inbound_legs = params[:inbound_legs].is_a?(Array) && params[:inbound_legs].any? ? build_legs(:inbound, params[:inbound_legs]) : []
17
+
18
+ context = SpreeCmCommissioner::Transit::DraftOrderCreator.call(
19
+ outbound_date: params[:outbound_date]&.to_date,
20
+ inbound_date: params[:inbound_date]&.to_date,
21
+ outbound_legs: @outbound_legs,
22
+ inbound_legs: @inbound_legs,
23
+ user: spree_current_user
24
+ )
25
+
26
+ if context.success?
27
+ render_serialized_payload { serialize_resource(context.order) }
28
+ else
29
+ render_error_payload(context.message)
30
+ end
31
+ end
32
+
33
+ def build_legs(direction, legs_params)
34
+ SpreeCmCommissioner::Transit::LegsBuilderService.new(direction: direction, legs_params: legs_params).call
35
+ end
36
+
37
+ # override
38
+ def resource_serializer
39
+ Spree::Api::Dependencies.storefront_cart_serializer.constantize
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,29 @@
1
+ module Spree
2
+ module Api
3
+ module V2
4
+ module Storefront
5
+ class TripPlacesController < ::Spree::Api::V2::ResourceController
6
+ # override
7
+ def collection
8
+ base_scope = model_class.joins(:location_vendor_places).distinct
9
+
10
+ if params[:q].present?
11
+ @search = base_scope.ransack(params[:q])
12
+ @search.result
13
+ else
14
+ base_scope
15
+ end
16
+ end
17
+
18
+ def model_class
19
+ SpreeCmCommissioner::Place
20
+ end
21
+
22
+ def collection_serializer
23
+ SpreeCmCommissioner::V2::Storefront::TripPlaceSerializer
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,62 @@
1
+ module Spree
2
+ module Api
3
+ module V2
4
+ module Storefront
5
+ class TripSearchController < ::Spree::Api::V2::ResourceController
6
+ def index
7
+ trips = SpreeCmCommissioner::TripQuery.new(
8
+ origin_id: params[:origin_id],
9
+ destination_id: params[:destination_id],
10
+ date: params[:date],
11
+ vendor_id: params[:vendor_id],
12
+ number_of_guests: params[:number_of_guests],
13
+ params: params
14
+ ).call
15
+
16
+ render_serialized_payload { serialize_collection(trips) }
17
+ end
18
+
19
+ private
20
+
21
+ # override
22
+ def default_resource_includes
23
+ [
24
+ 'trips.vendor',
25
+ 'trips.vendor.logo',
26
+ 'trips.vehicle',
27
+ 'trips.amenities'
28
+ ]
29
+ end
30
+
31
+ def serialize_collection(collection)
32
+ serialized_data = SpreeCmCommissioner::V2::Storefront::TripQueryResultSerializer.new(
33
+ collection,
34
+ include: default_resource_includes,
35
+ params: serializer_params
36
+ ).serializable_hash
37
+ serialized_data[:meta] = {
38
+ count: collection.size,
39
+ total_count: collection.respond_to?(:total_count) ? collection.total_count : collection.size,
40
+ current_page: collection.respond_to?(:current_page) ? collection.current_page : 1,
41
+ per_page: collection.respond_to?(:limit_value) ? collection.limit_value : collection.size,
42
+ pages: collection.respond_to?(:total_pages) ? collection.total_pages : 1,
43
+ next_page: collection.respond_to?(:next_page) ? collection.next_page : nil,
44
+ prev_page: collection.respond_to?(:prev_page) ? collection.prev_page : nil
45
+ }
46
+ serialized_data
47
+ end
48
+
49
+ # override
50
+ def serializer_params
51
+ params.permit(:include).to_hash
52
+ end
53
+
54
+ # override
55
+ def required_schema
56
+ SpreeCmCommissioner::TripSearchRequestSchema
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,24 @@
1
+ module Spree
2
+ module Api
3
+ module V2
4
+ module Storefront
5
+ class TripsController < ::Spree::Api::V2::ResourceController
6
+ # override
7
+ def resource
8
+ model_class.find(params[:id])
9
+ end
10
+
11
+ # override
12
+ def model_class
13
+ SpreeCmCommissioner::Trip
14
+ end
15
+
16
+ # override
17
+ def resource_serializer
18
+ SpreeCmCommissioner::V2::Storefront::TripSerializer
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -5,6 +5,7 @@ module SpreeCmCommissioner
5
5
  # spree update user sign_in_count
6
6
  base.around_action :set_writing_role, only: %i[index]
7
7
  base.after_action :set_tenant_after_update, only: %i[update]
8
+ base.before_action :merge_industry_taxons_into_taxons, only: [:update]
8
9
  end
9
10
 
10
11
  # Override
@@ -50,6 +51,19 @@ module SpreeCmCommissioner
50
51
 
51
52
  protected
52
53
 
54
+ def merge_industry_taxons_into_taxons
55
+ return if params[:product].blank?
56
+
57
+ industry_ids = Array(params[:product][:industry_taxon_ids]).compact_blank
58
+ taxon_ids = Array(params[:product][:taxon_ids]).compact_blank
59
+
60
+ merged_ids = (taxon_ids + industry_ids).uniq
61
+
62
+ params[:product][:taxon_ids] = merged_ids
63
+
64
+ params[:product].delete(:industry_taxon_ids)
65
+ end
66
+
53
67
  def find_resource
54
68
  product_scope.with_deleted.includes(vendor: :tenant).friendly.find(params[:id])
55
69
  end
@@ -0,0 +1,37 @@
1
+ module SpreeCmCommissioner
2
+ module Accommodations
3
+ class Find
4
+ attr_reader :from_date, :to_date, :state_id, :number_of_guests
5
+
6
+ def initialize(from_date:, to_date:, state_id:, number_of_adults:, number_of_kids:)
7
+ @from_date = from_date
8
+ @to_date = to_date
9
+ @state_id = state_id
10
+ @number_of_guests = number_of_adults.to_i + number_of_kids.to_i
11
+ end
12
+
13
+ def execute
14
+ scope
15
+ .where(default_state_id: state_id)
16
+ .where(inventory_items: { inventory_date: stay_dates })
17
+ .where('CAST(spree_variants.public_metadata->\'cm_options\'->>\'number-of-adults\' AS INTEGER) +
18
+ CAST(spree_variants.public_metadata->\'cm_options\'->>\'number-of-kids\' AS INTEGER) >= ?', number_of_guests
19
+ )
20
+ .where('inventory_items.quantity_available > 0')
21
+ .distinct
22
+ end
23
+
24
+ private
25
+
26
+ def scope
27
+ Spree::Vendor
28
+ .joins(variants: :inventory_items)
29
+ .where(primary_product_type: :accommodation, state: :active)
30
+ end
31
+
32
+ def stay_dates
33
+ from_date..to_date
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,32 @@
1
+ module SpreeCmCommissioner
2
+ module Accommodations
3
+ class FindVariant
4
+ attr_reader :vendor_id, :from_date, :to_date, :number_of_guests
5
+
6
+ def initialize(vendor_id:, from_date:, to_date:, number_of_adults:, number_of_kids:)
7
+ @vendor_id = vendor_id
8
+ @from_date = from_date
9
+ @to_date = to_date
10
+ @number_of_guests = number_of_adults.to_i + number_of_kids.to_i
11
+ end
12
+
13
+ def execute
14
+ Spree::Variant
15
+ .joins(:inventory_items)
16
+ .where(vendor_id: vendor_id)
17
+ .where(inventory_items: { inventory_date: stay_dates })
18
+ .where('CAST(public_metadata->\'cm_options\'->>\'number-of-adults\' AS INTEGER) +
19
+ CAST(public_metadata->\'cm_options\'->>\'number-of-kids\' AS INTEGER) >= ?', number_of_guests
20
+ )
21
+ .where('inventory_items.quantity_available > 0')
22
+ .distinct
23
+ end
24
+
25
+ private
26
+
27
+ def stay_dates
28
+ from_date..to_date
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,33 @@
1
+ module SpreeCmCommissioner
2
+ class BillingAddressCreator < BaseInteractor
3
+ delegate :order, to: :context
4
+
5
+ def call
6
+ validate_context!
7
+ create_address
8
+ end
9
+
10
+ private
11
+
12
+ def validate_context!
13
+ context.fail!(message: 'Order is missing') unless order
14
+ end
15
+
16
+ def create_address
17
+ line_item = order.line_items.first
18
+ guest = line_item&.guests&.first
19
+
20
+ billing_address = order.build_bill_address(
21
+ firstname: guest&.first_name,
22
+ lastname: guest&.last_name,
23
+ phone: order.intel_phone_number || order.phone_number
24
+ )
25
+
26
+ context.fail!(message: billing_address.errors.full_messages.to_sentence) unless billing_address.save!
27
+ # Persist association on the order so subsequent reloads reflect the new billing address
28
+ order.update!(bill_address: billing_address)
29
+
30
+ context.billing_address = billing_address
31
+ end
32
+ end
33
+ end
@@ -8,6 +8,7 @@ module SpreeCmCommissioner
8
8
  ActiveRecord::Base.transaction do
9
9
  create_vendor
10
10
  assign_vendor_to_user
11
+ create_logo
11
12
  create_role
12
13
  end
13
14
  end
@@ -30,9 +31,18 @@ module SpreeCmCommissioner
30
31
  context.user.vendors << @vendor
31
32
  end
32
33
 
34
+ def create_logo
35
+ return if context.logo.blank?
36
+
37
+ vendor_logo = SpreeCmCommissioner::VendorLogo.create(viewable: @vendor, attachment: context.logo)
38
+ return if vendor_logo.persisted?
39
+
40
+ context.fail!(message: vendor_logo.errors.full_messages.join(', '))
41
+ end
42
+
33
43
  def create_role
34
44
  role = context.user.spree_roles.create(
35
- name: "#{@vendor.name.downcase.parameterize(separator: '-')}-organizer",
45
+ name: "#{@vendor.id}-organizer",
36
46
  vendor_id: @vendor.id,
37
47
  presentation: 'Organizer'
38
48
  )
@@ -55,7 +55,8 @@ module SpreeCmCommissioner
55
55
  end
56
56
 
57
57
  def end_users
58
- users_scope = Spree.user_class.where(tenant_id: customer_notification.tenant_id)
58
+ users_scope = Spree.user_class
59
+ .where(tenant_id: notification_tenant_id)
59
60
 
60
61
  if customer_notification.notification_taxons.exists?
61
62
  taxon_ids = customer_notification.notification_taxons.pluck(:taxon_id)
@@ -63,12 +64,16 @@ module SpreeCmCommissioner
63
64
  .new(taxon_ids)
64
65
  .call
65
66
  .end_users_push_notificable
66
- .where(tenant_id: customer_notification.tenant_id)
67
+ .where(tenant_id: notification_tenant_id)
67
68
  else
68
69
  users_scope = users_scope.end_users_push_notificable
69
70
  end
70
71
 
71
72
  users_scope
72
73
  end
74
+
75
+ def notification_tenant_id
76
+ @notification_tenant_id ||= customer_notification.vendor&.tenant_id
77
+ end
73
78
  end
74
79
  end
@@ -0,0 +1,40 @@
1
+ module SpreeCmCommissioner
2
+ class EnsureCorrectProductType < BaseInteractor
3
+ def call
4
+ Spree::Product
5
+ .left_joins(variants_including_master: %i[inventory_items line_items])
6
+ .where(
7
+ 'spree_variants.product_type IS NULL OR
8
+ spree_variants.product_type != spree_products.product_type OR
9
+
10
+ cm_inventory_items.product_type IS NULL OR
11
+ cm_inventory_items.product_type != spree_products.product_type OR
12
+
13
+ spree_line_items.product_type IS NULL OR
14
+ spree_line_items.product_type != spree_products.product_type OR
15
+
16
+ spree_products.product_type IS NOT NULL
17
+ '
18
+ )
19
+ .distinct.find_each do |product|
20
+ sync_product_type_for(product)
21
+ end
22
+ end
23
+
24
+ def sync_product_type_for(product)
25
+ product_type = Spree::Variant.product_types[product.product_type]
26
+
27
+ product.variants_including_master
28
+ .where('spree_variants.product_type IS NULL OR spree_variants.product_type != ?', product_type)
29
+ .update_all(product_type: product_type) # rubocop:disable Rails/SkipsModelValidations
30
+
31
+ product.line_items
32
+ .where('spree_line_items.product_type IS NULL OR spree_line_items.product_type != ?', product_type)
33
+ .update_all(product_type: product_type) # rubocop:disable Rails/SkipsModelValidations
34
+
35
+ product.inventory_items
36
+ .where('cm_inventory_items.product_type IS NULL OR cm_inventory_items.product_type != ?', product_type)
37
+ .update_all(product_type: product_type) # rubocop:disable Rails/SkipsModelValidations
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,45 @@
1
+ module SpreeCmCommissioner
2
+ class FetchFacebookUserData < BaseInteractor
3
+ delegate :fb_access_token, to: :context
4
+
5
+ def call
6
+ context.fail!(message: 'fb_access_token_missing') if fb_access_token.blank?
7
+
8
+ graph_response = fetch_user_info
9
+
10
+ context.fail!(message: 'invalid_facebook_response') unless graph_response.is_a?(Hash)
11
+ context.fail!(message: graph_response['error']['message'] || 'facebook_error') if graph_response['error']
12
+
13
+ context.provider = {
14
+ identity_type: SpreeCmCommissioner::UserIdentityProvider.identity_types[:facebook],
15
+ sub: graph_response['id'],
16
+ name: graph_response['name'],
17
+ email: graph_response['email'], # can be nil
18
+ first_name: graph_response['first_name'],
19
+ last_name: graph_response['last_name'],
20
+ picture: graph_response.dig('picture', 'data', 'url')
21
+ }
22
+ end
23
+
24
+ private
25
+
26
+ def fetch_user_info
27
+ uri = URI('https://graph.facebook.com/v23.0/me')
28
+ uri.query = URI.encode_www_form(
29
+ fields: 'id,email,first_name,last_name,name,picture',
30
+ access_token: fb_access_token
31
+ )
32
+
33
+ http = Net::HTTP.new(uri.host, uri.port)
34
+ http.use_ssl = true
35
+ http.open_timeout = 5
36
+ http.read_timeout = 10
37
+
38
+ response = http.get(uri.request_uri)
39
+ JSON.parse(response.body)
40
+ rescue StandardError => e
41
+ CmAppLogger.error("Facebook API error: #{e.message}")
42
+ context.fail!(message: 'facebook_api_error', error: e.message)
43
+ end
44
+ end
45
+ end
@@ -11,6 +11,7 @@ module SpreeCmCommissioner
11
11
  types: json['types'].blank? ? '' : json['types'][0],
12
12
  name: json['name'],
13
13
  vicinity: json['vicinity'],
14
+ formatted_address: json['formatted_address'],
14
15
  lat: json['geometry']['location']['lat'],
15
16
  lon: json['geometry']['location']['lng'],
16
17
  icon: json['icon'],