spree_cm_commissioner 1.18.1 → 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 (202) 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 +18 -20
  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/place.rb +1 -3
  58. data/app/models/spree_cm_commissioner/price_decorator.rb +9 -0
  59. data/app/models/spree_cm_commissioner/product_decorator.rb +10 -4
  60. data/app/models/spree_cm_commissioner/redis_stock/cached_inventory_items_builder.rb +41 -0
  61. data/app/models/spree_cm_commissioner/redis_stock/inventory_updater.rb +126 -0
  62. data/app/models/spree_cm_commissioner/redis_stock/line_items_cached_inventory_items_builder.rb +36 -0
  63. data/app/models/spree_cm_commissioner/redis_stock/variant_cached_inventory_items_builder.rb +25 -0
  64. data/app/models/spree_cm_commissioner/reserved_block.rb +30 -0
  65. data/app/models/spree_cm_commissioner/seat_layout.rb +20 -0
  66. data/app/models/spree_cm_commissioner/seat_section.rb +16 -0
  67. data/app/models/spree_cm_commissioner/seats/blocks_canceler.rb +30 -0
  68. data/app/models/spree_cm_commissioner/seats/blocks_holder.rb +53 -0
  69. data/app/models/spree_cm_commissioner/seats/blocks_reserver.rb +49 -0
  70. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_on_hold_by_other_guest.rb +4 -0
  71. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_reserved_by_other_guest.rb +4 -0
  72. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_reserved_by_same_guest.rb +4 -0
  73. data/app/models/spree_cm_commissioner/seats/errors/unable_to_save_reserved_block_record.rb +4 -0
  74. data/app/models/spree_cm_commissioner/service_calendar.rb +0 -2
  75. data/app/models/spree_cm_commissioner/state_decorator.rb +0 -1
  76. data/app/models/spree_cm_commissioner/stock/availability_checker.rb +26 -25
  77. data/app/models/spree_cm_commissioner/stock/availability_validator_decorator.rb +2 -1
  78. data/app/models/spree_cm_commissioner/stock/line_item_availability_checker.rb +3 -3
  79. data/app/models/spree_cm_commissioner/stock/order_availability_checker.rb +44 -0
  80. data/app/models/spree_cm_commissioner/stock_item_decorator.rb +17 -0
  81. data/app/models/spree_cm_commissioner/taxon_decorator.rb +0 -2
  82. data/app/models/spree_cm_commissioner/taxonomy_decorator.rb +0 -6
  83. data/app/models/spree_cm_commissioner/trip.rb +20 -6
  84. data/app/models/spree_cm_commissioner/trip_connection.rb +5 -5
  85. data/app/models/spree_cm_commissioner/trip_stop.rb +2 -3
  86. data/app/models/spree_cm_commissioner/user_taxon.rb +0 -1
  87. data/app/models/spree_cm_commissioner/variant_block.rb +9 -0
  88. data/app/models/spree_cm_commissioner/variant_decorator.rb +36 -47
  89. data/app/models/spree_cm_commissioner/variant_options.rb +0 -23
  90. data/app/models/spree_cm_commissioner/vehicle.rb +9 -14
  91. data/app/models/spree_cm_commissioner/vendor_decorator.rb +7 -9
  92. data/app/models/spree_cm_commissioner/vendor_place.rb +6 -5
  93. data/app/models/spree_cm_commissioner/vendor_stop.rb +1 -2
  94. data/app/overrides/spree/admin/variants/_form/kyc_field.html.erb.deface +2 -2
  95. data/app/queries/spree_cm_commissioner/guest_searcher_query.rb +3 -45
  96. data/app/queries/spree_cm_commissioner/trip_query.rb +23 -26
  97. data/app/request_schemas/spree_cm_commissioner/accommodation_request_schema.rb +3 -0
  98. data/app/request_schemas/spree_cm_commissioner/application_request_schema.rb +1 -1
  99. data/app/request_schemas/spree_cm_commissioner/variant_request_schema.rb +19 -0
  100. data/app/serializers/spree/v2/storefront/accommodation_serializer.rb +2 -0
  101. data/app/serializers/spree/v2/storefront/line_item_serializer_decorator.rb +1 -0
  102. data/app/serializers/spree_cm_commissioner/v2/operator/dashboard_crew_event_serializer.rb +1 -4
  103. data/app/serializers/spree_cm_commissioner/v2/storefront/dynamic_field_option_serializer.rb +3 -1
  104. data/app/serializers/spree_cm_commissioner/v2/storefront/dynamic_field_serializer.rb +3 -1
  105. data/app/serializers/spree_cm_commissioner/v2/storefront/guest_dynamic_field_serializer.rb +1 -2
  106. data/app/services/spree_cm_commissioner/organizer/export_guest_csv_service.rb +15 -23
  107. data/app/views/spree/admin/inventory_items/show.html.erb +72 -0
  108. data/app/views/spree/admin/stock_managements/_variant_stock_items.html.erb +7 -2
  109. data/app/views/spree/admin/stock_managements/calendar.html.erb +56 -0
  110. data/app/views/spree/admin/stock_managements/index.html.erb +55 -6
  111. data/app/views/spree/admin/tenants/_form.html.erb +42 -109
  112. data/config/initializers/paper_trail.rb +1 -0
  113. data/config/initializers/spree_permitted_attributes.rb +5 -2
  114. data/config/locales/en.yml +0 -4
  115. data/config/routes.rb +22 -4
  116. data/db/migrate/20240202080634_update_counter_cache_of_vehicle_type.rb +3 -1
  117. data/db/migrate/20250304293518_create_cm_inventory_items.rb +21 -0
  118. data/db/migrate/20250429094228_add_lock_version_to_cm_inventory_items.rb +5 -0
  119. data/db/migrate/20250502025848_add_index_to_spree_products.rb +5 -0
  120. data/db/migrate/20250502030001_add_product_type_to_spree_variants.rb +5 -0
  121. data/db/migrate/20250502030002_add_product_type_to_spree_line_items.rb +5 -0
  122. data/db/migrate/20250603035256_add_inventory_item_to_spree_prices.rb +7 -0
  123. data/db/migrate/20250619073724_drop_table_cm_line_item_seats.rb +5 -0
  124. data/db/migrate/20250619073812_drop_table_cm_vehicle_seats.rb +5 -0
  125. data/db/migrate/20250619073844_drop_table_cm_vehicle_types.rb +9 -0
  126. data/db/migrate/20250619073957_drop_table_cm_option_value_vehicle_types.rb +5 -0
  127. data/db/migrate/20250619082354_remove_unnecessary_fields_from_cm_places.rb +9 -0
  128. data/db/migrate/20250619082736_remove_route_type_from_spree_products.rb +5 -0
  129. data/db/migrate/20250619083055_remove_unnecessary_fields_from_spree_taxons.rb +5 -0
  130. data/db/migrate/20250620083055_remove_variant_id_from_cm_trips.rb +5 -0
  131. data/db/migrate/20250620090000_update_cm_trip_connections_to_use_cm_trips.rb +6 -0
  132. data/db/migrate/20250620090001_create_cm_seat_layouts.rb +17 -0
  133. data/db/migrate/20250620090002_create_cm_seat_sections.rb +18 -0
  134. data/db/migrate/20250620090003_create_cm_blocks.rb +18 -0
  135. data/db/migrate/20250624091005_create_cm_reserved_blocks.rb +29 -0
  136. data/db/migrate/20250626083642_create_cm_variant_blocks.rb +24 -0
  137. data/db/migrate/20250627023314_add_block_id_to_cm_guests.rb +13 -0
  138. data/docker-compose.yml +1 -1
  139. data/lib/cm_app_logger.rb +11 -4
  140. data/lib/generators/spree_cm_commissioner/install/install_generator.rb +14 -11
  141. data/lib/generators/spree_cm_commissioner/install/templates/app/javascript/{spree_cm_commissioner → spree_dashboard/spree_cm_commissioner}/utilities.js +4 -0
  142. data/lib/spree_cm_commissioner/cached_inventory_item.rb +23 -0
  143. data/lib/spree_cm_commissioner/calendar_event.rb +11 -1
  144. data/lib/spree_cm_commissioner/test_helper/factories/block_factory.rb +9 -0
  145. data/lib/spree_cm_commissioner/test_helper/factories/guest_factory.rb +10 -0
  146. data/lib/spree_cm_commissioner/test_helper/factories/homepage_section_relatable_factory.rb +1 -1
  147. data/lib/spree_cm_commissioner/test_helper/factories/inventory_item_factory.rb +9 -0
  148. data/lib/spree_cm_commissioner/test_helper/factories/line_item_factory.rb +1 -1
  149. data/lib/spree_cm_commissioner/test_helper/factories/option_type_factory.rb +6 -30
  150. data/lib/spree_cm_commissioner/test_helper/factories/order_factory.rb +0 -36
  151. data/lib/spree_cm_commissioner/test_helper/factories/product_factory.rb +18 -34
  152. data/lib/spree_cm_commissioner/test_helper/factories/reserved_block_factory.rb +27 -0
  153. data/lib/spree_cm_commissioner/test_helper/factories/seat_layout_factory.rb +8 -0
  154. data/lib/spree_cm_commissioner/test_helper/factories/seat_section_factory.rb +8 -0
  155. data/lib/spree_cm_commissioner/test_helper/factories/stock_location_factory.rb +2 -2
  156. data/lib/spree_cm_commissioner/test_helper/factories/trip_connection_factory.rb +6 -0
  157. data/lib/spree_cm_commissioner/test_helper/factories/trip_factory.rb +10 -3
  158. data/lib/spree_cm_commissioner/test_helper/factories/variant_block_factory.rb +7 -0
  159. data/lib/spree_cm_commissioner/test_helper/factories/variant_factory.rb +41 -19
  160. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_factory.rb +1 -1
  161. data/lib/spree_cm_commissioner/test_helper/factories/vendor_factory.rb +1 -1
  162. data/lib/spree_cm_commissioner/version.rb +1 -1
  163. data/lib/spree_cm_commissioner.rb +35 -1
  164. data/lib/tasks/create_default_non_permanent_inventory_items.rake +16 -0
  165. data/lib/tasks/ensure_correct_product_type.rake +7 -0
  166. data/lib/tasks/generate_inventory_items.rake +7 -0
  167. data/spree_cm_commissioner.gemspec +7 -0
  168. metadata +134 -39
  169. data/app/assets/images/cm-hangmeas-checkout_image.svg +0 -63
  170. data/app/assets/images/cm-hangmeas-failed.svg +0 -56
  171. data/app/assets/images/cm-hangmeas-loader.svg +0 -50
  172. data/app/assets/images/cm-hangmeas-success.svg +0 -51
  173. data/app/assets/javascripts/spree_cm_commissioner/tenant_payment_icon_fields.js +0 -65
  174. data/app/assets/stylesheets/spree_cm_commissioner/backend/tenant_payment_icon_fields.scss +0 -60
  175. data/app/controllers/concerns/spree_cm_commissioner/transit/taxon_bitwise.rb +0 -44
  176. data/app/finders/spree_cm_commissioner/line_items/find_by_variant_decorator.rb +0 -20
  177. data/app/interactors/spree_cm_commissioner/universal_link_fetcher.rb +0 -54
  178. data/app/models/concerns/spree_cm_commissioner/event_check_in_flowable.rb +0 -30
  179. data/app/models/spree_cm_commissioner/branch.rb +0 -12
  180. data/app/models/spree_cm_commissioner/line_item_seat.rb +0 -10
  181. data/app/models/spree_cm_commissioner/option_value_vehicle_type.rb +0 -8
  182. data/app/models/spree_cm_commissioner/stop.rb +0 -23
  183. data/app/models/spree_cm_commissioner/vehicle_seat.rb +0 -11
  184. data/app/models/spree_cm_commissioner/vehicle_type.rb +0 -76
  185. data/app/overrides/spree/admin/taxons/_form/check_in_flows.html.erb.deface +0 -18
  186. data/app/queries/spree_cm_commissioner/trip_search_query.rb +0 -76
  187. data/app/queries/spree_cm_commissioner/variant_availability/non_permanent_stock_query.rb +0 -45
  188. data/app/queries/spree_cm_commissioner/variant_availability/permanent_stock_query.rb +0 -55
  189. data/app/services/spree_cm_commissioner/vehicle_option_value_creator.rb +0 -11
  190. data/db/migrate/20250616084219_add_description_to_cm_vendor_place.rb +0 -5
  191. data/db/migrate/20250701093203_add_configurations_to_cm_dynamic_field.rb +0 -6
  192. data/db/migrate/20250702091305_add_dynamic_field_option_to_guest_dynamic_field.rb +0 -5
  193. data/db/migrate/20250702091935_add_status_to_dynamic_field_option.rb +0 -5
  194. data/lib/spree_cm_commissioner/test_helper/factories/branch_factory.rb +0 -12
  195. data/lib/spree_cm_commissioner/test_helper/factories/departure_time_option_type_factory.rb +0 -8
  196. data/lib/spree_cm_commissioner/test_helper/factories/duration_option_type_factory.rb +0 -8
  197. data/lib/spree_cm_commissioner/test_helper/factories/line_item_seat_factory.rb +0 -7
  198. data/lib/spree_cm_commissioner/test_helper/factories/stop_factory.rb +0 -14
  199. data/lib/spree_cm_commissioner/test_helper/factories/transit_place_factory.rb +0 -8
  200. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_option_type_factory.rb +0 -8
  201. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_type_factory.rb +0 -96
  202. 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,54 +0,0 @@
