spree_cm_commissioner 2.0.3.pre.pre4 → 2.0.3.pre.pre6

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/.github/workflows/test_and_build_gem.yml +16 -2
  3. data/.gitignore +2 -1
  4. data/Gemfile.lock +28 -1
  5. data/Rakefile +33 -4
  6. data/app/assets/stylesheets/spree_cm_commissioner/backend/calendar.scss +8 -11
  7. data/app/controllers/spree/admin/inventory_items_controller.rb +83 -0
  8. data/app/controllers/spree/admin/stock_managements_controller.rb +63 -1
  9. data/app/controllers/spree/api/v2/storefront/accommodations/variants_controller.rb +42 -0
  10. data/app/controllers/spree/api/v2/storefront/accommodations_controller.rb +14 -31
  11. data/app/controllers/spree/api/v2/storefront/queue_cart/line_items_controller.rb +2 -2
  12. data/app/controllers/spree/api/v2/storefront/trip_places_controller.rb +29 -0
  13. data/app/controllers/spree/api/v2/storefront/trip_search_controller.rb +62 -0
  14. data/app/controllers/spree_cm_commissioner/admin/products_controller_decorator.rb +14 -0
  15. data/app/finders/spree_cm_commissioner/accommodations/find.rb +37 -0
  16. data/app/finders/spree_cm_commissioner/accommodations/find_variant.rb +32 -0
  17. data/app/interactors/spree_cm_commissioner/ensure_correct_product_type.rb +40 -0
  18. data/app/interactors/spree_cm_commissioner/inventory_item_syncer.rb +25 -0
  19. data/app/interactors/spree_cm_commissioner/stock/inventory_item_resetter.rb +44 -0
  20. data/app/interactors/spree_cm_commissioner/stock/inventory_items_adjuster.rb +13 -0
  21. data/app/interactors/spree_cm_commissioner/stock/inventory_items_generator.rb +15 -0
  22. data/app/interactors/spree_cm_commissioner/stock/permanent_inventory_items_generator.rb +75 -0
  23. data/app/interactors/spree_cm_commissioner/stock/stock_movement_creator.rb +32 -0
  24. data/app/interactors/spree_cm_commissioner/taxi_trip_creator.rb +66 -0
  25. data/app/interactors/spree_cm_commissioner/transit/draft_order_creator.rb +132 -0
  26. data/app/interactors/spree_cm_commissioner/variant_block_updater.rb +62 -0
  27. data/app/interactors/spree_cm_commissioner/vehicle_updater.rb +41 -0
  28. data/app/jobs/spree_cm_commissioner/application_job.rb +20 -0
  29. data/app/jobs/spree_cm_commissioner/application_unique_job.rb +20 -0
  30. data/app/jobs/spree_cm_commissioner/ensure_correct_product_type_job.rb +7 -0
  31. data/app/jobs/spree_cm_commissioner/inventory_item_syncer_job.rb +7 -0
  32. data/app/jobs/spree_cm_commissioner/stock/inventory_items_adjuster_job.rb +11 -0
  33. data/app/jobs/spree_cm_commissioner/stock/inventory_items_generator_job.rb +11 -0
  34. data/app/jobs/spree_cm_commissioner/stock/permanent_inventory_items_generator_job.rb +9 -0
  35. data/app/models/concerns/spree_cm_commissioner/line_item_durationable.rb +18 -15
  36. data/app/models/concerns/spree_cm_commissioner/line_item_guests_concern.rb +29 -15
  37. data/app/models/concerns/spree_cm_commissioner/line_item_transitable.rb +89 -0
  38. data/app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb +2 -12
  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/route_type.rb +1 -1
  44. data/app/models/concerns/spree_cm_commissioner/taxon_kind.rb +1 -1
  45. data/app/models/concerns/spree_cm_commissioner/vehicle_type.rb +11 -0
  46. data/app/models/spree_cm_commissioner/address_decorator.rb +36 -2
  47. data/app/models/spree_cm_commissioner/block.rb +43 -0
  48. data/app/models/spree_cm_commissioner/guest.rb +35 -0
  49. data/app/models/spree_cm_commissioner/inventory.rb +11 -0
  50. data/app/models/spree_cm_commissioner/inventory_item.rb +69 -0
  51. data/app/models/spree_cm_commissioner/line_item_decorator.rb +47 -78
  52. data/app/models/spree_cm_commissioner/notification_taxon.rb +1 -1
  53. data/app/models/spree_cm_commissioner/option_type_decorator.rb +1 -11
  54. data/app/models/spree_cm_commissioner/order/address_book_decorator.rb +30 -12
  55. data/app/models/spree_cm_commissioner/order_decorator.rb +38 -1
  56. data/app/models/spree_cm_commissioner/place.rb +3 -4
  57. data/app/models/spree_cm_commissioner/price_decorator.rb +9 -0
  58. data/app/models/spree_cm_commissioner/product_decorator.rb +39 -6
  59. data/app/models/spree_cm_commissioner/redis_stock/cached_inventory_items_builder.rb +41 -0
  60. data/app/models/spree_cm_commissioner/redis_stock/inventory_updater.rb +126 -0
  61. data/app/models/spree_cm_commissioner/redis_stock/line_items_cached_inventory_items_builder.rb +36 -0
  62. data/app/models/spree_cm_commissioner/redis_stock/variant_cached_inventory_items_builder.rb +25 -0
  63. data/app/models/spree_cm_commissioner/reserved_block.rb +30 -0
  64. data/app/models/spree_cm_commissioner/saved_guest.rb +15 -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 -1
  82. data/app/models/spree_cm_commissioner/taxonomy_decorator.rb +0 -6
  83. data/app/models/spree_cm_commissioner/trip.rb +19 -10
  84. data/app/models/spree_cm_commissioner/trip_connection.rb +5 -5
  85. data/app/models/spree_cm_commissioner/trip_stop.rb +10 -21
  86. data/app/models/spree_cm_commissioner/variant_block.rb +17 -0
  87. data/app/models/spree_cm_commissioner/variant_decorator.rb +37 -47
  88. data/app/models/spree_cm_commissioner/variant_options.rb +0 -23
  89. data/app/models/spree_cm_commissioner/vehicle.rb +11 -16
  90. data/app/models/spree_cm_commissioner/vendor_decorator.rb +14 -14
  91. data/app/models/spree_cm_commissioner/vendor_place.rb +13 -3
  92. data/app/overrides/spree/admin/products/_form/industry_taxons.html.erb.deface +26 -0
  93. data/app/overrides/spree/admin/products/_form/taxons.html.erb.deface +26 -0
  94. data/app/queries/spree_cm_commissioner/trip_query.rb +110 -131
  95. data/app/request_schemas/spree_cm_commissioner/accommodation_request_schema.rb +3 -0
  96. data/app/request_schemas/spree_cm_commissioner/application_request_schema.rb +1 -1
  97. data/app/request_schemas/spree_cm_commissioner/trip_search_request_schema.rb +20 -0
  98. data/app/request_schemas/spree_cm_commissioner/variant_request_schema.rb +19 -0
  99. data/app/serializers/spree/v2/storefront/accommodation_serializer.rb +2 -0
  100. data/app/serializers/spree/v2/storefront/amenity_serializer.rb +15 -0
  101. data/app/serializers/spree/v2/storefront/line_item_serializer_decorator.rb +1 -0
  102. data/app/serializers/spree/v2/storefront/product_serializer_decorator.rb +2 -0
  103. data/app/serializers/spree/v2/storefront/trip_place_serializer.rb +10 -0
  104. data/app/serializers/spree/v2/storefront/trip_query_result_serializer.rb +14 -0
  105. data/app/serializers/spree/v2/storefront/trip_result_serializer.rb +17 -0
  106. data/app/serializers/spree/v2/storefront/trip_vehicle_serializer.rb +11 -0
  107. data/app/serializers/spree/v2/storefront/trip_vendor_serializer.rb +13 -0
  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/config/initializers/paper_trail.rb +1 -0
  113. data/config/initializers/spree_permitted_attributes.rb +5 -0
  114. data/config/routes.rb +24 -2
  115. data/db/migrate/20240202080634_update_counter_cache_of_vehicle_type.rb +3 -1
  116. data/db/migrate/20250122000000_move_route_type_from_vehicles_to_trips.rb +7 -0
  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/db/migrate/20250716022821_add_location_reference_to_cm_vendor_places.rb +5 -0
  139. data/db/migrate/20250716031743_drop_table_cm_vendor_stops.rb +5 -0
  140. data/db/migrate/20250717023824_add_vendor_reference_to_cm_trips.rb +5 -0
  141. data/db/migrate/20250717041414_add_location_place_reference_to_cm_trip_stops.rb +5 -0
  142. data/db/migrate/20250717042539_rename_cm_trip_stops_stop_id_column_to_stop_place_id.rb +7 -0
  143. data/db/migrate/20250717042707_rename_cm_trips_origin_and_destination_to_origin_place_and_destination_place.rb +11 -0
  144. data/db/migrate/20250721080738_add_vehicle_type_to_cm_vehicles.rb +7 -0
  145. data/db/migrate/20250725092713_add_block_type_to_cm_blocks.rb +5 -0
  146. data/db/migrate/20250731062816_add_departure_time_and_arrival_time_to_trip_stop.rb +6 -0
  147. data/db/migrate/20250807033035_create_spree_cm_commissioner_saved_guests.rb +23 -0
  148. data/db/migrate/20250808054835_add_saved_guest_reference_to_cm_blocks.rb +5 -0
  149. data/db/migrate/20250812015522_remove_unique_indexes_from_cm_user_identity_providers.rb +8 -0
  150. data/db/migrate/20250814073854_add_call_to_action_to_spree_products.rb +5 -0
  151. data/docker-compose.yml +1 -1
  152. data/lib/cm_app_logger.rb +11 -4
  153. data/lib/generators/spree_cm_commissioner/install/install_generator.rb +14 -11
  154. data/lib/generators/spree_cm_commissioner/install/templates/app/javascript/{spree_cm_commissioner → spree_dashboard/spree_cm_commissioner}/utilities.js +4 -0
  155. data/lib/spree_cm_commissioner/cached_inventory_item.rb +23 -0
  156. data/lib/spree_cm_commissioner/calendar_event.rb +11 -1
  157. data/lib/spree_cm_commissioner/test_helper/factories/block_factory.rb +16 -0
  158. data/lib/spree_cm_commissioner/test_helper/factories/guest_factory.rb +10 -0
  159. data/lib/spree_cm_commissioner/test_helper/factories/homepage_section_relatable_factory.rb +1 -1
  160. data/lib/spree_cm_commissioner/test_helper/factories/inventory_item_factory.rb +9 -0
  161. data/lib/spree_cm_commissioner/test_helper/factories/line_item_factory.rb +1 -1
  162. data/lib/spree_cm_commissioner/test_helper/factories/option_type_factory.rb +6 -30
  163. data/lib/spree_cm_commissioner/test_helper/factories/order_factory.rb +0 -36
  164. data/lib/spree_cm_commissioner/test_helper/factories/product_factory.rb +18 -34
  165. data/lib/spree_cm_commissioner/test_helper/factories/reserved_block_factory.rb +27 -0
  166. data/lib/spree_cm_commissioner/test_helper/factories/seat_layout_factory.rb +11 -0
  167. data/lib/spree_cm_commissioner/test_helper/factories/seat_section_factory.rb +16 -0
  168. data/lib/spree_cm_commissioner/test_helper/factories/stock_location_factory.rb +2 -2
  169. data/lib/spree_cm_commissioner/test_helper/factories/trip_connection_factory.rb +6 -0
  170. data/lib/spree_cm_commissioner/test_helper/factories/trip_factory.rb +11 -3
  171. data/lib/spree_cm_commissioner/test_helper/factories/trip_stop_factory.rb +13 -0
  172. data/lib/spree_cm_commissioner/test_helper/factories/variant_block_factory.rb +7 -0
  173. data/lib/spree_cm_commissioner/test_helper/factories/variant_factory.rb +41 -19
  174. data/lib/spree_cm_commissioner/test_helper/factories/vehicle_factory.rb +1 -1
  175. data/lib/spree_cm_commissioner/test_helper/factories/vendor_factory.rb +6 -1
  176. data/lib/spree_cm_commissioner/test_helper/factories/vendor_place_factory.rb +13 -1
  177. data/lib/spree_cm_commissioner/transit/leg.rb +37 -0
  178. data/lib/spree_cm_commissioner/transit/seat_selection.rb +27 -0
  179. data/lib/spree_cm_commissioner/trip_query_result.rb +50 -0
  180. data/lib/spree_cm_commissioner/trip_result.rb +19 -10
  181. data/lib/spree_cm_commissioner/version.rb +1 -1
  182. data/lib/spree_cm_commissioner.rb +37 -1
  183. data/lib/tasks/create_default_non_permanent_inventory_items.rake +16 -0
  184. data/lib/tasks/ensure_correct_product_type.rake +7 -0
  185. data/lib/tasks/generate_inventory_items.rake +7 -0
  186. data/spree_cm_commissioner.gemspec +7 -0
  187. metadata +167 -26
  188. data/app/controllers/concerns/spree_cm_commissioner/transit/taxon_bitwise.rb +0 -44
  189. data/app/finders/spree_cm_commissioner/line_items/find_by_variant_decorator.rb +0 -20
  190. data/app/models/spree_cm_commissioner/branch.rb +0 -12
  191. data/app/models/spree_cm_commissioner/line_item_seat.rb +0 -10
  192. data/app/models/spree_cm_commissioner/option_value_vehicle_type.rb +0 -8
  193. data/app/models/spree_cm_commissioner/stop.rb +0 -23
  194. data/app/models/spree_cm_commissioner/vehicle_seat.rb +0 -11
  195. data/app/models/spree_cm_commissioner/vehicle_type.rb +0 -76
  196. data/app/models/spree_cm_commissioner/vendor_stop.rb +0 -10
  197. data/app/queries/spree_cm_commissioner/trip_search_query.rb +0 -76
  198. data/app/queries/spree_cm_commissioner/variant_availability/non_permanent_stock_query.rb +0 -45
  199. data/app/queries/spree_cm_commissioner/variant_availability/permanent_stock_query.rb +0 -55
  200. data/app/queries/spree_cm_commissioner/vendor_stop_place_query.rb +0 -54
  201. data/app/services/spree_cm_commissioner/vehicle_option_value_creator.rb +0 -11
  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
