spree_cm_commissioner 2.0.3.pre.pre → 2.0.3.pre.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test_and_build_gem.yml +2 -16
  3. data/.gitignore +1 -2
  4. data/Gemfile.lock +1 -28
  5. data/Rakefile +4 -33
  6. data/app/assets/images/mailer/mail.png +0 -0
  7. data/app/assets/images/mailer/tenant_phone.png +0 -0
  8. data/app/assets/images/mailer/tenant_user.png +0 -0
  9. data/app/assets/stylesheets/spree_cm_commissioner/backend/calendar.scss +11 -8
  10. data/app/controllers/blazer/queries_controller_decorator.rb +11 -0
  11. data/app/controllers/concerns/spree_cm_commissioner/transit/taxon_bitwise.rb +44 -0
  12. data/app/controllers/spree/admin/stock_managements_controller.rb +1 -63
  13. data/app/controllers/spree/api/v2/operator/event_charts_controller.rb +59 -0
  14. data/app/controllers/spree/api/v2/organizer/invite_guests_controller.rb +1 -1
  15. data/app/controllers/spree/api/v2/storefront/accommodations_controller.rb +31 -14
  16. data/app/controllers/spree/api/v2/storefront/guests_controller.rb +13 -13
  17. data/app/controllers/spree/api/v2/storefront/queue_cart/line_items_controller.rb +2 -2
  18. data/app/factory/spree_cm_commissioner/invite_guest_claimed_telegram_message_factory.rb +24 -81
  19. data/app/finders/spree_cm_commissioner/line_items/find_by_variant_decorator.rb +20 -0
  20. data/app/interactors/spree_cm_commissioner/create_event.rb +5 -0
  21. data/app/interactors/spree_cm_commissioner/create_ticket.rb +6 -5
  22. data/app/interactors/spree_cm_commissioner/create_vendor.rb +44 -0
  23. data/app/interactors/spree_cm_commissioner/pin_code_sender.rb +0 -1
  24. data/app/interactors/spree_cm_commissioner/reports_assigner.rb +17 -0
  25. data/app/interactors/spree_cm_commissioner/sms.rb +1 -1
  26. data/app/interactors/spree_cm_commissioner/user_id_token_authenticator.rb +7 -3
  27. data/app/interactors/spree_cm_commissioner/user_id_token_checker.rb +11 -3
  28. data/app/interactors/spree_cm_commissioner/user_identity_checker.rb +12 -6
  29. data/app/interactors/spree_cm_commissioner/user_registration_with_id_token.rb +7 -1
  30. data/app/jobs/spree_cm_commissioner/application_job.rb +0 -20
  31. data/app/jobs/spree_cm_commissioner/application_unique_job.rb +0 -20
  32. data/app/jobs/spree_cm_commissioner/reports_assigner_job.rb +7 -0
  33. data/app/jobs/spree_cm_commissioner/sms_pin_code_job.rb +1 -1
  34. data/app/mailers/spree/order_mailer_decorator.rb +18 -3
  35. data/app/models/concerns/spree_cm_commissioner/line_item_durationable.rb +33 -9
  36. data/app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb +12 -1
  37. data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +0 -39
  38. data/app/models/concerns/spree_cm_commissioner/product_delegation.rb +3 -1
  39. data/app/models/concerns/spree_cm_commissioner/product_type.rb +0 -10
  40. data/app/models/concerns/spree_cm_commissioner/route_type.rb +1 -1
  41. data/app/models/concerns/spree_cm_commissioner/taxon_kind.rb +1 -1
  42. data/app/models/concerns/spree_cm_commissioner/tenant_preference.rb +1 -0
  43. data/app/models/concerns/spree_cm_commissioner/variant_options_concern.rb +4 -2
  44. data/app/models/spree_cm_commissioner/branch.rb +12 -0
  45. data/app/models/spree_cm_commissioner/dynamic_field.rb +20 -0
  46. data/app/models/spree_cm_commissioner/guest.rb +56 -18
  47. data/app/models/spree_cm_commissioner/guest_dynamic_field.rb +41 -1
  48. data/app/models/spree_cm_commissioner/line_item_decorator.rb +78 -46
  49. data/app/models/spree_cm_commissioner/line_item_seat.rb +10 -0
  50. data/app/models/spree_cm_commissioner/notification_taxon.rb +1 -1
  51. data/app/models/spree_cm_commissioner/option_type_decorator.rb +11 -1
  52. data/app/models/spree_cm_commissioner/option_value_vehicle_type.rb +8 -0
  53. data/app/models/spree_cm_commissioner/order_decorator.rb +1 -30
  54. data/app/models/spree_cm_commissioner/place.rb +4 -1
  55. data/app/models/spree_cm_commissioner/product_decorator.rb +28 -10
  56. data/app/models/spree_cm_commissioner/service_calendar.rb +2 -0
  57. data/app/models/spree_cm_commissioner/state_decorator.rb +1 -0
  58. data/app/models/spree_cm_commissioner/stock/availability_checker.rb +25 -26
  59. data/app/models/spree_cm_commissioner/stock/availability_validator_decorator.rb +1 -2
  60. data/app/models/spree_cm_commissioner/stock/line_item_availability_checker.rb +3 -3
  61. data/app/models/spree_cm_commissioner/stock_item_decorator.rb +0 -17
  62. data/app/models/spree_cm_commissioner/stop.rb +23 -0
  63. data/app/models/spree_cm_commissioner/taxon_decorator.rb +1 -0
  64. data/app/models/spree_cm_commissioner/taxonomy_decorator.rb +6 -0
  65. data/app/models/spree_cm_commissioner/trip.rb +10 -10
  66. data/app/models/spree_cm_commissioner/trip_connection.rb +5 -5
  67. data/app/models/spree_cm_commissioner/trip_stop.rb +25 -6
  68. data/app/models/spree_cm_commissioner/user_decorator.rb +6 -0
  69. data/app/models/spree_cm_commissioner/user_identity_provider.rb +26 -4
  70. data/app/models/spree_cm_commissioner/variant_decorator.rb +47 -37
  71. data/app/models/spree_cm_commissioner/variant_options.rb +23 -0
  72. data/app/models/spree_cm_commissioner/vehicle.rb +15 -10
  73. data/app/models/spree_cm_commissioner/vehicle_seat.rb +11 -0
  74. data/app/models/spree_cm_commissioner/vehicle_type.rb +76 -0
  75. data/app/models/spree_cm_commissioner/vendor_decorator.rb +17 -11
  76. data/app/models/spree_cm_commissioner/vendor_place.rb +3 -9
  77. data/app/models/spree_cm_commissioner/vendor_stop.rb +10 -0
  78. data/app/queries/spree_cm_commissioner/event_chart_queries.rb +179 -0
  79. data/app/queries/spree_cm_commissioner/trip_query.rb +44 -70
  80. data/app/queries/spree_cm_commissioner/trip_search_query.rb +76 -0
  81. data/app/queries/spree_cm_commissioner/variant_availability/non_permanent_stock_query.rb +45 -0
  82. data/app/queries/spree_cm_commissioner/variant_availability/permanent_stock_query.rb +55 -0
  83. data/app/queries/spree_cm_commissioner/vendor_stop_place_query.rb +54 -0
  84. data/app/request_schemas/spree_cm_commissioner/accommodation_request_schema.rb +0 -3
  85. data/app/request_schemas/spree_cm_commissioner/application_request_schema.rb +1 -1
  86. data/app/serializables/spree_cm_commissioner/event_chart.rb +11 -0
  87. data/app/serializers/spree/v2/storefront/accommodation_serializer.rb +0 -2
  88. data/app/serializers/spree/v2/storefront/line_item_serializer_decorator.rb +0 -1
  89. data/app/serializers/spree/v2/tenant/user_serializer.rb +1 -0
  90. data/app/serializers/spree_cm_commissioner/v2/storefront/dynamic_field_serializer.rb +1 -1
  91. data/app/services/spree_cm_commissioner/user_authenticator.rb +1 -1
  92. data/app/services/spree_cm_commissioner/vehicle_option_value_creator.rb +11 -0
  93. data/app/views/blazer/queries/_content.html.erb +2 -0
  94. data/app/views/blazer/queries/_preset.html.erb +11 -0
  95. data/app/views/spree/admin/stock_managements/_variant_stock_items.html.erb +2 -7
  96. data/app/views/spree/admin/stock_managements/index.html.erb +6 -55
  97. data/app/views/spree/admin/tenant_vendors/index.html.erb +9 -2
  98. data/app/views/spree/admin/tenants/_form.html.erb +9 -0
  99. data/app/views/spree/admin/tenants/edit.html.erb +2 -1
  100. data/app/views/spree/admin/tenants/index.html.erb +7 -1
  101. data/app/views/spree/admin/vendors/_form.html.erb +14 -0
  102. data/app/views/spree/order_mailer/confirm_email.html.erb +27 -16
  103. data/app/views/spree_cm_commissioner/layouts/order_mailer.html.erb +5 -1
  104. data/app/views/spree_cm_commissioner/order_mailer/_mailer_stylesheets.html.erb +41 -4
  105. data/app/views/spree_cm_commissioner/order_mailer/tenant/_customer_info.html.erb +42 -0
  106. data/app/views/spree_cm_commissioner/order_mailer/tenant/_footer.html.erb +25 -0
  107. data/app/views/spree_cm_commissioner/order_mailer/tenant/_greeting.html.erb +19 -0
  108. data/app/views/spree_cm_commissioner/order_mailer/tenant/_support_contact.html.erb +33 -0
  109. data/config/initializers/spree_permitted_attributes.rb +0 -5
  110. data/config/locales/en.yml +5 -1
  111. data/config/routes.rb +3 -21
  112. data/db/migrate/20240202080634_update_counter_cache_of_vehicle_type.rb +1 -3
  113. data/db/migrate/20250709073455_add_email_fields_to_spree_vendors.rb +6 -0
  114. data/db/migrate/20250710082132_add_preset_to_blazer_queries.rb +5 -0
  115. data/db/migrate/20250715103333_remove_indexes_from_cm_user_identity_providers.rb +13 -0
  116. data/db/migrate/20250718071620_add_data_fill_stage_to_dynamic_fields.rb +5 -0
  117. data/docker-compose.yml +1 -1
  118. data/lib/cm_app_logger.rb +4 -11
  119. data/lib/generators/spree_cm_commissioner/install/install_generator.rb +11 -14
  120. data/lib/generators/spree_cm_commissioner/install/templates/app/javascript/{spree_dashboard/spree_cm_commissioner → spree_cm_commissioner}/utilities.js +0 -4
  121. data/lib/spree_cm_commissioner/calendar_event.rb +1 -11
  122. data/lib/spree_cm_commissioner/test_helper/factories/blazer_query_factory.rb +17 -0
  123. data/lib/spree_cm_commissioner/test_helper/factories/branch_factory.rb +12 -0
  124. data/lib/spree_cm_commissioner/test_helper/factories/departure_time_option_type_factory.rb +8 -0
  125. data/lib/spree_cm_commissioner/test_helper/factories/duration_option_type_factory.rb +8 -0
  126. data/lib/spree_cm_commissioner/test_helper/factories/guest_factory.rb +0 -10
  127. data/lib/spree_cm_commissioner/test_helper/factories/homepage_section_relatable_factory.rb +1 -1
  128. data/lib/spree_cm_commissioner/test_helper/factories/line_item_factory.rb +1 -1
  129. data/lib/spree_cm_commissioner/test_helper/factories/line_item_seat_factory.rb +7 -0
  130. data/lib/spree_cm_commissioner/test_helper/factories/option_type_factory.rb +30 -6
  131. data/lib/spree_cm_commissioner/test_helper/factories/order_factory.rb +36 -0
  132. data/lib/spree_cm_commissioner/test_helper/factories/product_factory.rb +34 -18
  133. data/lib/spree_cm_commissioner/test_helper/factories/stock_location_factory.rb +2 -2
  134. data/lib/spree_cm_commissioner/test_helper/factories/stop_factory.rb +14 -0
  135. data/lib/spree_cm_commissioner/test_helper/factories/transit_place_factory.rb +8 -0
  136. data/lib/spree_cm_commissioner/test_helper/factories/trip_factory.rb +3 -11
  137. data/lib/spree_cm_commissioner/test_helper/factories/user_identity_provider_factory.rb +1 -1
  138. data/lib/spree_cm_commissioner/test_helper/factories/variant_factory.rb +19 -41
  139. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_factory.rb +1 -1
  140. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_option_type_factory.rb +8 -0
  141. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_type_factory.rb +96 -0
  142. data/lib/spree_cm_commissioner/test_helper/factories/vendor_factory.rb +1 -6
  143. data/lib/spree_cm_commissioner/test_helper/factories/vendor_place_factory.rb +1 -13
  144. data/lib/spree_cm_commissioner/trip_query_result.rb +0 -8
  145. data/lib/spree_cm_commissioner/trip_result.rb +3 -5
  146. data/lib/spree_cm_commissioner/trip_seat_layout_result.rb +11 -0
  147. data/lib/spree_cm_commissioner/version.rb +1 -1
  148. data/lib/spree_cm_commissioner.rb +1 -35
  149. data/spree_cm_commissioner.gemspec +0 -7
  150. metadata +46 -145
  151. data/app/controllers/spree/admin/inventory_items_controller.rb +0 -83
  152. data/app/controllers/spree/api/v2/storefront/accommodations/variants_controller.rb +0 -42
  153. data/app/finders/spree_cm_commissioner/accommodations/find.rb +0 -37
  154. data/app/finders/spree_cm_commissioner/accommodations/find_variant.rb +0 -32
  155. data/app/interactors/spree_cm_commissioner/ensure_correct_product_type.rb +0 -40
  156. data/app/interactors/spree_cm_commissioner/inventory_item_syncer.rb +0 -25
  157. data/app/interactors/spree_cm_commissioner/stock/inventory_item_resetter.rb +0 -44
  158. data/app/interactors/spree_cm_commissioner/stock/inventory_items_adjuster.rb +0 -13
  159. data/app/interactors/spree_cm_commissioner/stock/inventory_items_generator.rb +0 -15
  160. data/app/interactors/spree_cm_commissioner/stock/permanent_inventory_items_generator.rb +0 -75
  161. data/app/interactors/spree_cm_commissioner/stock/stock_movement_creator.rb +0 -32
  162. data/app/interactors/spree_cm_commissioner/variant_block_updater.rb +0 -62
  163. data/app/interactors/spree_cm_commissioner/vehicle_updater.rb +0 -41
  164. data/app/jobs/spree_cm_commissioner/ensure_correct_product_type_job.rb +0 -7
  165. data/app/jobs/spree_cm_commissioner/inventory_item_syncer_job.rb +0 -7
  166. data/app/jobs/spree_cm_commissioner/stock/inventory_items_adjuster_job.rb +0 -11
  167. data/app/jobs/spree_cm_commissioner/stock/inventory_items_generator_job.rb +0 -11
  168. data/app/jobs/spree_cm_commissioner/stock/permanent_inventory_items_generator_job.rb +0 -9
  169. data/app/models/concerns/spree_cm_commissioner/order_seatable.rb +0 -44
  170. data/app/models/concerns/spree_cm_commissioner/vehicle_type.rb +0 -11
  171. data/app/models/spree_cm_commissioner/block.rb +0 -43
  172. data/app/models/spree_cm_commissioner/inventory.rb +0 -11
  173. data/app/models/spree_cm_commissioner/inventory_item.rb +0 -69
  174. data/app/models/spree_cm_commissioner/price_decorator.rb +0 -9
  175. data/app/models/spree_cm_commissioner/redis_stock/cached_inventory_items_builder.rb +0 -41
  176. data/app/models/spree_cm_commissioner/redis_stock/inventory_updater.rb +0 -126
  177. data/app/models/spree_cm_commissioner/redis_stock/line_items_cached_inventory_items_builder.rb +0 -36
  178. data/app/models/spree_cm_commissioner/redis_stock/variant_cached_inventory_items_builder.rb +0 -25
  179. data/app/models/spree_cm_commissioner/reserved_block.rb +0 -30
  180. data/app/models/spree_cm_commissioner/seat_layout.rb +0 -20
  181. data/app/models/spree_cm_commissioner/seat_section.rb +0 -16
  182. data/app/models/spree_cm_commissioner/seats/blocks_canceler.rb +0 -30
  183. data/app/models/spree_cm_commissioner/seats/blocks_holder.rb +0 -53
  184. data/app/models/spree_cm_commissioner/seats/blocks_reserver.rb +0 -49
  185. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_on_hold_by_other_guest.rb +0 -4
  186. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_reserved_by_other_guest.rb +0 -4
  187. data/app/models/spree_cm_commissioner/seats/errors/blocks_are_reserved_by_same_guest.rb +0 -4
  188. data/app/models/spree_cm_commissioner/seats/errors/unable_to_save_reserved_block_record.rb +0 -4
  189. data/app/models/spree_cm_commissioner/stock/order_availability_checker.rb +0 -44
  190. data/app/models/spree_cm_commissioner/variant_block.rb +0 -9
  191. data/app/request_schemas/spree_cm_commissioner/variant_request_schema.rb +0 -19
  192. data/app/views/spree/admin/inventory_items/show.html.erb +0 -72
  193. data/app/views/spree/admin/stock_managements/calendar.html.erb +0 -56
  194. data/config/initializers/paper_trail.rb +0 -1
  195. data/db/migrate/20250122000000_move_route_type_from_vehicles_to_trips.rb +0 -7
  196. data/db/migrate/20250304293518_create_cm_inventory_items.rb +0 -21
  197. data/db/migrate/20250429094228_add_lock_version_to_cm_inventory_items.rb +0 -5
  198. data/db/migrate/20250502025848_add_index_to_spree_products.rb +0 -5
  199. data/db/migrate/20250502030001_add_product_type_to_spree_variants.rb +0 -5
  200. data/db/migrate/20250502030002_add_product_type_to_spree_line_items.rb +0 -5
  201. data/db/migrate/20250603035256_add_inventory_item_to_spree_prices.rb +0 -7
  202. data/db/migrate/20250619073724_drop_table_cm_line_item_seats.rb +0 -5
  203. data/db/migrate/20250619073812_drop_table_cm_vehicle_seats.rb +0 -5
  204. data/db/migrate/20250619073844_drop_table_cm_vehicle_types.rb +0 -9
  205. data/db/migrate/20250619073957_drop_table_cm_option_value_vehicle_types.rb +0 -5
  206. data/db/migrate/20250619082354_remove_unnecessary_fields_from_cm_places.rb +0 -9
  207. data/db/migrate/20250619082736_remove_route_type_from_spree_products.rb +0 -5
  208. data/db/migrate/20250619083055_remove_unnecessary_fields_from_spree_taxons.rb +0 -5
  209. data/db/migrate/20250620083055_remove_variant_id_from_cm_trips.rb +0 -5
  210. data/db/migrate/20250620090000_update_cm_trip_connections_to_use_cm_trips.rb +0 -6
  211. data/db/migrate/20250620090001_create_cm_seat_layouts.rb +0 -17
  212. data/db/migrate/20250620090002_create_cm_seat_sections.rb +0 -18
  213. data/db/migrate/20250620090003_create_cm_blocks.rb +0 -18
  214. data/db/migrate/20250624091005_create_cm_reserved_blocks.rb +0 -29
  215. data/db/migrate/20250626083642_create_cm_variant_blocks.rb +0 -24
  216. data/db/migrate/20250627023314_add_block_id_to_cm_guests.rb +0 -13
  217. data/db/migrate/20250716022821_add_location_reference_to_cm_vendor_places.rb +0 -5
  218. data/db/migrate/20250716031743_drop_table_cm_vendor_stops.rb +0 -5
  219. data/db/migrate/20250717023824_add_vendor_reference_to_cm_trips.rb +0 -5
  220. data/db/migrate/20250717041414_add_location_place_reference_to_cm_trip_stops.rb +0 -5
  221. data/db/migrate/20250717042539_rename_cm_trip_stops_stop_id_column_to_stop_place_id.rb +0 -7
  222. data/db/migrate/20250717042707_rename_cm_trips_origin_and_destination_to_origin_place_and_destination_place.rb +0 -11
  223. data/db/migrate/20250721080738_add_vehicle_type_to_cm_vehicles.rb +0 -7
  224. data/db/migrate/20250725092713_add_block_type_to_cm_blocks.rb +0 -5
  225. data/lib/spree_cm_commissioner/cached_inventory_item.rb +0 -23
  226. data/lib/spree_cm_commissioner/test_helper/factories/block_factory.rb +0 -16
  227. data/lib/spree_cm_commissioner/test_helper/factories/inventory_item_factory.rb +0 -9
  228. data/lib/spree_cm_commissioner/test_helper/factories/reserved_block_factory.rb +0 -27
  229. data/lib/spree_cm_commissioner/test_helper/factories/seat_layout_factory.rb +0 -11
  230. data/lib/spree_cm_commissioner/test_helper/factories/seat_section_factory.rb +0 -16
  231. data/lib/spree_cm_commissioner/test_helper/factories/trip_connection_factory.rb +0 -6
  232. data/lib/spree_cm_commissioner/test_helper/factories/trip_stop_factory.rb +0 -10
  233. data/lib/spree_cm_commissioner/test_helper/factories/variant_block_factory.rb +0 -7
  234. data/lib/tasks/create_default_non_permanent_inventory_items.rake +0 -16
  235. data/lib/tasks/ensure_correct_product_type.rake +0 -7
  236. data/lib/tasks/generate_inventory_items.rake +0 -7