1
- module SpreeCmCommissioner
2
- class UniversalLinkFetcher < BaseInteractor
3
- delegate :universal_link, :store, :tenant, :refresh, to: :context
4
-
5
- def call
6
- return not_found unless resource
7
-
8
- data = load_cached_preference(resource)
9
- return not_found if data.blank?
10
-
11
- { success: true, data: data }
12
- end
13
-
14
- private
15
-
16
- def resource
17
- @resource ||= store.presence || tenant
18
- end
19
-
20
- def load_cached_preference(resource)
21
- preference_key = preference_key_for(universal_link)
22
- return nil unless preference_key && resource.respond_to?(preference_key)
23
-
24
- updated_at = resource.try(:updated_at)&.to_i || 'no_updated_at'
25
- cache_key = build_cache_key(universal_link, resource, updated_at)
26
-
27
- CmAppLogger.log(label: 'LOOKING_UP_CACHE', data: { cache_key: cache_key })
28
-
29
- Rails.cache.delete(cache_key) if refresh
30
-
31
- Rails.cache.fetch(cache_key, expires_in: 1.day, force: refresh) do
32
- CmAppLogger.log(label: 'CACHE_MISS', data: { cache_key: cache_key })
33
- resource.public_send(preference_key).presence
34
- end
35
- end
36
-
37
- def build_cache_key(universal_link, resource, updated_at)
38
- "well_known:#{universal_link}:#{resource.class.name}:#{resource.id}:#{updated_at}"
39
- end
40
-
41
- def preference_key_for(universal_link)
42
- case universal_link
43
- when 'assetlinks.json'
44
- :preferred_assetlinks
45
- when 'apple-app-site-association'
46
- :preferred_apple_app_site_association
47
- end
48
- end
49
-
50
- def not_found
51
- { success: false, error: 'Not found' }
52
- end
53
- end
54
- 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,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,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 %> %>