spree_cm_commissioner 2.0.1.pre.pre → 2.0.1.pre.pre2
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.
- checksums.yaml +4 -4
- data/.github/workflows/test_and_build_gem.yml +2 -16
- data/.gitignore +1 -2
- data/Gemfile.lock +1 -28
- data/Rakefile +4 -33
- data/app/assets/images/mailer/mail.png +0 -0
- data/app/assets/images/mailer/tenant_phone.png +0 -0
- data/app/assets/images/mailer/tenant_user.png +0 -0
- data/app/assets/stylesheets/spree_cm_commissioner/backend/calendar.scss +11 -8
- data/app/controllers/concerns/spree_cm_commissioner/transit/taxon_bitwise.rb +44 -0
- data/app/controllers/spree/admin/stock_managements_controller.rb +1 -63
- data/app/controllers/spree/api/v2/organizer/invite_guests_controller.rb +1 -1
- data/app/controllers/spree/api/v2/storefront/accommodations_controller.rb +31 -14
- data/app/controllers/spree/api/v2/storefront/queue_cart/line_items_controller.rb +2 -2
- data/app/factory/spree_cm_commissioner/invite_guest_claimed_telegram_message_factory.rb +22 -80
- data/app/finders/spree_cm_commissioner/line_items/find_by_variant_decorator.rb +20 -0
- data/app/interactors/spree_cm_commissioner/create_ticket.rb +6 -5
- data/app/interactors/spree_cm_commissioner/pin_code_sender.rb +0 -1
- data/app/interactors/spree_cm_commissioner/sms.rb +1 -1
- data/app/interactors/spree_cm_commissioner/user_id_token_authenticator.rb +7 -3
- data/app/interactors/spree_cm_commissioner/user_id_token_checker.rb +11 -3
- data/app/interactors/spree_cm_commissioner/user_identity_checker.rb +12 -6
- data/app/interactors/spree_cm_commissioner/user_registration_with_id_token.rb +7 -1
- data/app/jobs/spree_cm_commissioner/application_job.rb +0 -20
- data/app/jobs/spree_cm_commissioner/application_unique_job.rb +0 -20
- data/app/jobs/spree_cm_commissioner/sms_pin_code_job.rb +1 -1
- data/app/mailers/spree/order_mailer_decorator.rb +18 -3
- data/app/models/concerns/spree_cm_commissioner/line_item_durationable.rb +15 -9
- data/app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb +12 -1
- data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +0 -39
- data/app/models/concerns/spree_cm_commissioner/product_delegation.rb +3 -1
- data/app/models/concerns/spree_cm_commissioner/product_type.rb +0 -10
- data/app/models/concerns/spree_cm_commissioner/taxon_kind.rb +1 -1
- data/app/models/concerns/spree_cm_commissioner/tenant_preference.rb +1 -0
- data/app/models/spree_cm_commissioner/branch.rb +12 -0
- data/app/models/spree_cm_commissioner/guest.rb +0 -18
- data/app/models/spree_cm_commissioner/line_item_decorator.rb +78 -46
- data/app/models/spree_cm_commissioner/line_item_seat.rb +10 -0
- data/app/models/spree_cm_commissioner/notification_taxon.rb +1 -1
- data/app/models/spree_cm_commissioner/option_type_decorator.rb +11 -1
- data/app/models/spree_cm_commissioner/option_value_vehicle_type.rb +8 -0
- data/app/models/spree_cm_commissioner/order_decorator.rb +1 -30
- data/app/models/spree_cm_commissioner/place.rb +4 -1
- data/app/models/spree_cm_commissioner/product_decorator.rb +6 -10
- data/app/models/spree_cm_commissioner/service_calendar.rb +2 -0
- data/app/models/spree_cm_commissioner/state_decorator.rb +1 -0
- data/app/models/spree_cm_commissioner/stock/availability_checker.rb +25 -26
- data/app/models/spree_cm_commissioner/stock/availability_validator_decorator.rb +1 -2
- data/app/models/spree_cm_commissioner/stock/line_item_availability_checker.rb +3 -3
- data/app/models/spree_cm_commissioner/stock_item_decorator.rb +0 -17
- data/app/models/spree_cm_commissioner/stop.rb +23 -0
- data/app/models/spree_cm_commissioner/taxon_decorator.rb +1 -0
- data/app/models/spree_cm_commissioner/taxonomy_decorator.rb +6 -0
- data/app/models/spree_cm_commissioner/trip.rb +10 -8
- data/app/models/spree_cm_commissioner/trip_connection.rb +5 -5
- data/app/models/spree_cm_commissioner/trip_stop.rb +25 -6
- data/app/models/spree_cm_commissioner/user_identity_provider.rb +26 -4
- data/app/models/spree_cm_commissioner/variant_decorator.rb +47 -37
- data/app/models/spree_cm_commissioner/variant_options.rb +23 -0
- data/app/models/spree_cm_commissioner/vehicle.rb +14 -9
- data/app/models/spree_cm_commissioner/vehicle_seat.rb +11 -0
- data/app/models/spree_cm_commissioner/vehicle_type.rb +76 -0
- data/app/models/spree_cm_commissioner/vendor_decorator.rb +17 -11
- data/app/models/spree_cm_commissioner/vendor_place.rb +3 -9
- data/app/models/spree_cm_commissioner/vendor_stop.rb +10 -0
- data/app/queries/spree_cm_commissioner/trip_query.rb +44 -70
- data/app/queries/spree_cm_commissioner/trip_search_query.rb +76 -0
- data/app/queries/spree_cm_commissioner/variant_availability/non_permanent_stock_query.rb +45 -0
- data/app/queries/spree_cm_commissioner/variant_availability/permanent_stock_query.rb +55 -0
- data/app/queries/spree_cm_commissioner/vendor_stop_place_query.rb +54 -0
- data/app/request_schemas/spree_cm_commissioner/accommodation_request_schema.rb +0 -3
- data/app/request_schemas/spree_cm_commissioner/application_request_schema.rb +1 -1
- data/app/serializers/spree/v2/storefront/accommodation_serializer.rb +0 -2
- data/app/serializers/spree/v2/storefront/line_item_serializer_decorator.rb +0 -1
- data/app/serializers/spree/v2/tenant/user_serializer.rb +1 -0
- data/app/services/spree_cm_commissioner/user_authenticator.rb +1 -1
- data/app/services/spree_cm_commissioner/vehicle_option_value_creator.rb +11 -0
- data/app/views/spree/admin/stock_managements/_variant_stock_items.html.erb +2 -7
- data/app/views/spree/admin/stock_managements/index.html.erb +6 -55
- data/app/views/spree/admin/tenants/_form.html.erb +9 -0
- data/app/views/spree/admin/vendors/_form.html.erb +14 -0
- data/app/views/spree/order_mailer/confirm_email.html.erb +27 -16
- data/app/views/spree_cm_commissioner/layouts/order_mailer.html.erb +5 -1
- data/app/views/spree_cm_commissioner/order_mailer/_mailer_stylesheets.html.erb +41 -4
- data/app/views/spree_cm_commissioner/order_mailer/tenant/_customer_info.html.erb +42 -0
- data/app/views/spree_cm_commissioner/order_mailer/tenant/_footer.html.erb +25 -0
- data/app/views/spree_cm_commissioner/order_mailer/tenant/_greeting.html.erb +19 -0
- data/app/views/spree_cm_commissioner/order_mailer/tenant/_support_contact.html.erb +33 -0
- data/config/initializers/spree_permitted_attributes.rb +0 -5
- data/config/routes.rb +2 -21
- data/db/migrate/20240202080634_update_counter_cache_of_vehicle_type.rb +1 -3
- data/db/migrate/20250709073455_add_email_fields_to_spree_vendors.rb +6 -0
- data/db/migrate/20250715103333_remove_indexes_from_cm_user_identity_providers.rb +13 -0
- data/docker-compose.yml +1 -1
- data/lib/cm_app_logger.rb +4 -11
- data/lib/generators/spree_cm_commissioner/install/install_generator.rb +11 -14
- data/lib/generators/spree_cm_commissioner/install/templates/app/javascript/{spree_dashboard/spree_cm_commissioner → spree_cm_commissioner}/utilities.js +0 -4
- data/lib/spree_cm_commissioner/calendar_event.rb +1 -11
- data/lib/spree_cm_commissioner/test_helper/factories/branch_factory.rb +12 -0
- data/lib/spree_cm_commissioner/test_helper/factories/departure_time_option_type_factory.rb +8 -0
- data/lib/spree_cm_commissioner/test_helper/factories/duration_option_type_factory.rb +8 -0
- data/lib/spree_cm_commissioner/test_helper/factories/guest_factory.rb +0 -10
- data/lib/spree_cm_commissioner/test_helper/factories/homepage_section_relatable_factory.rb +1 -1
- data/lib/spree_cm_commissioner/test_helper/factories/line_item_factory.rb +1 -1
- data/lib/spree_cm_commissioner/test_helper/factories/line_item_seat_factory.rb +7 -0
- data/lib/spree_cm_commissioner/test_helper/factories/option_type_factory.rb +30 -6
- data/lib/spree_cm_commissioner/test_helper/factories/order_factory.rb +36 -0
- data/lib/spree_cm_commissioner/test_helper/factories/product_factory.rb +34 -18
- data/lib/spree_cm_commissioner/test_helper/factories/stock_location_factory.rb +2 -2
- data/lib/spree_cm_commissioner/test_helper/factories/stop_factory.rb +14 -0
- data/lib/spree_cm_commissioner/test_helper/factories/transit_place_factory.rb +8 -0
- data/lib/spree_cm_commissioner/test_helper/factories/trip_factory.rb +3 -11
- data/lib/spree_cm_commissioner/test_helper/factories/user_identity_provider_factory.rb +1 -1
- data/lib/spree_cm_commissioner/test_helper/factories/variant_factory.rb +19 -41
- data/lib/spree_cm_commissioner/test_helper/factories/vehicle_factory.rb +1 -1
- data/lib/spree_cm_commissioner/test_helper/factories/vehicle_option_type_factory.rb +8 -0
- data/lib/spree_cm_commissioner/test_helper/factories/vehicle_type_factory.rb +96 -0
- data/lib/spree_cm_commissioner/test_helper/factories/vendor_factory.rb +1 -6
- data/lib/spree_cm_commissioner/test_helper/factories/vendor_place_factory.rb +1 -13
- data/lib/spree_cm_commissioner/trip_query_result.rb +0 -8
- data/lib/spree_cm_commissioner/trip_result.rb +3 -5
- data/lib/spree_cm_commissioner/trip_seat_layout_result.rb +11 -0
- data/lib/spree_cm_commissioner/version.rb +1 -1
- data/lib/spree_cm_commissioner.rb +1 -35
- data/spree_cm_commissioner.gemspec +0 -7
- metadata +35 -139
- data/app/controllers/spree/admin/inventory_items_controller.rb +0 -83
- data/app/controllers/spree/api/v2/storefront/accommodations/variants_controller.rb +0 -42
- data/app/finders/spree_cm_commissioner/accommodations/find.rb +0 -37
- data/app/finders/spree_cm_commissioner/accommodations/find_variant.rb +0 -32
- data/app/interactors/spree_cm_commissioner/ensure_correct_product_type.rb +0 -40
- data/app/interactors/spree_cm_commissioner/inventory_item_syncer.rb +0 -25
- data/app/interactors/spree_cm_commissioner/stock/inventory_item_resetter.rb +0 -44
- data/app/interactors/spree_cm_commissioner/stock/inventory_items_adjuster.rb +0 -13
- data/app/interactors/spree_cm_commissioner/stock/inventory_items_generator.rb +0 -15
- data/app/interactors/spree_cm_commissioner/stock/permanent_inventory_items_generator.rb +0 -75
- data/app/interactors/spree_cm_commissioner/stock/stock_movement_creator.rb +0 -32
- data/app/jobs/spree_cm_commissioner/ensure_correct_product_type_job.rb +0 -7
- data/app/jobs/spree_cm_commissioner/inventory_item_syncer_job.rb +0 -7
- data/app/jobs/spree_cm_commissioner/stock/inventory_items_adjuster_job.rb +0 -11
- data/app/jobs/spree_cm_commissioner/stock/inventory_items_generator_job.rb +0 -11
- data/app/jobs/spree_cm_commissioner/stock/permanent_inventory_items_generator_job.rb +0 -9
- data/app/models/concerns/spree_cm_commissioner/order_seatable.rb +0 -44
- data/app/models/spree_cm_commissioner/block.rb +0 -23
- data/app/models/spree_cm_commissioner/inventory.rb +0 -11
- data/app/models/spree_cm_commissioner/inventory_item.rb +0 -69
- data/app/models/spree_cm_commissioner/price_decorator.rb +0 -9
- data/app/models/spree_cm_commissioner/redis_stock/cached_inventory_items_builder.rb +0 -41
- data/app/models/spree_cm_commissioner/redis_stock/inventory_updater.rb +0 -126
- data/app/models/spree_cm_commissioner/redis_stock/line_items_cached_inventory_items_builder.rb +0 -36
- data/app/models/spree_cm_commissioner/redis_stock/variant_cached_inventory_items_builder.rb +0 -25
- data/app/models/spree_cm_commissioner/reserved_block.rb +0 -30
- data/app/models/spree_cm_commissioner/seat_layout.rb +0 -20
- data/app/models/spree_cm_commissioner/seat_section.rb +0 -16
- data/app/models/spree_cm_commissioner/seats/blocks_canceler.rb +0 -30
- data/app/models/spree_cm_commissioner/seats/blocks_holder.rb +0 -53
- data/app/models/spree_cm_commissioner/seats/blocks_reserver.rb +0 -49
- data/app/models/spree_cm_commissioner/seats/errors/blocks_are_on_hold_by_other_guest.rb +0 -4
- data/app/models/spree_cm_commissioner/seats/errors/blocks_are_reserved_by_other_guest.rb +0 -4
- data/app/models/spree_cm_commissioner/seats/errors/blocks_are_reserved_by_same_guest.rb +0 -4
- data/app/models/spree_cm_commissioner/seats/errors/unable_to_save_reserved_block_record.rb +0 -4
- data/app/models/spree_cm_commissioner/stock/order_availability_checker.rb +0 -44
- data/app/models/spree_cm_commissioner/variant_block.rb +0 -9
- data/app/request_schemas/spree_cm_commissioner/variant_request_schema.rb +0 -19
- data/app/views/spree/admin/inventory_items/show.html.erb +0 -72
- data/app/views/spree/admin/stock_managements/calendar.html.erb +0 -56
- data/config/initializers/paper_trail.rb +0 -1
- data/db/migrate/20250304293518_create_cm_inventory_items.rb +0 -21
- data/db/migrate/20250429094228_add_lock_version_to_cm_inventory_items.rb +0 -5
- data/db/migrate/20250502025848_add_index_to_spree_products.rb +0 -5
- data/db/migrate/20250502030001_add_product_type_to_spree_variants.rb +0 -5
- data/db/migrate/20250502030002_add_product_type_to_spree_line_items.rb +0 -5
- data/db/migrate/20250603035256_add_inventory_item_to_spree_prices.rb +0 -7
- data/db/migrate/20250619073724_drop_table_cm_line_item_seats.rb +0 -5
- data/db/migrate/20250619073812_drop_table_cm_vehicle_seats.rb +0 -5
- data/db/migrate/20250619073844_drop_table_cm_vehicle_types.rb +0 -9
- data/db/migrate/20250619073957_drop_table_cm_option_value_vehicle_types.rb +0 -5
- data/db/migrate/20250619082354_remove_unnecessary_fields_from_cm_places.rb +0 -9
- data/db/migrate/20250619082736_remove_route_type_from_spree_products.rb +0 -5
- data/db/migrate/20250619083055_remove_unnecessary_fields_from_spree_taxons.rb +0 -5
- data/db/migrate/20250620083055_remove_variant_id_from_cm_trips.rb +0 -5
- data/db/migrate/20250620090000_update_cm_trip_connections_to_use_cm_trips.rb +0 -6
- data/db/migrate/20250620090001_create_cm_seat_layouts.rb +0 -17
- data/db/migrate/20250620090002_create_cm_seat_sections.rb +0 -18
- data/db/migrate/20250620090003_create_cm_blocks.rb +0 -18
- data/db/migrate/20250624091005_create_cm_reserved_blocks.rb +0 -29
- data/db/migrate/20250626083642_create_cm_variant_blocks.rb +0 -24
- data/db/migrate/20250627023314_add_block_id_to_cm_guests.rb +0 -13
- data/db/migrate/20250716022821_add_location_reference_to_cm_vendor_places.rb +0 -5
- data/db/migrate/20250716031743_drop_table_cm_vendor_stops.rb +0 -5
- data/db/migrate/20250717023824_add_vendor_reference_to_cm_trips.rb +0 -5
- data/db/migrate/20250717041414_add_location_place_reference_to_cm_trip_stops.rb +0 -5
- data/db/migrate/20250717042539_rename_cm_trip_stops_stop_id_column_to_stop_place_id.rb +0 -7
- data/db/migrate/20250717042707_rename_cm_trips_origin_and_destination_to_origin_place_and_destination_place.rb +0 -11
- data/lib/spree_cm_commissioner/cached_inventory_item.rb +0 -23
- data/lib/spree_cm_commissioner/test_helper/factories/block_factory.rb +0 -15
- data/lib/spree_cm_commissioner/test_helper/factories/inventory_item_factory.rb +0 -9
- data/lib/spree_cm_commissioner/test_helper/factories/reserved_block_factory.rb +0 -27
- data/lib/spree_cm_commissioner/test_helper/factories/seat_layout_factory.rb +0 -11
- data/lib/spree_cm_commissioner/test_helper/factories/seat_section_factory.rb +0 -16
- data/lib/spree_cm_commissioner/test_helper/factories/trip_connection_factory.rb +0 -6
- data/lib/spree_cm_commissioner/test_helper/factories/trip_stop_factory.rb +0 -10
- data/lib/spree_cm_commissioner/test_helper/factories/variant_block_factory.rb +0 -7
- data/lib/tasks/create_default_non_permanent_inventory_items.rake +0 -16
- data/lib/tasks/ensure_correct_product_type.rake +0 -7
- data/lib/tasks/generate_inventory_items.rake +0 -7
@@ -1,37 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
module Accommodations
|
3
|
-
class Find
|
4
|
-
attr_reader :from_date, :to_date, :state_id, :number_of_guests
|
5
|
-
|
6
|
-
def initialize(from_date:, to_date:, state_id:, number_of_adults:, number_of_kids:)
|
7
|
-
@from_date = from_date
|
8
|
-
@to_date = to_date
|
9
|
-
@state_id = state_id
|
10
|
-
@number_of_guests = number_of_adults.to_i + number_of_kids.to_i
|
11
|
-
end
|
12
|
-
|
13
|
-
def execute
|
14
|
-
scope
|
15
|
-
.where(default_state_id: state_id)
|
16
|
-
.where(inventory_items: { inventory_date: stay_dates })
|
17
|
-
.where('CAST(spree_variants.public_metadata->\'cm_options\'->>\'number-of-adults\' AS INTEGER) +
|
18
|
-
CAST(spree_variants.public_metadata->\'cm_options\'->>\'number-of-kids\' AS INTEGER) >= ?', number_of_guests
|
19
|
-
)
|
20
|
-
.where('inventory_items.quantity_available > 0')
|
21
|
-
.distinct
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def scope
|
27
|
-
Spree::Vendor
|
28
|
-
.joins(variants: :inventory_items)
|
29
|
-
.where(primary_product_type: :accommodation, state: :active)
|
30
|
-
end
|
31
|
-
|
32
|
-
def stay_dates
|
33
|
-
from_date..to_date
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
module Accommodations
|
3
|
-
class FindVariant
|
4
|
-
attr_reader :vendor_id, :from_date, :to_date, :number_of_guests
|
5
|
-
|
6
|
-
def initialize(vendor_id:, from_date:, to_date:, number_of_adults:, number_of_kids:)
|
7
|
-
@vendor_id = vendor_id
|
8
|
-
@from_date = from_date
|
9
|
-
@to_date = to_date
|
10
|
-
@number_of_guests = number_of_adults.to_i + number_of_kids.to_i
|
11
|
-
end
|
12
|
-
|
13
|
-
def execute
|
14
|
-
Spree::Variant
|
15
|
-
.joins(:inventory_items)
|
16
|
-
.where(vendor_id: vendor_id)
|
17
|
-
.where(inventory_items: { inventory_date: stay_dates })
|
18
|
-
.where('CAST(public_metadata->\'cm_options\'->>\'number-of-adults\' AS INTEGER) +
|
19
|
-
CAST(public_metadata->\'cm_options\'->>\'number-of-kids\' AS INTEGER) >= ?', number_of_guests
|
20
|
-
)
|
21
|
-
.where('inventory_items.quantity_available > 0')
|
22
|
-
.distinct
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
def stay_dates
|
28
|
-
from_date..to_date
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
class EnsureCorrectProductType < BaseInteractor
|
3
|
-
def call
|
4
|
-
Spree::Product
|
5
|
-
.left_joins(variants_including_master: %i[inventory_items line_items])
|
6
|
-
.where(
|
7
|
-
'spree_variants.product_type IS NULL OR
|
8
|
-
spree_variants.product_type != spree_products.product_type OR
|
9
|
-
|
10
|
-
cm_inventory_items.product_type IS NULL OR
|
11
|
-
cm_inventory_items.product_type != spree_products.product_type OR
|
12
|
-
|
13
|
-
spree_line_items.product_type IS NULL OR
|
14
|
-
spree_line_items.product_type != spree_products.product_type OR
|
15
|
-
|
16
|
-
spree_products.product_type IS NOT NULL
|
17
|
-
'
|
18
|
-
)
|
19
|
-
.distinct.find_each do |product|
|
20
|
-
sync_product_type_for(product)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def sync_product_type_for(product)
|
25
|
-
product_type = Spree::Variant.product_types[product.product_type]
|
26
|
-
|
27
|
-
product.variants_including_master
|
28
|
-
.where('spree_variants.product_type IS NULL OR spree_variants.product_type != ?', product_type)
|
29
|
-
.update_all(product_type: product_type) # rubocop:disable Rails/SkipsModelValidations
|
30
|
-
|
31
|
-
product.line_items
|
32
|
-
.where('spree_line_items.product_type IS NULL OR spree_line_items.product_type != ?', product_type)
|
33
|
-
.update_all(product_type: product_type) # rubocop:disable Rails/SkipsModelValidations
|
34
|
-
|
35
|
-
product.inventory_items
|
36
|
-
.where('cm_inventory_items.product_type IS NULL OR cm_inventory_items.product_type != ?', product_type)
|
37
|
-
.update_all(product_type: product_type) # rubocop:disable Rails/SkipsModelValidations
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
class InventoryItemSyncer < BaseInteractor
|
3
|
-
# inventory_id_and_quantities = [{ inventory_id: inventory_item1.id, quantity: 5 } ]
|
4
|
-
delegate :inventory_id_and_quantities, to: :context
|
5
|
-
|
6
|
-
def call
|
7
|
-
ActiveRecord::Base.transaction do
|
8
|
-
inventory_items.each do |inventory_item|
|
9
|
-
quantity = inventory_id_and_quantities.find { |item| item[:inventory_id] == inventory_item.id }&.dig(:quantity) || 0
|
10
|
-
adjust_quantity_available(inventory_item, quantity)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
def adjust_quantity_available(inventory_item, quantity)
|
18
|
-
inventory_item.update!(quantity_available: inventory_item.quantity_available + quantity)
|
19
|
-
end
|
20
|
-
|
21
|
-
def inventory_items
|
22
|
-
@inventory_items ||= InventoryItem.where(id: inventory_id_and_quantities.pluck(:inventory_id))
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
module Stock
|
3
|
-
class InventoryItemResetter < BaseInteractor
|
4
|
-
delegate :inventory_item, to: :context
|
5
|
-
|
6
|
-
def call
|
7
|
-
max_capacity = variant_total_inventory
|
8
|
-
total_purchases = variant_total_purchases
|
9
|
-
quantity_available = [max_capacity - total_purchases, 0].max
|
10
|
-
|
11
|
-
updated = inventory_item.update(max_capacity: max_capacity, quantity_available: quantity_available)
|
12
|
-
return context.fail!(message: 'Failed to update inventory item', errors: inventory_item.errors.full_messages) unless updated
|
13
|
-
|
14
|
-
clear_inventory_cache
|
15
|
-
end
|
16
|
-
|
17
|
-
def variant_total_inventory
|
18
|
-
# for shipment, total_on_hand is not orignal stock. shipment does subtract the stock.
|
19
|
-
# to get desire result, we need to add to total_purchase.
|
20
|
-
if inventory_item.variant.delivery_required?
|
21
|
-
inventory_item.variant.total_on_hand.to_i + variant_total_purchases
|
22
|
-
else
|
23
|
-
inventory_item.variant.total_on_hand.to_i
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def variant_total_purchases
|
28
|
-
scope = inventory_item.variant.complete_line_items
|
29
|
-
|
30
|
-
if inventory_item.permanent_stock?
|
31
|
-
scope.where('? BETWEEN from_date AND to_date', inventory_item.inventory_date).sum(:quantity).to_i
|
32
|
-
else
|
33
|
-
scope.sum(:quantity).to_i
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def clear_inventory_cache
|
38
|
-
SpreeCmCommissioner.redis_pool.with do |redis|
|
39
|
-
redis.del(inventory_item.redis_key)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
module Stock
|
3
|
-
class InventoryItemsAdjuster < BaseInteractor
|
4
|
-
delegate :variant, :quantity, to: :context
|
5
|
-
|
6
|
-
def call
|
7
|
-
variant.inventory_items.active.find_each do |inventory_item|
|
8
|
-
inventory_item.adjust_quantity!(quantity)
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
module Stock
|
3
|
-
class InventoryItemsGenerator < BaseInteractor
|
4
|
-
delegate :variant, to: :context
|
5
|
-
|
6
|
-
def call
|
7
|
-
if variant.permanent_stock?
|
8
|
-
SpreeCmCommissioner::Stock::PermanentInventoryItemsGenerator.call(variant_ids: [variant.id])
|
9
|
-
else
|
10
|
-
variant.create_default_non_permanent_inventory_item! unless variant.default_inventory_item_exist?
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,75 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
module Stock
|
3
|
-
class PermanentInventoryItemsGenerator < BaseInteractor
|
4
|
-
delegate :variant_ids, to: :context
|
5
|
-
|
6
|
-
def variants_per_batch = 1000
|
7
|
-
|
8
|
-
def pre_inventory_days_for(variant)
|
9
|
-
context.pre_inventory_days || variant.pre_inventory_days
|
10
|
-
end
|
11
|
-
|
12
|
-
def call
|
13
|
-
variants.in_batches(of: variants_per_batch) do |batch|
|
14
|
-
generate_inventory_items_for_batch(batch)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def generate_inventory_items_for_batch(batch)
|
21
|
-
total_on_hand_by_variant = total_on_hand_for(batch)
|
22
|
-
batch.each do |variant|
|
23
|
-
count_on_hand = total_on_hand_by_variant[variant.id] || 0
|
24
|
-
generate_inventory_items_for_variant(variant, count_on_hand)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def generate_inventory_items_for_variant(variant, count_on_hand)
|
29
|
-
inventory_dates_for(variant).each do |inventory_date|
|
30
|
-
next if inventory_exist?(variant, inventory_date)
|
31
|
-
|
32
|
-
create_inventory_item(variant, inventory_date, count_on_hand)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def inventory_dates_for(variant)
|
37
|
-
start_date = Time.zone.tomorrow
|
38
|
-
end_date = Time.zone.today + pre_inventory_days_for(variant)
|
39
|
-
|
40
|
-
(start_date..end_date)
|
41
|
-
end
|
42
|
-
|
43
|
-
def inventory_exist?(variant, inventory_date)
|
44
|
-
variant.inventory_items.exists?(inventory_date: inventory_date)
|
45
|
-
end
|
46
|
-
|
47
|
-
def create_inventory_item(variant, inventory_date, count_on_hand)
|
48
|
-
variant.inventory_items.create!(
|
49
|
-
inventory_date: inventory_date,
|
50
|
-
quantity_available: count_on_hand,
|
51
|
-
max_capacity: count_on_hand,
|
52
|
-
product_type: variant.product_type
|
53
|
-
)
|
54
|
-
end
|
55
|
-
|
56
|
-
# Returns a hash: { variant_id => total_on_hand, ... }
|
57
|
-
def total_on_hand_for(variants)
|
58
|
-
variant_ids = variants.pluck(:id)
|
59
|
-
|
60
|
-
Spree::StockItem
|
61
|
-
.joins(:stock_location)
|
62
|
-
.where(deleted_at: nil, variant_id: variant_ids)
|
63
|
-
.where(spree_stock_locations: { active: true })
|
64
|
-
.group(:variant_id)
|
65
|
-
.sum(:count_on_hand)
|
66
|
-
end
|
67
|
-
|
68
|
-
def variants
|
69
|
-
scope = Spree::Variant.active.with_permanent_stock.where(is_master: false)
|
70
|
-
scope = scope.where(id: variant_ids) if variant_ids.present?
|
71
|
-
scope
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
module Stock
|
3
|
-
class StockMovementCreator < BaseInteractor
|
4
|
-
delegate :variant_id, :stock_location_id, :current_store, :stock_movement_params, to: :context
|
5
|
-
|
6
|
-
def call
|
7
|
-
variant = current_store.variants.find(variant_id)
|
8
|
-
|
9
|
-
return context.fail!(message: Spree.t(:doesnt_track_inventory)) unless variant.track_inventory?
|
10
|
-
|
11
|
-
stock_location = Spree::StockLocation.find(stock_location_id)
|
12
|
-
stock_movement = stock_location.stock_movements.build(stock_movement_params)
|
13
|
-
stock_movement.stock_item = stock_location.set_up_stock_item(variant)
|
14
|
-
|
15
|
-
if stock_movement.save
|
16
|
-
adjust_inventory_items_async(variant_id, stock_movement.quantity)
|
17
|
-
context.stock_movement = stock_movement
|
18
|
-
else
|
19
|
-
context.fail!(message: stock_movement.errors.full_messages.join(', '))
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def adjust_inventory_items_async(variant_id, quantity)
|
26
|
-
CmAppLogger.log(label: "#{self.class.name}#adjust_inventory_items_async", data: { variant_id: variant_id, quantity: quantity }) do
|
27
|
-
SpreeCmCommissioner::Stock::InventoryItemsAdjusterJob.perform_later(variant_id: variant_id, quantity: quantity)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,11 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
module Stock
|
3
|
-
class InventoryItemsAdjusterJob < ApplicationUniqueJob
|
4
|
-
def perform(variant_id:, quantity:)
|
5
|
-
variant = Spree::Variant.find(variant_id)
|
6
|
-
|
7
|
-
SpreeCmCommissioner::Stock::InventoryItemsAdjuster.call(variant: variant, quantity: quantity)
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
@@ -1,11 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
module Stock
|
3
|
-
class InventoryItemsGeneratorJob < ApplicationUniqueJob
|
4
|
-
def perform(variant_id:)
|
5
|
-
variant = Spree::Variant.find(variant_id)
|
6
|
-
|
7
|
-
SpreeCmCommissioner::Stock::InventoryItemsGenerator.call(variant: variant)
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
module OrderSeatable
|
3
|
-
def should_manage_blocks?
|
4
|
-
preload_block_ids.any?
|
5
|
-
end
|
6
|
-
|
7
|
-
def hold_blocks!
|
8
|
-
return unless should_manage_blocks?
|
9
|
-
|
10
|
-
CmAppLogger.log(label: "#{self.class.name}#hold_blocks!", data: { order_id: id }) do
|
11
|
-
SpreeCmCommissioner::Seats::BlocksHolder.new(line_item_ids: line_item_ids, hold_by: user).hold_blocks!
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def cancel_blocks!
|
16
|
-
return unless should_manage_blocks?
|
17
|
-
|
18
|
-
CmAppLogger.log(label: "#{self.class.name}#cancel_blocks!", data: { order_id: id }) do
|
19
|
-
SpreeCmCommissioner::Seats::BlocksCanceler.new(order_id: id, cancel_by: user).cancel_blocks!
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def reserve_blocks!
|
24
|
-
return unless should_manage_blocks?
|
25
|
-
|
26
|
-
CmAppLogger.log(label: "#{self.class.name}#reserve_blocks!", data: { order_id: id }) do
|
27
|
-
SpreeCmCommissioner::Seats::BlocksReserver.new(line_item_ids: line_item_ids, reserve_by: user).reserve_blocks!
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
# Calling `.block_ids` directly can cause many slow database queries (N+1 problem)
|
32
|
-
# every time `.should_manage_blocks?` or `.preload_block_ids` runs.
|
33
|
-
# To avoid this, we store a precomputed list of block IDs in `private_metadata`.
|
34
|
-
# This list is updated whenever a guest’s block is saved or destroy.
|
35
|
-
def preload_block_ids=(preload_block_ids = [])
|
36
|
-
self.private_metadata ||= {}
|
37
|
-
self.private_metadata['preload_block_ids'] = preload_block_ids
|
38
|
-
end
|
39
|
-
|
40
|
-
def preload_block_ids
|
41
|
-
self.private_metadata&.fetch('preload_block_ids', []) || []
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
class Block < Base
|
3
|
-
belongs_to :seat_section, class_name: 'SpreeCmCommissioner::SeatSection', optional: true
|
4
|
-
belongs_to :seat_layout, class_name: 'SpreeCmCommissioner::SeatLayout', optional: false
|
5
|
-
|
6
|
-
validates :label, presence: true
|
7
|
-
|
8
|
-
has_many :variant_blocks, class_name: 'SpreeCmCommissioner::VariantBlock', dependent: :destroy
|
9
|
-
has_many :variants, class_name: 'Spree::Variant', through: :variant_blocks
|
10
|
-
|
11
|
-
validates :width, presence: true, numericality: { greater_than: 0 }
|
12
|
-
validates :height, presence: true, numericality: { greater_than: 0 }
|
13
|
-
validates :x, presence: true, numericality: true
|
14
|
-
validates :y, presence: true, numericality: true
|
15
|
-
validates :rotation, presence: true, numericality: { greater_than_or_equal_to: -360, less_than_or_equal_to: 360 }
|
16
|
-
|
17
|
-
before_validation :assign_layout_from_section, if: -> { seat_layout.nil? && seat_section.present? }
|
18
|
-
|
19
|
-
def assign_layout_from_section
|
20
|
-
self.seat_layout = seat_section.seat_layout
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,11 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
class Inventory
|
3
|
-
include ActiveModel::Model
|
4
|
-
|
5
|
-
attr_accessor :variant_id, :inventory_date, :quantity_available, :max_capacity, :product_type
|
6
|
-
|
7
|
-
validates :variant_id, presence: true
|
8
|
-
validates :quantity_available, numericality: { only_integer: true, greater_than_or_equal_to: 0 }, allow_nil: true
|
9
|
-
validates :max_capacity, numericality: { only_integer: true, greater_than_or_equal_to: 0 }, allow_nil: true
|
10
|
-
end
|
11
|
-
end
|
@@ -1,69 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
class InventoryItem < Base
|
3
|
-
include SpreeCmCommissioner::ProductType
|
4
|
-
|
5
|
-
# Association
|
6
|
-
belongs_to :variant, class_name: 'Spree::Variant', optional: false
|
7
|
-
has_many :prices, class_name: 'Spree::Price', inverse_of: :inventory_item
|
8
|
-
|
9
|
-
# Validation
|
10
|
-
validates :quantity_available, numericality: { greater_than_or_equal_to: 0 }
|
11
|
-
validates :max_capacity, numericality: { greater_than_or_equal_to: 0 } # Originally inventory of each variant.
|
12
|
-
validates :inventory_date, presence: true, if: :permanent_stock?
|
13
|
-
validates :variant_id, uniqueness: { scope: :inventory_date, message: -> (object, _data) { "The variant is taken on #{object.inventory_date}" } }
|
14
|
-
|
15
|
-
# Scope
|
16
|
-
scope :active, -> { where(inventory_date: nil).or(where('inventory_date >= ?', Time.zone.today)) }
|
17
|
-
|
18
|
-
before_save -> { self.product_type = variant.product_type }, if: -> { product_type.nil? }
|
19
|
-
|
20
|
-
# This method is only used when admin update stock
|
21
|
-
def adjust_quantity!(quantity)
|
22
|
-
with_lock do
|
23
|
-
self.max_capacity = [max_capacity + quantity, 0].max
|
24
|
-
self.quantity_available = [quantity_available + quantity, 0].max
|
25
|
-
save!
|
26
|
-
|
27
|
-
# When user has been searched or booked a product, it has cached the quantity in redis,
|
28
|
-
# So we need to update redis cache if inventory key has been created in redis
|
29
|
-
adjust_quantity_in_redis(quantity)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def redis_key
|
34
|
-
"inventory:#{id}"
|
35
|
-
end
|
36
|
-
|
37
|
-
def adjust_quantity_in_redis(quantity)
|
38
|
-
SpreeCmCommissioner.redis_pool.with do |redis|
|
39
|
-
cached_quantity_available = redis.get(redis_key)
|
40
|
-
# ignore if redis doesn't exist
|
41
|
-
return if cached_quantity_available.nil? # rubocop:disable Lint/NonLocalExitFromIterator
|
42
|
-
|
43
|
-
script = <<~LUA
|
44
|
-
local key = KEYS[1]
|
45
|
-
local increment = tonumber(ARGV[1])
|
46
|
-
local current = tonumber(redis.call('GET', key) or 0)
|
47
|
-
local new_value = current + increment
|
48
|
-
if new_value < 0 then
|
49
|
-
new_value = 0
|
50
|
-
end
|
51
|
-
redis.call('SET', key, new_value)
|
52
|
-
return new_value
|
53
|
-
LUA
|
54
|
-
|
55
|
-
redis.eval(script, keys: [redis_key], argv: [quantity])
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def active?
|
60
|
-
inventory_date.nil? || inventory_date >= Time.zone.today
|
61
|
-
end
|
62
|
-
|
63
|
-
def redis_expired_in
|
64
|
-
expired_in = 31_536_000 # 1 year for normal stock
|
65
|
-
expired_in = Time.parse(inventory_date.to_s).end_of_day.to_i - Time.zone.now.to_i if inventory_date.present?
|
66
|
-
[expired_in, 0].max
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
@@ -1,9 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
module PriceDecorator
|
3
|
-
def self.prepended(base)
|
4
|
-
base.belongs_to :inventory_item, class_name: 'SpreeCmCommissioner::InventoryItem', inverse_of: :prices, optional: true
|
5
|
-
end
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
Spree::Price.prepend(SpreeCmCommissioner::PriceDecorator) unless Spree::Price.included_modules.include?(SpreeCmCommissioner::PriceDecorator)
|
@@ -1,41 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
module RedisStock
|
3
|
-
class CachedInventoryItemsBuilder
|
4
|
-
attr_reader :inventory_items
|
5
|
-
|
6
|
-
def initialize(inventory_items)
|
7
|
-
@inventory_items = inventory_items
|
8
|
-
end
|
9
|
-
|
10
|
-
# output: [ CachedInventoryItem(...), CachedInventoryItem(...) ]
|
11
|
-
def call
|
12
|
-
keys = inventory_items.map { |item| "inventory:#{item.id}" }
|
13
|
-
return [] unless keys.any?
|
14
|
-
|
15
|
-
counts = SpreeCmCommissioner.redis_pool.with { |redis| redis.mget(*keys) }
|
16
|
-
inventory_items.map.with_index do |inventory_item, i|
|
17
|
-
::SpreeCmCommissioner::CachedInventoryItem.new(
|
18
|
-
inventory_key: keys[i],
|
19
|
-
active: inventory_item.active?,
|
20
|
-
quantity_available: cache_inventory(keys[i], inventory_item, counts[i]),
|
21
|
-
inventory_item_id: inventory_item.id,
|
22
|
-
variant_id: inventory_item.variant_id
|
23
|
-
)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def cache_inventory(key, inventory_item, count_in_redis)
|
30
|
-
return count_in_redis.to_i if count_in_redis.present?
|
31
|
-
return inventory_item.quantity_available unless inventory_item.active?
|
32
|
-
|
33
|
-
SpreeCmCommissioner.redis_pool.with do |redis|
|
34
|
-
redis.set(key, inventory_item.quantity_available, ex: inventory_item.redis_expired_in)
|
35
|
-
end
|
36
|
-
|
37
|
-
inventory_item.quantity_available
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|