@@ -1,26 +1,16 @@
1
- # 🎟️ --- [TICKET CLAIMED] ---
1
+ # 🎫 --- [NEW INVITATION CLAIMED] ---
2
2
  #
3
- # Order Number:
4
- # <code>R621016753</code>
5
- #
6
- # ✅ <b>Ticket Successfully Claimed!</b>
7
- #
8
- # [ x1 ]
9
- # <b>5km Running Ticket</b>
10
- # <i>👉 Distance: 5km, T-shirt: M</i>
11
- # <i>🗓️ Nov 15, 2023</i>
12
- # <i>🏪 Temple Run with Sai</i>
3
+ # <b>🙍 Claimed By</b>
4
+ # Name: Orng SreyMoch
5
+ # Tel: <code>+85570760548</code>
13
6
  #
14
- # [ x2 ]
15
7
  # <b>5km Running Ticket</b>
8
+ # Quantity: 1
16
9
  # <i>👉 Distance: 5km, T-shirt: S</i>
17
10
  # <i>🗓️ Nov 15, 2023 -> Nov 17, 2023</i>
18
- # <i>🏪 Temple Run with Sai</i>
19
11
  #
20
- # <b>🙍 Claimed By</b>
21
- # Name: Vaneath Awesome
22
- # Tel: <code>+85570760548</code>
23
- # Email: <code>admin_dev@cm.com</code>
12
+ # Order Number:
13
+ # <code>R621016753</code>
24
14
 