@@ -0,0 +1,23 @@
1
+ module SpreeCmCommissioner
2
+ class CachedInventoryItem
3
+ attr_reader :inventory_key, :active, :quantity_available, :inventory_item_id, :variant_id
4
+
5
+ def initialize(inventory_key:, active:, quantity_available:, inventory_item_id:, variant_id:)
6
+ @inventory_key = inventory_key
7
+ @active = active
8
+ @quantity_available = quantity_available
9
+ @inventory_item_id = inventory_item_id
10
+ @variant_id = variant_id
11
+ end
12
+
13
+ def active?
14
+ active
15
+ end
16
+
17
+ def to_h
18
+ instance_variables.each_with_object({}) do |var, hash|
19
+ hash[var.to_s.delete('@').to_sym] = instance_variable_get(var)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -2,7 +2,7 @@ module SpreeCmCommissioner
2
2
  class CalendarEvent
3
3
  attr_reader :from_date, :to_date, :title, :options
4
4
 
5
- def initialize(from_date:, to_date:, title:, options:)
5
+ def initialize(from_date:, to_date:, title: nil, options: nil)
6
6
  @from_date = from_date
7
7
  @to_date = to_date
8
8
  @title = title
@@ -23,5 +23,15 @@ module SpreeCmCommissioner
23
23
  )
