spree_cm_commissioner 2.13.4 → 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/.env.example +5 -0
- 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/inventory_items_controller.rb +11 -0
- data/app/controllers/spree/admin/payment_fee_rules_controller.rb +76 -0
- 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/service_fee_rules_controller.rb +1 -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/cart_payment_fees_controller.rb +48 -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/seat_layouts_controller.rb +3 -1
- 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/cart_payment_fees_controller.rb +43 -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/helpers/spree_cm_commissioner/admin/fee_rules_helper.rb +23 -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 +58 -8
- data/app/models/concerns/spree_cm_commissioner/percent_fee_calculable.rb +36 -0
- data/app/models/concerns/spree_cm_commissioner/product_type.rb +6 -2
- data/app/models/concerns/spree_cm_commissioner/reschedule_request_state_machine.rb +332 -0
- data/app/models/concerns/spree_cm_commissioner/scoped_fee_rule.rb +129 -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/adjustment_decorator.rb +1 -0
- data/app/models/spree_cm_commissioner/audit_event.rb +11 -0
- data/app/models/spree_cm_commissioner/calculators/payment_fee_flat_amount.rb +21 -0
- data/app/models/spree_cm_commissioner/calculators/payment_fee_percent.rb +17 -0
- data/app/models/spree_cm_commissioner/calculators/service_fee_flat_amount.rb +4 -0
- data/app/models/spree_cm_commissioner/calculators/service_fee_percent.rb +5 -2
- 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 +22 -5
- 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 +31 -3
- data/app/models/spree_cm_commissioner/order_updater_decorator.rb +6 -1
- data/app/models/spree_cm_commissioner/payment_decorator.rb +31 -0
- data/app/models/spree_cm_commissioner/payment_fee_rule.rb +97 -0
- data/app/models/spree_cm_commissioner/payment_method_decorator.rb +5 -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/redis_stock/cached_inventory_items_builder.rb +4 -2
- 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 +8 -0
- data/app/models/spree_cm_commissioner/service_calendar.rb +4 -0
- data/app/models/spree_cm_commissioner/service_fee_rule.rb +17 -114
- data/app/models/spree_cm_commissioner/stock/availability_checker.rb +1 -1
- data/app/models/spree_cm_commissioner/stock/order_availability_checker.rb +1 -1
- 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/overrides/spree/admin/shared/_product_tabs/stock_managements.html.erb.deface +1 -1
- data/app/overrides/spree/admin/shared/sub_menu/_configuration/menu_items.html.erb.deface +5 -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/cart_serializer.rb +2 -1
- data/app/serializers/spree/v2/tenant/payment_method_serializer.rb +3 -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/api/v2/platform/homepage_section_relatable_options_serializer.rb +5 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/cart_serializer_decorator.rb +3 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/inventory_item_serializer.rb +1 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/item_availability_sync_serializer.rb +10 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/payment_fee_preview_serializer.rb +19 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/payment_method_serializer_decorator.rb +16 -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/serializers/spree_cm_commissioner/v2/storefront/seat_layout_serializer.rb +8 -0
- data/app/services/spree_cm_commissioner/audit_logger.rb +59 -0
- data/app/services/spree_cm_commissioner/checkout/add_store_credit_decorator.rb +17 -0
- data/app/services/spree_cm_commissioner/checkout/add_store_credit_payments.rb +96 -0
- data/app/services/spree_cm_commissioner/checkout/remove_store_credit_decorator.rb +17 -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/payment_fees/apply.rb +30 -0
- data/app/services/spree_cm_commissioner/payment_fees/clear.rb +15 -0
- data/app/services/spree_cm_commissioner/payment_fees/preview.rb +70 -0
- data/app/services/spree_cm_commissioner/payments/find_or_create_decorator.rb +18 -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/payment_fee_rules/_form.html.erb +135 -0
- data/app/views/spree/admin/payment_fee_rules/edit.html.erb +11 -0
- data/app/views/spree/admin/payment_fee_rules/index.html.erb +100 -0
- data/app/views/spree/admin/payment_fee_rules/new.html.erb +11 -0
- 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/service_fee_rules/_form.html.erb +15 -9
- data/app/views/spree/admin/service_fee_rules/index.html.erb +1 -1
- 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/stock_managements/_header.html.erb +26 -0
- data/app/views/spree/admin/stock_managements/_variant_stock_items.html.erb +1 -1
- data/app/views/spree/admin/stock_managements/calendar.html.erb +285 -171
- data/app/views/spree/admin/stock_managements/index.html.erb +1 -18
- 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 +363 -1
- data/config/locales/km.yml +282 -1
- data/config/routes.rb +67 -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/20260928000001_add_closed_to_cm_inventory_items.rb +5 -0
- data/db/migrate/20261001100000_create_cm_payment_fee_rules.rb +17 -0
- data/db/migrate/20261001100001_add_payment_fee_total_to_spree_orders.rb +5 -0
- data/db/migrate/20261006073317_add_offline_to_spree_products.rb +6 -0
- data/lib/spree_cm_commissioner/cached_inventory_item.rb +7 -1
- data/lib/spree_cm_commissioner/payment_fees/payment_fee_preview.rb +24 -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 +5 -0
- data/lib/tasks/prepaid_reconciliation_cron_scheduler.rake +7 -0
- data/lib/tasks/prepaid_setup_types.rake +7 -0
- metadata +295 -2
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Platform
|
|
5
|
+
# Platform::ResourceController#authorize_spree_user only runs CanCan checks when the
|
|
6
|
+
# request carries a user OAuth token (`spree_current_user.present?`); a bare app
|
|
7
|
+
# (client_credentials) token skips it entirely by design, and the base permitted-params
|
|
8
|
+
# list falls back to every column on the model (`json_api_permitted_attributes`). That
|
|
9
|
+
# would let any app token holding the generic `:admin` doorkeeper scope rewrite
|
|
10
|
+
# `amount`/`amount_used`/`user_id`/`issuer_tenant_id` etc. directly -- bypassing the
|
|
11
|
+
# prepaid ledger (cm_prepaid_transactions) and the AdminCredit/ReverseTopUp/Freeze
|
|
12
|
+
# services that exist to keep it consistent, with no record of who changed what.
|
|
13
|
+
#
|
|
14
|
+
# Nothing in this monorepo (docs, internal services, cm-market-app/client) calls this
|
|
15
|
+
# endpoint -- it's just Spree's default auto-generated CRUD from `resources :store_credits`
|
|
16
|
+
# in spree_api's routes, not something built for a known consumer. Rather than maintain a
|
|
17
|
+
# safe-fields allowlist forever (every future Spree::StoreCredit column is a fresh chance
|
|
18
|
+
# to leak through it), the endpoint is disabled outright: every action 404s, same as an
|
|
19
|
+
# unrouted path would. The route itself still exists (routes.rb lives in gems/spree_api,
|
|
20
|
+
# which this repo's decorator-only rule forbids editing directly), so this is done from
|
|
21
|
+
# our own extension gem instead.
|
|
22
|
+
module StoreCreditsControllerDecorator
|
|
23
|
+
def self.prepended(base)
|
|
24
|
+
# prepend_before_action, not before_action -- runs ahead of the base controller's own
|
|
25
|
+
# doorkeeper_authorize!/authorize_spree_user checks, so this 404s unconditionally
|
|
26
|
+
# (same as an unrouted path would) rather than only after an auth check passes.
|
|
27
|
+
base.prepend_before_action { head :not_found }
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
Spree::Api::V2::Platform::StoreCreditsController.prepend Spree::Api::V2::Platform::StoreCreditsControllerDecorator
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Storefront
|
|
5
|
+
module Account
|
|
6
|
+
# Endpoint: GET /api/v2/storefront/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), omitted returns
|
|
9
|
+
# every currency the platform has issued the user. Replaces the old separate
|
|
10
|
+
# GET account/prepaid (show) + GET account/prepaid_balances (index) pair: #show
|
|
11
|
+
# couldn't express "no currency given" without an :id segment, and this app's other
|
|
12
|
+
# index/show split forced the response shape (object vs array) to vary by param, which
|
|
13
|
+
# is worse than one endpoint with one fixed (array) shape and an optional filter.
|
|
14
|
+
class PrepaidBalancesController < Spree::Api::V2::ResourceController
|
|
15
|
+
before_action :require_spree_current_user
|
|
16
|
+
|
|
17
|
+
def index
|
|
18
|
+
if params[:currency].present?
|
|
19
|
+
currency = params[:currency].to_s.upcase
|
|
20
|
+
unless Spree::Store.default.supported_currency_codes.include?(currency)
|
|
21
|
+
return render_error_payload("unsupported currency: #{currency}")
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
render_serialized_payload { collection_serializer.new(presented_collection(currency)).serializable_hash }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
# Platform-issued prepaid credit only (Spree::StoreCredit#platform_prepaid scope) --
|
|
31
|
+
# storefront is the platform namespace; tenant-issued wallet credit isn't
|
|
32
|
+
# spendable/visible here. Preferred currency sorted first (matches PrepaidConfig's
|
|
33
|
+
# supported_currencies order) rather than left in arbitrary DB order -- the client
|
|
34
|
+
# shouldn't have to inspect is_preferred on every item just to know which one to
|
|
35
|
+
# show first.
|
|
36
|
+
def presented_collection(currency)
|
|
37
|
+
preferred_currency = Spree::Store.default.default_currency
|
|
38
|
+
credits = spree_current_user.store_credits.platform_prepaid(currency).to_a
|
|
39
|
+
credits.sort_by! { |credit| credit.currency == preferred_currency ? 0 : 1 }
|
|
40
|
+
|
|
41
|
+
credits.map { |credit| SpreeCmCommissioner::PrepaidBalancePresenter.new(credit, preferred_currency) }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def collection_serializer
|
|
45
|
+
Spree::V2::Storefront::PrepaidBalanceSerializer
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -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
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V2
|
|
4
|
+
module Storefront
|
|
5
|
+
# GET /api/v2/storefront/cart_payment_fees?payment_method_ids[]=1&payment_method_ids[]=2
|
|
6
|
+
#
|
|
7
|
+
# Payment fee each requested payment method would add to the current cart. Order-scoped
|
|
8
|
+
# and uncached on purpose: the answer depends on line items and applied store credit, both
|
|
9
|
+
# of which change on the payment screen. The client skips methods whose catalog entry says
|
|
10
|
+
# `fee_configured: false`, so carts with no fees configured never hit this.
|
|
11
|
+
class CartPaymentFeesController < Spree::Api::V2::ResourceController
|
|
12
|
+
include OrderConcern
|
|
13
|
+
|
|
14
|
+
before_action :ensure_order
|
|
15
|
+
|
|
16
|
+
# override
|
|
17
|
+
def index
|
|
18
|
+
render_serialized_payload do
|
|
19
|
+
collection_serializer.new(collection).serializable_hash
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# override
|
|
24
|
+
def collection
|
|
25
|
+
@collection ||= requested_payment_methods.map do |payment_method|
|
|
26
|
+
SpreeCmCommissioner::PaymentFees::Preview.call(order: spree_current_order, payment_method: payment_method)
|
|
27
|
+
.value[:payment_fee_preview]
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# override
|
|
32
|
+
def collection_serializer
|
|
33
|
+
SpreeCmCommissioner::V2::Storefront::PaymentFeePreviewSerializer
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
# Ids the order can't actually pay with are dropped rather than rejected, so a stale client
|
|
39
|
+
# list (e.g. a method disabled since the catalog was cached) still gets the rest.
|
|
40
|
+
def requested_payment_methods
|
|
41
|
+
ids = Array(params[:payment_method_ids]).map(&:to_s)
|
|
42
|
+
spree_current_order.available_payment_methods.select { |pm| ids.include?(pm.id.to_s) }
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
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
|
|
@@ -10,6 +10,8 @@ module Spree
|
|
|
10
10
|
class SeatLayoutsController < Spree::Api::V2::ResourceController
|
|
11
11
|
# GET /api/v2/storefront/seat_layouts/:id
|
|
12
12
|
# - include_details=true|false (optional, default: true)
|
|
13
|
+
#
|
|
14
|
+
# Always returns `product_ids` (see SeatLayout#product_ids).
|
|
13
15
|
def show
|
|
14
16
|
render_serialized_payload { serialize_resource(resource) }
|
|
15
17
|
end
|
|
@@ -70,7 +72,7 @@ module Spree
|
|
|
70
72
|
|
|
71
73
|
# override
|
|
72
74
|
def serializer_params
|
|
73
|
-
super.merge(include_details: include_details
|
|
75
|
+
super.merge(include_details: include_details?, include_product_ids: action_name == 'show')
|
|
74
76
|
end
|
|
75
77
|
|
|
76
78
|
# default return true
|
|
@@ -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
|