spree_cm_commissioner 1.21.0 → 2.0.0.pre.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. checksums.yaml +4 -4
  2. data/.env.example +0 -3
  3. data/.github/workflows/test_and_build_gem.yml +16 -2
  4. data/.gitignore +2 -1
  5. data/Gemfile.lock +28 -1
  6. data/Rakefile +33 -4
  7. data/app/assets/javascripts/spree_cm_commissioner/backend.js +0 -1
  8. data/app/assets/stylesheets/spree_cm_commissioner/backend/calendar.scss +8 -11
  9. data/app/assets/stylesheets/spree_cm_commissioner/backend/commissioner_admin.css.scss +0 -1
  10. data/app/controllers/concerns/spree_cm_commissioner/content_cachable.rb +1 -2
  11. data/app/controllers/spree/admin/event_blazer_queries_controller.rb +4 -11
  12. data/app/controllers/spree/admin/inventory_items_controller.rb +83 -0
  13. data/app/controllers/spree/admin/stock_managements_controller.rb +63 -1
  14. data/app/controllers/spree/admin/tenants_controller.rb +0 -8
  15. data/app/controllers/spree/api/v2/organizer/invite_guests_controller.rb +1 -1
  16. data/app/controllers/spree/api/v2/storefront/accommodations/variants_controller.rb +42 -0
  17. data/app/controllers/spree/api/v2/storefront/accommodations_controller.rb +14 -31
  18. data/app/controllers/spree/api/v2/storefront/dynamic_field_options_controller.rb +1 -5
  19. data/app/controllers/spree/api/v2/storefront/guests_controller.rb +5 -31
  20. data/app/controllers/spree/api/v2/storefront/queue_cart/line_items_controller.rb +2 -2
  21. data/app/controllers/spree/api/v2/tenant/checkout_controller.rb +0 -2
  22. data/app/controllers/spree_cm_commissioner/admin/variants_controller_decorator.rb +1 -1
  23. data/app/controllers/spree_cm_commissioner/api/v2/storefront/checkout_controller_decorator.rb +0 -11
  24. data/app/controllers/spree_cm_commissioner/well_known_controller.rb +17 -31
  25. data/app/factory/spree_cm_commissioner/invite_guest_claimed_telegram_message_factory.rb +84 -37
  26. data/app/finders/spree_cm_commissioner/accommodations/find.rb +37 -0
  27. data/app/finders/spree_cm_commissioner/accommodations/find_variant.rb +32 -0
  28. data/app/interactors/spree_cm_commissioner/ensure_correct_product_type.rb +40 -0
  29. data/app/interactors/spree_cm_commissioner/inventory_item_syncer.rb +25 -0
  30. data/app/interactors/spree_cm_commissioner/pin_code_sender.rb +1 -0
  31. data/app/interactors/spree_cm_commissioner/sms.rb +1 -1
  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/user_id_token_authenticator.rb +3 -7
  38. data/app/interactors/spree_cm_commissioner/user_id_token_checker.rb +3 -11
  39. data/app/interactors/spree_cm_commissioner/user_identity_checker.rb +6 -12
  40. data/app/interactors/spree_cm_commissioner/user_registration_with_id_token.rb +1 -7
  41. data/app/interactors/spree_cm_commissioner/vattanac_bank_initiator.rb +1 -5
  42. data/app/jobs/spree_cm_commissioner/application_job.rb +20 -0
  43. data/app/jobs/spree_cm_commissioner/application_unique_job.rb +20 -0
  44. data/app/jobs/spree_cm_commissioner/ensure_correct_product_type_job.rb +7 -0
  45. data/app/jobs/spree_cm_commissioner/inventory_item_syncer_job.rb +7 -0
  46. data/app/jobs/spree_cm_commissioner/sms_pin_code_job.rb +1 -1
  47. data/app/jobs/spree_cm_commissioner/stock/inventory_items_adjuster_job.rb +11 -0
  48. data/app/jobs/spree_cm_commissioner/stock/inventory_items_generator_job.rb +11 -0
  49. data/app/jobs/spree_cm_commissioner/stock/permanent_inventory_items_generator_job.rb +9 -0
  50. data/app/models/concerns/spree_cm_commissioner/line_item_durationable.rb +9 -15
  51. data/app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb +1 -13
  52. data/app/models/concerns/spree_cm_commissioner/order_seatable.rb +44 -0
  53. data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +39 -0
  54. data/app/models/concerns/spree_cm_commissioner/product_delegation.rb +1 -3
  55. data/app/models/concerns/spree_cm_commissioner/product_type.rb +10 -0
  56. data/app/models/concerns/spree_cm_commissioner/taxon_kind.rb +1 -1
  57. data/app/models/concerns/spree_cm_commissioner/tenant_preference.rb +0 -4
  58. data/app/models/spree_cm_commissioner/block.rb +23 -0
  59. data/app/models/spree_cm_commissioner/dynamic_field.rb +3 -17
  60. data/app/models/spree_cm_commissioner/dynamic_field_option.rb +1 -7
  61. data/app/models/spree_cm_commissioner/guest.rb +19 -1
  62. data/app/models/spree_cm_commissioner/guest_dynamic_field.rb +3 -21
  63. data/app/models/spree_cm_commissioner/inventory.rb +11 -0
  64. data/app/models/spree_cm_commissioner/inventory_item.rb +69 -0
  65. data/app/models/spree_cm_commissioner/invite.rb +6 -4
  66. data/app/models/spree_cm_commissioner/invite_team.rb +1 -3
  67. data/app/models/spree_cm_commissioner/line_item_decorator.rb +46 -78
  68. data/app/models/spree_cm_commissioner/notification_taxon.rb +1 -1
  69. data/app/models/spree_cm_commissioner/option_type_decorator.rb +1 -11
  70. data/app/models/spree_cm_commissioner/order_decorator.rb +30 -1
  71. data/app/models/spree_cm_commissioner/pin_code.rb +2 -3
  72. data/app/models/spree_cm_commissioner/place.rb +1 -3
  73. data/app/models/spree_cm_commissioner/price_decorator.rb +9 -0
  74. data/app/models/spree_cm_commissioner/product_decorator.rb +10 -4
  75. data/app/models/spree_cm_commissioner/redis_stock/cached_inventory_items_builder.rb +41 -0
  76. data/app/models/spree_cm_commissioner/redis_stock/inventory_updater.rb +126 -0
  77. data/app/models/spree_cm_commissioner/redis_stock/line_items_cached_inventory_items_builder.rb +36 -0
  78. data/app/models/spree_cm_commissioner/redis_stock/variant_cached_inventory_items_builder.rb +25 -0
  79. data/app/models/spree_cm_commissioner/reserved_block.rb +30 -0
  80. data/app/models/spree_cm_commissioner/seat_layout.rb +20 -0
  81. data/app/models/spree_cm_commissioner/seat_section.rb +16 -0
  82. data/app/models/spree_cm_commissioner/seats/blocks_canceler.rb +30 -0
  83. data/app/models/spree_cm_commissioner/seats/blocks_holder.rb +53 -0
  84. data/app/models/spree_cm_commissioner/seats/blocks_reserver.rb +49 -0
  85. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_on_hold_by_other_guest.rb +4 -0
  86. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_reserved_by_other_guest.rb +4 -0
  87. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_reserved_by_same_guest.rb +4 -0
  88. data/app/models/spree_cm_commissioner/seats/errors/unable_to_save_reserved_block_record.rb +4 -0
  89. data/app/models/spree_cm_commissioner/service_calendar.rb +0 -2
  90. data/app/models/spree_cm_commissioner/state_decorator.rb +0 -1
  91. data/app/models/spree_cm_commissioner/stock/availability_checker.rb +26 -25
  92. data/app/models/spree_cm_commissioner/stock/availability_validator_decorator.rb +2 -1
  93. data/app/models/spree_cm_commissioner/stock/line_item_availability_checker.rb +3 -3
  94. data/app/models/spree_cm_commissioner/stock/order_availability_checker.rb +44 -0
  95. data/app/models/spree_cm_commissioner/stock_item_decorator.rb +17 -0
  96. data/app/models/spree_cm_commissioner/taxon_blazer_query.rb +8 -0
  97. data/app/models/spree_cm_commissioner/taxon_decorator.rb +2 -6
  98. data/app/models/spree_cm_commissioner/taxonomy_decorator.rb +0 -6
  99. data/app/models/spree_cm_commissioner/trip.rb +12 -10
  100. data/app/models/spree_cm_commissioner/trip_connection.rb +5 -5
  101. data/app/models/spree_cm_commissioner/trip_stop.rb +2 -3
  102. data/app/models/spree_cm_commissioner/user_identity_provider.rb +4 -26
  103. data/app/models/spree_cm_commissioner/user_taxon.rb +0 -1
  104. data/app/models/spree_cm_commissioner/variant_block.rb +9 -0
  105. data/app/models/spree_cm_commissioner/variant_decorator.rb +36 -47
  106. data/app/models/spree_cm_commissioner/variant_options.rb +0 -23
  107. data/app/models/spree_cm_commissioner/vehicle.rb +9 -14
  108. data/app/models/spree_cm_commissioner/vendor_decorator.rb +7 -10
  109. data/app/models/spree_cm_commissioner/vendor_place.rb +6 -5
  110. data/app/models/spree_cm_commissioner/vendor_stop.rb +1 -2
  111. data/app/overrides/spree/admin/variants/_form/kyc_field.html.erb.deface +2 -2
  112. data/app/queries/spree_cm_commissioner/guest_searcher_query.rb +3 -45
  113. data/app/queries/spree_cm_commissioner/trip_query.rb +23 -26
  114. data/app/request_schemas/spree_cm_commissioner/accommodation_request_schema.rb +3 -0
  115. data/app/request_schemas/spree_cm_commissioner/application_request_schema.rb +1 -1
  116. data/app/request_schemas/spree_cm_commissioner/variant_request_schema.rb +19 -0
  117. data/app/serializers/spree/v2/storefront/accommodation_serializer.rb +2 -0
  118. data/app/serializers/spree/v2/storefront/line_item_serializer_decorator.rb +1 -0
  119. data/app/serializers/spree/v2/tenant/user_serializer.rb +0 -1
  120. data/app/serializers/spree_cm_commissioner/v2/operator/dashboard_crew_event_serializer.rb +1 -4
  121. data/app/serializers/spree_cm_commissioner/v2/storefront/dynamic_field_option_serializer.rb +3 -1
  122. data/app/serializers/spree_cm_commissioner/v2/storefront/dynamic_field_serializer.rb +3 -1
  123. data/app/serializers/spree_cm_commissioner/v2/storefront/guest_dynamic_field_serializer.rb +1 -2
  124. data/app/services/spree_cm_commissioner/organizer/export_guest_csv_service.rb +15 -23
  125. data/app/services/spree_cm_commissioner/user_authenticator.rb +1 -1
  126. data/app/views/blazer/queries/_content.html.erb +0 -8
  127. data/app/views/spree/admin/inventory_items/show.html.erb +72 -0
  128. data/app/views/spree/admin/stock_managements/_variant_stock_items.html.erb +7 -2
  129. data/app/views/spree/admin/stock_managements/calendar.html.erb +56 -0
  130. data/app/views/spree/admin/stock_managements/index.html.erb +55 -6
  131. data/app/views/spree/admin/tenants/_form.html.erb +42 -109
  132. data/config/initializers/paper_trail.rb +1 -0
  133. data/config/initializers/spree_permitted_attributes.rb +5 -2
  134. data/config/locales/en.yml +0 -5
  135. data/config/routes.rb +22 -6
  136. data/db/migrate/20240202080634_update_counter_cache_of_vehicle_type.rb +3 -1
  137. data/db/migrate/20250304293518_create_cm_inventory_items.rb +21 -0
  138. data/db/migrate/20250429094228_add_lock_version_to_cm_inventory_items.rb +5 -0
  139. data/db/migrate/20250502025848_add_index_to_spree_products.rb +5 -0
  140. data/db/migrate/20250502030001_add_product_type_to_spree_variants.rb +5 -0
  141. data/db/migrate/20250502030002_add_product_type_to_spree_line_items.rb +5 -0
  142. data/db/migrate/20250603035256_add_inventory_item_to_spree_prices.rb +7 -0
  143. data/db/migrate/20250619073724_drop_table_cm_line_item_seats.rb +5 -0
  144. data/db/migrate/20250619073812_drop_table_cm_vehicle_seats.rb +5 -0
  145. data/db/migrate/20250619073844_drop_table_cm_vehicle_types.rb +9 -0
  146. data/db/migrate/20250619073957_drop_table_cm_option_value_vehicle_types.rb +5 -0
  147. data/db/migrate/20250619082354_remove_unnecessary_fields_from_cm_places.rb +9 -0
  148. data/db/migrate/20250619082736_remove_route_type_from_spree_products.rb +5 -0
  149. data/db/migrate/20250619083055_remove_unnecessary_fields_from_spree_taxons.rb +5 -0
  150. data/db/migrate/20250620083055_remove_variant_id_from_cm_trips.rb +5 -0
  151. data/db/migrate/20250620090000_update_cm_trip_connections_to_use_cm_trips.rb +6 -0
  152. data/db/migrate/20250620090001_create_cm_seat_layouts.rb +17 -0
  153. data/db/migrate/20250620090002_create_cm_seat_sections.rb +18 -0
  154. data/db/migrate/20250620090003_create_cm_blocks.rb +18 -0
  155. data/db/migrate/20250624091005_create_cm_reserved_blocks.rb +29 -0
  156. data/db/migrate/20250626083642_create_cm_variant_blocks.rb +24 -0
  157. data/db/migrate/20250627023314_add_block_id_to_cm_guests.rb +13 -0
  158. data/docker-compose.yml +1 -1
  159. data/lib/cm_app_logger.rb +11 -4
  160. data/lib/generators/spree_cm_commissioner/install/install_generator.rb +14 -11
  161. data/lib/generators/spree_cm_commissioner/install/templates/app/javascript/{spree_cm_commissioner → spree_dashboard/spree_cm_commissioner}/utilities.js +4 -0
  162. data/lib/spree_cm_commissioner/cached_inventory_item.rb +23 -0
  163. data/lib/spree_cm_commissioner/calendar_event.rb +11 -1
  164. data/lib/spree_cm_commissioner/test_helper/factories/block_factory.rb +9 -0
  165. data/lib/spree_cm_commissioner/test_helper/factories/guest_factory.rb +10 -0
  166. data/lib/spree_cm_commissioner/test_helper/factories/homepage_section_relatable_factory.rb +1 -1
  167. data/lib/spree_cm_commissioner/test_helper/factories/inventory_item_factory.rb +9 -0
  168. data/lib/spree_cm_commissioner/test_helper/factories/line_item_factory.rb +1 -1
  169. data/lib/spree_cm_commissioner/test_helper/factories/option_type_factory.rb +6 -30
  170. data/lib/spree_cm_commissioner/test_helper/factories/order_factory.rb +0 -36
  171. data/lib/spree_cm_commissioner/test_helper/factories/product_factory.rb +18 -34
  172. data/lib/spree_cm_commissioner/test_helper/factories/reserved_block_factory.rb +27 -0
  173. data/lib/spree_cm_commissioner/test_helper/factories/seat_layout_factory.rb +8 -0
  174. data/lib/spree_cm_commissioner/test_helper/factories/seat_section_factory.rb +8 -0
  175. data/lib/spree_cm_commissioner/test_helper/factories/stock_location_factory.rb +2 -2
  176. data/lib/spree_cm_commissioner/test_helper/factories/trip_connection_factory.rb +6 -0
  177. data/lib/spree_cm_commissioner/test_helper/factories/trip_factory.rb +10 -3
  178. data/lib/spree_cm_commissioner/test_helper/factories/user_identity_provider_factory.rb +1 -1
  179. data/lib/spree_cm_commissioner/test_helper/factories/variant_block_factory.rb +7 -0
  180. data/lib/spree_cm_commissioner/test_helper/factories/variant_factory.rb +41 -19
  181. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_factory.rb +1 -1
  182. data/lib/spree_cm_commissioner/test_helper/factories/vendor_factory.rb +1 -1
  183. data/lib/spree_cm_commissioner/version.rb +1 -1
  184. data/lib/spree_cm_commissioner.rb +35 -1
  185. data/lib/tasks/create_default_non_permanent_inventory_items.rake +16 -0
  186. data/lib/tasks/ensure_correct_product_type.rake +7 -0
  187. data/lib/tasks/generate_inventory_items.rake +7 -0
  188. data/spree_cm_commissioner.gemspec +7 -0
  189. metadata +135 -57
  190. data/app/assets/images/cm-hangmeas-checkout_image.svg +0 -63
  191. data/app/assets/images/cm-hangmeas-failed.svg +0 -56
  192. data/app/assets/images/cm-hangmeas-loader.svg +0 -50
  193. data/app/assets/images/cm-hangmeas-success.svg +0 -51
  194. data/app/assets/javascripts/spree_cm_commissioner/tenant_payment_icon_fields.js +0 -65
  195. data/app/assets/stylesheets/spree_cm_commissioner/backend/tenant_payment_icon_fields.scss +0 -60
  196. data/app/controllers/concerns/spree_cm_commissioner/transit/taxon_bitwise.rb +0 -44
  197. data/app/controllers/spree/admin/trip_blazer_queries_controller.rb +0 -35
  198. data/app/controllers/spree/api/v2/organizer/invite_crews_controller.rb +0 -33
  199. data/app/finders/spree_cm_commissioner/line_items/find_by_variant_decorator.rb +0 -20
  200. data/app/interactors/spree_cm_commissioner/apple_app_site_association_fetcher.rb +0 -27
  201. data/app/interactors/spree_cm_commissioner/asset_links_fetcher.rb +0 -27
  202. data/app/interactors/spree_cm_commissioner/crew_invite_link_handler.rb +0 -48
  203. data/app/interactors/spree_cm_commissioner/telegram_chats_auto_finder.rb +0 -144
  204. data/app/models/concerns/spree_cm_commissioner/event_check_in_flowable.rb +0 -30
  205. data/app/models/spree_cm_commissioner/blazer_queryable.rb +0 -8
  206. data/app/models/spree_cm_commissioner/branch.rb +0 -12
  207. data/app/models/spree_cm_commissioner/crew_invite_link.rb +0 -4
  208. data/app/models/spree_cm_commissioner/line_item_seat.rb +0 -10
  209. data/app/models/spree_cm_commissioner/option_value_vehicle_type.rb +0 -8
  210. data/app/models/spree_cm_commissioner/pin_code_telegram.rb +0 -28
  211. data/app/models/spree_cm_commissioner/promotion_category_decorator.rb +0 -11
  212. data/app/models/spree_cm_commissioner/stop.rb +0 -23
  213. data/app/models/spree_cm_commissioner/telegram_chat.rb +0 -6
  214. data/app/models/spree_cm_commissioner/vehicle_seat.rb +0 -11
  215. data/app/models/spree_cm_commissioner/vehicle_type.rb +0 -76
  216. data/app/overrides/spree/admin/taxons/_form/check_in_flows.html.erb.deface +0 -18
  217. data/app/queries/spree_cm_commissioner/trip_search_query.rb +0 -76
  218. data/app/queries/spree_cm_commissioner/variant_availability/non_permanent_stock_query.rb +0 -45
  219. data/app/queries/spree_cm_commissioner/variant_availability/permanent_stock_query.rb +0 -55
  220. data/app/serializers/spree/v2/organizer/invite_crews_serializer.rb +0 -11
  221. data/app/services/spree_cm_commissioner/vehicle_option_value_creator.rb +0 -11
  222. data/db/migrate/20250616084219_add_description_to_cm_vendor_place.rb +0 -5
  223. data/db/migrate/20250630103536_create_cm_telegram_chats.rb +0 -13
  224. data/db/migrate/20250701093203_add_configurations_to_cm_dynamic_field.rb +0 -6
  225. data/db/migrate/20250702091305_add_dynamic_field_option_to_guest_dynamic_field.rb +0 -5
  226. data/db/migrate/20250702091935_add_status_to_dynamic_field_option.rb +0 -5
  227. data/db/migrate/20250707032008_add_vendor_id_to_spree_category.rb +0 -7
  228. data/db/migrate/20250711092937_add_position_to_cm_dynamic_fields.rb +0 -11
  229. data/db/migrate/20250711093045_add_position_to_cm_dynamic_field_options.rb +0 -11
  230. data/db/migrate/20250714121508_rename_cm_taxon_blazer_query_to_blazer_queryables.rb +0 -7
  231. data/db/migrate/20250714124323_make_cm_blazer_queryables_polymorphic.rb +0 -19
  232. data/db/migrate/20250715103333_remove_indexes_from_cm_user_identity_providers.rb +0 -13
  233. data/lib/spree_cm_commissioner/test_helper/factories/branch_factory.rb +0 -12
  234. data/lib/spree_cm_commissioner/test_helper/factories/departure_time_option_type_factory.rb +0 -8
  235. data/lib/spree_cm_commissioner/test_helper/factories/duration_option_type_factory.rb +0 -8
  236. data/lib/spree_cm_commissioner/test_helper/factories/line_item_seat_factory.rb +0 -7
  237. data/lib/spree_cm_commissioner/test_helper/factories/stop_factory.rb +0 -14
  238. data/lib/spree_cm_commissioner/test_helper/factories/transit_place_factory.rb +0 -8
  239. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_option_type_factory.rb +0 -8
  240. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_type_factory.rb +0 -96
  241. data/lib/spree_cm_commissioner/trip_seat_layout_result.rb +0 -11