24
24
  end
25
25
  end
26
+
27
+ def self.from_inventory_items(inventory_items)
28
+ inventory_items.map do |item|
29
+ CalendarEvent.new(
30
+ from_date: item.inventory_date,
31
+ to_date: item.inventory_date,
32
+ options: { inventory_item: item }
33
+ )
34
+ end
35
+ end
26
36
  end
27
37
  end
@@ -0,0 +1,16 @@
1
+ FactoryBot.define do
2
+ factory :cm_block, class: SpreeCmCommissioner::Block do
3
+ label { "Block #{rand(1.0..100.0)}" }
4
+ block_type { :seat }
5
+
6
+ association :seat_section, factory: :cm_seat_section
7
+
8
+ width { rand(10.0..100.0) }
9
+ height { rand(10.0..100.0) }
10
+
11
+ x { rand(0.0..500.0) }
12
+ y { rand(0.0..500.0) }
13
+
14
+ rotation { rand(-180.0..180.0) }
15
+ end
16
+ end
@@ -1,4 +1,5 @@
1
1
  FactoryBot.define do
2
+ # use cm_guest instead for consistency
2
3
  factory :guest, class: SpreeCmCommissioner::Guest do
3
4
  line_item { |a| a.association(:line_item) }
4
5
  first_name { FFaker::Name.name }