25
15
  module SpreeCmCommissioner
26
16
  class InviteGuestClaimedTelegramMessageFactory < TelegramMessageFactory
@@ -36,85 +26,38 @@ module SpreeCmCommissioner
36
26
  end
37
27
 
38
28
  def selected_line_items
39
- return order.line_items.for_vendor(vendor) if vendor.present?
40
-
41
- order.line_items
29
+ vendor.present? ? order.line_items.for_vendor(vendor) : order.line_items
42
30
  end
43
31
 
44
32
  # override
45
33
  def body
46
34
  text = []
47
- text << "Order Number:\n<code>#{order.number}</code>\n"
48
- text << "\n✅ <b>Ticket Successfully Claimed!</b>\n"
49
- text << selected_line_items.map { |item| line_item_content(item) }.compact.join("\n\n")
50
- text.compact.join("\n")
51
- end
52
35
 
53
- def line_item_content(line_item)
54
- text = []
36
+ text << bold('🙍 Claimed By')
37
+ text << "Name: #{guest.first_name} #{guest.last_name}"
38
+ text << "Tel: #{inline_code(guest.phone_number)}"
39
+ text << ''
40
+
41
+ # Each invitation_link leads to one order with one line_item, claimed by one guest so quantity is always 1.
42
+ selected_line_items.each do |item|
43
+ text << bold(item.product.name.to_s)
44
+ text << '🎟️ Quantity: 1'
45
+ text << italic("👉 #{item.options_text}") if item.options_text.present?
46
+ text << italic(pretty_date_for(item)) if item.date_present?
47
+ text << ''
48
+ end
55
49
 
