spree_cm_commissioner 2.8.15.pre.pre8 → 2.8.15
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 +20 -0
- data/.github/workflows/test_and_build_gem.yml +2 -1
- data/Gemfile.lock +2 -2
- data/app/controllers/concerns/spree_cm_commissioner/content_cachable.rb +8 -0
- data/app/controllers/concerns/spree_cm_commissioner/load_test_account_management.rb +80 -0
- data/app/controllers/concerns/spree_cm_commissioner/load_test_account_scope.rb +39 -0
- data/app/controllers/concerns/spree_cm_commissioner/load_test_bypassable.rb +29 -0
- data/app/controllers/concerns/spree_cm_commissioner/load_test_login_token_generation.rb +53 -0
- data/app/controllers/concerns/spree_cm_commissioner/order_concern.rb +5 -0
- data/app/controllers/concerns/spree_cm_commissioner/turnstile_protectable.rb +9 -7
- data/app/controllers/spree/admin/guests_controller.rb +4 -2
- data/app/controllers/spree/admin/import_new_orders_controller.rb +25 -0
- data/app/controllers/spree/admin/inventory_holds_controller.rb +21 -1
- data/app/controllers/spree/admin/system/load_test_accounts_controller.rb +24 -0
- data/app/controllers/spree/admin/system/load_test_flows_controller.rb +11 -0
- data/app/controllers/spree/admin/system/load_test_login_tokens_controller.rb +16 -0
- data/app/controllers/spree/admin/system/load_testing_controller.rb +9 -0
- data/app/controllers/spree/admin/system/maintenance_tasks_controller.rb +64 -0
- data/app/controllers/spree/admin/system/waiting_room_controller.rb +22 -0
- data/app/controllers/spree/admin/taxons_controller_decorator.rb +5 -0
- data/app/controllers/spree/admin/users_controller_decorator.rb +18 -0
- data/app/controllers/spree/api/chatrace/guests_controller.rb +1 -1
- data/app/controllers/spree/api/v2/operator/event_charts_controller.rb +1 -0
- data/app/controllers/spree/api/v2/operator/guest_json_gzips_controller.rb +14 -4
- data/app/controllers/spree/api/v2/storefront/account/guest_dynamic_fields_controller.rb +19 -48
- data/app/controllers/spree/api/v2/storefront/account/mark_guest_info_complete_controller.rb +2 -2
- data/app/controllers/spree/api/v2/storefront/account/orders_controller_decorator.rb +10 -15
- data/app/controllers/spree/api/v2/storefront/account/saved_guests_controller.rb +65 -0
- data/app/controllers/spree/api/v2/storefront/account_checker_controller.rb +4 -0
- data/app/controllers/spree/api/v2/storefront/draft_orders_controller.rb +52 -0
- data/app/controllers/spree/api/v2/storefront/guests_controller.rb +13 -10
- data/app/controllers/spree/api/v2/storefront/order_histories_controller.rb +14 -3
- data/app/controllers/spree/api/v2/storefront/payment_methods_controller.rb +40 -0
- data/app/controllers/spree/api/v2/storefront/preview_sections_controller.rb +1 -7
- data/app/controllers/spree/api/v2/storefront/telegram_oauth_tokens_controller.rb +61 -0
- data/app/controllers/spree/api/v2/storefront/ticket_transfers_controller.rb +4 -3
- data/app/controllers/spree/api/v2/storefront/waiting_room_sessions_controller.rb +8 -1
- data/app/controllers/spree/api/v2/tenant/account/orders_controller.rb +1 -1
- data/app/controllers/spree/api/v2/tenant/account/saved_guests_controller.rb +70 -0
- data/app/controllers/spree/api/v2/tenant/draft_orders_controller.rb +50 -0
- data/app/controllers/spree/api/v2/tenant/episodes_controller.rb +3 -1
- data/app/controllers/spree/api/v2/tenant/guests_controller.rb +11 -21
- data/app/controllers/spree/api/v2/tenant/my_votes_controller.rb +51 -0
- data/app/controllers/spree/api/v2/tenant/order_histories_controller.rb +16 -3
- data/app/controllers/spree/api/v2/tenant/payment_methods_controller.rb +54 -0
- data/app/controllers/spree/api/v2/tenant/preview_products_controller.rb +1 -1
- data/app/controllers/spree/api/v2/tenant/preview_sections_controller.rb +1 -7
- data/app/controllers/spree/api/v2/tenant/show_people_controller.rb +1 -4
- data/app/controllers/spree/api/v2/tenant/show_person_assignments_controller.rb +4 -1
- data/app/controllers/spree/api/v2/tenant/voting_contestants_controller.rb +6 -3
- data/app/controllers/spree/api/v2/tenant/waiting_room_sessions_controller.rb +8 -1
- data/app/controllers/spree_cm_commissioner/admin/orders_controller_decorator.rb +9 -0
- data/app/controllers/spree_cm_commissioner/admin/variants_controller_decorator.rb +17 -0
- data/app/controllers/spree_cm_commissioner/api/v2/storefront/checkout_controller_decorator.rb +3 -3
- data/app/finders/spree_cm_commissioner/orders/find.rb +33 -3
- data/app/finders/spree_cm_commissioner/orders/find_by_all_state.rb +11 -0
- data/app/finders/spree_cm_commissioner/payment_methods/find.rb +59 -0
- data/app/finders/spree_cm_commissioner/routes/find.rb +1 -1
- data/app/interactors/spree_cm_commissioner/create_ticket.rb +7 -3
- data/app/interactors/spree_cm_commissioner/host_matcher.rb +6 -5
- data/app/interactors/spree_cm_commissioner/payment_incomplete_notification_sender.rb +25 -0
- data/app/interactors/spree_cm_commissioner/release_inventory_item_notification_sender.rb +24 -0
- data/app/interactors/spree_cm_commissioner/telegram_oauth_id_token_provider.rb +99 -0
- data/app/interactors/spree_cm_commissioner/telegram_oauth_token_exchanger.rb +71 -0
- data/app/interactors/spree_cm_commissioner/turnstile_token_validator.rb +43 -13
- data/app/interactors/spree_cm_commissioner/user_id_token_authenticator.rb +2 -5
- data/app/interactors/spree_cm_commissioner/user_password_authenticator.rb +23 -1
- data/app/interactors/spree_cm_commissioner/user_telegram_oauth_authenticator.rb +88 -0
- data/app/interactors/spree_cm_commissioner/waiting_guests_caller.rb +172 -20
- data/app/interactors/spree_cm_commissioner/waiting_room_latest_system_metadata_puller.rb +5 -3
- data/app/interactors/spree_cm_commissioner/waiting_room_session_creator.rb +56 -12
- data/app/jobs/concerns/spree_cm_commissioner/idempotent_job.rb +12 -0
- data/app/jobs/spree_cm_commissioner/cancel_import_order_job.rb +11 -0
- data/app/jobs/spree_cm_commissioner/idempotency_keys/prune_job.rb +20 -0
- data/app/jobs/spree_cm_commissioner/inventory_items/bulk_adjust_quantities_job.rb +21 -3
- data/app/jobs/spree_cm_commissioner/inventory_items/bulk_adjust_quantities_on_hold_job.rb +34 -3
- data/app/jobs/spree_cm_commissioner/maintenance_tasks/guest_data_fill_stage_batch_job.rb +28 -0
- data/app/jobs/spree_cm_commissioner/maintenance_tasks/refinalize_guests_batch_job.rb +36 -0
- data/app/jobs/spree_cm_commissioner/payment_incomplete_notification_job.rb +12 -0
- data/app/jobs/spree_cm_commissioner/telegram_alerts/order_integrity_check_job.rb +17 -0
- data/app/jobs/spree_cm_commissioner/waiting_guests_caller_job.rb +6 -1
- data/app/jobs/spree_cm_commissioner/waiting_room/publish_lobby_path_job.rb +17 -0
- data/app/jobs/spree_cm_commissioner/waiting_room/stamp_queue_positions_job.rb +14 -0
- data/app/jobs/spree_cm_commissioner/waiting_room_latest_system_metadata_puller_job.rb +1 -1
- data/app/mailers/spree/order_mailer_decorator.rb +4 -0
- data/app/models/concerns/spree_cm_commissioner/event_metadata.rb +17 -2
- data/app/models/concerns/spree_cm_commissioner/guest_data_fill_stage_concern.rb +82 -0
- data/app/models/concerns/spree_cm_commissioner/kyc_bitwise.rb +17 -0
- data/app/models/concerns/spree_cm_commissioner/line_item_durationable.rb +4 -0
- data/app/models/concerns/spree_cm_commissioner/line_item_guests_concern.rb +16 -2
- data/app/models/concerns/spree_cm_commissioner/line_items_filter_scope.rb +5 -3
- data/app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb +0 -1
- data/app/models/concerns/spree_cm_commissioner/order_holdable.rb +6 -0
- data/app/models/concerns/spree_cm_commissioner/order_qr_codeable.rb +39 -0
- data/app/models/concerns/spree_cm_commissioner/order_scopes.rb +5 -0
- data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +57 -30
- data/app/models/concerns/spree_cm_commissioner/product_delegation.rb +4 -0
- data/app/models/concerns/spree_cm_commissioner/purchase_limitable.rb +59 -0
- data/app/models/concerns/spree_cm_commissioner/store_preference.rb +3 -0
- data/app/models/concerns/spree_cm_commissioner/tenant_preference.rb +2 -0
- data/app/models/concerns/spree_cm_commissioner/variant_options_concern.rb +0 -1
- data/app/models/spree_cm_commissioner/check_in_session.rb +36 -0
- data/app/models/spree_cm_commissioner/current.rb +11 -0
- data/app/models/spree_cm_commissioner/dynamic_field.rb +12 -0
- data/app/models/spree_cm_commissioner/exports/operator_guest_json_gzip.rb +26 -1
- data/app/models/spree_cm_commissioner/guest.rb +5 -144
- data/app/models/spree_cm_commissioner/guest_dynamic_field.rb +43 -71
- data/app/models/spree_cm_commissioner/homepage_section_relatable.rb +25 -0
- data/app/models/spree_cm_commissioner/idempotency_key.rb +21 -0
- data/app/models/spree_cm_commissioner/import.rb +2 -1
- data/app/models/spree_cm_commissioner/imported_order.rb +6 -0
- data/app/models/spree_cm_commissioner/imports/import_order.rb +21 -0
- data/app/models/spree_cm_commissioner/inventory_hold.rb +1 -1
- data/app/models/spree_cm_commissioner/line_item_decorator.rb +4 -3
- data/app/models/spree_cm_commissioner/maintenance_task.rb +10 -0
- data/app/models/spree_cm_commissioner/maintenance_tasks/event.rb +15 -14
- data/app/models/spree_cm_commissioner/maintenance_tasks/guest_data_fill_stage.rb +21 -0
- data/app/models/spree_cm_commissioner/notification.rb +1 -0
- data/app/models/spree_cm_commissioner/order_decorator.rb +38 -29
- data/app/models/spree_cm_commissioner/payment_decorator.rb +11 -0
- data/app/models/spree_cm_commissioner/payment_method_decorator.rb +2 -0
- data/app/models/spree_cm_commissioner/pricing_model_route.rb +8 -0
- data/app/models/spree_cm_commissioner/product_decorator.rb +4 -22
- data/app/models/spree_cm_commissioner/product_dynamic_field.rb +17 -0
- data/app/models/spree_cm_commissioner/request_guard.rb +19 -0
- data/app/models/spree_cm_commissioner/role_decorator.rb +52 -4
- data/app/models/spree_cm_commissioner/role_user_decorator.rb +11 -0
- data/app/models/spree_cm_commissioner/seat_layout.rb +12 -4
- data/app/models/spree_cm_commissioner/show.rb +3 -1
- data/app/models/spree_cm_commissioner/show_episode.rb +3 -1
- data/app/models/spree_cm_commissioner/show_person.rb +5 -1
- data/app/models/spree_cm_commissioner/show_person_assignment.rb +1 -1
- data/app/models/spree_cm_commissioner/taxon_ad_banner.rb +12 -0
- data/app/models/spree_cm_commissioner/taxon_decorator.rb +3 -0
- data/app/models/spree_cm_commissioner/tenant.rb +17 -6
- data/app/models/spree_cm_commissioner/trip.rb +18 -1
- data/app/models/spree_cm_commissioner/user_decorator.rb +67 -1
- data/app/models/spree_cm_commissioner/variant_options.rb +0 -4
- data/app/models/spree_cm_commissioner/vehicle_type.rb +1 -0
- data/app/models/spree_cm_commissioner/voting_contestant.rb +21 -7
- data/app/models/spree_cm_commissioner/waiting_room_session.rb +14 -0
- data/app/notifications/spree_cm_commissioner/order_general_notification.rb +15 -0
- data/app/overrides/spree/admin/orders/_order_actions/actions.html.erb.deface +7 -0
- data/app/overrides/spree/admin/orders/_search/payment_number_search_field.html.erb.deface +8 -0
- data/app/overrides/spree/admin/payment_methods/index/pagination.html.erb.deface +3 -0
- data/app/overrides/spree/admin/payment_methods/index/preserve_tab_in_search.html.erb.deface +4 -0
- data/app/overrides/spree/admin/products/_form/allow_gift_transfer.html.erb.deface +1 -1
- data/app/overrides/spree/admin/products/_form/allow_transfer.html.erb.deface +1 -1
- data/app/overrides/spree/admin/products/_form/enable_send_receipt.html.erb.deface +13 -0
- data/app/overrides/spree/admin/products/_form/enable_social_sharing_email.html.erb.deface +13 -0
- data/app/overrides/spree/admin/products/_form/enable_telegram_alert.html.erb.deface +14 -0
- data/app/overrides/spree/admin/shared/_order_summary/internal_note.html.erb.deface +23 -0
- data/app/overrides/spree/admin/shared/_order_summary/internal_note_modal.html.erb.deface +40 -0
- data/app/overrides/spree/admin/stores/_form/store_preferences.html.erb.deface +9 -0
- data/app/overrides/spree/admin/stores/_form/telegram_auth.html.erb.deface +73 -0
- data/app/overrides/spree/admin/taxons/_form/assets_form.html.erb.deface +10 -1
- data/app/overrides/spree/admin/variants/index/fixture_action.html.erb.deface +9 -0
- data/app/overrides/spree/admin/vendors/_form/term_of_use.html.erb.deface +6 -0
- data/app/queries/spree_cm_commissioner/event_chart_queries.rb +25 -9
- data/app/queries/spree_cm_commissioner/guest_searcher_query.rb +16 -3
- data/app/queries/spree_cm_commissioner/multi_leg_trips_query.rb +7 -0
- data/app/queries/spree_cm_commissioner/pie_chart_event_aggregator_queries.rb +3 -2
- data/app/queries/spree_cm_commissioner/single_leg_trips_query.rb +2 -1
- data/app/queries/spree_cm_commissioner/user_votes_per_contestant_query.rb +48 -0
- data/app/serializers/spree/v2/storefront/line_item_serializer_decorator.rb +2 -2
- data/app/serializers/spree/v2/storefront/product_serializer_decorator.rb +4 -0
- data/app/serializers/spree/v2/storefront/taxon_serializer_decorator.rb +3 -0
- data/app/serializers/spree/v2/storefront/user_serializer_decorator.rb +5 -2
- data/app/serializers/spree/v2/storefront/variant_serializer_decorator.rb +2 -1
- data/app/serializers/spree/v2/tenant/guest_serializer.rb +2 -1
- data/app/serializers/spree/v2/tenant/my_vote_serializer.rb +19 -0
- data/app/serializers/spree/v2/tenant/product_serializer.rb +5 -0
- data/app/serializers/spree/v2/tenant/saved_guest_serializer.rb +23 -0
- data/app/serializers/spree/v2/tenant/show_episode_serializer.rb +1 -9
- data/app/serializers/spree/v2/tenant/show_serializer.rb +2 -1
- data/app/serializers/spree/v2/tenant/user_serializer.rb +1 -1
- data/app/serializers/spree/v2/tenant/variant_serializer.rb +2 -1
- data/app/serializers/spree/v2/tenant/voting_contestant_serializer.rb +2 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/cart_serializer_decorator.rb +1 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/guest_serializer.rb +3 -6
- data/app/serializers/spree_cm_commissioner/v2/storefront/ticket_transfer_serializer.rb +2 -2
- data/app/serializers/spree_cm_commissioner/v2/storefront/trip_result_serializer.rb +2 -2
- data/app/serializers/spree_cm_commissioner/v2/storefront/trip_serializer.rb +3 -1
- data/app/services/spree_cm_commissioner/api_caches/invalidate.rb +24 -3
- data/app/services/spree_cm_commissioner/cart/add_guest.rb +30 -3
- data/app/services/spree_cm_commissioner/cart/add_item_decorator.rb +22 -0
- data/app/services/spree_cm_commissioner/cart/empty_decorator.rb +23 -0
- data/app/services/spree_cm_commissioner/cart/remove_guest.rb +26 -1
- data/app/services/spree_cm_commissioner/cart/remove_item_decorator.rb +17 -0
- data/app/services/spree_cm_commissioner/cart/remove_line_item_decorator.rb +17 -0
- data/app/services/spree_cm_commissioner/cart/set_quantity_decorator.rb +17 -0
- data/app/services/spree_cm_commissioner/check_ins/create_bulk.rb +10 -6
- data/app/services/spree_cm_commissioner/draft_order/create.rb +95 -0
- data/app/services/spree_cm_commissioner/fraud_check.rb +9 -0
- data/app/services/spree_cm_commissioner/guests/create.rb +82 -0
- data/app/services/spree_cm_commissioner/guests/refresh_data_fill_stage.rb +20 -0
- data/app/services/spree_cm_commissioner/guests/send_dynamic_field_notification.rb +15 -0
- data/app/services/spree_cm_commissioner/guests/update.rb +68 -0
- data/app/services/spree_cm_commissioner/imports/contestants/create.rb +19 -1
- data/app/services/spree_cm_commissioner/imports/orders/cancel.rb +63 -0
- data/app/services/spree_cm_commissioner/imports/orders/create.rb +1 -0
- data/app/services/spree_cm_commissioner/inventory_holds/release.rb +18 -0
- data/app/services/spree_cm_commissioner/inventory_holds/validate_limits.rb +8 -3
- data/app/services/spree_cm_commissioner/line_items/validate_purchase_limits.rb +97 -0
- data/app/services/spree_cm_commissioner/load_test/create_accounts.rb +68 -0
- data/app/services/spree_cm_commissioner/load_test/destroy_accounts.rb +47 -0
- data/app/services/spree_cm_commissioner/load_test/flow_registry.rb +26 -0
- data/app/services/spree_cm_commissioner/load_test/generate_booking_ticket_data.rb +204 -0
- data/app/services/spree_cm_commissioner/load_test/generate_voting_fixture_data.rb +178 -0
- data/app/services/spree_cm_commissioner/load_test/login_token.rb +46 -0
- data/app/services/spree_cm_commissioner/operator_guest_json_gzips/create.rb +14 -7
- data/app/services/spree_cm_commissioner/order/guests/update.rb +53 -0
- data/app/services/spree_cm_commissioner/organizer/export_guest_csv_service.rb +12 -11
- data/app/services/spree_cm_commissioner/pricing_models/create_with_rule_groups.rb +9 -3
- data/app/services/spree_cm_commissioner/pricing_models/preview.rb +49 -6
- data/app/services/spree_cm_commissioner/pricing_models/update_with_rule_groups.rb +10 -7
- data/app/services/spree_cm_commissioner/show_contestants/normalize_video_highlights.rb +5 -1
- data/app/services/spree_cm_commissioner/telegram_alerts/checks/order_complete_payment_not_paid.rb +21 -0
- data/app/services/spree_cm_commissioner/telegram_alerts/checks/payment_paid_order_not_complete.rb +21 -0
- data/app/services/spree_cm_commissioner/telegram_alerts/order_integrity_alert.rb +112 -0
- data/app/services/spree_cm_commissioner/telegram_alerts/order_integrity_checks_runner.rb +32 -0
- data/app/services/spree_cm_commissioner/trips/update_single_leg.rb +6 -1
- data/app/services/spree_cm_commissioner/user_authenticator.rb +22 -1
- data/app/services/spree_cm_commissioner/voting_contestants/advancer.rb +10 -3
- data/app/services/spree_cm_commissioner/voting_contestants/assigner.rb +20 -2
- data/app/services/spree_cm_commissioner/voting_contestants/bulk_updater.rb +15 -9
- data/app/services/spree_cm_commissioner/voting_credits/allocate.rb +13 -2
- data/app/services/spree_cm_commissioner/voting_leaderboards/time_range_result.rb +79 -0
- data/app/services/spree_cm_commissioner/waiting_room/publish_lobby_path.rb +57 -0
- data/app/services/spree_cm_commissioner/waiting_room/stamp_queue_positions.rb +185 -0
- data/app/services/spree_cm_commissioner/waiting_room_lobby_metadata_fetcher.rb +47 -0
- data/app/services/spree_cm_commissioner/waiting_room_system_metadata_fetcher.rb +19 -5
- data/app/services/spree_cm_commissioner/waiting_room_system_metadata_setter.rb +28 -5
- data/app/views/spree/admin/featured_trips/index.html.erb +1 -1
- data/app/views/spree/admin/guests/_form.html.erb +37 -0
- data/app/views/spree/admin/import_new_orders/_cancel_modal.html.erb +35 -0
- data/app/views/spree/admin/import_new_orders/index.html.erb +4 -0
- data/app/views/spree/admin/import_new_orders/show.html.erb +30 -0
- data/app/views/spree/admin/imports/index.html.erb +2 -0
- data/app/views/spree/admin/inventory_holds/index.html.erb +8 -3
- data/app/views/spree/admin/shared/_system_tabs.html.erb +14 -0
- data/app/views/spree/admin/system/load_test_accounts/_login_tokens_modal.html.erb +52 -0
- data/app/views/spree/admin/system/load_test_accounts/index.html.erb +175 -0
- data/app/views/spree/admin/system/load_test_flows/index.html.erb +66 -0
- data/app/views/spree/admin/system/load_testing/index.html.erb +25 -0
- data/app/views/spree/admin/system/maintenance_tasks/_search.html.erb +28 -0
- data/app/views/spree/admin/system/maintenance_tasks/index.html.erb +71 -0
- data/app/views/spree/admin/system/waiting_room/show.html.erb +58 -0
- data/app/views/spree/admin/tenants/_form.html.erb +40 -1
- data/app/views/spree/admin/tenants/form/_telegram_auth.html.erb +61 -0
- data/app/views/spree/admin/variants/fixture.html.erb +49 -0
- data/app/views/spree/order_mailer/confirm_email.html.erb +10 -0
- data/app/views/spree_cm_commissioner/order_mailer/_mailer_stylesheets.html.erb +12 -0
- data/app/views/spree_cm_commissioner/order_mailer/purchased_items/_items.html.erb +12 -9
- data/config/initializers/doorkeeper.rb +10 -6
- data/config/initializers/spree_permitted_attributes.rb +57 -0
- data/config/load_test_flows/platform.yml +25 -0
- data/config/load_test_flows/tenant.yml +93 -0
- data/config/locales/en.yml +147 -17
- data/config/locales/km.yml +51 -12
- data/config/routes.rb +36 -1
- data/db/migrate/20260616000001_add_canceled_by_id_to_cm_imports.rb +5 -0
- data/db/migrate/20260617000002_create_cm_imported_orders.rb +12 -0
- data/db/migrate/20260619000001_create_cm_idempotency_keys.rb +11 -0
- data/db/migrate/20260629000001_add_term_of_use_to_spree_vendors.rb +5 -0
- data/db/migrate/20260630000001_add_trip_to_cm_pricing_model_routes.rb +7 -0
- data/db/migrate/20260701000001_add_device_info_to_cm_waiting_room_sessions.rb +14 -0
- data/db/migrate/20260703065239_add_position_to_cm_voting_contestants.rb +6 -0
- data/db/migrate/20260708150000_add_name_and_short_name_to_cm_trips.rb +6 -0
- data/db/migrate/20260713022227_add_advanced_to_episode_id_to_cm_voting_contestants.rb +8 -0
- data/db/migrate/20260714002626_rename_data_fill_stage_phase_on_cm_guests.rb +5 -0
- data/db/migrate/20260720000001_add_check_in_fields_to_spree_roles.rb +11 -0
- data/db/migrate/20260723000000_add_payment_host_to_cm_tenants.rb +6 -0
- data/db/migrate/20260723000001_add_metadata_to_spree_roles.rb +11 -0
- data/db/migrate/20260728074153_add_role_to_cm_exports.rb +5 -0
- data/db/migrate/20260729000000_add_visibility_to_cm_trips.rb +6 -0
- data/db/migrate/20260729000001_add_session_created_at_index_to_cm_votes.rb +12 -0
- data/db/migrate/20260730000000_add_purchase_limit_scopes_to_spree_orders.rb +22 -0
- data/lib/spree_cm_commissioner/test_helper/factories/option_type_factory.rb +0 -6
- data/lib/spree_cm_commissioner/test_helper/factories/pricing_model_trip_factory.rb +11 -0
- data/lib/spree_cm_commissioner/test_helper/factories/vehicle_factory.rb +1 -1
- data/lib/spree_cm_commissioner/trip_result.rb +3 -1
- data/lib/spree_cm_commissioner/version.rb +1 -1
- data/lib/tasks/recompute_guest_data_fill_stage.rake +19 -0
- metadata +118 -13
- data/app/controllers/spree/api/v2/storefront/saved_guests_controller.rb +0 -77
- data/app/interactors/spree_cm_commissioner/guest_dynamic_field_notification_sender.rb +0 -11
- data/app/interactors/spree_cm_commissioner/guest_dynamic_fields_manager.rb +0 -33
- data/app/serializers/spree/v2/storefront/order_serializer_decorator.rb +0 -63
- data/app/serializers/spree_cm_commissioner/v2/storefront/guest_minimal_serializer.rb +0 -30
- data/app/serializers/spree_cm_commissioner/v2/storefront/line_item_minimal_serializer.rb +0 -57
- data/app/serializers/spree_cm_commissioner/v2/storefront/ticket_transfer_minimal_serializer.rb +0 -17
- data/app/services/spree_cm_commissioner/update_guest_service.rb +0 -129
- data/app/services/spree_cm_commissioner/users/incomplete_guest_checker_service.rb +0 -34
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ca0138759a1da40541b5d076fb9709847d44d88885593f5b69921993cfd26591
|
|
4
|
+
data.tar.gz: 79408535d56a9d4b62cac5154a316f6652d6d8664c04a030f00588b39f7ddd24
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3e1a90b2f9115755fcd8cb777e0cd4d3c05b950a8a1b913ac526be4c5967d062533b5683bf48d3ca979e726347bb1945520b0701337872e7626d2fc3524d7952
|
|
7
|
+
data.tar.gz: 8b4813fe21cc8495e2a512ea1662e2105ba61994c1866794bd9da91ef5c805b1b49cc9d8ea5cdf53f35dd2fe6a96295491eea72853cfdaf899377264922e8a84
|
data/.env.example
CHANGED
|
@@ -20,11 +20,22 @@ WAITING_ROOM_SESSION_SIGNATURE="e6b2********************26e3"
|
|
|
20
20
|
WAITING_ROOM_SESSION_EXPIRE_DURATION_IN_SECOND=
|
|
21
21
|
WAITING_ROOM_MIN_SESSIONS_COUNT=5
|
|
22
22
|
WAITING_ROOM_DISABLED=no
|
|
23
|
+
WAITING_ROOM_POSITION_STAMP_LIMIT=1000
|
|
24
|
+
WAITING_ROOM_FIRESTORE_BATCH_SIZE=500
|
|
25
|
+
WAITING_ROOM_MIN_WAIT_TO_ENTER_SECONDS=600 # Waiting Room step floor (10 min)
|
|
26
|
+
WAITING_ROOM_MIN_QUEUE_TO_ENTER_SECONDS=300 # Queue step floor (5 min)
|
|
27
|
+
WAITING_ROOM_MAX_WAIT_TO_DISPLAY_SECONDS=3600 # above this the ETA is hidden (1 h)
|
|
28
|
+
WAITING_ROOM_CALLER_INTERVAL_SECONDS=60 # how often the caller runs; match the waiting_guests_caller cron
|
|
29
|
+
WAITING_ROOM_MAX_ETA_BATCH_SIZE=50 # cap on batch size assumed when estimating the ETA
|
|
23
30
|
|
|
24
31
|
# Vattanac Bank
|
|
25
32
|
VATTANAC_AES_SECRET_KEY= ""
|
|
26
33
|
VATTANAC_PUBLIC_KEY=""
|
|
27
34
|
|
|
35
|
+
# Telegram OAuth (OpenID Connect) login client_id/client_secret are configured
|
|
36
|
+
# per tenant (or on the default store for tenant-less logins) from the admin
|
|
37
|
+
# under Telegram Authentication - see docs/authentication/telegram-login.md.
|
|
38
|
+
|
|
28
39
|
# Organizer URL
|
|
29
40
|
ORGANIZER_URL=http://127.0.0.1:4000/organizer
|
|
30
41
|
|
|
@@ -45,6 +56,9 @@ CACHE_DEFAULT_MAX_AGE=300 # Default for unlisted controllers - 5 minutes
|
|
|
45
56
|
# Batch size for processing maintenance tasks in app/jobs/spree_cm_commissioner/maintenance_tasks/orchestrate_job.rb
|
|
46
57
|
MAINTENANCE_TASKS_BATCH_SIZE=100
|
|
47
58
|
|
|
59
|
+
# Batch size for slicing guest_ids when enqueuing RefinalizeGuestsBatchJob in app/models/spree_cm_commissioner/maintenance_tasks/event.rb
|
|
60
|
+
MAINTENANCE_TASKS_REFINALIZE_GUESTS_BATCH_SIZE=300
|
|
61
|
+
|
|
48
62
|
# Export related:
|
|
49
63
|
OPERATOR_GUEST_JSON_GZIP_CACHE_HOURS=24
|
|
50
64
|
EXPORT_PRESIGNED_URL_EXPIRATION_MINUTES=15
|
|
@@ -63,3 +77,9 @@ PAYMENT_LOCK_MIN_DURATION_IN_MINUTES=5 # Minimum remaining hold time requir
|
|
|
63
77
|
MAX_ACTIVE_HOLDS_PER_USER=3 # Max concurrent active holds allowed per user across all orders
|
|
64
78
|
MAX_HOLDS_PER_IP_PER_HOUR=5 # Max hold attempts per IP address within a rolling 1-hour window (abuse prevention)
|
|
65
79
|
HOLD_COOLDOWN_AFTER_EXPIRY_IN_MINUTES=2 # Cooldown period before a user can re-acquire a hold after one expired on them
|
|
80
|
+
|
|
81
|
+
# See: app/models/spree_cm_commissioner/payment_decorator.rb
|
|
82
|
+
PAYMENT_INCOMPLETE_NOTIFICATION_DELAY_IN_MINUTES=5 # Delay before notifying a customer that their order is still unpaid after payment is created
|
|
83
|
+
|
|
84
|
+
# See: app/jobs/spree_cm_commissioner/telegram_alerts/order_integrity_check_job.rb
|
|
85
|
+
ORDER_INTEGRITY_TELEGRAM_ALERT_ENABLED="no" # Set to yes to enable the order integrity Telegram alert job (off by default to avoid flooding Telegram rate limits during traffic spikes)
|
|
@@ -163,8 +163,9 @@ jobs:
|
|
|
163
163
|
- name: Security
|
|
164
164
|
env:
|
|
165
165
|
DATABASE_URL: postgres://myuser:mypassword@localhost:5432/test_db
|
|
166
|
+
|
|
167
|
+
# Using --no-threads to bypass a known Ruby 3.2.0 GC segmentation fault in CI.
|
|
166
168
|
run: |
|
|
167
|
-
# Using --no-threads to bypass a known Ruby 3.2.0 GC segmentation fault in CI.
|
|
168
169
|
bundle exec brakeman --no-threads --no-exit-on-warn
|
|
169
170
|
|
|
170
171
|
test:
|
data/Gemfile.lock
CHANGED
|
@@ -34,7 +34,7 @@ GIT
|
|
|
34
34
|
PATH
|
|
35
35
|
remote: .
|
|
36
36
|
specs:
|
|
37
|
-
spree_cm_commissioner (2.8.15
|
|
37
|
+
spree_cm_commissioner (2.8.15)
|
|
38
38
|
activerecord-multi-tenant
|
|
39
39
|
activerecord_json_validator (~> 2.1, >= 2.1.3)
|
|
40
40
|
aws-sdk-cloudfront
|
|
@@ -886,7 +886,7 @@ GEM
|
|
|
886
886
|
spree_backend (>= 4.3.0.rc1)
|
|
887
887
|
spree_emails (>= 4.3.0.rc1)
|
|
888
888
|
spree_extension
|
|
889
|
-
spree_vpago (2.
|
|
889
|
+
spree_vpago (2.3.4)
|
|
890
890
|
faraday
|
|
891
891
|
google-cloud-firestore
|
|
892
892
|
spree_api (>= 4.5)
|
|
@@ -27,6 +27,13 @@ module SpreeCmCommissioner
|
|
|
27
27
|
PopularRoutesController
|
|
28
28
|
RoutePlacesController
|
|
29
29
|
ShowsController
|
|
30
|
+
EpisodesController
|
|
31
|
+
ShowPeopleController
|
|
32
|
+
ShowPersonAssignmentsController
|
|
33
|
+
ShowContestantsController
|
|
34
|
+
VotePackagesController
|
|
35
|
+
ShowEliminationSessionsController
|
|
36
|
+
PaymentMethodsController
|
|
30
37
|
].freeze
|
|
31
38
|
|
|
32
39
|
# Priority 3: Moderate Freshness (30 minutes)
|
|
@@ -46,6 +53,7 @@ module SpreeCmCommissioner
|
|
|
46
53
|
HIGH_FRESHNESS_CONTROLLERS = %w[
|
|
47
54
|
TripsController
|
|
48
55
|
TripSearchController
|
|
56
|
+
VotingContestantsController
|
|
49
57
|
].freeze
|
|
50
58
|
|
|
51
59
|
def shared_max_age
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
module LoadTestAccountManagement
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
include SpreeCmCommissioner::LoadTestAccountScope
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
before_action :authorize_load_testing!, only: %i[create bulk_destroy]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Ensures N load-test accounts exist (idempotent) for `load_test_tenant` (nil = platform).
|
|
12
|
+
def create
|
|
13
|
+
result = SpreeCmCommissioner::LoadTest::CreateAccounts.call(**pool_params)
|
|
14
|
+
|
|
15
|
+
if result.success?
|
|
16
|
+
flash[:success] = "#{result.value[:created]} load-test accounts created."
|
|
17
|
+
else
|
|
18
|
+
flash[:error] = result.error.value
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
redirect_to manage_accounts_redirect_path
|
|
22
|
+
rescue StandardError => e
|
|
23
|
+
flash[:error] = e.message
|
|
24
|
+
redirect_to manage_accounts_redirect_path
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def bulk_destroy
|
|
28
|
+
result = SpreeCmCommissioner::LoadTest::DestroyAccounts.call(**pool_params)
|
|
29
|
+
|
|
30
|
+
if result.success?
|
|
31
|
+
flash[:success] = "#{result.value[:destroyed]} destroyed, #{result.value[:not_found]} not found (already removed)."
|
|
32
|
+
else
|
|
33
|
+
flash[:error] = result.error.value
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
redirect_to manage_accounts_redirect_path
|
|
37
|
+
rescue StandardError => e
|
|
38
|
+
flash[:error] = e.message
|
|
39
|
+
redirect_to manage_accounts_redirect_path
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
# Default: cancancan's `authorize!`. Override in the including controller if it doesn't use
|
|
45
|
+
# cancancan (e.g. the organizer dashboard, which authorizes via RoleAuthorization/can_manage?).
|
|
46
|
+
def authorize_load_testing!
|
|
47
|
+
authorize! :manage, :load_testing
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Where create/bulk_destroy redirect back to. Must be implemented by the including controller
|
|
51
|
+
# (points at its own Load Test Accounts page).
|
|
52
|
+
def manage_accounts_redirect_path
|
|
53
|
+
raise NotImplementedError, "#{self.class} must implement #manage_accounts_redirect_path"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def pool_params
|
|
57
|
+
{
|
|
58
|
+
client_id: resolve_client_id,
|
|
59
|
+
count: params[:count].presence&.to_i || 20,
|
|
60
|
+
email_prefix: params[:email_prefix].presence || 'loadtest',
|
|
61
|
+
email_domain: params[:email_domain].presence
|
|
62
|
+
}
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Carries the form field values through the redirect so the index page re-renders with the
|
|
66
|
+
# same count/prefix/domain/page/per_page the admin/organizer just submitted with.
|
|
67
|
+
def redirect_params
|
|
68
|
+
params.slice(:count, :email_prefix, :email_domain, :page, :per_page).permit!
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def resolve_client_id
|
|
72
|
+
return nil if load_test_tenant.nil?
|
|
73
|
+
|
|
74
|
+
application = Spree::OauthApplication.where(tenant_id: load_test_tenant.id).order(:id).first
|
|
75
|
+
raise "No OAuth application found for tenant #{load_test_tenant.name}" unless application
|
|
76
|
+
|
|
77
|
+
application.uid
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
module LoadTestAccountScope
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
private
|
|
6
|
+
|
|
7
|
+
# The tenant these accounts are scoped to. nil means the platform (no tenant). Must be
|
|
8
|
+
# implemented by the including controller.
|
|
9
|
+
def load_test_tenant
|
|
10
|
+
raise NotImplementedError, "#{self.class} must implement #load_test_tenant"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
DEFAULT_EXPORT_PER_PAGE = 10
|
|
14
|
+
|
|
15
|
+
# Queried fresh from the DB every time, so it's always in sync with the current pool rather than
|
|
16
|
+
# a stashed file or session state.
|
|
17
|
+
#
|
|
18
|
+
# Filters the `load_test_account` flag in SQL via the model's `load_test_accounts` scope (see
|
|
19
|
+
# UserDecorator), so only the tenant's load-test accounts are considered — never the whole users
|
|
20
|
+
# table. Unlike the old `order(:id).limit(2000).select(&:...)` approach, there's no scan cap:
|
|
21
|
+
# newly created accounts (highest ids, ordered first below) always show up even on tenants with
|
|
22
|
+
# far more than 2,000 users.
|
|
23
|
+
#
|
|
24
|
+
# Kaminari pages on the relation itself, so the DB only ever loads the current page's rows
|
|
25
|
+
# (`LIMIT`/`OFFSET`) — never the full pool into memory — via the same `page`/`per_page` params
|
|
26
|
+
# and `paginate` view helper every other index page in this app uses.
|
|
27
|
+
#
|
|
28
|
+
# Shared between LoadTestAccountManagement (lists/mutates the pool) and
|
|
29
|
+
# LoadTestLoginTokenGeneration (mints tokens for exactly the page shown), so both controllers
|
|
30
|
+
# resolve the same page the same way.
|
|
31
|
+
def export_accounts
|
|
32
|
+
Spree::User.where(tenant_id: load_test_tenant&.id)
|
|
33
|
+
.load_test_accounts
|
|
34
|
+
.order(id: :desc)
|
|
35
|
+
.page(params[:page])
|
|
36
|
+
.per(params[:per_page] || DEFAULT_EXPORT_PER_PAGE)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
# Sets Current.load_test_bypass when the request carries the correct X-Request-Verify secret, so
|
|
3
|
+
# anti-abuse services (e.g. InventoryHolds::ValidateLimits) can skip their checks for trusted
|
|
4
|
+
# load tests. No-op unless LOAD_TEST_BYPASS_KEY is set. Include in any controller that can
|
|
5
|
+
# trigger such a check.
|
|
6
|
+
module LoadTestBypassable
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
included do
|
|
10
|
+
before_action :set_load_test_bypass_current
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
# Always assigns the flag (false unless the request carries the correct
|
|
16
|
+
# secret), so its value never leaks from a previous request.
|
|
17
|
+
def set_load_test_bypass_current
|
|
18
|
+
SpreeCmCommissioner::Current.load_test_bypass = load_test_bypass_requested?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def load_test_bypass_requested?
|
|
22
|
+
key = ENV.fetch('LOAD_TEST_BYPASS_KEY', nil)
|
|
23
|
+
return false if key.blank?
|
|
24
|
+
|
|
25
|
+
provided = request.headers.fetch('X-Request-Verify', nil).to_s
|
|
26
|
+
ActiveSupport::SecurityUtils.secure_compare(provided, key)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
module LoadTestLoginTokenGeneration
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
include SpreeCmCommissioner::LoadTestAccountScope
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
before_action :authorize_load_testing!, only: %i[create]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Mints a fresh, stateless login-token JWT for each account on the requested page (same
|
|
12
|
+
# page/per_page as the Load Test Accounts index) and returns them as JSON. Nothing is
|
|
13
|
+
# persisted — the tokens are self-contained and verified by signature + expiry alone (see
|
|
14
|
+
# SpreeCmCommissioner::LoadTest::LoginToken).
|
|
15
|
+
def create
|
|
16
|
+
render json: login_tokens_payload(export_accounts)
|
|
17
|
+
rescue StandardError => e
|
|
18
|
+
render json: { error: e.message }, status: :unprocessable_entity
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
# Default: cancancan's `authorize!`. Override in the including controller if it doesn't use
|
|
24
|
+
# cancancan (e.g. the organizer dashboard, which authorizes via RoleAuthorization/can_manage?).
|
|
25
|
+
def authorize_load_testing!
|
|
26
|
+
authorize! :manage, :load_testing
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# aud claim: the admin/organizer who minted the tokens. No fallback — both hosting controllers
|
|
30
|
+
# already require an authenticated user for every action here, so spree_current_user being
|
|
31
|
+
# absent would be a bug worth raising on, not silently mislabeling as 'system'.
|
|
32
|
+
def token_audience
|
|
33
|
+
spree_current_user.id
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# user_id + the user_id_token are all k6 needs (email and expiry are already claims inside the
|
|
37
|
+
# JWT itself — sub / exp — and the token alone identifies + authenticates the account via
|
|
38
|
+
# UserPasswordAuthenticator's token-only path). expires_at is included too, purely so the
|
|
39
|
+
# generated-tokens list can show it to a human without decoding the JWT. Named `user_id_token`
|
|
40
|
+
# (not `id_token`) so UserAuthenticator can route on the params key alone, without decoding
|
|
41
|
+
# every request's `id_token` to check whether it's a load-test token.
|
|
42
|
+
def login_tokens_payload(accounts)
|
|
43
|
+
accounts.map do |user|
|
|
44
|
+
generated = SpreeCmCommissioner::LoadTest::LoginToken.generate(user: user, audience: token_audience)
|
|
45
|
+
{
|
|
46
|
+
user_id: user.id,
|
|
47
|
+
user_id_token: generated[:token],
|
|
48
|
+
expires_at: generated[:expires_at]
|
|
49
|
+
}
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -12,6 +12,7 @@ module SpreeCmCommissioner
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
@spree_current_order.last_ip_address = request.remote_ip
|
|
15
|
+
@spree_current_order.device_id = device_id if device_id.present?
|
|
15
16
|
@spree_current_order
|
|
16
17
|
end
|
|
17
18
|
|
|
@@ -25,5 +26,9 @@ module SpreeCmCommissioner
|
|
|
25
26
|
state: params[:state]
|
|
26
27
|
)
|
|
27
28
|
end
|
|
29
|
+
|
|
30
|
+
def device_id
|
|
31
|
+
params[:device_id].presence
|
|
32
|
+
end
|
|
28
33
|
end
|
|
29
34
|
end
|
|
@@ -27,13 +27,15 @@ module SpreeCmCommissioner
|
|
|
27
27
|
return unless result.failure?
|
|
28
28
|
|
|
29
29
|
render json: {
|
|
30
|
-
errors: [
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
errors: [
|
|
31
|
+
{
|
|
32
|
+
status: '403',
|
|
33
|
+
error_code: 'human_verification_failed',
|
|
34
|
+
title: I18n.t('turnstile.verification_failed'),
|
|
35
|
+
detail: result.message,
|
|
36
|
+
turnstile_error_code: result.respond_to?(:error_code) ? result.error_code : nil
|
|
37
|
+
}
|
|
38
|
+
]
|
|
37
39
|
}, status: :forbidden
|
|
38
40
|
end
|
|
39
41
|
|
|
@@ -80,8 +80,10 @@ module Spree
|
|
|
80
80
|
|
|
81
81
|
def permitted_resource_params
|
|
82
82
|
params.require(object_name).permit(:first_name, :last_name, :gender, :dob, :occupation_id,
|
|
83
|
-
:nationality_id, :age, :emergency_contact,
|
|
84
|
-
:seat_number, :phone_number
|
|
83
|
+
:nationality_id, :age, :emergency_contact,
|
|
84
|
+
:line_item_id, :seat_number, :phone_number, :contact,
|
|
85
|
+
:other_organization, :expectation, :address,
|
|
86
|
+
:social_contact_platform, :social_contact
|
|
85
87
|
)
|
|
86
88
|
end
|
|
87
89
|
|
|
@@ -23,6 +23,31 @@ module Spree
|
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
|
+
|
|
27
|
+
# POST: /admin/orders/import_new_orders/:id/cancel
|
|
28
|
+
def cancel
|
|
29
|
+
import = model_class.find(params[:id])
|
|
30
|
+
show_url = spree.admin_import_new_order_url(import.id)
|
|
31
|
+
|
|
32
|
+
unless import.cancellable?
|
|
33
|
+
flash[:error] = 'These orders cannot be canceled.' # rubocop:disable Rails/I18nLocaleTexts
|
|
34
|
+
redirect_to show_url and return
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
if params[:confirm_name].to_s.strip != import.name.to_s.strip
|
|
38
|
+
flash[:error] = 'Import name did not match. Cancellation aborted.' # rubocop:disable Rails/I18nLocaleTexts
|
|
39
|
+
redirect_to show_url and return
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
SpreeCmCommissioner::CancelImportOrderJob.perform_later(
|
|
43
|
+
import_order_id: import.id,
|
|
44
|
+
canceled_by_user_id: spree_current_user.id,
|
|
45
|
+
cancellation_reason: params[:cancellation_reason].to_s.strip.presence
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
flash[:success] = "Canceling orders from \"#{import.name}\". This runs in the background."
|
|
49
|
+
redirect_to show_url
|
|
50
|
+
end
|
|
26
51
|
end
|
|
27
52
|
end
|
|
28
53
|
end
|
|
@@ -9,6 +9,7 @@ module Spree
|
|
|
9
9
|
q['s'] ||= 'created_at desc'
|
|
10
10
|
q['created_at_gt'] = parse_time_or_nil(q['created_at_gt'], :beginning_of_day) if q['created_at_gt'].present?
|
|
11
11
|
q['created_at_lt'] = parse_time_or_nil(q['created_at_lt'], :end_of_day) if q['created_at_lt'].present?
|
|
12
|
+
normalize_enum_filters!(q)
|
|
12
13
|
|
|
13
14
|
@search = scope.ransack(q)
|
|
14
15
|
result_scope = @search.result(distinct: true)
|
|
@@ -18,7 +19,11 @@ module Spree
|
|
|
18
19
|
.page(params[:page])
|
|
19
20
|
.per(params[:per_page] || Spree::Backend::Config[:admin_orders_per_page])
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
# Status tab counts must reflect every other filter but NOT the status filter, so
|
|
23
|
+
# each tab shows how many holds it would return (otherwise selecting one status
|
|
24
|
+
# zeroes out all the other tabs).
|
|
25
|
+
@status_counts = scope.ransack(q.except('status_eq')).result(distinct: true)
|
|
26
|
+
.reorder(nil).group(:status).count
|
|
22
27
|
end
|
|
23
28
|
|
|
24
29
|
def release
|
|
@@ -44,8 +49,23 @@ module Spree
|
|
|
44
49
|
|
|
45
50
|
private
|
|
46
51
|
|
|
52
|
+
# `status` and `release_reason` are integer-backed enums. Ransack casts a string
|
|
53
|
+
# value for an integer column with String#to_i, so "payment_locked" becomes 0
|
|
54
|
+
# (== :pending) and every label silently filters to the wrong status. Translate
|
|
55
|
+
# enum labels to their stored integer before searching.
|
|
56
|
+
def normalize_enum_filters!(query)
|
|
57
|
+
{
|
|
58
|
+
'status_eq' => SpreeCmCommissioner::InventoryHold.statuses,
|
|
59
|
+
'release_reason_eq' => SpreeCmCommissioner::InventoryHold.release_reasons
|
|
60
|
+
}.each do |key, mapping|
|
|
61
|
+
value = query[key]
|
|
62
|
+
query[key] = mapping[value.to_s] if value.present? && mapping.key?(value.to_s)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
47
66
|
def back_params
|
|
48
67
|
raw_params = params[:back_params].presence || params
|
|
68
|
+
raw_params = raw_params.to_unsafe_h if raw_params.respond_to?(:to_unsafe_h)
|
|
49
69
|
ActionController::Parameters.new(raw_params).permit(:page, :per_page, q: {})
|
|
50
70
|
end
|
|
51
71
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Admin
|
|
3
|
+
module System
|
|
4
|
+
class LoadTestAccountsController < Spree::Admin::BaseController
|
|
5
|
+
include SpreeCmCommissioner::LoadTestAccountManagement
|
|
6
|
+
|
|
7
|
+
def index
|
|
8
|
+
@export_accounts = export_accounts
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
# nil = platform. Admin load testing never operates on a tenant.
|
|
14
|
+
def load_test_tenant
|
|
15
|
+
nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def manage_accounts_redirect_path
|
|
19
|
+
admin_system_load_test_accounts_path(**redirect_params)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Admin
|
|
3
|
+
module System
|
|
4
|
+
class LoadTestLoginTokensController < Spree::Admin::BaseController
|
|
5
|
+
include SpreeCmCommissioner::LoadTestLoginTokenGeneration
|
|
6
|
+
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
# nil = platform. Admin load testing never operates on a tenant.
|
|
10
|
+
def load_test_tenant
|
|
11
|
+
nil
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Admin
|
|
3
|
+
module System
|
|
4
|
+
class MaintenanceTasksController < Spree::Admin::BaseController
|
|
5
|
+
def index
|
|
6
|
+
authorize! :manage, SpreeCmCommissioner::MaintenanceTask
|
|
7
|
+
|
|
8
|
+
@search = scope.ransack(params[:q])
|
|
9
|
+
@tasks = @search.result(distinct: true)
|
|
10
|
+
.order(created_at: :desc)
|
|
11
|
+
.page(params[:page])
|
|
12
|
+
.per(params[:per_page] || Spree::Backend::Config[:admin_orders_per_page])
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def run_now
|
|
16
|
+
authorize! :manage, SpreeCmCommissioner::MaintenanceTask
|
|
17
|
+
|
|
18
|
+
task = SpreeCmCommissioner::MaintenanceTask.find(params[:id])
|
|
19
|
+
|
|
20
|
+
if task.completed_at.present?
|
|
21
|
+
flash[:error] = "Task ##{task.id} is already completed."
|
|
22
|
+
else
|
|
23
|
+
task.update!(manually_triggered: true)
|
|
24
|
+
task.execute
|
|
25
|
+
|
|
26
|
+
if task.completed_at.present?
|
|
27
|
+
flash[:success] = "Task ##{task.id} (#{task.type.demodulize}) ran successfully."
|
|
28
|
+
else
|
|
29
|
+
flash[:error] = "Task ##{task.id} (#{task.type.demodulize}) failed: #{task.last_error}"
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
redirect_to admin_system_maintenance_tasks_path(back_params)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def destroy
|
|
37
|
+
authorize! :manage, SpreeCmCommissioner::MaintenanceTask
|
|
38
|
+
|
|
39
|
+
task = SpreeCmCommissioner::MaintenanceTask.find(params[:id])
|
|
40
|
+
|
|
41
|
+
if task.destroy
|
|
42
|
+
flash[:success] = "Task ##{task.id} has been deleted."
|
|
43
|
+
else
|
|
44
|
+
flash[:error] = task.errors.full_messages.to_sentence.presence || "Failed to delete task ##{task.id}."
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
redirect_to admin_system_maintenance_tasks_path(back_params)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def scope
|
|
53
|
+
SpreeCmCommissioner::MaintenanceTask.accessible_by(current_ability, :manage)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def back_params
|
|
57
|
+
raw_params = params[:back_params].presence || params
|
|
58
|
+
raw_params = raw_params.to_unsafe_h if raw_params.respond_to?(:to_unsafe_h)
|
|
59
|
+
ActionController::Parameters.new(raw_params).permit(:page, :per_page, q: {})
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -4,7 +4,10 @@ module Spree
|
|
|
4
4
|
class WaitingRoomController < Spree::Admin::BaseController
|
|
5
5
|
def show
|
|
6
6
|
@fetcher = SpreeCmCommissioner::WaitingRoomSystemMetadataFetcher.new
|
|
7
|
+
@lobby_fetcher = SpreeCmCommissioner::WaitingRoomLobbyMetadataFetcher.new
|
|
8
|
+
|
|
7
9
|
@fetcher.load_document_data
|
|
10
|
+
@lobby_fetcher.load_document_data
|
|
8
11
|
|
|
9
12
|
@active_sesions_count = SpreeCmCommissioner::WaitingRoomSession.active.count
|
|
10
13
|
end
|
|
@@ -23,12 +26,31 @@ module Spree
|
|
|
23
26
|
redirect_back fallback_location: admin_system_waiting_room_path
|
|
24
27
|
end
|
|
25
28
|
|
|
29
|
+
def modify_max_sessions_count_cap
|
|
30
|
+
modifier = params[:max_sessions_count_cap]&.to_i || 0
|
|
31
|
+
SpreeCmCommissioner::WaitingRoomSystemMetadataSetter.new.modify_max_sessions_count_cap(modifier)
|
|
32
|
+
|
|
33
|
+
redirect_back fallback_location: admin_system_waiting_room_path
|
|
34
|
+
end
|
|
35
|
+
|
|
26
36
|
def force_pull
|
|
27
37
|
SpreeCmCommissioner::WaitingRoomLatestSystemMetadataPullerJob.perform_now
|
|
28
38
|
SpreeCmCommissioner::WaitingGuestsCallerJob.perform_now
|
|
29
39
|
|
|
30
40
|
redirect_back fallback_location: admin_system_waiting_room_path
|
|
31
41
|
end
|
|
42
|
+
|
|
43
|
+
def publish_lobby_path
|
|
44
|
+
result = SpreeCmCommissioner::WaitingRoom::PublishLobbyPath.call
|
|
45
|
+
|
|
46
|
+
if result.success?
|
|
47
|
+
flash[:success] = "Published waiting guests records path: #{result.value[:records_path]}"
|
|
48
|
+
else
|
|
49
|
+
flash[:error] = result.error.to_s
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
redirect_back fallback_location: admin_system_waiting_room_path
|
|
53
|
+
end
|
|
32
54
|
end
|
|
33
55
|
end
|
|
34
56
|
end
|
|
@@ -28,6 +28,10 @@ module Spree
|
|
|
28
28
|
remove_asset(@taxon.home_banner)
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
+
def remove_ad_banner
|
|
32
|
+
remove_asset(@taxon.ad_banner)
|
|
33
|
+
end
|
|
34
|
+
|
|
31
35
|
def remove_video_banner
|
|
32
36
|
remove_asset(@taxon.video_banner)
|
|
33
37
|
end
|
|
@@ -49,6 +53,7 @@ module Spree
|
|
|
49
53
|
@taxon.build_app_banner(attachment: permitted_resource_params.delete(:app_banner)) if permitted_resource_params[:app_banner]
|
|
50
54
|
@taxon.build_web_banner(attachment: permitted_resource_params.delete(:web_banner)) if permitted_resource_params[:web_banner]
|
|
51
55
|
@taxon.build_home_banner(attachment: permitted_resource_params.delete(:home_banner)) if permitted_resource_params[:home_banner]
|
|
56
|
+
@taxon.build_ad_banner(attachment: permitted_resource_params.delete(:ad_banner)) if permitted_resource_params[:ad_banner]
|
|
52
57
|
@taxon.build_video_banner(attachment: permitted_resource_params.delete(:video_banner)) if permitted_resource_params[:video_banner]
|
|
53
58
|
end
|
|
54
59
|
|
|
@@ -20,8 +20,26 @@ module Spree
|
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
# override
|
|
24
|
+
def update
|
|
25
|
+
preserve_non_form_roles
|
|
26
|
+
super
|
|
27
|
+
end
|
|
28
|
+
|
|
23
29
|
private
|
|
24
30
|
|
|
31
|
+
# Role types the user form doesn't render (assigned in organizer dashboards), e.g. check-in groups and preview.
|
|
32
|
+
NON_FORM_ROLE_TYPES = %i[check_in preview].freeze
|
|
33
|
+
|
|
34
|
+
# spree_role_ids= replaces the whole role set, so a submit that omits these would drop them. Merge
|
|
35
|
+
# the user's existing ones back in so they survive. Skip when the form didn't submit roles at all.
|
|
36
|
+
def preserve_non_form_roles
|
|
37
|
+
return if params.dig(:user, :spree_role_ids).nil?
|
|
38
|
+
|
|
39
|
+
preserved_ids = @user.spree_roles.where(role_type: NON_FORM_ROLE_TYPES).pluck(:id).map(&:to_s)
|
|
40
|
+
params[:user][:spree_role_ids] = (params[:user][:spree_role_ids] + preserved_ids).uniq
|
|
41
|
+
end
|
|
42
|
+
|
|
25
43
|
def build_profile
|
|
26
44
|
return unless permitted_resource_params[:profile]
|
|
27
45
|
|