spree_cm_commissioner 1.18.2.pre.pre1 → 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 (210) 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/inventory_items_controller.rb +83 -0
  12. data/app/controllers/spree/admin/stock_managements_controller.rb +63 -1
  13. data/app/controllers/spree/admin/tenants_controller.rb +0 -8
  14. data/app/controllers/spree/api/v2/storefront/accommodations/variants_controller.rb +42 -0
  15. data/app/controllers/spree/api/v2/storefront/accommodations_controller.rb +14 -31
  16. data/app/controllers/spree/api/v2/storefront/guests_controller.rb +5 -31
  17. data/app/controllers/spree/api/v2/storefront/queue_cart/line_items_controller.rb +2 -2
  18. data/app/controllers/spree_cm_commissioner/admin/variants_controller_decorator.rb +1 -1
  19. data/app/controllers/spree_cm_commissioner/well_known_controller.rb +17 -31
  20. data/app/finders/spree_cm_commissioner/accommodations/find.rb +37 -0
  21. data/app/finders/spree_cm_commissioner/accommodations/find_variant.rb +32 -0
  22. data/app/interactors/spree_cm_commissioner/ensure_correct_product_type.rb +40 -0
  23. data/app/interactors/spree_cm_commissioner/inventory_item_syncer.rb +25 -0
  24. data/app/interactors/spree_cm_commissioner/stock/inventory_item_resetter.rb +44 -0
  25. data/app/interactors/spree_cm_commissioner/stock/inventory_items_adjuster.rb +13 -0
  26. data/app/interactors/spree_cm_commissioner/stock/inventory_items_generator.rb +15 -0
  27. data/app/interactors/spree_cm_commissioner/stock/permanent_inventory_items_generator.rb +75 -0
  28. data/app/interactors/spree_cm_commissioner/stock/stock_movement_creator.rb +32 -0
  29. data/app/interactors/spree_cm_commissioner/vattanac_bank_initiator.rb +1 -5
  30. data/app/jobs/spree_cm_commissioner/application_job.rb +20 -0
  31. data/app/jobs/spree_cm_commissioner/application_unique_job.rb +20 -0
  32. data/app/jobs/spree_cm_commissioner/ensure_correct_product_type_job.rb +7 -0
  33. data/app/jobs/spree_cm_commissioner/inventory_item_syncer_job.rb +7 -0
  34. data/app/jobs/spree_cm_commissioner/stock/inventory_items_adjuster_job.rb +11 -0
  35. data/app/jobs/spree_cm_commissioner/stock/inventory_items_generator_job.rb +11 -0
  36. data/app/jobs/spree_cm_commissioner/stock/permanent_inventory_items_generator_job.rb +9 -0
  37. data/app/models/concerns/spree_cm_commissioner/line_item_durationable.rb +9 -15
  38. data/app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb +1 -13
  39. data/app/models/concerns/spree_cm_commissioner/order_seatable.rb +44 -0
  40. data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +39 -0
  41. data/app/models/concerns/spree_cm_commissioner/product_delegation.rb +1 -3
  42. data/app/models/concerns/spree_cm_commissioner/product_type.rb +10 -0
  43. data/app/models/concerns/spree_cm_commissioner/taxon_kind.rb +1 -1
  44. data/app/models/concerns/spree_cm_commissioner/tenant_preference.rb +0 -4
  45. data/app/models/spree_cm_commissioner/block.rb +23 -0
  46. data/app/models/spree_cm_commissioner/dynamic_field.rb +3 -15
  47. data/app/models/spree_cm_commissioner/dynamic_field_option.rb +1 -5
  48. data/app/models/spree_cm_commissioner/guest.rb +19 -1
  49. data/app/models/spree_cm_commissioner/guest_dynamic_field.rb +3 -21
  50. data/app/models/spree_cm_commissioner/inventory.rb +11 -0
  51. data/app/models/spree_cm_commissioner/inventory_item.rb +69 -0
  52. data/app/models/spree_cm_commissioner/invite_team.rb +1 -3
  53. data/app/models/spree_cm_commissioner/line_item_decorator.rb +46 -78
  54. data/app/models/spree_cm_commissioner/notification_taxon.rb +1 -1
  55. data/app/models/spree_cm_commissioner/option_type_decorator.rb +1 -11
  56. data/app/models/spree_cm_commissioner/order_decorator.rb +30 -1
  57. data/app/models/spree_cm_commissioner/pin_code.rb +2 -3
  58. data/app/models/spree_cm_commissioner/place.rb +1 -3
  59. data/app/models/spree_cm_commissioner/price_decorator.rb +9 -0
  60. data/app/models/spree_cm_commissioner/product_decorator.rb +10 -4
  61. data/app/models/spree_cm_commissioner/redis_stock/cached_inventory_items_builder.rb +41 -0
  62. data/app/models/spree_cm_commissioner/redis_stock/inventory_updater.rb +126 -0
  63. data/app/models/spree_cm_commissioner/redis_stock/line_items_cached_inventory_items_builder.rb +36 -0
  64. data/app/models/spree_cm_commissioner/redis_stock/variant_cached_inventory_items_builder.rb +25 -0
  65. data/app/models/spree_cm_commissioner/reserved_block.rb +30 -0
  66. data/app/models/spree_cm_commissioner/seat_layout.rb +20 -0
  67. data/app/models/spree_cm_commissioner/seat_section.rb +16 -0
  68. data/app/models/spree_cm_commissioner/seats/blocks_canceler.rb +30 -0
  69. data/app/models/spree_cm_commissioner/seats/blocks_holder.rb +53 -0
  70. data/app/models/spree_cm_commissioner/seats/blocks_reserver.rb +49 -0
  71. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_on_hold_by_other_guest.rb +4 -0
  72. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_reserved_by_other_guest.rb +4 -0
  73. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_reserved_by_same_guest.rb +4 -0
  74. data/app/models/spree_cm_commissioner/seats/errors/unable_to_save_reserved_block_record.rb +4 -0
  75. data/app/models/spree_cm_commissioner/service_calendar.rb +0 -2
  76. data/app/models/spree_cm_commissioner/state_decorator.rb +0 -1
  77. data/app/models/spree_cm_commissioner/stock/availability_checker.rb +26 -25
  78. data/app/models/spree_cm_commissioner/stock/availability_validator_decorator.rb +2 -1
  79. data/app/models/spree_cm_commissioner/stock/line_item_availability_checker.rb +3 -3
  80. data/app/models/spree_cm_commissioner/stock/order_availability_checker.rb +44 -0
  81. data/app/models/spree_cm_commissioner/stock_item_decorator.rb +17 -0
  82. data/app/models/spree_cm_commissioner/taxon_decorator.rb +0 -2
  83. data/app/models/spree_cm_commissioner/taxonomy_decorator.rb +0 -6
  84. data/app/models/spree_cm_commissioner/trip.rb +20 -6
  85. data/app/models/spree_cm_commissioner/trip_connection.rb +5 -5
  86. data/app/models/spree_cm_commissioner/trip_stop.rb +2 -3
  87. data/app/models/spree_cm_commissioner/user_taxon.rb +0 -1
  88. data/app/models/spree_cm_commissioner/variant_block.rb +9 -0
  89. data/app/models/spree_cm_commissioner/variant_decorator.rb +36 -47
  90. data/app/models/spree_cm_commissioner/variant_options.rb +0 -23
  91. data/app/models/spree_cm_commissioner/vehicle.rb +9 -14
  92. data/app/models/spree_cm_commissioner/vendor_decorator.rb +7 -10
  93. data/app/models/spree_cm_commissioner/vendor_place.rb +6 -5
  94. data/app/models/spree_cm_commissioner/vendor_stop.rb +1 -2
  95. data/app/overrides/spree/admin/variants/_form/kyc_field.html.erb.deface +2 -2
  96. data/app/queries/spree_cm_commissioner/guest_searcher_query.rb +3 -45
  97. data/app/queries/spree_cm_commissioner/trip_query.rb +23 -26
  98. data/app/request_schemas/spree_cm_commissioner/accommodation_request_schema.rb +3 -0
  99. data/app/request_schemas/spree_cm_commissioner/application_request_schema.rb +1 -1
  100. data/app/request_schemas/spree_cm_commissioner/variant_request_schema.rb +19 -0
  101. data/app/serializers/spree/v2/storefront/accommodation_serializer.rb +2 -0
  102. data/app/serializers/spree/v2/storefront/line_item_serializer_decorator.rb +1 -0
  103. data/app/serializers/spree_cm_commissioner/v2/operator/dashboard_crew_event_serializer.rb +1 -4
  104. data/app/serializers/spree_cm_commissioner/v2/storefront/dynamic_field_option_serializer.rb +3 -1
  105. data/app/serializers/spree_cm_commissioner/v2/storefront/dynamic_field_serializer.rb +3 -1
  106. data/app/serializers/spree_cm_commissioner/v2/storefront/guest_dynamic_field_serializer.rb +1 -2
  107. data/app/services/spree_cm_commissioner/organizer/export_guest_csv_service.rb +15 -23
  108. data/app/views/spree/admin/inventory_items/show.html.erb +72 -0
  109. data/app/views/spree/admin/stock_managements/_variant_stock_items.html.erb +7 -2
  110. data/app/views/spree/admin/stock_managements/calendar.html.erb +56 -0
  111. data/app/views/spree/admin/stock_managements/index.html.erb +55 -6
  112. data/app/views/spree/admin/tenants/_form.html.erb +42 -109
  113. data/config/initializers/paper_trail.rb +1 -0
  114. data/config/initializers/spree_permitted_attributes.rb +5 -2
  115. data/config/locales/en.yml +0 -5
  116. data/config/routes.rb +22 -4
  117. data/db/migrate/20240202080634_update_counter_cache_of_vehicle_type.rb +3 -1
  118. data/db/migrate/20250304293518_create_cm_inventory_items.rb +21 -0
  119. data/db/migrate/20250429094228_add_lock_version_to_cm_inventory_items.rb +5 -0
  120. data/db/migrate/20250502025848_add_index_to_spree_products.rb +5 -0
  121. data/db/migrate/20250502030001_add_product_type_to_spree_variants.rb +5 -0
  122. data/db/migrate/20250502030002_add_product_type_to_spree_line_items.rb +5 -0
  123. data/db/migrate/20250603035256_add_inventory_item_to_spree_prices.rb +7 -0
  124. data/db/migrate/20250619073724_drop_table_cm_line_item_seats.rb +5 -0
  125. data/db/migrate/20250619073812_drop_table_cm_vehicle_seats.rb +5 -0
  126. data/db/migrate/20250619073844_drop_table_cm_vehicle_types.rb +9 -0
  127. data/db/migrate/20250619073957_drop_table_cm_option_value_vehicle_types.rb +5 -0
  128. data/db/migrate/20250619082354_remove_unnecessary_fields_from_cm_places.rb +9 -0
  129. data/db/migrate/20250619082736_remove_route_type_from_spree_products.rb +5 -0
  130. data/db/migrate/20250619083055_remove_unnecessary_fields_from_spree_taxons.rb +5 -0
  131. data/db/migrate/20250620083055_remove_variant_id_from_cm_trips.rb +5 -0
  132. data/db/migrate/20250620090000_update_cm_trip_connections_to_use_cm_trips.rb +6 -0
  133. data/db/migrate/20250620090001_create_cm_seat_layouts.rb +17 -0
  134. data/db/migrate/20250620090002_create_cm_seat_sections.rb +18 -0
  135. data/db/migrate/20250620090003_create_cm_blocks.rb +18 -0
  136. data/db/migrate/20250624091005_create_cm_reserved_blocks.rb +29 -0
  137. data/db/migrate/20250626083642_create_cm_variant_blocks.rb +24 -0
  138. data/db/migrate/20250627023314_add_block_id_to_cm_guests.rb +13 -0
  139. data/docker-compose.yml +1 -1
  140. data/lib/cm_app_logger.rb +11 -4
  141. data/lib/generators/spree_cm_commissioner/install/install_generator.rb +14 -11
  142. data/lib/generators/spree_cm_commissioner/install/templates/app/javascript/{spree_cm_commissioner → spree_dashboard/spree_cm_commissioner}/utilities.js +4 -0
  143. data/lib/spree_cm_commissioner/cached_inventory_item.rb +23 -0
  144. data/lib/spree_cm_commissioner/calendar_event.rb +11 -1
  145. data/lib/spree_cm_commissioner/test_helper/factories/block_factory.rb +9 -0
  146. data/lib/spree_cm_commissioner/test_helper/factories/guest_factory.rb +10 -0
  147. data/lib/spree_cm_commissioner/test_helper/factories/homepage_section_relatable_factory.rb +1 -1
  148. data/lib/spree_cm_commissioner/test_helper/factories/inventory_item_factory.rb +9 -0
  149. data/lib/spree_cm_commissioner/test_helper/factories/line_item_factory.rb +1 -1
  150. data/lib/spree_cm_commissioner/test_helper/factories/option_type_factory.rb +6 -30
  151. data/lib/spree_cm_commissioner/test_helper/factories/order_factory.rb +0 -36
  152. data/lib/spree_cm_commissioner/test_helper/factories/product_factory.rb +18 -34
  153. data/lib/spree_cm_commissioner/test_helper/factories/reserved_block_factory.rb +27 -0
  154. data/lib/spree_cm_commissioner/test_helper/factories/seat_layout_factory.rb +8 -0
  155. data/lib/spree_cm_commissioner/test_helper/factories/seat_section_factory.rb +8 -0
  156. data/lib/spree_cm_commissioner/test_helper/factories/stock_location_factory.rb +2 -2
  157. data/lib/spree_cm_commissioner/test_helper/factories/trip_connection_factory.rb +6 -0
  158. data/lib/spree_cm_commissioner/test_helper/factories/trip_factory.rb +10 -3
  159. data/lib/spree_cm_commissioner/test_helper/factories/variant_block_factory.rb +7 -0
  160. data/lib/spree_cm_commissioner/test_helper/factories/variant_factory.rb +41 -19
  161. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_factory.rb +1 -1
  162. data/lib/spree_cm_commissioner/test_helper/factories/vendor_factory.rb +1 -1
  163. data/lib/spree_cm_commissioner/version.rb +1 -1
  164. data/lib/spree_cm_commissioner.rb +35 -1
  165. data/lib/tasks/create_default_non_permanent_inventory_items.rake +16 -0
  166. data/lib/tasks/ensure_correct_product_type.rake +7 -0
  167. data/lib/tasks/generate_inventory_items.rake +7 -0
  168. data/spree_cm_commissioner.gemspec +7 -0
  169. metadata +131 -43
  170. data/app/assets/images/cm-hangmeas-checkout_image.svg +0 -63
  171. data/app/assets/images/cm-hangmeas-failed.svg +0 -56
  172. data/app/assets/images/cm-hangmeas-loader.svg +0 -50
  173. data/app/assets/images/cm-hangmeas-success.svg +0 -51
  174. data/app/assets/javascripts/spree_cm_commissioner/tenant_payment_icon_fields.js +0 -65
  175. data/app/assets/stylesheets/spree_cm_commissioner/backend/tenant_payment_icon_fields.scss +0 -60
  176. data/app/controllers/concerns/spree_cm_commissioner/transit/taxon_bitwise.rb +0 -44
  177. data/app/finders/spree_cm_commissioner/line_items/find_by_variant_decorator.rb +0 -20
  178. data/app/interactors/spree_cm_commissioner/apple_app_site_association_fetcher.rb +0 -27
  179. data/app/interactors/spree_cm_commissioner/asset_links_fetcher.rb +0 -27
  180. data/app/interactors/spree_cm_commissioner/telegram_chats_auto_finder.rb +0 -144
  181. data/app/models/concerns/spree_cm_commissioner/event_check_in_flowable.rb +0 -30
  182. data/app/models/spree_cm_commissioner/branch.rb +0 -12
  183. data/app/models/spree_cm_commissioner/line_item_seat.rb +0 -10
  184. data/app/models/spree_cm_commissioner/option_value_vehicle_type.rb +0 -8
  185. data/app/models/spree_cm_commissioner/pin_code_telegram.rb +0 -28
  186. data/app/models/spree_cm_commissioner/promotion_category_decorator.rb +0 -11
  187. data/app/models/spree_cm_commissioner/stop.rb +0 -23
  188. data/app/models/spree_cm_commissioner/telegram_chat.rb +0 -6
  189. data/app/models/spree_cm_commissioner/vehicle_seat.rb +0 -11
  190. data/app/models/spree_cm_commissioner/vehicle_type.rb +0 -76
  191. data/app/overrides/spree/admin/taxons/_form/check_in_flows.html.erb.deface +0 -18
  192. data/app/queries/spree_cm_commissioner/trip_search_query.rb +0 -76
  193. data/app/queries/spree_cm_commissioner/variant_availability/non_permanent_stock_query.rb +0 -45
  194. data/app/queries/spree_cm_commissioner/variant_availability/permanent_stock_query.rb +0 -55
  195. data/app/services/spree_cm_commissioner/vehicle_option_value_creator.rb +0 -11
  196. data/db/migrate/20250616084219_add_description_to_cm_vendor_place.rb +0 -5
  197. data/db/migrate/20250630103536_create_cm_telegram_chats.rb +0 -13
  198. data/db/migrate/20250701093203_add_configurations_to_cm_dynamic_field.rb +0 -6
  199. data/db/migrate/20250702091305_add_dynamic_field_option_to_guest_dynamic_field.rb +0 -5
  200. data/db/migrate/20250702091935_add_status_to_dynamic_field_option.rb +0 -5
  201. data/db/migrate/20250707032008_add_vendor_id_to_spree_category.rb +0 -7
  202. data/lib/spree_cm_commissioner/test_helper/factories/branch_factory.rb +0 -12
  203. data/lib/spree_cm_commissioner/test_helper/factories/departure_time_option_type_factory.rb +0 -8
  204. data/lib/spree_cm_commissioner/test_helper/factories/duration_option_type_factory.rb +0 -8
  205. data/lib/spree_cm_commissioner/test_helper/factories/line_item_seat_factory.rb +0 -7
  206. data/lib/spree_cm_commissioner/test_helper/factories/stop_factory.rb +0 -14
  207. data/lib/spree_cm_commissioner/test_helper/factories/transit_place_factory.rb +0 -8
  208. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_option_type_factory.rb +0 -8
  209. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_type_factory.rb +0 -96
  210. data/lib/spree_cm_commissioner/trip_seat_layout_result.rb +0 -11