56
- text << bold(line_item.product.name.to_s)
57
- text << "Quantity: #{line_item.quantity}"
58
- text << italic("👉 #{line_item.options_text}") if line_item.options_text.present?
59
- text << italic(pretty_date_for(line_item)) if pretty_date_for(line_item).present?
60
- text << italic("🏪 #{line_item.vendor.name}") if line_item.vendor&.name.present? && vendor.blank?
50
+ text << bold('Order Number:')
51
+ text << inline_code(order.number)
61
52
 
62
53
  text.compact.join("\n")
63
54
  end
64
55
 
65
56
  def pretty_date_for(line_item)
66
- return nil unless line_item.date_present?
67
-
68
57
  from_date = pretty_date(line_item.from_date)
69
58
  to_date = pretty_date(line_item.to_date)
70
59
 
71
- if from_date == to_date
72
- "🗓️ #{from_date}"
73
- else
74
- "🗓️ #{from_date} -> #{to_date}"
75
- end
76
- end
77
-
78
- # override
79
- def footer
80
- text = []
81
-
82
- text << bold('🙍 Claimed By')
83
- text << "Name: #{guest.first_name} #{guest.last_name}" if guest.first_name.present? || guest.last_name.present?
84
- text << "Tel: #{inline_code(guest.intel_phone_number)}" if guest.intel_phone_number.present?
85
-
86
- if show_details_link && order.guests.any?
87
- text << ''
88
- text << 'View Tickets:'
89
- text += generate_guests_links(order.guests)
90
- end
91
-
92
- text.compact.join("\n")
93
- end
94
-
95
- # Result:
96
- # | No. A24 | No. A24 |
97
- # | No. A24 | No. A24 |
98
- # | No. A24 | No. A24 |
99
- # | No. A24 | No. A24 |
100
- # | No. A24 | No. A24 |
101
- # | No. A24 |
102
- def generate_guests_links(guests, guests_per_row = 2)
103
- rows = (guests.size.to_f / guests_per_row).ceil
104
- formatted_rows = []
105
-
106
- rows.times do |i|
107
- row_guests = guests.slice(i * guests_per_row, guests_per_row)
108
- formatted_row = row_guests.map do |guest|
109
- button_label = guest.seat_number.present? ? "No. #{guest.seat_number}" : "No. #{guest.formatted_bib_number || 'N/A'}"
110
- link = Rails.application.routes.url_helpers.guest_cards_url(guest.token)
111
- "| <a href='#{link}'>#{button_label}</a>"
112
- end.join(' ')
113
-
114
- formatted_rows << ("#{formatted_row} |")
115
- end
116
-
117
- formatted_rows
60
+ from_date == to_date ? "🗓️ #{from_date}" : "🗓️ #{from_date} -> #{to_date}"
118
61
  end
