spree_cm_commissioner 2.13.5 → 2.13.7
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/Gemfile.lock +1 -1
- data/app/controllers/spree/admin/base_controller_decorator.rb +14 -0
- data/app/controllers/spree/admin/customer_notifications_controller.rb +16 -1
- data/app/controllers/spree/admin/prepaid_transactions_controller.rb +69 -0
- data/app/controllers/spree/admin/private_sales_controller.rb +6 -0
- data/app/controllers/spree/admin/product_commissions_controller.rb +2 -1
- data/app/controllers/spree/admin/reschedule_policies_controller.rb +148 -0
- data/app/controllers/spree/admin/reschedule_requests_controller.rb +82 -0
- data/app/controllers/spree/admin/store_credit_admin_controller.rb +122 -0
- data/app/controllers/spree/admin/ticket_transfer_rules_controller.rb +7 -0
- data/app/controllers/spree/api/v2/platform/store_credits_controller_decorator.rb +35 -0
- data/app/controllers/spree/api/v2/storefront/account/prepaid_balances_controller.rb +52 -0
- data/app/controllers/spree/api/v2/storefront/account/prepaid_transactions_controller.rb +56 -0
- data/app/controllers/spree/api/v2/storefront/draft_orders_controller.rb +37 -0
- data/app/controllers/spree/api/v2/storefront/prepaid_config_controller.rb +22 -0
- data/app/controllers/spree/api/v2/storefront/reschedule_requests_controller.rb +156 -0
- data/app/controllers/spree/api/v2/storefront/transit/item_availabilities_controller.rb +66 -0
- data/app/controllers/spree/api/v2/tenant/account/prepaid_balances_controller.rb +51 -0
- data/app/controllers/spree/api/v2/tenant/account/prepaid_transactions_controller.rb +53 -0
- data/app/controllers/spree/api/v2/tenant/base_controller.rb +20 -0
- data/app/controllers/spree/api/v2/tenant/draft_orders_controller.rb +42 -0
- data/app/controllers/spree/api/v2/tenant/prepaid_config_controller.rb +29 -0
- data/app/controllers/spree_cm_commissioner/admin/store_credits_controller_decorator.rb +217 -0
- data/app/errors/spree_cm_commissioner/reschedule_policies/invalid_policyable_error.rb +8 -0
- data/app/errors/spree_cm_commissioner/reschedule_policies/not_reschedulable_error.rb +11 -0
- data/app/errors/spree_cm_commissioner/reschedule_requests/cancel_not_allowed_error.rb +6 -0
- data/app/errors/spree_cm_commissioner/reschedule_requests/complete_cash_payment_error.rb +6 -0
- data/app/errors/spree_cm_commissioner/reschedule_requests/eligibility_denied_error.rb +7 -0
- data/app/factory/spree_cm_commissioner/order_telegram_message_factory.rb +6 -2
- data/app/factory/spree_cm_commissioner/reschedule_telegram_message_factory.rb +141 -0
- data/app/finders/spree_cm_commissioner/inventory_items/recently_changed_finder.rb +1 -1
- data/app/helpers/spree/admin/base_helper_decorator.rb +12 -0
- data/app/helpers/spree/admin/reschedule_policies_helper.rb +35 -0
- data/app/helpers/spree/admin/reschedule_requests_helper.rb +79 -0
- data/app/interactors/spree_cm_commissioner/create_ticket.rb +1 -0
- data/app/jobs/spree_cm_commissioner/audit_event_job.rb +29 -0
- data/app/jobs/spree_cm_commissioner/prepaid_reconciliation_cron_job.rb +9 -0
- data/app/jobs/spree_cm_commissioner/prepaid_reverse_top_up_job.rb +16 -0
- data/app/jobs/spree_cm_commissioner/prepaid_setup_types_job.rb +24 -0
- data/app/jobs/spree_cm_commissioner/prepaid_top_up_credit_job.rb +31 -0
- data/app/jobs/spree_cm_commissioner/reschedule_requests/approval_reminder_job.rb +17 -0
- data/app/jobs/spree_cm_commissioner/reschedule_requests/execute_job.rb +20 -0
- data/app/jobs/spree_cm_commissioner/reschedule_requests/expire_overdue_requests_job.rb +12 -0
- data/app/jobs/spree_cm_commissioner/reschedule_requests/expire_request_job.rb +15 -0
- data/app/jobs/spree_cm_commissioner/reschedule_requests/payment_reminder_job.rb +17 -0
- data/app/models/concerns/spree_cm_commissioner/audit_wrapper.rb +139 -0
- data/app/models/concerns/spree_cm_commissioner/integrations/inventory_sync_cachable.rb +9 -0
- data/app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb +2 -1
- data/app/models/concerns/spree_cm_commissioner/order_prepaid_payment.rb +15 -0
- data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +56 -8
- data/app/models/concerns/spree_cm_commissioner/product_type.rb +1 -1
- data/app/models/concerns/spree_cm_commissioner/reschedule_request_state_machine.rb +332 -0
- data/app/models/concerns/spree_cm_commissioner/service_type.rb +1 -1
- data/app/models/concerns/spree_cm_commissioner/store_preference.rb +1 -0
- data/app/models/concerns/spree_cm_commissioner/tenant_preference.rb +6 -0
- data/app/models/concerns/spree_cm_commissioner/variant_metadata.rb +24 -0
- data/app/models/concerns/spree_cm_commissioner/vehicle_kind.rb +1 -1
- data/app/models/spree/core/controller_helpers/currency_decorator.rb +70 -0
- data/app/models/spree_cm_commissioner/audit_event.rb +11 -0
- data/app/models/spree_cm_commissioner/configuration.rb +17 -9
- data/app/models/spree_cm_commissioner/currency_rate.rb +15 -0
- data/app/models/spree_cm_commissioner/current.rb +8 -0
- data/app/models/spree_cm_commissioner/customer_notification.rb +4 -1
- data/app/models/spree_cm_commissioner/exports/import_order_guests_csv.rb +153 -0
- data/app/models/spree_cm_commissioner/guest.rb +21 -0
- data/app/models/spree_cm_commissioner/integration.rb +31 -0
- data/app/models/spree_cm_commissioner/integrations/book_me_bus_v1.rb +64 -0
- data/app/models/spree_cm_commissioner/integrations/larryta.rb +81 -0
- data/app/models/spree_cm_commissioner/integrations/stadium_x_v1.rb +4 -10
- data/app/models/spree_cm_commissioner/integrations/vireak_buntham.rb +82 -0
- data/app/models/spree_cm_commissioner/inventory_item.rb +12 -0
- data/app/models/spree_cm_commissioner/line_item_decorator.rb +6 -2
- data/app/models/spree_cm_commissioner/notification.rb +8 -0
- data/app/models/spree_cm_commissioner/order_decorator.rb +19 -2
- data/app/models/spree_cm_commissioner/payment_decorator.rb +31 -0
- data/app/models/spree_cm_commissioner/payment_method_store_credit_decorator.rb +81 -0
- data/app/models/spree_cm_commissioner/place.rb +2 -0
- data/app/models/spree_cm_commissioner/prepaid_config.rb +59 -0
- data/app/models/spree_cm_commissioner/prepaid_transaction.rb +102 -0
- data/app/models/spree_cm_commissioner/product_decorator.rb +6 -0
- data/app/models/spree_cm_commissioner/reschedule_policy.rb +94 -0
- data/app/models/spree_cm_commissioner/reschedule_policy_assignment.rb +19 -0
- data/app/models/spree_cm_commissioner/reschedule_request.rb +227 -0
- data/app/models/spree_cm_commissioner/reschedule_requests/guest_selection.rb +80 -0
- data/app/models/spree_cm_commissioner/reschedule_snapshot.rb +65 -0
- data/app/models/spree_cm_commissioner/route.rb +1 -0
- data/app/models/spree_cm_commissioner/seat_layout.rb +1 -0
- data/app/models/spree_cm_commissioner/service_calendar.rb +4 -0
- data/app/models/spree_cm_commissioner/stock_item_decorator.rb +4 -0
- data/app/models/spree_cm_commissioner/store_credit_category_decorator.rb +23 -0
- data/app/models/spree_cm_commissioner/store_credit_decorator.rb +142 -0
- data/app/models/spree_cm_commissioner/store_credit_event_decorator.rb +94 -0
- data/app/models/spree_cm_commissioner/store_credit_type_decorator.rb +43 -0
- data/app/models/spree_cm_commissioner/store_decorator.rb +8 -0
- data/app/models/spree_cm_commissioner/tenant.rb +37 -0
- data/app/models/spree_cm_commissioner/trip.rb +2 -1
- data/app/models/spree_cm_commissioner/trip_stop.rb +2 -0
- data/app/models/spree_cm_commissioner/user_decorator.rb +79 -0
- data/app/models/spree_cm_commissioner/variant_decorator.rb +9 -1
- data/app/models/spree_cm_commissioner/vehicle.rb +3 -0
- data/app/models/spree_cm_commissioner/vehicle_type.rb +1 -0
- data/app/models/spree_cm_commissioner/vendor_decorator.rb +53 -0
- data/app/models/spree_cm_commissioner/vendor_place.rb +2 -0
- data/app/notifications/spree_cm_commissioner/reschedule_approved_notification.rb +7 -0
- data/app/notifications/spree_cm_commissioner/reschedule_cancelled_notification.rb +7 -0
- data/app/notifications/spree_cm_commissioner/reschedule_completed_notification.rb +7 -0
- data/app/notifications/spree_cm_commissioner/reschedule_expired_notification.rb +7 -0
- data/app/notifications/spree_cm_commissioner/reschedule_failed_notification.rb +7 -0
- data/app/notifications/spree_cm_commissioner/reschedule_notification_base.rb +41 -0
- data/app/notifications/spree_cm_commissioner/reschedule_payment_reminder_notification.rb +15 -0
- data/app/notifications/spree_cm_commissioner/reschedule_rejected_notification.rb +7 -0
- data/app/notifications/spree_cm_commissioner/reschedule_requested_notification.rb +7 -0
- data/app/overrides/spree/admin/products/_form/offline.html.erb.deface +9 -0
- data/app/overrides/spree/admin/shared/_main_menu/sidebar_reschedule.html.erb.deface +9 -0
- data/app/overrides/spree/admin/shared/_main_menu/sidebar_store_credit.html.erb.deface +8 -0
- data/app/overrides/spree/admin/shared/_order_tabs/reschedule_requests.html.erb.deface +10 -0
- data/app/presenters/spree_cm_commissioner/prepaid_balance_presenter.rb +16 -0
- data/app/queries/spree_cm_commissioner/store_credit_overview_query.rb +75 -0
- data/app/queries/spree_cm_commissioner/user_store_credit_summary_query.rb +53 -0
- data/app/serializables/spree_cm_commissioner/item_availability_sync.rb +10 -0
- data/app/serializers/spree/v2/storefront/prepaid_balance_serializer.rb +15 -0
- data/app/serializers/spree/v2/storefront/prepaid_config_serializer.rb +11 -0
- data/app/serializers/spree/v2/storefront/prepaid_transaction_serializer.rb +17 -0
- data/app/serializers/spree/v2/storefront/user_serializer_decorator.rb +6 -0
- data/app/serializers/spree/v2/tenant/prepaid_balance_serializer.rb +15 -0
- data/app/serializers/spree/v2/tenant/prepaid_config_serializer.rb +16 -0
- data/app/serializers/spree/v2/tenant/prepaid_transaction_serializer.rb +16 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/cart_serializer_decorator.rb +2 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/item_availability_sync_serializer.rb +10 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/reschedule_request_serializer.rb +49 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/reschedule_snapshot_serializer.rb +24 -0
- data/app/services/spree_cm_commissioner/audit_logger.rb +59 -0
- data/app/services/spree_cm_commissioner/checkout/add_store_credit_payments.rb +96 -0
- data/app/services/spree_cm_commissioner/currency_converter/create.rb +27 -0
- data/app/services/spree_cm_commissioner/currency_rates/manage.rb +99 -0
- data/app/services/spree_cm_commissioner/customer_notifications/clone.rb +39 -0
- data/app/services/spree_cm_commissioner/google_maps_geocoder.rb +41 -0
- data/app/services/spree_cm_commissioner/imports/orders/create.rb +24 -11
- data/app/services/spree_cm_commissioner/integrations/base/sync_manager.rb +1 -2
- data/app/services/spree_cm_commissioner/integrations/base/sync_result.rb +11 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/external_client/client.rb +230 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/external_client/connection.rb +147 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/inventory/external_inventory_item_status.rb +52 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/inventory/external_inventory_items.rb +91 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/inventory/unstock_inventory.rb +188 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_inventory.rb +79 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_item_availability.rb +354 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_locations.rb +103 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_nationality_pricing.rb +93 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_product.rb +70 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_route_stops.rb +121 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_routes.rb +128 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_seat_layout.rb +412 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_service_calendars.rb +59 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_trip_stop.rb +224 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_trips.rb +769 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_variant.rb +69 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/sync_vehicle_types.rb +92 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/polling/time_parser.rb +19 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/base.rb +40 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/inventory_item_status.rb +148 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/location.rb +55 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/reservation_cart.rb +85 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/seat.rb +128 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/seat_layout.rb +386 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/stop.rb +84 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/trip.rb +237 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/resources/wallet_payment.rb +48 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/sync_manager.rb +22 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/sync_strategies/full_sync_strategy.rb +116 -0
- data/app/services/spree_cm_commissioner/integrations/book_me_bus_v1/sync_strategies/incremental_sync_strategy.rb +63 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/external_client/client.rb +314 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/external_client/connection.rb +74 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/inventory/external_inventory_item_status.rb +53 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/inventory/external_inventory_items.rb +106 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/inventory/hold_seats.rb +143 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/inventory/release_seats.rb +90 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/inventory/unstock_inventory.rb +143 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_item_availability.rb +325 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_product.rb +72 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_routes.rb +142 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_seat_layout.rb +255 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_stock_item.rb +55 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_trip_stop.rb +171 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_trips.rb +397 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_variant.rb +63 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/polling/sync_vehicle_type.rb +79 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/resources/base.rb +39 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/resources/booking.rb +113 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/resources/booking_session.rb +43 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/resources/booking_transaction.rb +236 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/resources/direction.rb +71 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/resources/passenger.rb +48 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/resources/schedule.rb +150 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/resources/seat.rb +31 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/resources/seat_availability.rb +49 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/resources/seat_layout.rb +211 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/sync_manager.rb +17 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/sync_strategies/full_sync_strategy.rb +79 -0
- data/app/services/spree_cm_commissioner/integrations/larryta/sync_strategies/incremental_sync_strategy.rb +58 -0
- data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/external_client/client.rb +14 -15
- data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/polling/sync_matches.rb +7 -4
- data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/polling/sync_zones.rb +6 -3
- data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/sync_manager.rb +0 -3
- data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/sync_strategies/full_sync_strategy.rb +1 -3
- data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/sync_strategies/incremental_sync_strategy.rb +1 -3
- data/app/services/spree_cm_commissioner/integrations/stadium_x_v1/sync_strategies/webhook_sync_strategy.rb +1 -2
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/external_client/client.rb +170 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/external_client/connection.rb +59 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/inventory/external_inventory_item_status.rb +48 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/inventory/external_inventory_items.rb +92 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/inventory/unstock_inventory.rb +230 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_item_availability.rb +270 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_locations.rb +96 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_nationality_pricing.rb +76 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_product.rb +69 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_routes.rb +110 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_seat_layout.rb +207 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_stock_item.rb +43 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_trip_stop.rb +192 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_trips.rb +377 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_variant.rb +56 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/polling/sync_vehicle_type.rb +51 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/base.rb +32 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/booking.rb +48 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/booking_transaction.rb +46 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/cell.rb +53 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/confirm_booking_request.rb +43 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/location.rb +37 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/schedule.rb +138 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/seat.rb +48 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/resources/seat_layout.rb +79 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/sync_manager.rb +17 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/sync_strategies/full_sync_strategy.rb +87 -0
- data/app/services/spree_cm_commissioner/integrations/vireak_buntham/sync_strategies/incremental_sync_strategy.rb +53 -0
- data/app/services/spree_cm_commissioner/inventory_holds/release.rb +13 -0
- data/app/services/spree_cm_commissioner/inventory_items/generate_permanent_item.rb +48 -0
- data/app/services/spree_cm_commissioner/order_holds/hold.rb +17 -0
- data/app/services/spree_cm_commissioner/order_holds/release.rb +31 -0
- data/app/services/spree_cm_commissioner/place_resolver.rb +95 -0
- data/app/services/spree_cm_commissioner/prepaid/admin_credit.rb +44 -0
- data/app/services/spree_cm_commissioner/prepaid/check_top_up_limits.rb +47 -0
- data/app/services/spree_cm_commissioner/prepaid/freeze.rb +58 -0
- data/app/services/spree_cm_commissioner/prepaid/mutation.rb +78 -0
- data/app/services/spree_cm_commissioner/prepaid/reverse_order_top_up.rb +23 -0
- data/app/services/spree_cm_commissioner/prepaid/reverse_top_up.rb +53 -0
- data/app/services/spree_cm_commissioner/prepaid/top_up.rb +68 -0
- data/app/services/spree_cm_commissioner/prepaid/unfreeze.rb +47 -0
- data/app/services/spree_cm_commissioner/prepaid_metrics.rb +37 -0
- data/app/services/spree_cm_commissioner/prepaid_reconciliation_service.rb +71 -0
- data/app/services/spree_cm_commissioner/reschedule_policies/assign.rb +52 -0
- data/app/services/spree_cm_commissioner/reschedule_policies/create.rb +71 -0
- data/app/services/spree_cm_commissioner/reschedule_policies/exclude.rb +40 -0
- data/app/services/spree_cm_commissioner/reschedule_policies/resolve.rb +109 -0
- data/app/services/spree_cm_commissioner/reschedule_policies/unassign.rb +23 -0
- data/app/services/spree_cm_commissioner/reschedule_policies/update.rb +73 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/authorize_initiator.rb +79 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/build_request.rb +317 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/calculate_fee.rb +71 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/cancel.rb +55 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/check_eligibility.rb +243 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/collect_payment.rb +204 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/execute.rb +252 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/expire_overdue_requests.rb +28 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/expire_request.rb +24 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/guests/update_seats.rb +210 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/initiate.rb +255 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/issue_compensation.rb +67 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/issue_coupon.rb +90 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/issue_store_credit.rb +16 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/notifications/send_approval_reminder.rb +43 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/notifications/send_payment_reminder.rb +46 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/notifications/send_status_update.rb +42 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/seats/hold.rb +137 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/split_line_item.rb +86 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/telegram/notify_operations.rb +37 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/telegram/notify_vendor.rb +51 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/vendors/approve.rb +61 -0
- data/app/services/spree_cm_commissioner/reschedule_requests/vendors/reject.rb +58 -0
- data/app/services/spree_cm_commissioner/topup_draft_orders/create.rb +234 -0
- data/app/services/spree_cm_commissioner/trips/service_calendars/create_or_update.rb +25 -14
- data/app/services/spree_cm_commissioner/trips/update_single_leg.rb +43 -6
- data/app/views/spree/admin/classifications/edit.html.erb +17 -2
- data/app/views/spree/admin/classifications/new.html.erb +18 -2
- data/app/views/spree/admin/customer_notifications/index.html.erb +45 -3
- data/app/views/spree/admin/integrations/_book_me_bus_v1_fields.html.erb +47 -0
- data/app/views/spree/admin/integrations/_form.html.erb +12 -0
- data/app/views/spree/admin/integrations/_larryta_fields.html.erb +58 -0
- data/app/views/spree/admin/integrations/_vireak_buntham_fields.html.erb +75 -0
- data/app/views/spree/admin/integrations/index.html.erb +1 -1
- data/app/views/spree/admin/prepaid_transactions/index.html.erb +102 -0
- data/app/views/spree/admin/prepaid_transactions/show.html.erb +146 -0
- data/app/views/spree/admin/private_sales/_form.html.erb +24 -1
- data/app/views/spree/admin/private_sales/_stock.html.erb +6 -1
- data/app/views/spree/admin/product_commissions/index.html.erb +7 -2
- data/app/views/spree/admin/reschedule_policies/_form.html.erb +65 -0
- data/app/views/spree/admin/reschedule_policies/edit.html.erb +11 -0
- data/app/views/spree/admin/reschedule_policies/index.html.erb +84 -0
- data/app/views/spree/admin/reschedule_policies/new.html.erb +11 -0
- data/app/views/spree/admin/reschedule_requests/_cancel_modal.html.erb +34 -0
- data/app/views/spree/admin/reschedule_requests/_search_form.html.erb +57 -0
- data/app/views/spree/admin/reschedule_requests/_tabs.html.erb +14 -0
- data/app/views/spree/admin/reschedule_requests/index.html.erb +64 -0
- data/app/views/spree/admin/reschedule_requests/show.html.erb +212 -0
- data/app/views/spree/admin/reschedule_requests/state_changes.html.erb +42 -0
- data/app/views/spree/admin/shared/_products.html.erb +3 -0
- data/app/views/spree/admin/shared/_reschedule_policies_tabs.html.erb +22 -0
- data/app/views/spree/admin/shared/_ticket_transfer_details.html.erb +3 -0
- data/app/views/spree/admin/shared/sub_menu/_reschedule.html.erb +4 -0
- data/app/views/spree/admin/store_credit_admin/_tabs.html.erb +31 -0
- data/app/views/spree/admin/store_credit_admin/_tenant_selector.html.erb +17 -0
- data/app/views/spree/admin/store_credit_admin/show.html.erb +200 -0
- data/app/views/spree/admin/store_credits/index.html.erb +224 -0
- data/app/views/spree/admin/tenants/_form.html.erb +33 -0
- data/app/views/spree/admin/ticket_transfer_rules/_form.html.erb +28 -5
- data/config/initializers/spree_dependencies.rb +3 -0
- data/config/initializers/spree_permitted_attributes.rb +1 -0
- data/config/locales/en.yml +351 -0
- data/config/locales/km.yml +270 -0
- data/config/routes.rb +63 -2
- data/db/migrate/20260327143200_create_cm_audit_events.rb +21 -0
- data/db/migrate/20260410045815_create_cm_currency_rates.rb +23 -0
- data/db/migrate/20260411102139_add_metadata_to_cm_inventory_items.rb +6 -0
- data/db/migrate/20260506120000_create_cm_reschedule_policies.rb +38 -0
- data/db/migrate/20260506120001_create_cm_reschedule_requests.rb +67 -0
- data/db/migrate/20260506120002_add_reschedule_count_to_cm_guests.rb +5 -0
- data/db/migrate/20260521140000_create_cm_reschedule_snapshots.rb +38 -0
- data/db/migrate/20260522160000_create_cm_reschedule_policy_assignments.rb +17 -0
- data/db/migrate/20260722000001_create_cm_prepaid_transactions.rb +31 -0
- data/db/migrate/20260722000002_add_constraints_to_store_credits.rb +46 -0
- data/db/migrate/20260722000003_add_expires_at_to_store_credits.rb +6 -0
- data/db/migrate/20260722000004_add_issuer_tenant_id_to_spree_store_credits.rb +7 -0
- data/db/migrate/20260722000005_add_immutability_trigger_to_cm_prepaid_transactions.rb +36 -0
- data/db/migrate/20260918045558_add_prepaid_currency_columns_to_cm_tenants.rb +6 -0
- data/db/migrate/20260923090000_add_public_private_metadata_to_cm_prepaid_transactions.rb +36 -0
- data/db/migrate/20261006073317_add_offline_to_spree_products.rb +6 -0
- data/lib/spree_cm_commissioner/reschedule_policy_rules.rb +75 -0
- data/lib/spree_cm_commissioner/serializable_transaction.rb +38 -0
- data/lib/spree_cm_commissioner/store_credit_currency_summary.rb +11 -0
- data/lib/spree_cm_commissioner/store_credit_summary.rb +11 -0
- data/lib/spree_cm_commissioner/test_helper/factories/integration_factory.rb +11 -0
- data/lib/spree_cm_commissioner/test_helper/factories/prepaid_transaction_factory.rb +12 -0
- data/lib/spree_cm_commissioner/test_helper/factories/reschedule_policy_assignment_factory.rb +7 -0
- data/lib/spree_cm_commissioner/test_helper/factories/reschedule_policy_factory.rb +59 -0
- data/lib/spree_cm_commissioner/test_helper/factories/reschedule_request_factory.rb +51 -0
- data/lib/spree_cm_commissioner/test_helper/factories/reschedule_snapshot_factory.rb +27 -0
- data/lib/spree_cm_commissioner/version.rb +1 -1
- data/lib/spree_cm_commissioner.rb +4 -0
- data/lib/tasks/prepaid_reconciliation_cron_scheduler.rake +7 -0
- data/lib/tasks/prepaid_setup_types.rake +7 -0
- metadata +269 -2
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Storefront
|
|
5
|
+
module Account
|
|
6
|
+
class PrepaidTransactionsController < Spree::Api::V2::ResourceController
|
|
7
|
+
before_action :require_spree_current_user
|
|
8
|
+
|
|
9
|
+
# See PrepaidTransaction::CUSTOMER_FACING_TYPES for which types these are and why.
|
|
10
|
+
# top_up/admin_credit are the credit-increasing rows; authorize is the negative (hold)
|
|
11
|
+
# row at spend time, already stored with a negative amount (see
|
|
12
|
+
# StoreCreditEventDecorator#signed_amount) so no sign flip is needed here. void is the
|
|
13
|
+
# reversal of an authorize that never captured (order failed/abandoned) -- its amount
|
|
14
|
+
# is positive (money back), pairing with the authorize row it reverses so a "Purchase"
|
|
15
|
+
# doesn't look permanent when it wasn't.
|
|
16
|
+
DISPLAYED_TRANSACTION_TYPES = SpreeCmCommissioner::PrepaidTransaction::CUSTOMER_FACING_TYPES
|
|
17
|
+
|
|
18
|
+
def index
|
|
19
|
+
if params[:currency].present?
|
|
20
|
+
currency = params[:currency].to_s.upcase
|
|
21
|
+
unless Spree::Store.default.supported_currency_codes.include?(currency)
|
|
22
|
+
return render_error_payload("unsupported currency: #{currency}")
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
super
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def collection
|
|
30
|
+
@collection ||= SpreeCmCommissioner::PrepaidTransaction
|
|
31
|
+
.where(store_credit_id: prepaid_credit_ids, transaction_type: DISPLAYED_TRANSACTION_TYPES)
|
|
32
|
+
.includes(order: { payments: :payment_method })
|
|
33
|
+
.order(created_at: :desc)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
# Mirrors PrepaidBalancesController#presented_collection -- an optional ?currency=
|
|
39
|
+
# narrows to one wallet, omitted returns transactions across every currency the user
|
|
40
|
+
# holds. Previously pinned to current_currency (session/store default), which had no
|
|
41
|
+
# way to request a non-default wallet's history, so a KHR top-up never showed up here
|
|
42
|
+
# even though its cm_prepaid_transactions row was written correctly.
|
|
43
|
+
def prepaid_credit_ids
|
|
44
|
+
currency = params[:currency].presence&.upcase
|
|
45
|
+
spree_current_user.store_credits.platform_prepaid(currency).pluck(:id)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def collection_serializer
|
|
49
|
+
Spree::V2::Storefront::PrepaidTransactionSerializer
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -9,6 +9,10 @@ module Spree
|
|
|
9
9
|
|
|
10
10
|
before_action -> { ensure_anonymous_booking_allowed!(draft_order_products) }, only: :create
|
|
11
11
|
|
|
12
|
+
# A top-up credits a wallet, which must belong to a real user -- unlike #create,
|
|
13
|
+
# this action has no guest-checkout path.
|
|
14
|
+
before_action :require_spree_current_user, only: [:topup]
|
|
15
|
+
|
|
12
16
|
# Creates a generic draft order from a locally-assembled cart in a single request.
|
|
13
17
|
# Endpoint: POST /api/v2/storefront/draft_orders
|
|
14
18
|
# Params:
|
|
@@ -36,6 +40,39 @@ module Spree
|
|
|
36
40
|
end
|
|
37
41
|
end
|
|
38
42
|
|
|
43
|
+
# Builds a prepaid top-up order from just an amount and a payment method -- the client
|
|
44
|
+
# never fetches/knows the prepaid_top_up product or variant.
|
|
45
|
+
# Endpoint: POST /api/v2/storefront/draft_orders/topup
|
|
46
|
+
# Params:
|
|
47
|
+
# - amount: the custom top-up amount (required)
|
|
48
|
+
# - payment_method_id: id of the payment method to attach (required)
|
|
49
|
+
# - currency: the wallet currency the client's own currency picker selected (optional --
|
|
50
|
+
# TopupDraftOrders::Create falls back to store.default_currency when nil). Deliberately
|
|
51
|
+
# NOT current_currency: that helper resolves general storefront browsing currency
|
|
52
|
+
# (session -> ?currency= -> store default) -- a stale session[:currency] would
|
|
53
|
+
# silently override what the client explicitly picked here, leading to the amount
|
|
54
|
+
# being validated against the wrong currency's min/max (e.g. a KHR amount checked
|
|
55
|
+
# against the USD cap).
|
|
56
|
+
def topup
|
|
57
|
+
result = SpreeCmCommissioner::TopupDraftOrders::Create.call(
|
|
58
|
+
amount: params[:amount],
|
|
59
|
+
payment_method_id: params[:payment_method_id],
|
|
60
|
+
user: spree_current_user,
|
|
61
|
+
store: current_store,
|
|
62
|
+
currency: params[:currency].presence&.upcase,
|
|
63
|
+
options: {
|
|
64
|
+
device_id: device_id,
|
|
65
|
+
last_ip_address: request.remote_ip
|
|
66
|
+
}
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
if result.success?
|
|
70
|
+
render_serialized_payload(201) { serialize_resource(serializable_order(result.value[:order])) }
|
|
71
|
+
else
|
|
72
|
+
render_error_payload(result.error)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
39
76
|
private
|
|
40
77
|
|
|
41
78
|
# Re-fetch the created order with everything the enriched payload touches eager-loaded, so
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Storefront
|
|
5
|
+
# Endpoint: GET /api/v2/storefront/prepaid_config
|
|
6
|
+
# Public (no sign-in required): a guest should be able to discover currencies/limits
|
|
7
|
+
# before a top-up is submitted.
|
|
8
|
+
class PrepaidConfigController < Spree::Api::V2::ResourceController
|
|
9
|
+
def show
|
|
10
|
+
render_serialized_payload { serialize_resource(SpreeCmCommissioner::PrepaidConfig.resolve) }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def resource_serializer
|
|
16
|
+
Spree::V2::Storefront::PrepaidConfigSerializer
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# Customer-initiated reschedule lifecycle, scoped to the signed-in customer's
|
|
2
|
+
# own bookings. Every action delegates to the same RescheduleRequests::*
|
|
3
|
+
# services the vendor console drives.
|
|
4
|
+
#
|
|
5
|
+
# Actions:
|
|
6
|
+
# - index/show - the customer's own requests only, scoped by `load_request!`
|
|
7
|
+
# - preview - quote only, nothing persisted, terms not required yet
|
|
8
|
+
# - create - persists and auto-advances per policy
|
|
9
|
+
# - pay - online balance-due payment
|
|
10
|
+
# - cancel - withdraws a request already in flight
|
|
11
|
+
#
|
|
12
|
+
|
|
13
|
+
module Spree
|
|
14
|
+
module Api
|
|
15
|
+
module V2
|
|
16
|
+
module Storefront
|
|
17
|
+
class RescheduleRequestsController < ::Spree::Api::V2::ResourceController
|
|
18
|
+
before_action :require_spree_current_user
|
|
19
|
+
|
|
20
|
+
def index
|
|
21
|
+
render_serialized_payload { serialize_collection(paginated_collection) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def show
|
|
25
|
+
render_serialized_payload { serialize_resource(load_request!) }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def preview
|
|
29
|
+
result = run_initiate(preview: true)
|
|
30
|
+
return render_error_payload(result.error) if result.failure?
|
|
31
|
+
|
|
32
|
+
render_serialized_payload { { data: preview_payload(result.value) } }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def create
|
|
36
|
+
return render_error_payload(I18n.t('reschedule_requests.initiate.terms_not_accepted')) unless terms_accepted?
|
|
37
|
+
|
|
38
|
+
result = run_initiate(
|
|
39
|
+
preview: false,
|
|
40
|
+
terms_accepted_at: Time.current,
|
|
41
|
+
reason: reschedule_params[:reason]
|
|
42
|
+
)
|
|
43
|
+
return render_error_payload(result.error) if result.failure?
|
|
44
|
+
|
|
45
|
+
render_serialized_payload(201) { serialize_resource(result.value[:reschedule_request]) }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def cancel
|
|
49
|
+
result = SpreeCmCommissioner::RescheduleRequests::Cancel.call(
|
|
50
|
+
reschedule_request: load_request!,
|
|
51
|
+
cancelled_by: spree_current_user,
|
|
52
|
+
reason: params[:reason]
|
|
53
|
+
)
|
|
54
|
+
return render_error_payload(result.error) if result.failure?
|
|
55
|
+
|
|
56
|
+
render_serialized_payload { serialize_resource(result.value[:reschedule_request]) }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def pay
|
|
60
|
+
result = SpreeCmCommissioner::RescheduleRequests::CollectPayment.call(
|
|
61
|
+
reschedule_request: load_request!,
|
|
62
|
+
payment_params: payment_params,
|
|
63
|
+
acting_user: spree_current_user
|
|
64
|
+
)
|
|
65
|
+
return render_error_payload(result.error) if result.failure?
|
|
66
|
+
|
|
67
|
+
render_serialized_payload do
|
|
68
|
+
Spree::V2::Storefront::PaymentSerializer.new(result.value[:payment], params: serializer_params).serializable_hash
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
def terms_accepted?
|
|
75
|
+
ActiveModel::Type::Boolean.new.cast(reschedule_params[:terms_accepted])
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def run_initiate(preview:, terms_accepted_at: nil, reason: nil)
|
|
79
|
+
SpreeCmCommissioner::RescheduleRequests::Initiate.call(
|
|
80
|
+
order_id: reschedule_params[:order_number],
|
|
81
|
+
line_item_ids: reschedule_params[:line_item_ids],
|
|
82
|
+
new_from_date: reschedule_params[:new_from_date],
|
|
83
|
+
new_to_date: reschedule_params[:new_to_date],
|
|
84
|
+
targets: reschedule_params[:targets],
|
|
85
|
+
initiated_by: spree_current_user,
|
|
86
|
+
initiated_as: 'user',
|
|
87
|
+
options: {
|
|
88
|
+
preview: preview,
|
|
89
|
+
terms_accepted_at: terms_accepted_at,
|
|
90
|
+
reason: reason,
|
|
91
|
+
request_ip: request.remote_ip
|
|
92
|
+
}.compact
|
|
93
|
+
)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def load_request!
|
|
97
|
+
SpreeCmCommissioner::RescheduleRequest
|
|
98
|
+
.for_user(spree_current_user.id)
|
|
99
|
+
.find_by!(number: params[:id])
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def collection
|
|
103
|
+
SpreeCmCommissioner::RescheduleRequest
|
|
104
|
+
.for_user(spree_current_user.id)
|
|
105
|
+
.includes(:order, :previous_request_snapshots, :new_request_snapshots)
|
|
106
|
+
.order(id: :desc)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def default_resource_includes
|
|
110
|
+
%w[before_snapshots after_snapshots]
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def resource_serializer
|
|
114
|
+
SpreeCmCommissioner::V2::Storefront::RescheduleRequestSerializer
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def collection_serializer
|
|
118
|
+
SpreeCmCommissioner::V2::Storefront::RescheduleRequestSerializer
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def preview_payload(value)
|
|
122
|
+
request = value[:reschedule_request]
|
|
123
|
+
{
|
|
124
|
+
fee_amount: request.fee_amount,
|
|
125
|
+
amount_due_total: request.amount_due_total,
|
|
126
|
+
credit_amount_total: request.credit_amount_total,
|
|
127
|
+
currency: request.currency,
|
|
128
|
+
payment_required: request.payment_required?,
|
|
129
|
+
requires_vendor_approval: value[:requires_vendor_approval],
|
|
130
|
+
fee_breakdown: value[:fee_breakdown]
|
|
131
|
+
}
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def reschedule_params
|
|
135
|
+
params.require(:reschedule_request).permit(
|
|
136
|
+
:order_number, :new_from_date, :new_to_date, :reason, :terms_accepted,
|
|
137
|
+
line_item_ids: [],
|
|
138
|
+
targets: [
|
|
139
|
+
:line_item_id, :new_from_date, :new_to_date, :trip_id,
|
|
140
|
+
:boarding_trip_stop_id, :drop_off_trip_stop_id, :variant_id,
|
|
141
|
+
{ guest_ids: [], block_ids: [] }
|
|
142
|
+
]
|
|
143
|
+
)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def payment_params
|
|
147
|
+
params.require(:payment).permit(
|
|
148
|
+
:payment_method_id, :payment_option, :gateway_payment_profile_id,
|
|
149
|
+
:gateway_customer_profile_id, :last_digits, :month, :year, :name
|
|
150
|
+
)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Storefront
|
|
5
|
+
module Transit
|
|
6
|
+
class ItemAvailabilitiesController < ::Spree::Api::V2::ResourceController
|
|
7
|
+
include SpreeCmCommissioner::Integrations::InventorySyncCachable
|
|
8
|
+
|
|
9
|
+
def create
|
|
10
|
+
sync_result = sync_item_availability!
|
|
11
|
+
|
|
12
|
+
unless sync_result.success?
|
|
13
|
+
error_message = sync_result.to_h.dig(:error, :message) || 'Sync failed'
|
|
14
|
+
return render_error_payload(error_message, 422)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
item_availability = SpreeCmCommissioner::ItemAvailabilitySync.new(
|
|
18
|
+
id: trip.id,
|
|
19
|
+
last_sync_at: sync_result.last_synced_at
|
|
20
|
+
)
|
|
21
|
+
render_serialized_payload { serialize_resource(item_availability) }
|
|
22
|
+
rescue ActiveRecord::RecordNotFound => e
|
|
23
|
+
render_error_payload(e.message, 404)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def trip
|
|
29
|
+
@trip ||= SpreeCmCommissioner::Trip.find(params[:trip_id])
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def integration
|
|
33
|
+
@integration ||= trip.vendor&.integration
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def sync_item_availability!
|
|
37
|
+
# Return success result if vendor has no integration
|
|
38
|
+
return SpreeCmCommissioner::Integrations::Base::SyncResult.new if integration.nil?
|
|
39
|
+
|
|
40
|
+
# Check cache first for successful results only
|
|
41
|
+
cached_result = Rails.cache.read(sync_cache_key)
|
|
42
|
+
return cached_result if cached_result
|
|
43
|
+
|
|
44
|
+
# Perform sync
|
|
45
|
+
result = integration.sync_item_availability!(trip_id: trip.id, on_date: params[:on_date])
|
|
46
|
+
|
|
47
|
+
# Only cache successful results to avoid sticky failures
|
|
48
|
+
Rails.cache.write(sync_cache_key, result, expires_in: sync_cache_ttl) if result.success?
|
|
49
|
+
|
|
50
|
+
result
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def sync_cache_key
|
|
54
|
+
# Include trip.updated_at to auto-bust cache when trip is updated by background syncs
|
|
55
|
+
"item_availability_syncs:#{trip.id}:#{params[:on_date]}:#{trip.updated_at.to_i}"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def resource_serializer
|
|
59
|
+
SpreeCmCommissioner::V2::Storefront::ItemAvailabilitySyncSerializer
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Tenant
|
|
5
|
+
module Account
|
|
6
|
+
# Endpoint: GET /api/v2/tenant/account/prepaid_balances
|
|
7
|
+
# Single endpoint for both "my one balance" and "all my balances" -- an optional
|
|
8
|
+
# ?currency= filters down to one (still an array, just 0-or-1 items; hard-rejected if
|
|
9
|
+
# outside the tenant's supported_currencies_list, via BaseController#
|
|
10
|
+
# resolve_requested_currency), omitted returns every currency this tenant has issued the
|
|
11
|
+
# user (ignoring supported_currencies_list -- a balance in a since-unsupported currency
|
|
12
|
+
# stays visible/spendable). Replaces the old separate GET account/prepaid (show) +
|
|
13
|
+
# GET account/prepaid_balances (index) pair -- see Storefront::Account::
|
|
14
|
+
# PrepaidController's own comment for why one endpoint with a fixed array shape beats
|
|
15
|
+
# two endpoints whose response type differs by param.
|
|
16
|
+
class PrepaidBalancesController < BaseController
|
|
17
|
+
before_action :require_spree_current_user
|
|
18
|
+
|
|
19
|
+
def index
|
|
20
|
+
currency = nil
|
|
21
|
+
if params[:currency].present?
|
|
22
|
+
currency, error = resolve_requested_currency
|
|
23
|
+
return render_error_payload(error) if error
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
render_serialized_payload { collection_serializer.new(presented_collection(currency)).serializable_hash }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
# Tenant-issued prepaid credit only (Spree::StoreCredit#tenant_prepaid) -- unlike the
|
|
32
|
+
# storefront version, this is never platform-issued credit: a tenant's own wallet
|
|
33
|
+
# screen shows only what that tenant itself issued this user. Preferred currency
|
|
34
|
+
# sorted first -- see Storefront::Account::PrepaidBalancesController's own comment.
|
|
35
|
+
def presented_collection(currency)
|
|
36
|
+
preferred_currency = @tenant.preferred_currency_or_default
|
|
37
|
+
credits = spree_current_user.store_credits.tenant_prepaid(@tenant.id, currency).to_a
|
|
38
|
+
credits.sort_by! { |credit| credit.currency == preferred_currency ? 0 : 1 }
|
|
39
|
+
|
|
40
|
+
credits.map { |credit| SpreeCmCommissioner::PrepaidBalancePresenter.new(credit, preferred_currency) }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def collection_serializer
|
|
44
|
+
Spree::V2::Tenant::PrepaidBalanceSerializer
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Tenant
|
|
5
|
+
module Account
|
|
6
|
+
# Endpoint: GET /api/v2/tenant/account/prepaid_transactions
|
|
7
|
+
# Mirrors Spree::Api::V2::Storefront::Account::PrepaidTransactionsController, scoped to
|
|
8
|
+
# this tenant's own issued credit only (Spree::StoreCredit#tenant_prepaid) -- same
|
|
9
|
+
# scoping split as Tenant::Account::PrepaidController vs its storefront counterpart.
|
|
10
|
+
class PrepaidTransactionsController < BaseController
|
|
11
|
+
before_action :require_spree_current_user
|
|
12
|
+
|
|
13
|
+
# See PrepaidTransaction::CUSTOMER_FACING_TYPES for which types these are and why.
|
|
14
|
+
DISPLAYED_TRANSACTION_TYPES = SpreeCmCommissioner::PrepaidTransaction::CUSTOMER_FACING_TYPES
|
|
15
|
+
|
|
16
|
+
# Overridden (rather than left to ResourceController#index) so an out-of-list
|
|
17
|
+
# ?currency= is a hard rejection here too, same as Tenant::Account::PrepaidController
|
|
18
|
+
# #show -- without this check, collection's `prepaid_credit&.id` would just silently
|
|
19
|
+
# render an empty list for a bad currency instead of telling the client why.
|
|
20
|
+
def index
|
|
21
|
+
_currency, error = resolve_requested_currency
|
|
22
|
+
return render_error_payload(error) if error
|
|
23
|
+
|
|
24
|
+
super
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def collection
|
|
28
|
+
@collection ||= SpreeCmCommissioner::PrepaidTransaction
|
|
29
|
+
.where(store_credit_id: prepaid_credit&.id, transaction_type: DISPLAYED_TRANSACTION_TYPES)
|
|
30
|
+
.includes(order: { payments: :payment_method })
|
|
31
|
+
.order(created_at: :desc)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
# Same currency resolution as Tenant::Account::PrepaidController#show -- the currency
|
|
37
|
+
# this tenant's wallet screen is currently viewing, not every currency at once (that's
|
|
38
|
+
# what prepaid_balances is for). #index already rejected a bad currency above, so
|
|
39
|
+
# resolve_requested_currency's error here is always nil by the time collection runs.
|
|
40
|
+
def prepaid_credit
|
|
41
|
+
currency, = resolve_requested_currency
|
|
42
|
+
@prepaid_credit ||= spree_current_user.store_credits.tenant_prepaid(@tenant.id, currency).take
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def collection_serializer
|
|
46
|
+
Spree::V2::Tenant::PrepaidTransactionSerializer
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -20,6 +20,26 @@ module Spree
|
|
|
20
20
|
@current_vendor ||= @tenant.active_vendor
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
# current_currency/supported_currency?/supported_currencies are tenant-aware via
|
|
24
|
+
# Spree::Core::ControllerHelpers::CurrencyDecorator (keys off @tenant, set above) --
|
|
25
|
+
# see that file for the tenant-vs-store resolution logic.
|
|
26
|
+
|
|
27
|
+
# Resolves the wallet currency for a tenant-scoped prepaid request: an explicit
|
|
28
|
+
# ?currency= param must be inside this tenant's own supported_currencies_list -- a hard
|
|
29
|
+
# rejection, not a silent fallback, per the design doc (a currency outside the
|
|
30
|
+
# tenant's configured set would otherwise make the restriction cosmetic). Omitted,
|
|
31
|
+
# falls back to Tenant#preferred_currency_or_default. Returns [currency, error_message]
|
|
32
|
+
# -- error_message is nil on success.
|
|
33
|
+
def resolve_requested_currency
|
|
34
|
+
requested = params[:currency].presence
|
|
35
|
+
return [@tenant.preferred_currency_or_default, nil] if requested.blank?
|
|
36
|
+
|
|
37
|
+
currency = requested.to_s.upcase
|
|
38
|
+
return [nil, "unsupported currency: #{currency}"] unless @tenant.supports_currency?(currency)
|
|
39
|
+
|
|
40
|
+
[currency, nil]
|
|
41
|
+
end
|
|
42
|
+
|
|
23
43
|
def render_serialized_payload(status = 200)
|
|
24
44
|
render json: yield, status: status, content_type: content_type
|
|
25
45
|
end
|
|
@@ -7,6 +7,10 @@ module Spree
|
|
|
7
7
|
|
|
8
8
|
before_action -> { ensure_anonymous_booking_allowed!(draft_order_products) }, only: :create
|
|
9
9
|
|
|
10
|
+
# A top-up credits a wallet, which must belong to a real user -- unlike #create,
|
|
11
|
+
# this action has no guest-checkout path.
|
|
12
|
+
before_action :require_spree_current_user, only: [:topup]
|
|
13
|
+
|
|
10
14
|
# Creates a generic draft order from a locally-assembled cart in a single request.
|
|
11
15
|
# Endpoint: POST /api/v2/tenant/draft_orders
|
|
12
16
|
# Params:
|
|
@@ -33,6 +37,44 @@ module Spree
|
|
|
33
37
|
end
|
|
34
38
|
end
|
|
35
39
|
|
|
40
|
+
# Builds a prepaid top-up order from just an amount and a payment method -- the client
|
|
41
|
+
# never fetches/knows the prepaid_top_up product or variant. Tenant-scoped: the resulting
|
|
42
|
+
# order.tenant_id makes PrepaidTopUpCreditJob produce tenant-issued (not platform-issued)
|
|
43
|
+
# credit.
|
|
44
|
+
# Endpoint: POST /api/v2/tenant/draft_orders/topup
|
|
45
|
+
# Params:
|
|
46
|
+
# - amount: the custom top-up amount (required)
|
|
47
|
+
# - payment_method_id: id of the payment method to attach (required)
|
|
48
|
+
# - currency: optional -- must be inside this tenant's own supported_currencies_list if
|
|
49
|
+
# given; omitted, resolves to Tenant#preferred_currency_or_default (see
|
|
50
|
+
# BaseController#resolve_requested_currency). This deliberately doesn't read
|
|
51
|
+
# current_currency here even though it's tenant-aware now too -- resolve_requested_currency
|
|
52
|
+
# hard-rejects an out-of-list currency (422), where current_currency would silently
|
|
53
|
+
# fall back instead, which would make this endpoint's own validation cosmetic.
|
|
54
|
+
def topup
|
|
55
|
+
currency, error = resolve_requested_currency
|
|
56
|
+
return render_error_payload(error) if error
|
|
57
|
+
|
|
58
|
+
result = SpreeCmCommissioner::TopupDraftOrders::Create.call(
|
|
59
|
+
amount: params[:amount],
|
|
60
|
+
payment_method_id: params[:payment_method_id],
|
|
61
|
+
user: spree_current_user,
|
|
62
|
+
store: current_store,
|
|
63
|
+
currency: currency,
|
|
64
|
+
tenant: @tenant,
|
|
65
|
+
options: {
|
|
66
|
+
device_id: params[:device_id],
|
|
67
|
+
last_ip_address: request.remote_ip
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
if result.success?
|
|
72
|
+
render_serialized_payload(201) { serialize_resource(serializable_order(result.value[:order])) }
|
|
73
|
+
else
|
|
74
|
+
render_error_payload(result.error)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
36
78
|
private
|
|
37
79
|
|
|
38
80
|
# Re-fetch the created order with everything the enriched payload touches eager-loaded, so
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Tenant
|
|
5
|
+
# Endpoint: GET /api/v2/tenant/prepaid_config
|
|
6
|
+
# Mirrors Spree::Api::V2::Storefront::PrepaidConfigController, resolved with this tenant
|
|
7
|
+
# so supported_currencies/preferred_currency reflect Tenant#supported_currencies_list/
|
|
8
|
+
# #preferred_currency_or_default -- the same values BaseController#
|
|
9
|
+
# resolve_requested_currency already validates/defaults `?currency=` against on
|
|
10
|
+
# GET account/prepaid_balances and POST draft_orders/topup, now discoverable up front
|
|
11
|
+
# instead of only enforced after the fact on submit. Not under account/ -- this is
|
|
12
|
+
# tenant-wide config, not per-user account data (identical response for every user).
|
|
13
|
+
class PrepaidConfigController < BaseController
|
|
14
|
+
before_action :require_spree_current_user
|
|
15
|
+
|
|
16
|
+
def show
|
|
17
|
+
render_serialized_payload { serialize_resource(SpreeCmCommissioner::PrepaidConfig.resolve(tenant: @tenant)) }
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def resource_serializer
|
|
23
|
+
Spree::V2::Tenant::PrepaidConfigSerializer
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|