@@ -1,144 +0,0 @@
1
- module SpreeCmCommissioner
2
- class TelegramChatsAutoFinder < BaseInteractor
3
- delegate :contact, :pin_code, to: :context
4
-
5
- def call
6
- context.chats = []
7
- context.verified_chat_ids = []
8
-
9
- updates = fetch_updates
10
-
11
- if updates['result'].any?
12
- updates['result'].sort_by { |u| u['update_id'] }.reverse.each do |update|
13
- handle_message_update(update) if update['message']
14
- handle_channel_post_update(update) if update['channel_post']
15
- handle_chat_member_update(update) if update['my_chat_member']
16
- end
17
- end
18
- context.fail!(message: 'No pin codes verified') if context.verified_chat_ids.empty?
19
- end
20
-
21
- private
22
-
23
- def handle_chat_member_update(update)
24
- chat = update.dig('my_chat_member', 'chat')
25
- return unless chat
26
-
27
- chat_data = {
28
- id: chat['id'],
29
- title: chat['title'] || 'Unnamed Chat',
30
- type: chat['type']
31
- }
32
-
33
- return if context.chats.any? { |c| c[:id] == chat_data[:id] }
34
-
35
- db_chat = SpreeCmCommissioner::TelegramChat.find_or_initialize_by(chat_id: chat_data[:id])
36
- is_new_chat = db_chat.new_record?
37
- db_chat.update(chat_title: chat_data[:title], chat_type: chat_data[:type])
38
- context.chats << chat_data
39
- message = "👋Hello! This is Bookme+ bot.\n\nPlease enter the 6-digit PIN code displayed in your portal."
40
- send_message(chat_data[:id], message) if is_new_chat
41
- end
42
-
43
- def handle_channel_post_update(update)
44
- message = update['channel_post']
45
- process_pin_code_message(message)
46
- end
47
-
48
- def handle_message_update(update)
49
- message = update['message']
50
- process_pin_code_message(message)
51
- end
52
-
53
- def process_pin_code_message(message)
54
- chat_id = message.dig('chat', 'id')
55
- text = message['text']&.strip
56
-
57
- return unless valid_pin_code?(text, chat_id)
58
-
59
- pin_code_record = find_pin_code_record
60
- return unless pin_code_record
61
-
62
- vendor = find_vendor
63
- return unless vendor
64
-
65
- chat = update_telegram_chat(message, chat_id)
66
- return unless chat
67
-
68
- handle_successful_verification(chat, vendor, pin_code_record)
69
- end
70
-
71
- def valid_pin_code?(text, chat_id)
72
- text && chat_id && text == pin_code
73
- end
74
-
75
- def find_pin_code_record
76
- pin_code_record = SpreeCmCommissioner::PinCodeTelegram.find_by(code: pin_code, contact: contact)
77
- unless pin_code_record
78
- context.fail!(message: "Pin code #{pin_code} not found for contact #{contact}")
79
- return nil
80
- end
81
- pin_code_record
82
- end
83
-
84
- def find_vendor
85
- vendor = Spree::Vendor.find_by(id: contact)
86
- unless vendor
87
- context.fail!(message: "Vendor not found for contact #{contact}")
88
- return nil
89
- end
90
- vendor
91
- end
92
-
93
- def update_telegram_chat(message, chat_id)
94
- chat = SpreeCmCommissioner::TelegramChat.find_or_initialize_by(chat_id: chat_id)
95
- unless chat.update(
96
- chat_title: message.dig('chat', 'title') || 'Unnamed Chat',
97
- chat_type: message.dig('chat', 'type')
98
- )
99
- context.fail!(message: "Failed to update chat: #{chat.errors.full_messages.join(', ')}")
100
- return nil
101
- end
102
-
103
- context.chats << { id: chat.chat_id, title: chat.chat_title, type: chat.chat_type }
104
- chat
105
- end
106
-
107
- def handle_successful_verification(chat, vendor, pin_code_record)
108
- return if chat.vendor && chat.vendor != vendor
109
-
110
- update_vendor_preferences(vendor, chat)
111
- chat.update(active: true, vendor: vendor)
112
- expire_pin_code(pin_code_record)
113
- send_success_message(chat.chat_id, vendor.name)
114
- context.verified_chat_ids << chat.chat_id
115
- end
116
-
117
- def update_vendor_preferences(vendor, chat)
118
- vendor.update(
119
- preferred_telegram_chat_id: chat.chat_id,
120
- preferred_telegram_chat_name: chat.chat_title,
121
- preferred_telegram_chat_type: chat.chat_type
122
- )
123
- end
124
-
125
- def expire_pin_code(pin_code_record)
126
- pin_code_record.expire
127
- pin_code_record.save
128
- end
129
-
130
- def send_success_message(chat_id, vendor_name)
131
- message = "✅ PIN code verified successfully! This chat is now connected to <b>#{vendor_name}</b>.\n\n" \
132
- 'All completed orders will be sent to this chat.'
133
- send_message(chat_id, message)
134
- end
135
-
136
- def fetch_updates
137
- ::Telegram.bot.get_updates
138
- end
139
-
140
- def send_message(chat_id, text)
141
- ::Telegram.bot.send_message(chat_id: chat_id, text: text, parse_mode: 'HTML')
142
- end
143
- end
144
- end
@@ -1,30 +0,0 @@
1
- module SpreeCmCommissioner
2
- module EventCheckInFlowable
3
- extend ActiveSupport::Concern
4
-
5
- included do
6
- preference :group_check_in_enabled, :boolean, default: true
7
- preference :individual_check_in_enabled, :boolean, default: true
8
-
9
- before_validation :validate_at_least_one_check_in_flow_presence
10
- end
11
-
12
- def check_in_flows
13
- flows = []
14
- flows << 'group' if group_check_in_enabled?
15
- flows << 'individual' if individual_check_in_enabled?
16
- flows
17
- end
18
-
19
- def group_check_in_enabled? = preferred_group_check_in_enabled
20
- def individual_check_in_enabled? = preferred_individual_check_in_enabled
21
-
22
- private
23
-
24
- def validate_at_least_one_check_in_flow_presence
25
- return if check_in_flows.any?
26
-
27
- errors.add(:check_in_flows, 'must have at least one flow selected')
28
- end
29
- end
30
- end
@@ -1,8 +0,0 @@
1
- module SpreeCmCommissioner
2
- class BlazerQueryable < SpreeCmCommissioner::Base
3
- belongs_to :queryable, polymorphic: true
4
- belongs_to :blazer_query, class_name: 'Blazer::Query'
5
-
6
- validates :queryable_id, uniqueness: { scope: %i[queryable_type blazer_query_id], message: I18n.t('event_blazer_queries.fail') }
7
- end
8
- end
@@ -1,12 +0,0 @@
1
- require_dependency 'spree_cm_commissioner'
2
-
3
- module SpreeCmCommissioner
4
- class Branch < SpreeCmCommissioner::Place
5
- belongs_to :state, class_name: 'Spree::State', optional: true
6
- belongs_to :vendor, class_name: 'Spree::Vendor'
7
-
8
- def validate_reference?
9
- false
10
- end
11
- end
12
- end
@@ -1,4 +0,0 @@
1
- module SpreeCmCommissioner
2
- class CrewInviteLink < Invite
3
- end
4
- end
@@ -1,10 +0,0 @@
1
- require_dependency 'spree_cm_commissioner'
2
- module SpreeCmCommissioner
3
- class LineItemSeat < SpreeCmCommissioner::Base
4
- belongs_to :line_item, class_name: 'Spree::LineItem'
5
- belongs_to :seat, class_name: 'SpreeCmCommissioner::VehicleSeat'
6
- belongs_to :variant, class_name: 'Spree::Variant'
7
-
8
- validates :date, presence: true
9
- end
10
- end
@@ -1,8 +0,0 @@
1
- require_dependency 'spree_cm_commissioner'
2
-
3
- module SpreeCmCommissioner
4
- class OptionValueVehicleType < ApplicationRecord
5
- belongs_to :vehicle_type, class_name: 'SpreeCmCommissioner::VehicleType', dependent: :destroy
6
- belongs_to :option_value, class_name: 'Spree::OptionValue', dependent: :destroy
7
- end
8
- end
@@ -1,28 +0,0 @@
1
- module SpreeCmCommissioner
2
- class PinCodeTelegram < PinCode
3
- before_validation :set_telegram_attrs, on: :create
4
- validates :contact, presence: true, numericality: { only_integer: true }, if: :telegram?
5
-
6
- belongs_to :vendor, class_name: 'Spree::Vendor', foreign_key: 'contact', primary_key: 'id'
7
-
8
- def telegram?
9
- true
10
- end
11
-
12
- def expires_in_seconds
13
- 5 * 60
14
- end
15
-
16
- def expired?
17
- expired_at < Time.zone.now
18
- end
19
-
20
- private
21
-
22
- def set_telegram_attrs
23
- self.contact_type = :telegram
24
- self.type = 'SpreeCmCommissioner::PinCodeTelegram'
25
- self.expired_at = Time.zone.now + expires_in_seconds unless expired_at
26
- end
27
- end
28
- end
@@ -1,11 +0,0 @@
1
- module SpreeCmCommissioner
2
- module PromotionCategoryDecorator
3
- def self.prepended(base)
4
- base.belongs_to :vendor, class_name: 'Spree::Vendor', optional: true
5
- end
6
- end
7
- end
8
-
9
- unless Spree::PromotionCategory.included_modules.include?(SpreeCmCommissioner::PromotionCategoryDecorator)
10
- Spree::PromotionCategory.prepend(SpreeCmCommissioner::PromotionCategoryDecorator)
11
- end
@@ -1,23 +0,0 @@
1
- require_dependency 'spree_cm_commissioner'
2
-
3
- module SpreeCmCommissioner
4
- class Stop < SpreeCmCommissioner::Place
5
- belongs_to :branch, class_name: 'SpreeCmCommissioner::Branch'
6
- belongs_to :state, class_name: 'Spree::State', optional: true
7
- belongs_to :vendor, class_name: 'Spree::Vendor'
8
-
9
- after_save :add_to_option_value
10
-
11
- def validate_reference?
12
- false
13
- end
14
-
15
- def add_to_option_value
16
- origin = Spree::OptionType.find_by(attr_type: 'origin')&.id
17
- destination = Spree::OptionType.find_by(attr_type: 'destination')&.id
18
-
19
- Spree::OptionValue.create(option_type_id: origin, name: name, presentation: id)
20
- Spree::OptionValue.create(option_type_id: destination, name: name, presentation: id)
21
- end
22
- end
23
- end
@@ -1,6 +0,0 @@
1
- module SpreeCmCommissioner
2
- class TelegramChat < Base
3
- belongs_to :vendor, class_name: 'Spree::Vendor'
4
- validates :chat_id, presence: true, uniqueness: true
5
- end
6
- end
@@ -1,11 +0,0 @@
1
- module SpreeCmCommissioner
2
- class VehicleSeat < SpreeCmCommissioner::Base
3
- belongs_to :vehicle_type, class_name: 'SpreeCmCommissioner::VehicleType', dependent: :destroy
4
- has_many :line_item_seats, class_name: 'SpreeCmCommissioner::LineItemSeat', dependent: :destroy
5
- counter_culture :vehicle_type, column_name: proc { |model|
6
- model.seat_type.in?(%w[normal vip]) && model.vehicle_type.allow_seat_selection == true ? 'vehicle_seats_count' : nil # rubocop:disable Layout/LineLength
7
- },
8
- column_names: { ['cm_vehicle_seats.seat_type IN (?)', %i[0 2]] => 'vehicle_seats_count' }
9
- enum seat_type: %i[normal empty vip driver].freeze
10
- end
11
- end
@@ -1,76 +0,0 @@
1
- module SpreeCmCommissioner
2
- class VehicleType < SpreeCmCommissioner::Base
3
- include SpreeCmCommissioner::RouteType
4
-
5
- after_commit :recalculate_vehicle_seats_count, if: -> { saved_change_to_allow_seat_selection? && allow_seat_selection }
6
- after_commit :set_vehicles_attributes
7
-
8
- has_many :vehicle_seats, class_name: 'SpreeCmCommissioner::VehicleSeat', dependent: :destroy
9
- has_many :option_value_vehicle_types, class_name: 'SpreeCmCommissioner::OptionValueVehicleType'
10
- has_many :option_values, through: :option_value_vehicle_types, class_name: 'Spree::OptionValue'
11
- has_many :vehicles, class_name: 'SpreeCmCommissioner::Vehicle', dependent: :destroy
12
- belongs_to :vendor, class_name: 'Spree::Vendor'
13
-
14
- validates :code, presence: true
15
- validates :code, uniqueness: true
16
- validates :name, presence: true
17
- validates :name, uniqueness: true
18
- accepts_nested_attributes_for :vehicle_seats, allow_destroy: true
19
-
20
- state_machine :status, initial: :draft do
21
- event :draft do
22
- transition to: :draft
23
- end
24
- after_transition to: :draft, do: :after_draft
25
-
26
- event :activate do
27
- transition to: :active
28
- end
29
- after_transition to: :active, do: :after_activate
30
-
31
- event :archive do
32
- transition to: :archived
33
- end
34
- after_transition to: :archived, do: :after_archive
35
- end
36
-
37
- self.whitelisted_ransackable_attributes = %w[name code route_type id status]
38
-
39
- def after_activate; end
40
- def after_archive; end
41
- def after_draft; end
42
-
43
- def set_vehicles_attributes
44
- vehicles.each(&:set_attributes)
45
- vehicles.each(&:save)
46
- end
47
-
48
- def recalculate_vehicle_seats_count
49
- self.vehicle_seats_count = vehicle_seats.where(seat_type: %w[normal vip]).count
50
- save
51
- end
52
-
53
- def seat_layers
54
- grouped_seats = SpreeCmCommissioner::VehicleSeat.where(vehicle_type_id: id).group_by(&:layer).transform_values do |seats|
55
- seats.group_by(&:row).transform_values do |row_seats|
56
- row_seats.sort_by(&:column).map do |seat|
57
- {
58
- row: seat.row,
59
- column: seat.column,
60
- label: seat.label,
61
- layer: seat.layer,
62
- seat_type: seat.seat_type,
63
- created_at: seat.created_at,
64
- vehicle_type_id: seat.vehicle_type_id
65
- }
66
- end
67
- end
68
- end
69
- grouped_seats.map do |_layer, layer_seats|
70
- layer_seats.map do |_row, row_seats|
71
- row_seats
72
- end
73
- end
74
- end
75
- end
76
- end
@@ -1,18 +0,0 @@
1
- <!-- insert_before "erb[loud]:contains('field_container :hide_from_nav')" -->
2
-
3
- <%# Sections don't use video banner, so we hide the form here to avoid confusing admin. %>
4
-
5
- <%= f.field_container :preferred_group_check_in_enabled, class: ['custom-control', 'custom-checkbox', 'my-4'] do %>
6
- <%= f.check_box :preferred_group_check_in_enabled, class: 'custom-control-input' %>
7
- <%= f.label :preferred_group_check_in_enabled, Spree.t(:enable_group_check_in), class: 'custom-control-label' %>
8
- <%= f.error_message_on :preferred_group_check_in_enabled %>
9
- <small class="form-text text-muted">
10
- Enabled by default for most events where users can purchase multiple tickets or use group scanning. For large events (like PSK, ASK, etc.) or invitation-based events, you should disable this to ensure each ticket or invitation is scanned individually.
11
- </small>
12
- <% end if @taxon.event? && @taxon.depth == 1 %> %>
13
-
14
- <%= f.field_container :preferred_individual_check_in_enabled, class: ['custom-control', 'custom-checkbox', 'my-4'] do %>
15
- <%= f.check_box :preferred_individual_check_in_enabled, class: 'custom-control-input' %>
16
- <%= f.label :preferred_individual_check_in_enabled, Spree.t(:enable_individual_check_in), class: 'custom-control-label' %>
17
- <%= f.error_message_on :preferred_individual_check_in_enabled %>
18
- <% end if @taxon.event? && @taxon.depth == 1 %> %>
@@ -1,76 +0,0 @@
1
- module SpreeCmCommissioner
2
- class TripSearchQuery
3
- attr_reader :origin_id, :destination_id, :vendor_id, :date
4
-
5
- def initialize(origin_id:, destination_id:, date:, vendor_id: nil)
6
- @origin_id = origin_id
7
- @destination_id = destination_id
8
- @vendor_id = vendor_id
9
- @date = date
10
- end
11
-
12
- def call
13
- trips_info.map do |trip|
14
- trip_result_options = {
15
- trip_id: trip.trip_id,
16
- vendor_id: trip.vendor_id,
17
- vendor_name: trip.vendor_name,
18
- route_name: trip.route_name,
19
- short_name: trip.short_name,
20
- detail: trip.trip_id,
21
- origin_id: trip.origin_id,
22
- origin: trip.origin,
23
- destination_id: trip.destination_id,
24
- destination: trip.destination,
25
- total_sold: trip.total_sold,
26
- total_seats: trip.total_seats,
27
- vehicle_id: trip.vehicle_id,
28
- departure_time: trip.departure_time.strftime('%H:%M'),
29
- duration: trip.duration
30
- }
31
- SpreeCmCommissioner::TripResult.new(trip_result_options)
32
- end
33
- end
34
-
35
- def trips_info
36
- result = Spree::Variant.select('spree_variants.id as trip_id,
37
- spree_vendors.id as vendor_id,
38
- spree_vendors.name as vendor_name,
39
- routes.name as route_name,
40
- routes.short_name as short_name,
41
- details.id as detail_id,
42
- boarding.stop_id as origin_id,
43
- drop_off.stop_id as destination_id,
44
- details.departure_time as departure_time,
45
- details.duration as duration,
46
- boarding.stop_name as origin,
47
- drop_off.stop_name as destination,
48
- COALESCE(ts.total_sold, 0) as total_sold,
49
- cm_vehicles.number_of_seats as total_seats,
50
- cm_vehicles.id as vehicle_id
51
- '
52
- )
53
- .joins('INNER JOIN spree_products routes ON routes.id = spree_variants.product_id')
54
- .joins('INNER JOIN cm_trips details on details.product_id = routes.id')
55
- .joins('INNER JOIN cm_vehicles ON cm_vehicles.id = details.vehicle_id')
56
- .joins("INNER JOIN cm_trip_stops boarding ON boarding.trip_id = details.id AND boarding.stop_type = '0'")
57
- .joins("INNER JOIN cm_trip_stops drop_off ON drop_off.trip_id = details.id AND drop_off.stop_type = '1'")
58
- .joins('INNER JOIN spree_vendors ON spree_vendors.id = spree_variants.vendor_id')
59
- .joins("LEFT JOIN (#{total_sold.to_sql}) ts ON spree_variants.id = ts.trip_id")
60
-
61
- # TODO: migrat to new table: vehicle, orign and destination
62
- result = result.where(boarding: { stop_id: origin_id }, drop_off: { stop_id: destination_id })
63
- result = result.where(vendor_id: vendor_id) if vendor_id.present?
64
- result
65
- end
66
-
67
- def total_sold
68
- Spree::Variant.select('spree_variants.id as trip_id, SUM(spree_line_items.quantity) as total_sold')
69
- .joins('INNER JOIN spree_line_items ON spree_line_items.variant_id = spree_variants.id')
70
- .joins('INNER JOIN spree_orders ON spree_orders.id = spree_line_items.order_id')
71
- .where(spree_orders: { state: 'complete' })
72
- .where(spree_line_items: { date: date })
73
- .group('spree_variants.id')
74
- end
75
- end
76
- end
@@ -1,45 +0,0 @@
1
- module SpreeCmCommissioner
2
- module VariantAvailability
3
- class NonPermanentStockQuery
4
- attr_reader :variant, :except_line_item_id, :error_message
5
-
6
- def initialize(variant:, except_line_item_id: nil)
7
- @variant = variant
8
- @except_line_item_id = except_line_item_id
9
- @error_message = nil
10
- end
11
-
12
- def available?(quantity)
13
- reserve_variants =
14
- Spree::LineItem
15
- .complete
16
- .select('(SUM(DISTINCT spree_stock_items.count_on_hand) - SUM(spree_line_items.quantity)) AS available_quantity')
17
- .joins(variant: :stock_items)
18
- .where(variant_id: variant.id)
19
- .where.not(id: except_line_item_id)
20
- .group(:variant_id)
21
-
22
- # there is a case when variant does not have any purchaces yet, it will return empty & always available true.
23
- # in this case, we check with stock items directly.
24
-
25
- available_quantity = if reserve_variants.any?
26
- reserve_variants.sum(&:available_quantity)
27
- else
28
- variant.stock_items.sum(:count_on_hand)
29
- end
30
- if available_quantity >= quantity
31
- true
32
- elsif available_quantity == 1
33
- @error_message = I18n.t('variant_availability.item_available_instock')
34
- false
35
- elsif available_quantity <= 0
36
- @error_message = I18n.t('variant_availability.items_out_of_stock')
37
- false
38
- else
39
- @error_message = I18n.t('variant_availability.items_available_instock', available_quantity: available_quantity)
40
- false
41
- end
42
- end
43
- end
44
- end
45
- end
@@ -1,55 +0,0 @@
1
- module SpreeCmCommissioner
2
- module VariantAvailability
3
- class PermanentStockQuery
4
- attr_reader :variant, :from_date, :to_date, :except_line_item_id
5
-
6
- def initialize(variant:, from_date:, to_date:, except_line_item_id: nil)
7
- @variant = variant
8
- @from_date = from_date
9
- @to_date = to_date
10
- @except_line_item_id = except_line_item_id
11
- end
12
-
13
- def available?(quantity)
14
- (from_date..from_date).all? do |booking_date|
15
- booked_date_quantity[booking_date].nil? ||
16
- (booked_date_quantity[booking_date] - quantity) >= 0
17
- end
18
- end
19
-
20
- def booked_date_quantity
21
- dates_sql = ApplicationRecord.sanitize_sql_array(
22
- [
23
- 'SELECT date FROM generate_series(?::date, ?::date, ?) AS date',
24
- from_date,
25
- to_date,
26
- date_interval
27
- ]
28
- )
29
-
30
- @booked_variants ||=
31
- Spree::LineItem
32
- .complete
33
- .select(
34
- '(SUM(DISTINCT spree_stock_items.count_on_hand) - SUM(spree_line_items.quantity)) AS available_quantity',
35
- 'dates.date AS reservation_date'
36
- )
37
- .joins(variant: :stock_items)
38
- .where(variant_id: variant.id)
39
- .where.not(id: except_line_item_id)
40
- .joins("INNER JOIN (#{dates_sql}) dates ON dates.date >= spree_line_items.from_date AND dates.date < spree_line_items.to_date")
41
- .group(:variant_id, :reservation_date)
42
- .order(:reservation_date)
43
- .each_with_object({}) do |record, hash|
44
- hash[record.reservation_date.to_date] = record.available_quantity
45
- end
46
- end
47
-
48
- # override this for product that have
49
- # different date time interval than 1 day.
50
- def date_interval
51
- '1 day'
52
- end
53
- end
54
- end
55
- end
@@ -1,11 +0,0 @@
1
- module Spree
2
- module V2
3
- module Organizer
4
- class InviteCrewsSerializer < BaseSerializer
5
- attributes :token, :expires_at
6
- belongs_to :taxon, serializer: Spree::V2::Organizer::TaxonSerializer
7
- belongs_to :inviter, serializer: Spree::V2::Organizer::UserSerializer
8
- end
9
- end
10
- end
11
- end
@@ -1,11 +0,0 @@
1
- module SpreeCmCommissioner
2
- class VehicleOptionValueCreator
3
- def self.call(vehicle)
4
- vehicle_option_type = Spree::OptionType.vehicle
5
-
6
- value = vehicle_option_type.option_values.where(name: vehicle.id).first_or_initialize
7
- value.presentation = vehicle.code
8
- value.save
9
- end
10
- end
11
- end
@@ -1,5 +0,0 @@
1
- class AddDescriptionToCmVendorPlace < ActiveRecord::Migration[7.0]
2
- def change
3
- add_column :cm_vendor_places, :description, :string, if_not_exists: true
4
- end
5
- end
@@ -1,13 +0,0 @@
1
- class CreateCmTelegramChats < ActiveRecord::Migration[7.0]
2
- def change
3
- create_table :cm_telegram_chats, if_not_exists: true do |t|
4
- t.bigint :chat_id, null: false
5
- t.string :chat_title
6
- t.string :chat_type
7
- t.boolean :active, default: false
8
- t.references :vendor, foreign_key: { to_table: :spree_vendors }
9
- t.timestamps
10
- end
11
- add_index :cm_telegram_chats, :chat_id, unique: true, if_not_exists: true
12
- end
13
- end
@@ -1,6 +0,0 @@
1
- class AddConfigurationsToCmDynamicField < ActiveRecord::Migration[7.0]
2
- def change
3
- add_column :cm_dynamic_fields, :configurations, :jsonb, default: {}, null: false, if_not_exists: true
4
- add_index :cm_dynamic_fields, :configurations, if_not_exists: true
5
- end
6
- end
@@ -1,5 +0,0 @@
1
- class AddDynamicFieldOptionToGuestDynamicField < ActiveRecord::Migration[7.0]
2
- def change
3
- add_reference :cm_guest_dynamic_fields, :dynamic_field_option, index: true, foreign_key: { to_table: :cm_dynamic_field_options }, if_not_exists: true
4
- end
5
- end
@@ -1,5 +0,0 @@
1
- class AddStatusToDynamicFieldOption < ActiveRecord::Migration[7.0]
2
- def change
3
- add_column :cm_dynamic_field_options, :status, :integer, default: 0, if_not_exists: true
4
- end
5
- end
@@ -1,7 +0,0 @@
1
- class AddVendorIdToSpreeCategory < ActiveRecord::Migration[7.0]
2
- def change
3
- unless column_exists?(:spree_promotion_categories, :vendor_id)
4
- add_reference :spree_promotion_categories, :vendor, index: true, foreign_key: { to_table: :spree_vendors }
5
- end
6
- end
7
- end