119
62
  end
120
63
  end
@@ -0,0 +1,20 @@
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
@@ -11,6 +11,7 @@ module SpreeCmCommissioner
11
11
  create_child_taxon
12
12
  build_asset
13
13
  create_place
14
+ generate_reports
14
15
  end
15
16
  end
16
17
 
@@ -91,5 +92,9 @@ module SpreeCmCommissioner
91
92
  context.fail!(message: place.errors.full_messages.join(', '))
92
93
  end
93
94
  end
95
+
96
+ def generate_reports
97
+ SpreeCmCommissioner::ReportsAssignerJob.perform_later(@parent_taxon.id, @parent_taxon.class.to_s)
98
+ end
94
99
  end
95
100
  end
@@ -9,7 +9,8 @@ module SpreeCmCommissioner
9
9
  set_option_value
10
10
  create_variant
11
11
  create_stock_item
12
- upload_image
12
+ upload_image_to(@ticket.master)
13
+ upload_image_to(@variant)
13
14
  create_place
14
15
  end
15
16
  end
@@ -77,13 +78,13 @@ module SpreeCmCommissioner
77
78
  context.fail!(message: @stock_item.errors.full_messages.join(', '))
78
79
  end
79
80
 
80
- def upload_image
81
+ def upload_image_to(target)
81
82
  return if context.params[:ticket_image].blank?
82
83
 
83
- @image = @ticket.master.images.new(attachment: context.params[:ticket_image])
84
- return if @image.save
84
+ image = target.images.new(attachment: context.params[:ticket_image])
85
+ return if image.save
85
86
 
86
- context.fail!(message: @image.errors.full_messages.join(', '))
87
+ context.fail!(message: image.errors.full_messages.join(', '))
87
88
  end