@@ -7,4 +8,13 @@ FactoryBot.define do
7
8
  dob { '1986-03-28' }
8
9
  token { SecureRandom.hex(32) }
9
10
  end
11
+
12
+ factory :cm_guest, class: SpreeCmCommissioner::Guest do
13
+ line_item { |a| a.association(:line_item) }
14
+ first_name { FFaker::Name.name }
15
+ last_name { FFaker::Name.name }
16
+ gender { 1 }
17
+ dob { '1986-03-28' }
18
+ token { SecureRandom.hex(32) }
19
+ end
10
20
  end
@@ -17,7 +17,7 @@ FactoryBot.define do
17
17
  end
18
18
 
19
19
  factory :cm_product_homepage_section_relatable do
20
- relatable { create(:product) }
20
+ relatable { create(:cm_product) }
21
21
  end
22
22
 
23
23
  factory :cm_taxon_homepage_section_relatable do
@@ -0,0 +1,9 @@
1
+ FactoryBot.define do
2
+ factory :cm_inventory_item, class: SpreeCmCommissioner::InventoryItem do
3
+ variant { create(:cm_variant) }
4
+ max_capacity { 10 }
5
+ quantity_available { 10 }
6
+ product_type { 'accommodation' }
7
+ inventory_date { Date.today }
8
+ end
9
+ end
@@ -16,7 +16,7 @@ FactoryBot.define do
16
16
  variant { product.master }
17
17
 
18
18
  factory :cm_need_confirmation_line_item do
19
- product { create(:product, need_confirmation: true) }
19
+ product { create(:cm_product, need_confirmation: true) }
20
20
  end
21
21
 
22
22
  factory :cm_kyc_line_item do
@@ -9,6 +9,12 @@ FactoryBot.define do
9
9
  presentation { 'location' }
10
10
  end
11
11
 
12
+ trait :vehicle do
13
+ attr_type { :string }
14
+ name { 'vehicle' }
15
+ presentation { 'vehicle' }
16
+ end
17
+
12
18
  trait :start_date do
13
19
  attr_type { :date }
14
20
  name { 'start-date' }
@@ -147,36 +153,6 @@ FactoryBot.define do
147
153
  presentation { 'seat-number-positions' }
148
154
  end
149
155
 
150
- trait :origin do
151
- attr_type { :origin }
152
- name { 'origin' }
153
- presentation { 'origin' }
154
- end
155
-
156
- trait :destination do
157
- attr_type { :destination }
158
- name { 'destination' }
159
- presentation { 'destination' }
160
- end
161
-
162
- trait :departure_time do
163
- attr_type { :time }
164
- name { 'departure-time' }
165
- presentation { 'departure-time' }
166
- end
167
-
168
- trait :vehicle do
169
- attr_type { :vehicle_id }
170
- name { 'vehicle' }
171
- presentation { 'vehicle' }
172
- end
173
-
174
- trait :allow_seat_selection do
175
- attr_type { :boolean }
176
- name { 'allow-seat-selection' }
177
- presentation { 'allow-seat-selection' }
178
- end
179
-
180
156
  initialize_with { Spree::OptionType.where(name: name).first_or_initialize }
181
157
  end
182
158
  end
@@ -1,38 +1,2 @@
1
1
  FactoryBot.define do
