spree_cm_commissioner 2.0.0.pre.pre → 2.0.0.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.
- checksums.yaml +4 -4
- data/.env.example +3 -0
- data/.github/workflows/test_and_build_gem.yml +2 -16
- data/.gitignore +1 -2
- data/Gemfile.lock +1 -32
- data/Rakefile +4 -33
- data/app/assets/images/cm-hangmeas-checkout_image.svg +63 -0
- data/app/assets/images/cm-hangmeas-failed.svg +56 -0
- data/app/assets/images/cm-hangmeas-loader.svg +50 -0
- data/app/assets/images/cm-hangmeas-success.svg +51 -0
- 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/javascripts/spree_cm_commissioner/backend.js +1 -0
- data/app/assets/javascripts/spree_cm_commissioner/tenant_payment_icon_fields.js +65 -0
- data/app/assets/stylesheets/spree_cm_commissioner/backend/calendar.scss +11 -8
- data/app/assets/stylesheets/spree_cm_commissioner/backend/commissioner_admin.css.scss +1 -0
- data/app/assets/stylesheets/spree_cm_commissioner/backend/tenant_payment_icon_fields.scss +60 -0
- data/app/controllers/concerns/spree_cm_commissioner/content_cachable.rb +2 -1
- data/app/controllers/concerns/spree_cm_commissioner/transit/taxon_bitwise.rb +44 -0
- data/app/controllers/spree/admin/event_blazer_queries_controller.rb +11 -4
- data/app/controllers/spree/admin/stock_managements_controller.rb +1 -63
- data/app/controllers/spree/admin/tenants_controller.rb +8 -0
- data/app/controllers/spree/admin/trip_blazer_queries_controller.rb +35 -0
- data/app/controllers/spree/api/v2/operator/pie_chart_events_controller.rb +46 -0
- data/app/controllers/spree/api/v2/organizer/invite_crews_controller.rb +33 -0
- 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/dynamic_field_options_controller.rb +5 -1
- data/app/controllers/spree/api/v2/storefront/guests_controller.rb +30 -4
- data/app/controllers/spree/api/v2/storefront/queue_cart/line_items_controller.rb +2 -2
- data/app/controllers/spree/api/v2/tenant/checkout_controller.rb +2 -0
- data/app/controllers/spree_cm_commissioner/admin/variants_controller_decorator.rb +1 -1
- data/app/controllers/spree_cm_commissioner/api/v2/storefront/checkout_controller_decorator.rb +11 -0
- data/app/controllers/spree_cm_commissioner/well_known_controller.rb +31 -17
- data/app/factory/spree_cm_commissioner/invite_guest_claimed_telegram_message_factory.rb +24 -81
- data/app/finders/spree_cm_commissioner/line_items/find_by_variant_decorator.rb +20 -0
- data/app/interactors/spree_cm_commissioner/apple_app_site_association_fetcher.rb +27 -0
- data/app/interactors/spree_cm_commissioner/asset_links_fetcher.rb +27 -0
- data/app/interactors/spree_cm_commissioner/create_ticket.rb +6 -5
- data/app/interactors/spree_cm_commissioner/create_vendor.rb +44 -0
- data/app/interactors/spree_cm_commissioner/crew_invite_link_handler.rb +48 -0
- 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/telegram_chats_auto_finder.rb +144 -0
- 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/interactors/spree_cm_commissioner/vattanac_bank_initiator.rb +5 -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/event_check_in_flowable.rb +30 -0
- data/app/models/concerns/spree_cm_commissioner/line_item_durationable.rb +33 -9
- data/app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb +13 -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 +5 -0
- data/app/models/concerns/spree_cm_commissioner/variant_options_concern.rb +4 -2
- data/app/models/spree_cm_commissioner/blazer_queryable.rb +8 -0
- data/app/models/spree_cm_commissioner/branch.rb +12 -0
- data/app/models/spree_cm_commissioner/chart_type.rb +10 -0
- data/app/models/spree_cm_commissioner/crew_invite_link.rb +4 -0
- data/app/models/spree_cm_commissioner/dynamic_field.rb +37 -3
- data/app/models/spree_cm_commissioner/dynamic_field_option.rb +7 -1
- data/app/models/spree_cm_commissioner/guest.rb +57 -19
- data/app/models/spree_cm_commissioner/guest_dynamic_field.rb +61 -3
- data/app/models/spree_cm_commissioner/invite.rb +4 -6
- data/app/models/spree_cm_commissioner/invite_team.rb +3 -1
- 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/pin_code.rb +3 -2
- data/app/models/spree_cm_commissioner/pin_code_telegram.rb +28 -0
- data/app/models/spree_cm_commissioner/place.rb +3 -1
- data/app/models/spree_cm_commissioner/product_decorator.rb +26 -10
- data/app/models/spree_cm_commissioner/promotion_category_decorator.rb +11 -0
- 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 +6 -2
- data/app/models/spree_cm_commissioner/taxonomy_decorator.rb +6 -0
- data/app/models/spree_cm_commissioner/telegram_chat.rb +6 -0
- data/app/models/spree_cm_commissioner/trip.rb +10 -12
- data/app/models/spree_cm_commissioner/trip_connection.rb +5 -5
- data/app/models/spree_cm_commissioner/trip_stop.rb +3 -2
- data/app/models/spree_cm_commissioner/user_decorator.rb +6 -0
- data/app/models/spree_cm_commissioner/user_identity_provider.rb +26 -4
- data/app/models/spree_cm_commissioner/user_taxon.rb +1 -0
- data/app/models/spree_cm_commissioner/variant_decorator.rb +47 -36
- 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 +13 -7
- data/app/models/spree_cm_commissioner/vendor_place.rb +5 -6
- data/app/models/spree_cm_commissioner/vendor_stop.rb +2 -1
- data/app/overrides/spree/admin/taxons/_form/check_in_flows.html.erb.deface +18 -0
- data/app/overrides/spree/admin/variants/_form/kyc_field.html.erb.deface +2 -2
- data/app/queries/spree_cm_commissioner/guest_searcher_query.rb +45 -3
- data/app/queries/spree_cm_commissioner/pie_chart_event_queries.rb +179 -0
- data/app/queries/spree_cm_commissioner/trip_query.rb +26 -23
- 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/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/serializables/spree_cm_commissioner/pie_chart_event.rb +11 -0
- data/app/serializers/spree/v2/organizer/invite_crews_serializer.rb +11 -0
- 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/serializers/spree_cm_commissioner/v2/operator/chart_type_serializer.rb +10 -0
- data/app/serializers/spree_cm_commissioner/v2/operator/dashboard_crew_event_serializer.rb +4 -1
- data/app/serializers/spree_cm_commissioner/v2/storefront/dynamic_field_option_serializer.rb +1 -3
- data/app/serializers/spree_cm_commissioner/v2/storefront/dynamic_field_serializer.rb +1 -3
- data/app/serializers/spree_cm_commissioner/v2/storefront/guest_dynamic_field_serializer.rb +2 -1
- data/app/services/spree_cm_commissioner/organizer/export_guest_csv_service.rb +23 -15
- 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/blazer/queries/_content.html.erb +8 -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/tenant_vendors/index.html.erb +9 -2
- data/app/views/spree/admin/tenants/_form.html.erb +118 -42
- data/app/views/spree/admin/tenants/edit.html.erb +2 -1
- data/app/views/spree/admin/tenants/index.html.erb +7 -1
- 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 +2 -5
- data/config/locales/en.yml +10 -1
- data/config/routes.rb +7 -22
- data/db/migrate/20240202080634_update_counter_cache_of_vehicle_type.rb +1 -3
- data/db/migrate/20250616084219_add_description_to_cm_vendor_place.rb +5 -0
- data/db/migrate/20250630103536_create_cm_telegram_chats.rb +13 -0
- data/db/migrate/20250701093203_add_configurations_to_cm_dynamic_field.rb +6 -0
- data/db/migrate/20250702091305_add_dynamic_field_option_to_guest_dynamic_field.rb +5 -0
- data/db/migrate/20250702091935_add_status_to_dynamic_field_option.rb +5 -0
- data/db/migrate/20250707032008_add_vendor_id_to_spree_category.rb +7 -0
- data/db/migrate/20250709073455_add_email_fields_to_spree_vendors.rb +6 -0
- data/db/migrate/20250711092937_add_position_to_cm_dynamic_fields.rb +11 -0
- data/db/migrate/20250711093045_add_position_to_cm_dynamic_field_options.rb +11 -0
- data/db/migrate/20250714121508_rename_cm_taxon_blazer_query_to_blazer_queryables.rb +7 -0
- data/db/migrate/20250714124323_make_cm_blazer_queryables_polymorphic.rb +19 -0
- data/db/migrate/20250715103333_remove_indexes_from_cm_user_identity_providers.rb +13 -0
- data/db/migrate/20250718071620_add_data_fill_stage_to_dynamic_fields.rb +5 -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 -10
- 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 -1
- 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 +70 -133
- 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/taxon_blazer_query.rb +0 -8
- 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/lib/spree_cm_commissioner/cached_inventory_item.rb +0 -23
- data/lib/spree_cm_commissioner/test_helper/factories/block_factory.rb +0 -9
- 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 -8
- data/lib/spree_cm_commissioner/test_helper/factories/seat_section_factory.rb +0 -8
- data/lib/spree_cm_commissioner/test_helper/factories/trip_connection_factory.rb +0 -6
- 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,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
|
@@ -1,126 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
module RedisStock
|
3
|
-
class InventoryUpdater
|
4
|
-
class UnableToRestock < StandardError; end
|
5
|
-
class UnableToUnstock < StandardError; end
|
6
|
-
|
7
|
-
def initialize(line_item_ids)
|
8
|
-
@line_item_ids = line_item_ids
|
9
|
-
end
|
10
|
-
|
11
|
-
def unstock!
|
12
|
-
keys, quantities, inventory_ids = extract_inventory_data
|
13
|
-
|
14
|
-
raise UnableToUnstock, Spree.t(:insufficient_stock_lines_present) unless unstock(keys, quantities)
|
15
|
-
|
16
|
-
inventory_id_and_quantities = inventory_ids.map.with_index do |inventory_id, i|
|
17
|
-
{ inventory_id: inventory_id, quantity: -quantities[i] }
|
18
|
-
end
|
19
|
-
|
20
|
-
schedule_sync_inventory(inventory_id_and_quantities)
|
21
|
-
end
|
22
|
-
|
23
|
-
def restock!
|
24
|
-
keys, quantities, inventory_ids = extract_inventory_data
|
25
|
-
|
26
|
-
raise UnableToRestock unless restock(keys, quantities)
|
27
|
-
|
28
|
-
inventory_id_and_quantities = inventory_ids.map.with_index do |inventory_id, i|
|
29
|
-
{ inventory_id: inventory_id, quantity: quantities[i] }
|
30
|
-
end
|
31
|
-
|
32
|
-
schedule_sync_inventory(inventory_id_and_quantities)
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
# only unstock or restock when variants is available, track inventory, not backorderable & not need_confirmation.
|
38
|
-
# otherwise, we can ignore them.
|
39
|
-
def line_items
|
40
|
-
return @line_items if defined?(@line_items)
|
41
|
-
|
42
|
-
@line_items = Spree::LineItem.where(id: @line_item_ids).includes(variant: :stock_items)
|
43
|
-
@line_items = @line_items.map do |line_item|
|
44
|
-
next unless line_item.variant.available?
|
45
|
-
next unless line_item.variant.should_track_inventory?
|
46
|
-
next if line_item.variant.backorderable?
|
47
|
-
next if line_item.variant.need_confirmation?
|
48
|
-
|
49
|
-
line_item
|
50
|
-
end.compact
|
51
|
-
end
|
52
|
-
|
53
|
-
def unstock(keys, quantities)
|
54
|
-
SpreeCmCommissioner.redis_pool.with do |redis|
|
55
|
-
redis.eval(unstock_redis_script, keys: keys, argv: quantities)
|
56
|
-
end.positive?
|
57
|
-
end
|
58
|
-
|
59
|
-
def restock(keys, quantities)
|
60
|
-
SpreeCmCommissioner.redis_pool.with do |redis|
|
61
|
-
redis.eval(restock_redis_script, keys: keys, argv: quantities)
|
62
|
-
end.positive?
|
63
|
-
end
|
64
|
-
|
65
|
-
# Return: [CachedInventoryItem(...), CachedInventoryItem(...)]
|
66
|
-
def cached_inventory_items
|
67
|
-
@cached_inventory_items ||= SpreeCmCommissioner::RedisStock::LineItemsCachedInventoryItemsBuilder.new(line_item_ids: line_items.pluck(:id))
|
68
|
-
.call.values.flatten
|
69
|
-
end
|
70
|
-
|
71
|
-
def extract_inventory_data
|
72
|
-
keys = []
|
73
|
-
quantities = []
|
74
|
-
inventory_ids = []
|
75
|
-
|
76
|
-
cached_inventory_items.each do |cached_inventory_item|
|
77
|
-
keys << cached_inventory_item.inventory_key
|
78
|
-
quantities << line_items.find { |item| item.variant_id == cached_inventory_item.variant_id }.quantity
|
79
|
-
inventory_ids << cached_inventory_item.inventory_item_id
|
80
|
-
end
|
81
|
-
|
82
|
-
[keys, quantities, inventory_ids]
|
83
|
-
end
|
84
|
-
|
85
|
-
def unstock_redis_script
|
86
|
-
<<~LUA
|
87
|
-
local keys = KEYS
|
88
|
-
local quantities = ARGV
|
89
|
-
|
90
|
-
-- Check availability first
|
91
|
-
for i, key in ipairs(keys) do
|
92
|
-
local current = tonumber(redis.call('GET', key) or 0)
|
93
|
-
if current - tonumber(quantities[i]) < 0 then
|
94
|
-
return 0
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
-- Apply updates
|
99
|
-
for i, key in ipairs(keys) do
|
100
|
-
redis.call('DECRBY', key, tonumber(quantities[i]))
|
101
|
-
end
|
102
|
-
|
103
|
-
return 1
|
104
|
-
LUA
|
105
|
-
end
|
106
|
-
|
107
|
-
def restock_redis_script
|
108
|
-
<<~LUA
|
109
|
-
local keys = KEYS
|
110
|
-
local quantities = ARGV
|
111
|
-
|
112
|
-
-- Apply restock updates
|
113
|
-
for i, key in ipairs(keys) do
|
114
|
-
redis.call('INCRBY', key, tonumber(quantities[i]))
|
115
|
-
end
|
116
|
-
|
117
|
-
return 1
|
118
|
-
LUA
|
119
|
-
end
|
120
|
-
|
121
|
-
def schedule_sync_inventory(inventory_id_and_quantities)
|
122
|
-
SpreeCmCommissioner::InventoryItemSyncerJob.perform_later(inventory_id_and_quantities:)
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
data/app/models/spree_cm_commissioner/redis_stock/line_items_cached_inventory_items_builder.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
module RedisStock
|
3
|
-
class LineItemsCachedInventoryItemsBuilder
|
4
|
-
attr_reader :line_item_ids
|
5
|
-
|
6
|
-
def initialize(line_item_ids:)
|
7
|
-
@line_item_ids = line_item_ids
|
8
|
-
end
|
9
|
-
|
10
|
-
# return list of inventory items group by :line_item_id:
|
11
|
-
# {
|
12
|
-
# 1: [ CachedInventoryItem(...), CachedInventoryItem(...) ],
|
13
|
-
# 2: [ CachedInventoryItem(...), CachedInventoryItem(...) ],
|
14
|
-
# }
|
15
|
-
def call
|
16
|
-
cached_inventory_items.group_by do |cached_inventory_item|
|
17
|
-
line_item = line_items.find { |item| item.variant_id == cached_inventory_item.variant_id }
|
18
|
-
line_item.id
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def cached_inventory_items
|
23
|
-
@cached_inventory_items ||= SpreeCmCommissioner::RedisStock::CachedInventoryItemsBuilder.new(inventory_items)
|
24
|
-
.call
|
25
|
-
end
|
26
|
-
|
27
|
-
def inventory_items
|
28
|
-
@inventory_items ||= line_items.flat_map(&:inventory_items)
|
29
|
-
end
|
30
|
-
|
31
|
-
def line_items
|
32
|
-
@line_items ||= Spree::LineItem.where(id: line_item_ids).includes(:inventory_items)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
module RedisStock
|
3
|
-
class VariantCachedInventoryItemsBuilder
|
4
|
-
attr_reader :variant_id, :dates
|
5
|
-
|
6
|
-
def initialize(variant_id:, dates: [])
|
7
|
-
@variant_id = variant_id
|
8
|
-
@dates = dates
|
9
|
-
end
|
10
|
-
|
11
|
-
# output: [ CachedInventoryItem(...), CachedInventoryItem(...) ]
|
12
|
-
def call
|
13
|
-
::SpreeCmCommissioner::RedisStock::CachedInventoryItemsBuilder.new(inventory_items).call
|
14
|
-
end
|
15
|
-
|
16
|
-
def inventory_items
|
17
|
-
variant = Spree::Variant.find(variant_id)
|
18
|
-
|
19
|
-
inventory_items = variant.inventory_items
|
20
|
-
inventory_items = inventory_items.where(inventory_date: dates) if variant.permanent_stock?
|
21
|
-
inventory_items
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
class ReservedBlock < Base
|
3
|
-
has_paper_trail
|
4
|
-
|
5
|
-
belongs_to :updated_by, optional: true, class_name: 'Spree::User'
|
6
|
-
belongs_to :guest, optional: true, class_name: 'SpreeCmCommissioner::Guest'
|
7
|
-
belongs_to :inventory_item, class_name: 'SpreeCmCommissioner::InventoryItem'
|
8
|
-
belongs_to :block, class_name: 'SpreeCmCommissioner::Block'
|
9
|
-
|
10
|
-
enum status: {
|
11
|
-
reserved: 0, # confirmed reservation
|
12
|
-
on_hold: 1, # temporary hold
|
13
|
-
canceled: 2
|
14
|
-
}
|
15
|
-
|
16
|
-
validates :status, presence: true
|
17
|
-
validates :expired_at, presence: true, if: -> { on_hold? }
|
18
|
-
|
19
|
-
scope :active_on_hold, -> { on_hold.where('expired_at IS NULL OR expired_at > ?', Time.current) }
|
20
|
-
scope :active, -> { where('expired_at IS NULL OR expired_at > ?', Time.current) }
|
21
|
-
|
22
|
-
def expired?
|
23
|
-
expired_at.present? && expired_at <= Time.current
|
24
|
-
end
|
25
|
-
|
26
|
-
def active_on_hold?
|
27
|
-
on_hold? && !expired?
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
class SeatLayout < Base
|
3
|
-
has_many :seat_sections, class_name: 'SpreeCmCommissioner::SeatSection', dependent: :destroy
|
4
|
-
|
5
|
-
has_many :top_level_blocks, -> { where(seat_section_id: nil) }, class_name: 'SpreeCmCommissioner::Block', dependent: :destroy
|
6
|
-
has_many :section_blocks, -> { where.not(seat_section_id: nil) }, class_name: 'SpreeCmCommissioner::Block', dependent: :destroy
|
7
|
-
|
8
|
-
belongs_to :layoutable, polymorphic: true
|
9
|
-
|
10
|
-
enum status: {
|
11
|
-
inactive: 0,
|
12
|
-
active: 1,
|
13
|
-
archived: 2
|
14
|
-
}
|
15
|
-
|
16
|
-
validates :name, presence: true
|
17
|
-
|
18
|
-
accepts_nested_attributes_for :seat_sections, :top_level_blocks
|
19
|
-
end
|
20
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
class SeatSection < Base
|
3
|
-
belongs_to :seat_layout, class_name: 'SpreeCmCommissioner::SeatLayout', optional: false
|
4
|
-
|
5
|
-
has_many :blocks, class_name: 'SpreeCmCommissioner::Block', dependent: :destroy
|
6
|
-
|
7
|
-
validates :name, presence: true
|
8
|
-
validates :width, presence: true, numericality: { greater_than: 0 }
|
9
|
-
validates :height, presence: true, numericality: { greater_than: 0 }
|
10
|
-
validates :x, presence: true, numericality: true
|
11
|
-
validates :y, presence: true, numericality: true
|
12
|
-
validates :rotation, presence: true, numericality: { greater_than_or_equal_to: -360, less_than_or_equal_to: 360 }
|
13
|
-
|
14
|
-
accepts_nested_attributes_for :blocks
|
15
|
-
end
|
16
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
module Seats
|
3
|
-
class BlocksCanceler
|
4
|
-
def initialize(order_id:, cancel_by: nil)
|
5
|
-
@order_id = order_id
|
6
|
-
@cancel_by = cancel_by
|
7
|
-
end
|
8
|
-
|
9
|
-
# Cancels all reserved blocks associated with a given order.
|
10
|
-
#
|
11
|
-
# Typically used when:
|
12
|
-
# - The order is canceled.
|
13
|
-
# - The user abandons the order before completing checkout.
|
14
|
-
def cancel_blocks!
|
15
|
-
order = Spree::Order.find(@order_id)
|
16
|
-
|
17
|
-
ActiveRecord::Base.transaction do
|
18
|
-
order.reserved_blocks.each do |reserved_block|
|
19
|
-
reserved_block.assign_attributes(
|
20
|
-
status: :canceled,
|
21
|
-
expired_at: nil,
|
22
|
-
updated_by: @cancel_by
|
23
|
-
)
|
24
|
-
raise Errors::UnableToSaveReservedBlockRecord unless reserved_block.save
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
module Seats
|
3
|
-
class BlocksHolder
|
4
|
-
HOLD_DURATION = 8.minutes
|
5
|
-
|
6
|
-
def initialize(line_item_ids:, hold_by: nil)
|
7
|
-
@line_item_ids = line_item_ids
|
8
|
-
@hold_by = hold_by
|
9
|
-
end
|
10
|
-
|
11
|
-
# Hold blocks for the given line items, preventing dublicate block selection.
|
12
|
-
#
|
13
|
-
# It ensures:
|
14
|
-
# - Raises an error if already reserved.
|
15
|
-
# - Raises an error if currently on_hold by someone else.
|
16
|
-
# - Allows re-locking if already on_hold by the same guest.
|
17
|
-
# - Otherwise, proceeds to lock the given blocks.
|
18
|
-
def hold_blocks!
|
19
|
-
line_items = Spree::LineItem.where(id: @line_item_ids).includes(:inventory_items, guests_with_blocks: :block)
|
20
|
-
guests_with_blocks = line_items.flat_map(&:guests_with_blocks).compact
|
21
|
-
inventory_items = line_items.flat_map(&:inventory_items).compact
|
22
|
-
|
23
|
-
ActiveRecord::Base.transaction do
|
24
|
-
guests_with_blocks.each do |guest|
|
25
|
-
inventory_items.each do |inventory_item|
|
26
|
-
hold_specific_block!(inventory_item, guest)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def hold_specific_block!(inventory_item, guest)
|
35
|
-
reserved_block = SpreeCmCommissioner::ReservedBlock.find_or_initialize_by(inventory_item: inventory_item, block: guest.block)
|
36
|
-
|
37
|
-
raise Errors::BlocksAreReservedByOtherGuest if reserved_block.reserved? && reserved_block.guest_id != guest.id
|
38
|
-
raise Errors::BlocksAreReservedBySameGuest if reserved_block.reserved? && reserved_block.guest_id == guest.id
|
39
|
-
raise Errors::BlocksAreOnHoldByOtherGuest if reserved_block.active_on_hold? && reserved_block.guest_id != guest.id
|
40
|
-
|
41
|
-
reserved_block.assign_attributes(
|
42
|
-
status: :on_hold,
|
43
|
-
guest: guest,
|
44
|
-
expired_at: HOLD_DURATION.from_now,
|
45
|
-
inventory_date: inventory_item.inventory_date,
|
46
|
-
updated_by: @hold_by
|
47
|
-
)
|
48
|
-
|
49
|
-
raise Errors::UnableToSaveReservedBlockRecord unless reserved_block.save
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
@@ -1,49 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
module Seats
|
3
|
-
class BlocksReserver
|
4
|
-
def initialize(line_item_ids:, reserve_by: nil)
|
5
|
-
@line_item_ids = line_item_ids
|
6
|
-
@reserve_by = reserve_by
|
7
|
-
end
|
8
|
-
|
9
|
-
# Mark blocks as reserved for the given line items.
|
10
|
-
#
|
11
|
-
# It ensures:
|
12
|
-
# - Raises an error if already reserved by same guest or other guest.
|
13
|
-
# - Raises an error if currently on_hold by someone else.
|
14
|
-
# - Otherwise, proceeds to reserve the given blocks.
|
15
|
-
def reserve_blocks!
|
16
|
-
line_items = Spree::LineItem.where(id: @line_item_ids).includes(:inventory_items, guests_with_blocks: :block)
|
17
|
-
guests_with_blocks = line_items.flat_map(&:guests_with_blocks).compact
|
18
|
-
inventory_items = line_items.flat_map(&:inventory_items).compact
|
19
|
-
|
20
|
-
ActiveRecord::Base.transaction do
|
21
|
-
guests_with_blocks.each do |guest|
|
22
|
-
inventory_items.each do |inventory_item|
|
23
|
-
reserve_specific_block!(inventory_item, guest)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def reserve_specific_block!(inventory_item, guest)
|
30
|
-
reserved_block = SpreeCmCommissioner::ReservedBlock.find_or_initialize_by(inventory_item_id: inventory_item.id, block_id: guest.block_id)
|
31
|
-
|
32
|
-
raise Errors::BlocksAreReservedByOtherGuest if reserved_block.reserved? && reserved_block.guest_id != guest.id
|
33
|
-
raise Errors::BlocksAreReservedBySameGuest if reserved_block.reserved? && reserved_block.guest_id == guest.id
|
34
|
-
raise Errors::BlocksAreOnHoldByOtherGuest if reserved_block.active_on_hold? && reserved_block.guest_id != guest.id
|
35
|
-
|
36
|
-
# mark the block as reserved if not on_hold or lock by anyone but already expired
|
37
|
-
reserved_block.assign_attributes(
|
38
|
-
guest: guest,
|
39
|
-
status: :reserved,
|
40
|
-
expired_at: nil,
|
41
|
-
inventory_date: inventory_item.inventory_date,
|
42
|
-
updated_by: @reserve_by
|
43
|
-
)
|
44
|
-
|
45
|
-
raise Errors::UnableToSaveReservedBlockRecord unless reserved_block.save
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
# On top of SpreeCmCommissioner::Stock::AvailabilityChecker, this class does the same thing but in bulk check with redis.
|
2
|
-
# Which mean, it check basic condition with db first, once pass, it check with redis.
|
3
|
-
module SpreeCmCommissioner
|
4
|
-
module Stock
|
5
|
-
class OrderAvailabilityChecker
|
6
|
-
attr_reader :order
|
7
|
-
|
8
|
-
def initialize(order)
|
9
|
-
@order = order
|
10
|
-
end
|
11
|
-
|
12
|
-
def can_supply_all?
|
13
|
-
insufficient_stock_lines.empty?
|
14
|
-
end
|
15
|
-
|
16
|
-
def insufficient_stock_lines
|
17
|
-
cached_inventory_items_group_by_line_item_id.map do |line_item_id, cached_inventory_items|
|
18
|
-
line_item = order.line_items.find { |item| item.id == line_item_id }
|
19
|
-
line_item unless sufficient_stock_for?(line_item, cached_inventory_items)
|
20
|
-
end.compact
|
21
|
-
end
|
22
|
-
|
23
|
-
# {
|
24
|
-
# 1: [ {inventory_key: "inventory:1", active: true, quantity_available: 5, inventory_item_id: 1, variant_id: 1}],
|
25
|
-
# 2: [ {inventory_key: "inventory:2", active: true, quantity_available: 5, inventory_item_id: 2, variant_id: 2}],
|
26
|
-
# }
|
27
|
-
def cached_inventory_items_group_by_line_item_id
|
28
|
-
@cached_inventory_items_group_by_line_item_id ||=
|
29
|
-
::SpreeCmCommissioner::RedisStock::LineItemsCachedInventoryItemsBuilder.new(
|
30
|
-
line_item_ids: order.line_items.pluck(:id)
|
31
|
-
).call
|
32
|
-
end
|
33
|
-
|
34
|
-
def sufficient_stock_for?(line_item, cached_inventory_items)
|
35
|
-
return false unless line_item.variant.available?
|
36
|
-
return true unless line_item.variant.should_track_inventory?
|
37
|
-
return true if line_item.variant.backorderable?
|
38
|
-
return true if line_item.variant.need_confirmation?
|
39
|
-
|
40
|
-
cached_inventory_items.all? { |item| item.active? && item.quantity_available >= line_item.quantity }
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,8 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
class TaxonBlazerQuery < SpreeCmCommissioner::Base
|
3
|
-
belongs_to :taxon, class_name: 'Spree::Taxon'
|
4
|
-
belongs_to :blazer_query, class_name: 'Blazer::Query'
|
5
|
-
|
6
|
-
validates :taxon_id, uniqueness: { scope: :blazer_query_id, message: I18n.t('event_blazer_queries.fail') }
|
7
|
-
end
|
8
|
-
end
|
@@ -1,9 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
class VariantBlock < Base
|
3
|
-
belongs_to :variant, class_name: 'Spree::Variant', optional: false
|
4
|
-
belongs_to :trip, class_name: 'SpreeCmCommissioner::Trip', optional: false
|
5
|
-
belongs_to :block, class_name: 'SpreeCmCommissioner::Block', optional: false
|
6
|
-
|
7
|
-
validates :block_id, uniqueness: { scope: %i[variant_id trip_id] }
|
8
|
-
end
|
9
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
class VariantRequestSchema < ApplicationRequestSchema
|
3
|
-
params do
|
4
|
-
required(:from_date).value(:date)
|
5
|
-
required(:to_date).value(:date)
|
6
|
-
required(:adult).value(:integer)
|
7
|
-
required(:children).value(:integer)
|
8
|
-
end
|
9
|
-
|
10
|
-
rule(:from_date, :to_date) do
|
11
|
-
from_date = values[:from_date]
|
12
|
-
to_date = values[:to_date]
|
13
|
-
|
14
|
-
key.failure(:must_be_in_future) if from_date < Time.zone.today
|
15
|
-
key.failure(:must_be_later_than_start_date) if from_date > to_date
|
16
|
-
key.failure(:stay_is_too_long) if (to_date - from_date).to_i > ENV.fetch('ACCOMMODATION_MAX_STAY_DAYS', 10).to_i
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,72 +0,0 @@
|
|
1
|
-
<%= turbo_frame_tag "inventory_item" do %>
|
2
|
-
<div>
|
3
|
-
<h5 class="modal-title">Inventory</h5>
|
4
|
-
<p>
|
5
|
-
<% if @inventory_item.inventory_date.present? %>
|
6
|
-
<span><%= @inventory_item.inventory_date %></span><br>
|
7
|
-
<% end %>
|
8
|
-
<%= @inventory_item.variant.options_text %>
|
9
|
-
</p>
|
10
|
-
|
11
|
-
<ul class="list-group mb-1">
|
12
|
-
<li class="list-group-item d-flex justify-content-between align-items-center">
|
13
|
-
Max capacity
|
14
|
-
<span class="badge badge-primary badge-pill"><%= @inventory_item.max_capacity %></span>
|
15
|
-
</li>
|
16
|
-
<li class="list-group-item d-flex justify-content-between align-items-center">
|
17
|
-
Quantity available
|
18
|
-
<span class="badge badge-primary badge-pill"><%= @inventory_item.quantity_available %></span>
|
19
|
-
</li>
|
20
|
-
</ul>
|
21
|
-
|
22
|
-
<small class="text-muted">
|
23
|
-
<%= inventory_item_message(@inventory_item, @cached_inventory_item) %>
|
24
|
-
</small>
|
25
|
-
|
26
|
-
<%= link_to_with_icon('arrow-counterclockwise.svg', "Reset Inventory Item", reset_admin_product_variant_inventory_item_path(@product, @inventory_item.variant_id, @inventory_item.id),
|
27
|
-
method: :patch,
|
28
|
-
remote: false,
|
29
|
-
class: 'icon_link btn btn-sm outline text-dark',
|
30
|
-
data: { confirm: "Only reset if stock is incorrect. Are you sure?" }, no_text: true
|
31
|
-
) %>
|
32
|
-
</div>
|
33
|
-
|
34
|
-
<hr />
|
35
|
-
|
36
|
-
<div class="mt-2">
|
37
|
-
<h6 class="modal-title mb-1 d-flex flex-row justify-content-between">
|
38
|
-
Custom Prices
|
39
|
-
<%= link_to_with_icon('delete.svg', Spree.t(:remove),
|
40
|
-
delete_prices_admin_product_variant_inventory_item_path(@product, @inventory_item.variant_id, @inventory_item.id),
|
41
|
-
method: :delete, remote: false, class: 'icon_link btn btn-sm text-danger', data: { action: :remove, confirm: "Are you sure to remove these prices & use base price?" }, no_text: true
|
42
|
-
) if @prices.any?(&:persisted?) %>
|
43
|
-
</h6>
|
44
|
-
|
45
|
-
<%= form_with url: update_prices_admin_product_variant_inventory_item_path(@product, @inventory_item.variant_id, @inventory_item.id), method: :patch, local: true, html: { class: 'inventory-item-prices-form' } do |form| %>
|
46
|
-
<table class="table">
|
47
|
-
<tbody>
|
48
|
-
<% @prices.each do |price| %>
|
49
|
-
<% currency = price.currency %>
|
50
|
-
<% default_price = @default_prices[currency] || Spree::Price.new %>
|
51
|
-
<tr id="inventory-item_prices_row_<%= currency %>" data-hook="inventory-item_prices_row">
|
52
|
-
<td><%= form.label "price_#{currency}", currency, class: 'form-label' %></td>
|
53
|
-
<td>
|
54
|
-
<%= form.hidden_field "prices[#{currency}][currency]", value: currency %>
|
55
|
-
<%= form.text_field "prices[#{currency}][price]", value: price.amount, placeholder: "Default: #{default_price.amount || 'N/A'}", class: 'form-control' %>
|
56
|
-
</td>
|
57
|
-
<td>
|
58
|
-
<%= form.text_field "prices[#{currency}][compare_at_price]", value: price.compare_at_price, placeholder: "Default: #{default_price.compare_at_price || 'N/A'}", class: 'form-control' %>
|
59
|
-
</td>
|
60
|
-
</tr>
|
61
|
-
<% end %>
|
62
|
-
</tbody>
|
63
|
-
</table>
|
64
|
-
|
65
|
-
<div class="d-flex flex-row justify-content-end mt-2">
|
66
|
-
<div class="form-actions" data-hook="buttons">
|
67
|
-
<%= button Spree.t('actions.save'), 'save.svg', 'submit', { class: 'btn-outline-success', data: { disable_with: "#{ Spree.t(:saving) }...", turbo_frame: "_top" } } %>
|
68
|
-
</div>
|
69
|
-
</div>
|
70
|
-
<% end %>
|
71
|
-
</div>
|
72
|
-
<% end %>
|
@@ -1,56 +0,0 @@
|
|
1
|
-
<%= turbo_frame_tag "calendar" do %>
|
2
|
-
<%= form_with url: admin_product_stock_managements_path, method: :get, class: "mt-4" do %>
|
3
|
-
<%= select_year(params[:year]&.to_i || @year, { start_year: 2025, end_year: @year + 3 }, { name: "year", onchange: "this.form.submit()" }) %>
|
4
|
-
<% end %>
|
5
|
-
|
6
|
-
<div class="c-annual-calendar-container mt-2">
|
7
|
-
<div class="c-annual-calendar">
|
8
|
-
<% (1..12).each do |month| %>
|
9
|
-
<%= month_calendar(start_date: Date.new(@year, month, 1), attribute: :from_date, end_attribute: :to_date, events: @events) do |date, events| %>
|
10
|
-
<div class="c-annual-day" data-date="<%= date.strftime '%Y-%m-%d' %>">
|
11
|
-
<%= date.day %>
|
12
|
-
<ul class="p-0 m-0 list-unstyled">
|
13
|
-
<% events = events.sort_by { |e| e.options[:inventory_item]&.variant_id.to_i } %>
|
14
|
-
<% events.each do |event| %>
|
15
|
-
<% inventory_item = event.options[:inventory_item] %>
|
16
|
-
<% synced = inventory_item.quantity_available == @cached_inventory_items[inventory_item.id].quantity_available %>
|
17
|
-
|
18
|
-
<% classes = 'badge ' %>
|
19
|
-
<% classes += synced ? 'badge-primary ' : 'badge-danger ' %>
|
20
|
-
<% classes += 'badge-success ' if inventory_item.prices.any? %>
|
21
|
-
|
22
|
-
<li class="<%= classes %>"
|
23
|
-
data-toggle="modal"
|
24
|
-
data-target="#inventoryItemModal"
|
25
|
-
role="button"
|
26
|
-
onclick="updateModalTurboFrameSrc('<%= admin_product_variant_inventory_item_path(@product, inventory_item.variant_id, inventory_item.id) %>')">
|
27
|
-
<%= inventory_item.quantity_available %>
|
28
|
-
<%= inventory_item.prices.first.display_amount if inventory_item.prices.any? %>
|
29
|
-
</li>
|
30
|
-
<% end %>
|
31
|
-
</ul>
|
32
|
-
</div>
|
33
|
-
<% end %>
|
34
|
-
<% end %>
|
35
|
-
</div>
|
36
|
-
</div>
|
37
|
-
|
38
|
-
<div class="modal fade" id="inventoryItemModal" tabindex="-1" role="dialog">
|
39
|
-
<div class="modal-dialog" role="document">
|
40
|
-
<div class="modal-content">
|
41
|
-
<div class="modal-body">
|
42
|
-
<%= turbo_frame_tag "inventory_item" %>
|
43
|
-
</div>
|
44
|
-
</div>
|
45
|
-
</div>
|
46
|
-
</div>
|
47
|
-
|
48
|
-
<script>
|
49
|
-
function updateModalTurboFrameSrc(url) {
|
50
|
-
let frame = document.getElementById('inventory_item');
|
51
|
-
frame.src = null;
|
52
|
-
frame.innerHTML = `<div class="spinner-border mt-2" role="status"></div>`;
|
53
|
-
frame.src = url
|
54
|
-
}
|
55
|
-
</script>
|
56
|
-
<% end %>
|