88
89
 
89
90
  def create_place
@@ -0,0 +1,44 @@
1
+ module SpreeCmCommissioner
2
+ class CreateVendor
3
+ include Interactor
4
+
5
+ def call
6
+ validate_context!
7
+
8
+ ActiveRecord::Base.transaction do
9
+ create_vendor
10
+ assign_vendor_to_user
11
+ create_role
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def validate_context!
18
+ context.fail!(message: 'User is missing') unless context.user
19
+ context.fail!(message: 'Vendor parameters are missing') unless context.vendor_params
20
+ end
21
+
22
+ def create_vendor
23
+ @vendor = Spree::Vendor.new(context.vendor_params)
24
+ return if @vendor.save
25
+
26
+ context.fail!(message: @vendor.errors.full_messages.join(', '))
27
+ end
28
+
29
+ def assign_vendor_to_user
30
+ context.user.vendors << @vendor
31
+ end
32
+
33
+ def create_role
34
+ role = context.user.spree_roles.create(
35
+ name: "#{@vendor.name.downcase.parameterize(separator: '-')}-organizer",
36
+ vendor_id: @vendor.id,
37
+ presentation: 'Organizer'
38
+ )
39
+ return if role.persisted?
40
+
41
+ context.fail!(message: role.errors.full_messages.to_sentence)
42
+ end
43
+ end
44
+ end
@@ -18,7 +18,6 @@ module SpreeCmCommissioner
18
18
 
19
19
  def send_sms
20
20
  options = {
21
- from: sender_name(context.tenant),
22
21
  to: context.pin_code.contact,
23
22
  body: I18n.t('pincode_sender.sms.body', code: context.pin_code.code, readable_type: context.pin_code.readable_type)
24
23
  }
@@ -0,0 +1,17 @@
1
+ module SpreeCmCommissioner
2
+ class ReportsAssigner < BaseInteractor
3
+ delegate :queryable_id, :queryable_type, to: :context
4
+
5
+ def call
6
+ preset_queries = Blazer::Query.where(preset: true)
7
+
8
+ preset_queries.find_each do |query|
9
+ SpreeCmCommissioner::BlazerQueryable.find_or_create_by!(
10
+ queryable_type: queryable_type,
11
+ queryable_id: queryable_id,
12
+ blazer_query_id: query.id
13
+ )
14
+ end
15
+ end
16
+ end
17
+ end
@@ -42,7 +42,7 @@ module SpreeCmCommissioner
42
42
  end
43
43
 
44
44
  def sms_options
45
- opts = { from: context.from, to: context.to, body: context.body }
45
+ opts = { to: context.to, body: context.body }
46
46
  opts[:to] = sanitize(opts[:to]) if opts[:to].present?
47
47
  opts[:from] = from_number
48
48
  opts
@@ -1,6 +1,6 @@
1
1
  module SpreeCmCommissioner
2
2
  class UserIdTokenAuthenticator < BaseInteractor
3
- # :id_token
3
+ # :id_token, :tenant_id (optional)
4
4
  def call
5
5
  context.user = if checker.user.nil?
6
6
  register_user
@@ -14,7 +14,11 @@ module SpreeCmCommissioner
14
14
  end
15
15
 
16
16
  def register_user
17
- register_context = SpreeCmCommissioner::UserRegistrationWithIdToken.call(id_token: context.id_token)
17
+ register_context = SpreeCmCommissioner::UserRegistrationWithIdToken.call(
18
+ id_token: context.id_token,
19
+ tenant_id: context.tenant_id
20
+ )
21
+
18
22
  register_context.user
19
23
  end
20
24
 
@@ -27,7 +31,7 @@ module SpreeCmCommissioner
27
31
  end
28
32
 
29
33
  def checker
30
- @checker ||= SpreeCmCommissioner::UserIdTokenChecker.call(id_token: context.id_token)
34
+ @checker ||= SpreeCmCommissioner::UserIdTokenChecker.call(id_token: context.id_token, tenant_id: context.tenant_id)
31
35
  @checker
32
36
  end
33
37
  end
@@ -1,6 +1,9 @@
1
1
  module SpreeCmCommissioner
2
2
  class UserIdTokenChecker < BaseInteractor
3
- # :id_token
3
+ # expects:
4
+ # context.id_token
5
+ # context.tenant_id (optional)
6
+
4
7
  def call
5
8
  firebase_id_token_context = SpreeCmCommissioner::FirebaseIdTokenProvider.call(id_token: context.id_token)
6
9
 
@@ -11,9 +14,14 @@ module SpreeCmCommissioner
11
14
  end
12
15
  end
13
16
 
14
- # :identity_type, :sub
17
+ # :identity_type, :sub, :tenant_id
15
18
  def validate_user_by_provider(provider)
16
- identity_checker = SpreeCmCommissioner::UserIdentityChecker.call(provider)
19
+ identity_checker = SpreeCmCommissioner::UserIdentityChecker.call(
20
+ identity_type: provider[:identity_type],
21
+ sub: provider[:sub],
22
+ tenant_id: context.tenant_id
23
+ )
24
+
17
25
  if identity_checker.success?
18
26
  context.user = identity_checker.user
19
27
  else
@@ -1,6 +1,10 @@
1
1
  module SpreeCmCommissioner
2
2
  class UserIdentityChecker < BaseInteractor
3
- # :identity_type, :sub
3
+ # expects:
4
+ # context.identity_type
5
+ # context.sub
6
+ # context.tenant_id (optional)
7
+
4
8
  def call
5
9
  load_user
6
10
 
@@ -11,12 +15,14 @@ module SpreeCmCommissioner
11
15
  end
12
16
 
13
17
  def load_user
14
- user_identity_provider = UserIdentityProvider.where(
15
- identity_type: context.identity_type,
16
- sub: context.sub
17
- ).first
18
+ return if context.sub.blank? || context.identity_type.blank?
19
+
20
+ user_identity_provider = UserIdentityProvider.joins(:user)
21
+ .where(identity_type: context.identity_type, sub: context.sub)
22
+ .where(spree_users: { tenant_id: context.tenant_id })
23
+ .first
18
24
 