2
- factory :transit_order, class: Spree::Order do
3
- bill_address
4
- ship_address
5
- state {'complete'}
6
- payment_state {'paid'}
7
-
8
- transient do
9
- line_items_count { 1 }
10
- shipment_cost { 100 }
11
- shipping_method_filter { Spree::ShippingMethod::DISPLAY_ON_FRONT_END }
12
- seats {}
13
- variant {}
14
- quantity {}
15
- date { Date.today }
16
- selected_seats {[]}
17
- line_item_seats_attributes{[]}
18
- end
19
-
20
- after(:create) do |order, evaluator|
21
- if evaluator.quantity.nil? && evaluator.seats.present?
22
- @line_item_seats_attributes = evaluator.seats.map do |seat|
23
- {seat_id: seat.id, date: evaluator.date, variant_id: evaluator.variant.id}
24
- end
25
- create(:line_item, order: order, variant: evaluator.variant, date: evaluator.date, line_item_seats_attributes: @line_item_seats_attributes)
26
- order.line_items.reload
27
- else
28
- create(:line_item, order: order, variant: evaluator.variant, date: evaluator.date, quantity: evaluator.quantity)
29
- end
30
-
31
- stock_location = order.line_items&.first&.variant&.stock_items&.first&.stock_location || create(:stock_location)
32
- create(:shipment, order: order, cost: evaluator.shipment_cost, stock_location: stock_location)
33
- order.shipments.reload
34
-
35
- order.update_with_updater!
36
- end
37
- end
38
2
  end
@@ -1,6 +1,19 @@
1
1
  FactoryBot.define do
2
- factory :cm_product, parent: :base_product do
2
+ factory :cm_product_in_stock, parent: :product_in_stock do
3
+ product_type { :ecommerce }
4
+ end
5
+
6
+ factory :cm_product_with_option_types, parent: :product_with_option_types do
7
+ product_type { :ecommerce }
8
+ end
9
+
10
+ factory :cm_base_product, parent: :base_product do
11
+ product_type { :ecommerce }
12
+ end
13
+
14
+ factory :cm_product, parent: :product do
3
15
  vendor { Spree::Vendor.first || create(:cm_vendor) }
16
+ product_type { :ecommerce }
4
17
 
5
18
  before(:create) do |product|
6
19
  create(:stock_location) unless Spree::StockLocation.any?
@@ -33,35 +46,6 @@ FactoryBot.define do
33
46
  end
34
47
  end
35
48
 
36
- factory :route do
37
- route_type {:automobile}
38
- product_type { :transit }
39
- before(:create) do |route, evaluator|
40
- create(:stock_location) unless Spree::StockLocation.any?
41
- if route.stores.empty?
42
- default_store = Spree::Store.default.persisted? ? Spree::Store.default : nil
43
- store = default_store || create(:store)
44
-
45
- route.stores << [store]
46
- end
47
- end
48
- after(:create) do |route, evaluator|
49
- trip = route.master
50
- trip.permanent_stock = 10
51
- trip.stock_items = [create(:stock_item, variant: trip, stock_location: route.vendor.stock_locations.first)]
52
- trip.stock_items.first.adjust_count_on_hand(10)
53
-
54
- # option types
55
- route.option_types << create(:cm_option_type, :origin)
56
- route.option_types << create(:cm_option_type, :destination)
57
- route.option_types << create(:cm_option_type, :departure_time)
58
- route.option_types << create(:cm_option_type, :duration_in_hours)
59
- route.option_types << create(:cm_option_type, :duration_in_minutes)
60
- route.option_types << create(:cm_option_type, :allow_seat_selection)
61
- route.option_types << create(:cm_option_type, :vehicle)
62
- end
63
- end
64
-
65
49
  factory :cm_subscribable_product do