@@ -1,56 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <svg
3
- xmlns="http://www.w3.org/2000/svg"
4
- viewBox="0 0 52 52"
5
- width="100"
6
- height="100"
7
- >
8
- <style>
9
- .svg-failed {
10
- stroke: white;
11
- stroke-width: 5;
12
- stroke-miterlimit: 10;
13
- stroke-linecap: round;
14
- stroke-linejoin: round;
15
- fill: none;
16
- animation: svg-failed-scale 0.3s ease-in-out 0.9s both;
17
- }
18
-
19
- .svg-failed-circle {
20
- stroke: none;
21
- fill: #FF5A5F;
22
- }
23
-
24
- .svg-failed-x {
25
- stroke-dasharray: 48;
26
- stroke-dashoffset: 48;
27
- animation: svg-failed-draw 0.5s ease forwards 0.6s;
28
- }
29
-
30
- @keyframes svg-failed-draw {
31
- to {
32
- stroke-dashoffset: 0;
33
- }
34
- }
35
-
36
- @keyframes svg-failed-scale {
37
- 0%, 100% {
38
- transform: scale(1);
39
- }
40
- 50% {
41
- transform: scale(1.1);
42
- }
43
- }
44
- </style>
45
-
46
- <circle class="svg-failed-circle" cx="26" cy="26" r="25" />
47
- <!-- X mark: two lines crossing -->
48
- <path
49
- class="svg-failed svg-failed-x"
50
- d="M16 16 L36 36"
51
- />
52
- <path
53
- class="svg-failed svg-failed-x"
54
- d="M36 16 L16 36"
55
- />
56
- </svg>
@@ -1,50 +0,0 @@
1
- <svg class="pl" width="300" height="300" viewBox="0 0 300 300" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <style>
3
- .pl__ring { animation: ringA 3s linear infinite; }
4
- .pl__ring--a { stroke: #F79E1B; }
5
- .pl__ring--b { animation-name: ringB; stroke: #F79E1B; }
6
- .pl__ring--c { animation-name: ringC; stroke: #F79E1B; }
7
- .pl__ring--d { animation-name: ringD; stroke: #F79E1B; }
8
-
9
- @keyframes ringA {
10
- from, 4% { stroke-dasharray: 0 660; stroke-width: 20; stroke-dashoffset: -330; }
11
- 12% { stroke-dasharray: 60 600; stroke-width: 30; stroke-dashoffset: -335; }
12
- 32% { stroke-dasharray: 60 600; stroke-width: 30; stroke-dashoffset: -595; }
13
- 40%, 54% { stroke-dasharray: 0 660; stroke-width: 20; stroke-dashoffset: -660; }
14
- 62% { stroke-dasharray: 60 600; stroke-width: 30; stroke-dashoffset: -665; }
15
- 82% { stroke-dasharray: 60 600; stroke-width: 30; stroke-dashoffset: -925; }
16
- 90%, to { stroke-dasharray: 0 660; stroke-width: 20; stroke-dashoffset: -990; }
17
- }
18
- @keyframes ringB {
19
- from, 12% { stroke-dasharray: 0 220; stroke-width: 20; stroke-dashoffset: -110; }
20
- 20% { stroke-dasharray: 20 200; stroke-width: 30; stroke-dashoffset: -115; }
21
- 40% { stroke-dasharray: 20 200; stroke-width: 30; stroke-dashoffset: -195; }
22
- 48%, 62% { stroke-dasharray: 0 220; stroke-width: 20; stroke-dashoffset: -220; }
23
- 70% { stroke-dasharray: 20 200; stroke-width: 30; stroke-dashoffset: -225; }
24
- 90% { stroke-dasharray: 20 200; stroke-width: 30; stroke-dashoffset: -305; }
25
- 98%, to { stroke-dasharray: 0 220; stroke-width: 20; stroke-dashoffset: -330; }
26
- }
27
- @keyframes ringC {
28
- from { stroke-dasharray: 0 440; stroke-width: 20; stroke-dashoffset: 0; }
29
- 8% { stroke-dasharray: 40 400; stroke-width: 30; stroke-dashoffset: -5; }
30
- 28% { stroke-dasharray: 40 400; stroke-width: 30; stroke-dashoffset: -175; }
31
- 36%, 58% { stroke-dasharray: 0 440; stroke-width: 20; stroke-dashoffset: -220; }
32
- 66% { stroke-dasharray: 40 400; stroke-width: 30; stroke-dashoffset: -225; }
33
- 86% { stroke-dasharray: 40 400; stroke-width: 30; stroke-dashoffset: -395; }
34
- 94%, to { stroke-dasharray: 0 440; stroke-width: 20; stroke-dashoffset: -440; }
35
- }
36
- @keyframes ringD {
37
- from, 8% { stroke-dasharray: 0 440; stroke-width: 20; stroke-dashoffset: 0; }
38
- 16% { stroke-dasharray: 40 400; stroke-width: 30; stroke-dashoffset: -5; }
39
- 36% { stroke-dasharray: 40 400; stroke-width: 30; stroke-dashoffset: -175; }
40
- 44%, 50% { stroke-dasharray: 0 440; stroke-width: 20; stroke-dashoffset: -220; }
41
- 58% { stroke-dasharray: 40 400; stroke-width: 30; stroke-dashoffset: -225; }
42
- 78% { stroke-dasharray: 40 400; stroke-width: 30; stroke-dashoffset: -395; }
43
- 86%, to { stroke-dasharray: 0 440; stroke-width: 20; stroke-dashoffset: -440; }
44
- }
45
- </style>
46
- <circle class="pl__ring pl__ring--a" cx="150" cy="150" r="105" fill="none" stroke-width="20" stroke-dasharray="0 660" stroke-dashoffset="-330" stroke-linecap="round"/>
47
- <circle class="pl__ring pl__ring--b" cx="150" cy="150" r="35" fill="none" stroke-width="20" stroke-dasharray="0 220" stroke-dashoffset="-110" stroke-linecap="round"/>
48
- <circle class="pl__ring pl__ring--c" cx="115" cy="150" r="70" fill="none" stroke-width="20" stroke-dasharray="0 440" stroke-linecap="round"/>
49
- <circle class="pl__ring pl__ring--d" cx="185" cy="150" r="70" fill="none" stroke-width="20" stroke-dasharray="0 440" stroke-linecap="round"/>
50
- </svg>
@@ -1,51 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <svg
3
- xmlns="http://www.w3.org/2000/svg"
4
- viewBox="0 0 52 52"
5
- width="100"
6
- height="100"
7
- >
8
- <style>
9
- .svg-checkmark {
10
- stroke: white;
11
- stroke-width: 5;
12
- stroke-miterlimit: 10;
13
- stroke-linecap: round;
14
- stroke-linejoin: round;
15
- fill: none;
16
- animation: svg-success-scale 0.3s ease-in-out 0.9s both;
17
- }
18
-
19
- .svg-checkmark-circle {
20
- stroke: none;
21
- fill: #00D290;
22
- }
23
-
24
- .svg-checkmark-check {
25
- stroke-dasharray: 48;
26
- stroke-dashoffset: 48;
27
- animation: svg-success-draw 0.5s ease forwards 0.6s;
28
- }
29
-
30
- @keyframes svg-success-draw {
31
- to {
32
- stroke-dashoffset: 0;
33
- }
34
- }
35
-
36
- @keyframes svg-success-scale {
37
- 0%, 100% {
38
- transform: scale(1);
39
- }
40
- 50% {
41
- transform: scale(1.1);
42
- }
43
- }
44
- </style>
45
-
46
- <circle class="svg-checkmark-circle" cx="26" cy="26" r="25" />
47
- <path
48
- class="svg-checkmark svg-checkmark-check"
49
- d="M14.1 27.2l7.1 7.2 16.7-16.8"
50
- />
51
- </svg>
@@ -1,65 +0,0 @@
1
- document.addEventListener('DOMContentLoaded', function () {
2
- // Initialize Select2 for all tenant-payment-icon-select elements
3
- if (window.$ && $.fn.select2) {
4
- $('.tenant-payment-icon-select').each(function () {
5
- $(this).select2({
6
- width: '100%'
7
- });
8
- });
9
- }
10
-
11
- // Handle icon selection change
12
- document.querySelectorAll('.tenant-payment-icon-select').forEach(function (select) {
13
- select.addEventListener('change', function (e) {
14
- const field = e.target.name.match(/\[([^\]]*)\]$/)[1]; // Extract field name
15
- const preview = document.getElementById(`icon-preview-${field}`);
16
- const removeBtn = document.querySelector(`.remove-icon-btn[data-target="${field}"]`);
17
- const iconPath = e.target.value;
18
-
19
- if (!preview || !removeBtn) return;
20
-
21
- if (!iconPath) {
22
- preview.innerHTML = '<span class="no-icon-placeholder"></span>';
23
- removeBtn.classList.add('hidden');
24
- return;
25
- }
26
-
27
- // Fetch SVG for the selected icon
28
- fetch(`/admin/vector_icons/svg?path=${encodeURIComponent(iconPath)}`)
29
- .then((response) => {
30
- if (!response.ok) throw new Error('Failed to fetch SVG');
31
- return response.text();
32
- })
33
- .then((svg) => {
34
- preview.innerHTML = svg;
35
- removeBtn.classList.remove('hidden');
36
- })
37
- .catch((error) => {
38
- console.error('Error fetching SVG:', error);
39
- preview.innerHTML = '<span class="no-icon-placeholder">Error loading icon</span>';
40
- });
41
- });
42
- });
43
-
44
- document.addEventListener('click', function (e) {
45
- if (!e.target.classList.contains('remove-icon-btn')) return;
46
-
47
- const field = e.target.getAttribute('data-target');
48
- const select = document.querySelector(`.tenant-payment-icon-select[name*="[${field}]"]`);
49
- const preview = document.getElementById(`icon-preview-${field}`);
50
- const removeBtn = e.target;
51
-
52
- if (!select || !preview || !removeBtn) return;
53
-
54
- // Clear the select input
55
- select.value = '';
56
-
57
- if (window.$ && $(select).hasClass('select2-hidden-accessible')) {
58
- $(select).val('').trigger('change.select2');
59
- } else {
60
- select.dispatchEvent(new Event('change', { bubbles: true }));
61
- }
62
- preview.innerHTML = '<span class="no-icon-placeholder"></span>';
63
- removeBtn.classList.add('hidden');
64
- });
65
- });
@@ -1,60 +0,0 @@
1
- .payment-icon-preview {
2
- width: 80px;
3
- height: 80px;
4
- background: #f8f9fa;
5
- border: 1px dashed #ccc;
6
- display: inline-flex;
7
- align-items: center;
8
- justify-content: center;
9
- cursor: pointer;
10
- }
11
-
12
- .payment-icon-preview svg {
13
- width: 100%;
14
- height: 100%;
15
- object-fit: contain;
16
- }
17
-
18
-
19
- .no-icon-placeholder {
20
- width: 40px;
21
- height: 40px;
22
- border: 1px dashed #ddd;
23
- background: #f8f9fa;
24
- display: inline-block;
25
- }
26
-
27
- .icon-preview-container {
28
- position: relative;
29
- display: inline-block;
30
- }
31
-
32
- .remove-icon-btn {
33
- position: absolute;
34
- top: -8px;
35
- right: -8px;
36
- width: 24px;
37
- height: 24px;
38
- border-radius: 50%;
39
- background: #dc3545;
40
- color: white;
41
- border: 2px solid white;
42
- display: flex;
43
- align-items: center;
44
- justify-content: center;
45
- cursor: pointer;
46
- font-size: 12px;
47
- box-shadow: 0 2px 4px rgba(0,0,0,0.2);
48
- transition: all 0.2s ease;
49
- z-index: 10;
50
- }
51
-
52
- .remove-icon-btn:hover {
53
- background: #c82333;
54
- transform: scale(1.1);
55
- box-shadow: 0 3px 6px rgba(0,0,0,0.3);
56
- }
57
-
58
- .remove-icon-btn.hidden {
59
- display: none;
60
- }
@@ -1,44 +0,0 @@
1
- module SpreeCmCommissioner
2
- module Transit
3
- module TaxonBitwise
4
- extend ActiveSupport::Concern
5
-
6
- BIT_STOP = 0b001
7
- BIT_STATION = 0b010
8
- BIT_BRANCH = 0b100
9
- BIT_LOCATION = 0b1000
10
-
11
- included do
12
- attr_accessor :stop, :station, :branch, :location
13
-
14
- before_validation :at_least_one_checkbox_selected
15
- end
16
-
17
- def stop?
18
- data_type & BIT_STOP != 0
19
- end
20
-
21
- def station?
22
- data_type & BIT_STATION != 0
23
- end
24
-
25
- def branch?
26
- data_type & BIT_BRANCH != 0
27
- end
28
-
29
- def location?
30
- data_type & BIT_LOCATION != 0
31
- end
32
-
33
- private
34
-
35
- def at_least_one_checkbox_selected
36
- if stop.nil? && station.nil? && branch.nil? && location.nil?
37
- nil
38
- elsif stop.to_i.zero? && station.to_i.zero? && branch.to_i.zero? && location.to_i.zero?
39
- errors.add(:base, 'At least one checkbox (stop, branch, or location) must be selected')
40
- end
41
- end
42
- end
43
- end
44
- end
@@ -1,20 +0,0 @@
1
- module SpreeCmCommissioner
2
- module LineItems
3
- module FindByVariantDecorator
4
- # ovveride
5
- def execute(order:, variant:, options: {})
6
- return super unless variant.product.product_type == 'transit'
7
-
8
- order.line_items.detect do |line_item|
9
- next if options[:date].present? && !(line_item.variant_id == variant.id && line_item.date == options[:date])
10
-
11
- Spree::Dependencies.cart_compare_line_items_service.constantize.call(order: order, line_item: line_item, options: options).value
12
- end
13
- end
14
- end
15
- end
16
- end
17
-
18
- unless Spree::LineItems::FindByVariant.included_modules.include?(SpreeCmCommissioner::LineItems::FindByVariantDecorator)
19
- Spree::LineItems::FindByVariant.prepend(SpreeCmCommissioner::LineItems::FindByVariantDecorator)
20
- end
@@ -1,27 +0,0 @@
1
- module SpreeCmCommissioner
2
- class AppleAppSiteAssociationFetcher < BaseInteractor
3
- delegate :store, :tenant, :refreshed, to: :context
4
-
5
- def call
6
- key = cache_key
7
-
8
- CmAppLogger.log(label: 'LOOKING_UP_CACHE', data: { cache_key: key })
9
-
10
- Rails.cache.delete(key) if refreshed
11
-
12
- context.contents = Rails.cache.fetch(key) do
13
- CmAppLogger.log(label: 'CACHE_MISS', data: { cache_key: key })
14
- resource.preferred_apple_app_site_association
15
- end
16
- end
17
-
18
- def cache_key
19
- updated_at = tenant&.updated_at || store&.updated_at
20
- "well_known:apple-app-site-association:#{resource.class.name}:#{resource.id}:#{updated_at}"
21
- end
22
-
23
- def resource
24
- tenant || store
25
- end
26
- end
27
- end
@@ -1,27 +0,0 @@
1
- module SpreeCmCommissioner
2
- class AssetLinksFetcher < BaseInteractor
3
- delegate :store, :tenant, :refreshed, to: :context
4
-
5
- def call
6
- key = cache_key
7
-
8
- CmAppLogger.log(label: 'LOOKING_UP_CACHE', data: { cache_key: key })
9
-
10
- Rails.cache.delete(key) if refreshed
11
-
12
- context.contents = Rails.cache.fetch(key) do
13
- CmAppLogger.log(label: 'CACHE_MISS', data: { cache_key: key })
14
- resource.preferred_assetlinks
15
- end
16
- end
17
-
18
- def cache_key
19
- updated_at = tenant&.updated_at || store&.updated_at
20
- "well_known:assetlinks.json:#{resource.class.name}:#{resource.id}:#{updated_at}"
21
- end
22
-
23
- def resource
24
- tenant || store
25
- end
26
- end
27
- end
@@ -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,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,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