19
- context.user = (user_identity_provider.user if user_identity_provider.present?)
25
+ context.user = user_identity_provider&.user
20
26
  end
21
27
  end
22
28
  end
@@ -15,7 +15,13 @@ module SpreeCmCommissioner
15
15
  end
16
16
 
17
17
  def register_user!(name, email)
18
- user = Spree.user_class.new(password: SecureRandom.base64(16), email: email, **name_attributes(name))
18
+ user = Spree.user_class.new(
19
+ password: SecureRandom.base64(16),
20
+ email: email,
21
+ tenant_id: context.tenant_id,
22
+ **name_attributes(name)
23
+ )
24
+
19
25
  if user.save(validate: false)
20
26
  context.user = user
21
27
  else
@@ -1,25 +1,5 @@
1
1
  module SpreeCmCommissioner
2
2
  class ApplicationJob < ::ApplicationJob
3
3
  queue_as :default
4
-
5
- around_perform :log_exceptions
6
-
7
- private
8
-
9
- def log_exceptions
10
- yield
11
- rescue StandardError => e
12
- CmAppLogger.log(
13
- label: "#{self.class.name} failed",
14
- data: {
15
- error_class: e.class.name,
16
- error_message: e.message,
17
- arguments: arguments.inspect,
18
- backtrace: e.backtrace&.first(5)&.join("\n")
19
- }
20
- )
21
-
22
- raise # Re-raise the exception to let Sidekiq handle retries or failure
23
- end
24
4
  end
25
5
  end
@@ -2,25 +2,5 @@
2
2
  module SpreeCmCommissioner
3
3
  class ApplicationUniqueJob < ::ApplicationUniqueJob
4
4
  queue_as :default
5
-
6
- around_perform :log_exceptions
7
-
8
- private
9
-
10
- def log_exceptions
11
- yield
12
- rescue StandardError => e
13
- CmAppLogger.log(
14
- label: "#{self.class.name} failed",
15
- data: {
16
- error_class: e.class.name,
17
- error_message: e.message,
18
- arguments: arguments.inspect,
19
- backtrace: e.backtrace&.first(5)&.join("\n")
20
- }
21
- )
22
-
23
- raise # Re-raise the exception to let Sidekiq handle retries or failure
24
- end
25
5
  end
26
6
  end
@@ -0,0 +1,7 @@
1
+ module SpreeCmCommissioner
2
+ class ReportsAssignerJob < ApplicationUniqueJob
3
+ def perform(queryable_id, queryable_type)
4
+ SpreeCmCommissioner::ReportsAssigner.call(queryable_id: queryable_id, queryable_type: queryable_type)
5
+ end
6
+ end
7
+ end
@@ -1,6 +1,6 @@
1
1
  module SpreeCmCommissioner
2
2
  class SmsPinCodeJob < SpreeCmCommissioner::SmsJob
3
- # options = { from: xxx, to: xxxx, body: xxxx }
3
+ # options = { to: xxxx, body: xxxx }
4
4
  def perform(options)
5
5
  SpreeCmCommissioner::Sms.call(options)
6
6
  end
@@ -1,6 +1,5 @@
1
1
  module Spree
2
2
  module OrderMailerDecorator
3
- # overrided
4
3
  def cancel_email(order, resend: false)
5
4
  @order = order.respond_to?(:id) ? order : Spree::Order.find(order)
6
5
  return false if @order.email.blank?
@@ -12,18 +11,34 @@ module Spree
12
11
  @order = order.respond_to?(:id) ? order : Spree::Order.find(order)
13
12
  return false if @order.email.blank?
14
13
 
14
+ @tenant = @order.tenant
15
+ if @tenant.present?
16
+ @brand_color = @tenant.preferences[:brand_primary_color]
17
+ @vendor_logo_url = @tenant.active_vendor&.logo&.original_url
18
+ end
19
+
15
20
  @current_store = @order.store
16
21
  @product_type = @order.products.first&.product_type || 'accommodation'
17
22
 
18
- subject = (resend ? "[#{Spree.t(:resend).upcase}] " : '')
23
+ subject = resend ? "[#{Spree.t(:resend).upcase}] " : ''
19
24
  subject += "#{@current_store&.name} Booking Confirmation ##{@order.number}"
20
25
 
21
- mail(to: @order.email, from: from_address, subject: subject, store_url: @current_store.url) do |format|
26
+ mail(to: @order.email, from: from_email_address, subject: subject, store_url: @current_store.url) do |format|
22
27
  format.html { render layout: 'spree_cm_commissioner/layouts/order_mailer' }
23
28
  format.text
24
29
  end
25
30
  end
26
31
 
32
+ private
33
+
34
+ def from_email_address
35
+ if @order.tenant.nil?
36
+ from_address
37
+ else
38
+ @order.tenant.active_vendor&.from_email
39
+ end
40
+ end
41
+
27
42
  def ticket_email(guest, email)
28
43
  @guest = guest
29
44
  @event = @guest.event
@@ -18,23 +18,29 @@ module SpreeCmCommissioner
18
18
  def date_unit
19
19
  return nil unless permanent_stock?
20
20
 
21
- date_range.size
21
+ date_range_excluding_checkout.size if accommodation?
22
22
  end
23
23
 
24
- def date_range
24
+ def date_range_excluding_checkout
25
25
  return [] unless date_present?
26
26
 
27
- (from_date.to_date..to_date.to_date).to_a
27
+ date_range = (from_date.to_date..to_date.to_date).to_a
28
+ date_range.pop if date_range.size > 1
29
+ date_range
28
30
  end
29
31
 
30
- def checkin_date
31
- from_date&.to_date
32
- end
32
+ def date_range_including_checkout
33
+ return [] unless date_present?
33
34
 