66
50
  option_types { [
67
51
  create(:cm_option_type, :month),
@@ -85,7 +69,7 @@ FactoryBot.define do
85
69
  option_value2 = create(:cm_option_value, presentation: "#{evaluator.due_date} Days", name: evaluator.due_date.to_s, option_type: product.option_types[1])
86
70
  option_value3 = create(:cm_option_value, presentation: "#{evaluator.payment_option}", name: evaluator.payment_option.to_s, option_type: product.option_types[2])
87
71
 
88
- variant = create(:variant, price: product.price, product: product)
72
+ variant = create(:cm_variant, price: product.price, product: product)
89
73
  variant.option_values = [option_value1, option_value2, option_value3]
90
74
  variant.save!
91
75
 
@@ -103,7 +87,7 @@ FactoryBot.define do
103
87
  end
104
88
 
105
89
  after(:create) do |product, evaluator|
106
- variant = create(:variant, price: product.price, product: product)
90
+ variant = create(:cm_variant, price: product.price, product: product)
107
91
  variant.save!
108
92
 
109
93
  variant.stock_items.first.adjust_count_on_hand(evaluator.total_inventory)
@@ -136,12 +120,12 @@ FactoryBot.define do
136
120
  create(:cm_option_value, presentation: 'Yes', name: '1', option_type: product.option_types.find_by(name: 'bib-pre-generation-on-create'))
137
121
  end
138
122
 
139
- variant1 = create(:variant, price: product.price, product: product)
123
+ variant1 = create(:cm_variant, price: product.price, product: product)
140
124
  variant1.option_values = [option_value1]
141
125
  variant1.option_values << bib_pre_generation_option_value if evaluator.bib_pre_generation_on_create
142
126
  variant1.save!
143
127
 
144
- variant2 = create(:variant, price: product.price, product: product)
128
+ variant2 = create(:cm_variant, price: product.price, product: product)
145
129
  variant2.option_values = [option_value2]
146
130
  variant2.option_values << bib_pre_generation_option_value if evaluator.bib_pre_generation_on_create
147
131
  variant2.save!
@@ -0,0 +1,27 @@
1
+ FactoryBot.define do
2
+ factory :cm_reserved_block, class: SpreeCmCommissioner::ReservedBlock do
3
+ association :inventory_item, factory: :cm_inventory_item
4
+ association :block, factory: :cm_block
5
+ association :guest, factory: :guest
6
+ association :updated_by, factory: :user
7
+
8
+ status { :on_hold } # or :reserved, :canceled based on enum
9
+ inventory_date { Time.current }
10
+ expired_at { 10.minutes.from_now }
11
+
12
+ trait :reserved do
13
+ status { :reserved }
14
+ expired_at { nil }
15
+ end
16
+
17
+ trait :on_hold do
18
+ status { :on_hold }
19
+ expired_at { 8.minutes.from_now }
20
+ end
21
+
22
+ trait :canceled do
23
+ status { :canceled }
24
+ expired_at { nil }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,11 @@
1
+ FactoryBot.define do
2
+ factory :cm_seat_layout, class: SpreeCmCommissioner::SeatLayout do
3
+ association :layoutable, factory: :cm_vehicle
4
+
5
+ name { "Layout #{rand(1.0..50.0)}" }
6
+ status { :active }
7
+
8
+ width { rand(200.0..1000.0) }
9
+ height { rand(200.0..1000.0) }
10
+ end
11
+ end
@@ -0,0 +1,16 @@
1
+ FactoryBot.define do
2
+ factory :cm_seat_section, class: SpreeCmCommissioner::SeatSection do
3
+ name { "Section #{rand(1.0..50.0)}" }
4
+
5
+ association :seat_layout, factory: :cm_seat_layout
6
+
7
+ width { rand(50.0..500.0) }
8
+ height { rand(50.0..500.0) }
9
+
10
+ x { rand(0.0..500.0) }
11
+ y { rand(0.0..500.0) }
12
+
13
+ rotation { rand(-180.0..180.0) }
14
+ shape_path { "M0,0 L10,0 L10,10 L0,10 Z" }
15
+ end
16
+ end
@@ -24,8 +24,8 @@ FactoryBot.define do
24
24
  # variant will add itself to all stock_locations in an after_create
25
25
  # creating a product will automatically create a master variant
26
26
  store = Spree::Store.first || create(:store)
27
- product_1 = create(:product, stores: [store])
28
- product_2 = create(:product, stores: [store])
27
+ product_1 = create(:cm_product, stores: [store])
28
+ product_2 = create(:cm_product, stores: [store])
29
29
 
30
30
  stock_location.stock_items.where(variant_id: product_1.master.id).first.adjust_count_on_hand(10)
31
31
  stock_location.stock_items.where(variant_id: product_2.master.id).first.adjust_count_on_hand(20)
@@ -0,0 +1,6 @@
1
+ FactoryBot.define do
2
+ factory :cm_trip_connection, class: SpreeCmCommissioner::TripConnection do
3
+ from_trip_id { create(:cm_trip) }
4
+ to_trip_id { create(:cm_trip) }
5
+ end
6
+ end
@@ -1,6 +1,14 @@
1
1
  FactoryBot.define do
2
- factory :trip_connection, class: 'SpreeCmCommissioner::TripConnection' do
3
- association :from_trip, factory: :variant
4
- association :to_trip, factory: :variant
2
+ factory :cm_trip, class: SpreeCmCommissioner::Trip do
3
+ departure_time { Time.zone.now.change(hour: 8, min: 0) } # example 8:00 AM
4
+ duration { 3600 } # 1 hour in seconds
5
+ allow_seat_selection { true }
6
+
7
+ product { create(:cm_product, product_type: :transit) }
8
+
9
+ association :vendor, factory: :cm_transit_vendor
10
+ association :vehicle, factory: :cm_vehicle
11
+ association :origin_place, factory: :cm_place
12
+ association :destination_place, factory: :cm_place
5
13
  end
6
14
  end
@@ -0,0 +1,13 @@
1
+ FactoryBot.define do
2
+ factory :cm_trip_stop, class: SpreeCmCommissioner::TripStop do
3
+ association :trip, factory: :cm_trip
4
+ association :stop_place, factory: :cm_place
5
+ association :location_place, factory: :cm_place
6
+
7
+ stop_type { :boarding }
8
+ stop_name { stop_place.name }
9
+
10
+ arrival_time { Time.current }
11
+ departure_time { Time.current + 10.minutes }
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ FactoryBot.define do
2
+ factory :cm_variant_block, class: SpreeCmCommissioner::VariantBlock do
3
+ association :variant, factory: :cm_variant
4
+ association :trip, factory: :cm_trip
5
+ association :block, factory: :cm_block
6
+ end
7
+ end
@@ -1,38 +1,60 @@
1
1
  FactoryBot.define do
2
2
  factory :cm_base_variant, parent: :base_variant do
3
+ is_master { false }
4
+ product { create(:cm_product) }
5
+
3
6
  transient do
4
7
  total_inventory { 10 }
8
+ backorderable { false }
9
+ pregenerate_inventory_items { true }
10
+ pre_inventory_days { nil } # optional for permanent only
5
11
  end
6
12
 
7
13
  after :create do |variant, evaluator|
8
14
  variant.stock_items.first.adjust_count_on_hand(evaluator.total_inventory)
9
- end
10
- end
15
+ variant.stock_items.update_all(backorderable: evaluator.backorderable)
11
16
 
12
- factory :cm_variant, parent: :variant do
13
- product do
14
- stock_locations = [create(:stock_location)]
15
- product = create(:product, vendor: create(:active_vendor, stock_locations: stock_locations))
16
- product
17
+ # stock_items is created then enqueue create inventory items job
18
+ # but we want to create inventory items directly in this factory without waiting for job
19
+ if evaluator.pregenerate_inventory_items
20
+ if variant.permanent_stock?
21
+ SpreeCmCommissioner::Stock::PermanentInventoryItemsGenerator.call(variant_ids: [variant.id], pre_inventory_days: evaluator.pre_inventory_days || 3)
22
+ else
23
+ variant.create_default_non_permanent_inventory_item! unless variant.default_inventory_item_exist?
24
+ end
25
+ end
17
26
  end
18
27
  end
19
28
 
20
- factory :trip, class: Spree::Variant do
21
- permanent_stock { 5 }
29
+ factory :cm_variant, parent: :cm_base_variant do
30
+ product { create(:cm_product) }
31
+
22
32
  transient do
23
- departure_time { "10:00" }
24
- duration { "1" }
25
- route { }
33
+ number_of_adults { nil }
34
+ number_of_kids { nil }
35
+ delivery_required { nil }
26
36
  end
27
- before(:create) do |trip, evaluator|
28
- trip.product = evaluator.route
29
37
 
30
- trip.option_values = [evaluator.departure_time, evaluator.duration]
38
+ after(:create) do |variant, evaluator|
39
+ if evaluator.number_of_adults.present?
40
+ number_of_adults = create(:cm_option_type, :number_of_adults)
41
+ variant.product.option_types << number_of_adults
42
+ variant.option_values << create(:cm_option_value, presentation: evaluator.number_of_adults, name: evaluator.number_of_adults, option_type: number_of_adults)
43
+ end
31
44
 
32
- end
33
- after(:create) do |trip, evaluator|
34
- trip.stock_items = [create(:stock_item, variant: trip, stock_location: evaluator.product.vendor.stock_locations.first)]
35
- trip.stock_items.first.adjust_count_on_hand(10)
45
+ if evaluator.number_of_kids.present?
46
+ number_of_kids = create(:cm_option_type, :number_of_kids)
47
+ variant.product.option_types << number_of_kids
48
+ variant.option_values << create(:cm_option_value, presentation: evaluator.number_of_kids, name: evaluator.number_of_kids, option_type: number_of_kids)
49
+ end
50
+
51
+ if evaluator.delivery_required == true
52
+ delivery_option = create(:cm_option_type, :delivery_option)
53
+ variant.product.option_types << delivery_option
54
+ variant.option_values << create(:cm_option_value, presentation: 'Delivery', name: 'delivery', option_type: delivery_option)
55
+ end
56
+
57
+ variant.save!
36
58
  end
37
59
  end
38
60
  end
@@ -1,5 +1,5 @@
1
1
  FactoryBot.define do
2
- factory :vehicle, class: SpreeCmCommissioner::Vehicle do
2
+ factory :cm_vehicle, class: SpreeCmCommissioner::Vehicle do
3
3
  sequence(:code) { |n| "vehicle_#{n}" }
4
4
  sequence(:license_plate) { |n| "2KH-#{'%04d' % (n % 10000)}" }
5
5
  end
@@ -1,4 +1,9 @@
1
1
  FactoryBot.define do
2
+ factory :cm_transit_vendor, parent: :vendor do
3
+ state { :active }
4
+ primary_product_type { :transit }
5
+ end
6
+
2
7
  factory :cm_vendor, parent: :vendor do
3
8
  state { :active }
4
9
  default_state_id { Spree::State.first&.id }
@@ -30,7 +35,7 @@ FactoryBot.define do
30
35
  if vendor.primary_product_type == :accommodation
31
36
  product = create(:cm_accommodation_product, vendor: vendor, total_inventory: evaluator.total_inventory)
32
37
  else
33
- product = create(:product, vendor: vendor, product_type: vendor.primary_product_type)
38
+ product = create(:cm_product, vendor: vendor, product_type: vendor.primary_product_type)
34
39
  product.master.stock_items.first.adjust_count_on_hand(evaluator.total_inventory)
35
40
  end
36
41
 
@@ -1,7 +1,19 @@
1
1
  FactoryBot.define do
2
- factory :vendor_place, class: SpreeCmCommissioner::VendorPlace do
2
+ factory :cm_location_vendor_place, class: SpreeCmCommissioner::VendorPlace do
3
3
  association :vendor, factory: :vendor
4
4
  association :place, factory: :cm_place
5
+
6
+ distance { FFaker::Number.decimal }
7
+ position { FFaker::Number.number }
8
+
9
+ place_type { :location }
10
+ end
11
+
12
+ factory :cm_vendor_place, class: SpreeCmCommissioner::VendorPlace do
13
+ association :vendor, factory: :vendor
14
+ association :place, factory: :cm_place
15
+ association :location, factory: :cm_location_vendor_place
16
+
5
17
  distance { FFaker::Number.decimal }
6
18
  position { FFaker::Number.number }
7
19
  place_type { :branch }
@@ -0,0 +1,37 @@
1
+ module SpreeCmCommissioner::Transit
2
+ class Leg
3
+ attr_accessor :direction, :trip_id, :boarding_trip_stop_id, :drop_off_trip_stop_id, :seat_selections
4
+
5
+ def initialize(options = {})
6
+ @direction = options[:direction]
7
+ @trip_id = options[:trip_id]
8
+ @boarding_trip_stop_id = options[:boarding_trip_stop_id]
9
+ @drop_off_trip_stop_id = options[:drop_off_trip_stop_id]
10
+ @seat_selections = options[:seat_selections] || []
11
+ end
12
+
13
+ def self.from_hash(hash)
14
+ new(
15
+ direction: hash[:direction], # outbound / inbound
16
+ trip_id: hash[:trip_id],
17
+ boarding_trip_stop_id: hash[:boarding_trip_stop_id],
18
+ drop_off_trip_stop_id: hash[:drop_off_trip_stop_id],
19
+ seat_selections: (hash[:seat_selections] || []).map { |seat_selection| SeatSelection.from_hash(seat_selection) }
20
+ )
21
+ end
22
+
23
+ def quantity
24
+ @seat_selections.sum(&:quantity).to_i
25
+ end
26
+
27
+ def to_h
28
+ {
29
+ direction: @direction,
30
+ trip_id: @trip_id,
31
+ boarding_trip_stop_id: @boarding_trip_stop_id,
32
+ drop_off_trip_stop_id: @drop_off_trip_stop_id,
33
+ seat_selections: @seat_selections.map(&:to_h)
34
+ }
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,27 @@
1
+ module SpreeCmCommissioner::Transit
2
+ class SeatSelection
3
+ attr_accessor :variant_id, :quantity, :block_ids
4
+
5
+ def initialize(options = {})
6
+ @variant_id = options[:variant_id]
7
+ @quantity = options[:quantity]&.to_i
8
+ @block_ids = options[:block_ids] || []
9
+ end
10
+
11
+ def self.from_hash(hash)
12
+ new(
13
+ variant_id: hash[:variant_id],
14
+ quantity: hash[:quantity],
15
+ block_ids: hash[:block_ids] || [] # empty when no seat selection.
16
+ )
17
+ end
18
+
19
+ def to_h
20
+ {
21
+ variant_id: @variant_id,
22
+ quantity: @quantity,
23
+ block_ids: @block_ids
24
+ }
25
+ end
26
+ end
27
+ end
@@ -7,8 +7,58 @@ module SpreeCmCommissioner
7
7
  @connection_id = connection_id
8
8
  end
9
9
 
10
+ def id
11
+ @trips.map(&:id).join('-')
12
+ end
13
+
14
+ def trip_ids
15
+ @trips.map(&:id)
16
+ end
17
+
10
18
  def direct?
11
19
  @trips.size == 1
12
20
  end
21
+
22
+ def quantity_available
23
+ @trips.map(&:quantity_available).compact.min
24
+ end
25
+
26
+ def max_capacity
27
+ @trips.map(&:max_capacity).compact.min
28
+ end
29
+
30
+ def total_price
31
+ @trips.map(&:price).compact.sum
32
+ end
33
+
34
+ def total_duration
35
+ @trips.map(&:duration).compact.sum
36
+ end
37
+
38
+ def total_duration_in_hms
39
+ total_seconds = total_duration || 0
40
+ return { hours: 0, minutes: 0, seconds: 0 } if total_seconds.nil? || total_seconds <= 0
41
+
42
+ hours = total_seconds / 3600
43
+ minutes = (total_seconds % 3600) / 60
44
+ seconds = total_seconds % 60
45
+ { hours: hours, minutes: minutes, seconds: seconds }
46
+ end
47
+
48
+ def departure_time
49
+ @trips.first.departure_time
50
+ end
51
+
52
+ def arrival_time
53
+ @trips.last.arrival_time
54
+ end
55
+
56
+ def vendors
57
+ @trips.map(&:vendor).uniq
58
+ end
59
+
60
+ def vehicle_types
61
+ @trips.map(&:vehicle).map(&:vehicle_type).uniq
62
+ end
13
63
  end
14
64
  end