34
- def checkout_date
35
- return to_date ? to_date.to_date - 1.day : nil if accommodation?
35
+ (from_date.to_date..to_date.to_date).to_a
36
+ end
36
37
 
37
- to_date&.to_date
38
+ def date_range
39
+ if accommodation?
40
+ date_range_excluding_checkout
41
+ else
42
+ date_range_including_checkout
43
+ end
38
44
  end
39
45
 
40
46
  private
@@ -49,6 +55,24 @@ module SpreeCmCommissioner
49
55
  def set_duration
50
56
  self.from_date ||= variant.start_date_time || event&.from_date
51
57
  self.to_date ||= variant.end_date_time || event&.to_date
58
+
59
+ return if persisted?
60
+
61
+ apply_variant_time(:from_date, variant.start_date_time)
62
+ apply_variant_time(:to_date, variant.end_date_time)
63
+ end
64
+
65
+ def apply_variant_time(field, variant_time)
66
+ field_value = send(field)
67
+
68
+ return unless field_value.present? && field_value.hour.zero? && variant_time.present?
69
+
70
+ send("#{field}=", field_value.change(
71
+ hour: variant_time.hour,
72
+ min: variant_time.min,
73
+ sec: variant_time.sec
74
+ )
75
+ )
52
76
  end
53
77
  end
54
78
  end
@@ -14,6 +14,13 @@ module SpreeCmCommissioner
14
14
  state_selection
15
15
  payment_option
16
16
  delivery_option
17
+ amenity
18
+ departure_time
19
+ duration
20
+ vehicle_id
21
+ origin
22
+ destination
23
+ place_id
17
24
  ].freeze
18
25
 
19
26
  RESERVED_OPTIONS = {
@@ -41,7 +48,11 @@ module SpreeCmCommissioner
41
48
  'bib-display-prefix' => 'boolean',
42
49
  'bib-pre-generation-on-create' => 'boolean',
43
50
  'seat-number-positions' => 'array',
44
- 'seat-type' => 'string'
51
+ 'origin' => 'place_id',
52
+ 'destination' => 'place_id',
53
+ 'departure-time' => 'time',
54
+ 'vehicle' => 'vehicle_id',
55
+ 'allow-seat-selection' => 'boolean'
45
56
  }.freeze
46
57
 
47
58
  included do
@@ -5,8 +5,6 @@ module SpreeCmCommissioner
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  included do
8
- state_machine.before_transition to: :payment, do: :hold_blocks!
9
-
10
8
  state_machine.before_transition to: :complete, do: :request, if: :need_confirmation?
11
9
  state_machine.before_transition to: :complete, do: :generate_bib_number
12
10
 
@@ -16,14 +14,10 @@ module SpreeCmCommissioner
16
14
  state_machine.after_transition to: :complete, do: :send_order_complete_telegram_alert_to_vendors, unless: :need_confirmation?
17
15
  state_machine.after_transition to: :complete, do: :send_order_complete_telegram_alert_to_store, unless: :need_confirmation?
18
16
 
19
- state_machine.around_transition to: :complete, do: :unstock_inventory!
20
-
21
17
  state_machine.after_transition to: :complete, do: :send_transaction_email_to_user, if: :user_has_email?
22
18
  state_machine.after_transition to: :resumed, do: :precalculate_conversion
23
- state_machine.around_transition to: :resumed, do: :unstock_inventory!
24
19
 
25
20
  state_machine.after_transition to: :canceled, do: :precalculate_conversion
26
- state_machine.after_transition to: :canceled, do: :restock_inventory!
27
21
 
28
22
  scope :accepted, -> { where(request_state: 'accepted') }
29
23
 
@@ -73,39 +67,6 @@ module SpreeCmCommissioner
73
67
  end
74
68
  end
75
69
 
76
- def unstock_inventory!
77
- ActiveRecord::Base.transaction do
78
- yield # Equal to block.call
79
-
80
- # After the transition is complete, the following code will execute first before proceeding to other `after_transition` callbacks.
81
- # This ensures that if `reserve_blocks!` or `unstock_inventory_in_redis!` fails, the state will be rolled back,
82
- # and neither the `finalize!` method nor any notifications will be triggered.
83
- # The payment will be reversed in vPago gem, and `Spree::Checkout::Complete` will be called, which checks `order.reload.complete?`.
84
- # This is critical because if the order state is complete, the payment will be marked as paid.
85
-
86
- reserve_blocks!
87
- unstock_inventory_in_redis!
88
-
89
- # We rollback only order state, and we keep payment state as it is.
90
- # We implement payment in vPago gem, and it will be reversed in the gem.
91
- # Some bank has api for refund, but some don't have the api to refund yet. So we keep the payment state as it is and refund manually.
92
- end
93
- rescue StandardError => e
94
- CmAppLogger.log(
95
- label: 'SpreeCmCommissioner::OrderStateMachine#reserve_inventory failed',
96
- data: { order_id: id, error: e.message, type: e.class.name, backtrace: e.backtrace&.first(5)&.join("\n") }
97
- )
98
-
99
- raise e
100
- end
101
-
102
- def restock_inventory!
103
- ActiveRecord::Base.transaction do
104
- cancel_blocks!
105
- restock_inventory_in_redis!
106
- end
107
- end
108
-
109
70
  def generate_bib_number
110
71
  line_items.find_each(&:generate_remaining_guests)
111
72
 
@@ -3,10 +3,12 @@ module SpreeCmCommissioner
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  included do
6
- delegate :subscribable?,
6
+ delegate :product_type,
7
+ :subscribable?,
7
8
  :allowed_upload_later?,
8
9
  :need_confirmation?, :need_confirmation,
9
10
  :allow_anonymous_booking,
11
+ :accommodation?, :service?, :ecommerce?,
10
12
  :allow_self_check_in,
11
13
  :allow_self_check_in?,
12
14
  :required_self_check_in_location,