"""Blueprint for Payment Group Payment API.""" from http import HTTPStatus from typing import List, Tuple from abacus_common_logic.marshalling.base import PaginationSchema from common_apispec import doc, marshal_with, use_kwargs from flask import Blueprint, Response from payment.logic import ( payment_group_payment as logic, payment_group_payment_account as account_logic, payment_group_payment_batch as payment_batch_logic, ) from payment.schemas.payment_group_payment import ( PaymentGroupPaymentDetailSchema, PaymentGroupPaymentListSchema, PaymentGroupPaymentOverviewDataloaderResponseSchema, PaymentGroupPaymentOverviewSchema, PaymentGroupPaymentStatusOverviewDataloaderSchema, PaymentGroupPaymentStatusOverviewSchema, PaymentGroupPaymentTotalsSchema, ) from payment.schemas.payment_group_payment_account import ( PaymentGroupPaymentAccountListItemsSchema, PaymentGroupPaymentAccountPaginationSchema, PaymentGroupPaymentAccountSchema, ) from payment.schemas.payment_group_payment_batch import ( PaymentGroupPaymentBatchStatusSchema, ) from payment.schemas.request import DataloaderParamsPostSchema from payment.utils.authorization import check_access payment_group_payment_api = Blueprint( 'payment_group_payment_api', __name__, url_prefix='/payment-group-payment' ) @payment_group_payment_api.route('/', methods=['POST']) @doc( tags=['Payment Group Payment'], description='Create payment group payment.', ) @check_access @use_kwargs( PaymentGroupPaymentDetailSchema(only=('payment_group_id', 'payment_name')), location='json', ) @marshal_with( PaymentGroupPaymentDetailSchema, code=HTTPStatus.CREATED, description=HTTPStatus.CREATED.phrase, ) def create_payment_group_payment(**params): """Endpoint to create payment group payment.""" return logic.create_payment_group_payment(**params), HTTPStatus.CREATED @payment_group_payment_api.route('//', methods=['GET']) @doc( tags=['Payment Group Payment'], description='Get payment group payment.', ) @check_access @marshal_with( PaymentGroupPaymentDetailSchema, code=HTTPStatus.OK, description=HTTPStatus.OK.phrase, ) def get_payment_group_payment(object_id: int) -> Tuple[dict, int]: """GET payment group payment.""" return logic.get_payment_group_payment(object_id), HTTPStatus.OK @payment_group_payment_api.route('//', methods=['DELETE']) @doc( tags=['Payment Group Payment'], description='Delete payment group payment.', ) @check_access @marshal_with( None, code=HTTPStatus.NO_CONTENT, description=HTTPStatus.NO_CONTENT.phrase, apply=False, ) def delete_payment_group_payment(object_id: int) -> Tuple[None, int]: """GET payment group payment.""" logic.delete_payment_group_payment(object_id) return None, HTTPStatus.NO_CONTENT @payment_group_payment_api.route('/', methods=['GET']) @doc( tags=['Payment Group Payment'], description='Get payment group payments list.', ) @check_access @use_kwargs(PaginationSchema, location='query') @marshal_with( PaymentGroupPaymentListSchema, code=HTTPStatus.OK, description=HTTPStatus.OK.phrase, ) def get_payment_group_payment_list(limit: int, offset: int): """GET payment group payment list.""" return logic.get_payment_group_payments(limit, offset), HTTPStatus.OK @payment_group_payment_api.route( '//irrevocable_revert', methods=['DELETE'] ) @doc( tags=['Payment Group Payment'], description='Hard delete payment_group_payment related data for irrevocable revert to draft. ' 'This permanently deletes payment_group_payment_account_detail, payment_group_payment_account, ' 'and report_payment_group_payment records.', ) @marshal_with( None, code=HTTPStatus.NO_CONTENT, description=HTTPStatus.NO_CONTENT.phrase, ) @marshal_with( None, code=HTTPStatus.FORBIDDEN, description=HTTPStatus.FORBIDDEN.phrase, apply=False, ) @check_access def irrevocable_revert_payment_group_payment(payment_group_payment_id): """DELETE payment_group_payment related data for irrevocable revert to draft. Hard deletes: - payment_group_payment_account_detail by payment_group_payment_account_id - payment_group_payment_account by payment_group_payment_id - report_payment_group_payment by payment_group_payment_id """ logic.irrevocable_revert_payment_group_payment(payment_group_payment_id) return None, HTTPStatus.NO_CONTENT @payment_group_payment_api.route( '//accounts/', methods=['POST'] ) @doc( tags=['Payment Group Payment'], description='Get payment group payments list.', ) @check_access @use_kwargs( PaymentGroupPaymentAccountSchema( exclude=( 'payment_group_payment_account_id', 'payment_group_payment_id', 'current_statement_period_id', ), many=True, ), location='json', ) @marshal_with(PaymentGroupPaymentAccountSchema(many=True), code=HTTPStatus.CREATED) def bulk_create_payment_group_payment_accounts( *create_params: dict, payment_group_payment_id: int ): """POST one or more payment_group_payment_account records.""" return account_logic.bulk_create( payment_group_payment_id, create_params ), HTTPStatus.CREATED @payment_group_payment_api.route( '//accounts/', methods=['GET'] ) @doc( tags=['Payment Group Payment'], description='Get payment group payments accounts list.', ) @check_access @use_kwargs( PaymentGroupPaymentAccountPaginationSchema, location='query', ) @marshal_with( PaymentGroupPaymentAccountListItemsSchema, code=HTTPStatus.OK, description=HTTPStatus.OK.phrase, ) def get_payment_group_payment_accounts( payment_group_payment_id: int, **params: dict ) -> Tuple[object, int]: """GET paginated list of payment_group_payment_account records.""" return account_logic.get_accounts_list( payment_group_payment_id=payment_group_payment_id, **params ), HTTPStatus.OK @payment_group_payment_api.route( '//overview', methods=['GET'] ) @doc( tags=['Payment Group Payment'], description='Get total amounts and total number of accounts by currency_code.', ) @check_access @marshal_with( PaymentGroupPaymentOverviewSchema(many=True), code=HTTPStatus.OK, description=HTTPStatus.OK.phrase, ) def get_payment_group_payment_overview( payment_group_payment_id: int, ) -> tuple[list[dict], int]: """Get total amounts and total number of accounts by currency_code.""" return account_logic.get_totals_by_payment_group_payment( payment_group_payment_id ), HTTPStatus.OK @payment_group_payment_api.route('/overview/dataloader', methods=['POST']) @check_access @use_kwargs(DataloaderParamsPostSchema(), location='json') @marshal_with( PaymentGroupPaymentOverviewDataloaderResponseSchema(), code=str(HTTPStatus.OK), description=HTTPStatus.OK.phrase, ) @marshal_with( None, code=str(HTTPStatus.BAD_REQUEST), description=HTTPStatus.BAD_REQUEST.phrase, ) def get_payment_group_payment_overview_dataloader(ids: List[int]): """Get total amounts and total number of accounts by currency_code for multiple Payment Group Payments.""" return account_logic.get_totals_by_payment_group_payment_ids(ids), HTTPStatus.OK @payment_group_payment_api.route( '//program-currency-totals', methods=['GET'] ) @doc( tags=['Payment Group Payment'], description='Get total amounts grouped by payoneer program id.', ) @check_access @marshal_with( PaymentGroupPaymentTotalsSchema(many=True), code=HTTPStatus.OK, description=HTTPStatus.OK.phrase, ) def get_payment_group_payment_totals_per_program_id( payment_group_payment_id: int, ) -> tuple[list[dict], int]: """Get total amounts grouped by payoneer program id.""" return account_logic.get_totals_grouped_by_program_id( payment_group_payment_id ), HTTPStatus.OK @payment_group_payment_api.route( '//accounts/pending/', methods=['GET'] ) @doc( tags=['Payment Group Payment'], description='Get pending payment group payments accounts list.', ) @check_access @use_kwargs( PaymentGroupPaymentAccountPaginationSchema, location='query', ) @marshal_with( PaymentGroupPaymentAccountListItemsSchema, code=HTTPStatus.OK, description=HTTPStatus.OK.phrase, ) def get_prior_payment_pending_accounts( payment_group_payment_id: int, **params: dict ) -> Tuple[object, int]: """GET payment_accounts already associated to a pending payment_group_payment.""" return account_logic.get_accounts_list( is_pending=True, payment_group_payment_id=payment_group_payment_id, **params, ), HTTPStatus.OK @payment_group_payment_api.route( '//payment-batches/', defaults={'payment_batch_status': None}, methods=['GET'], ) @payment_group_payment_api.route( '//payment-batches/', methods=['GET'], ) @doc( tags=['Payment Group Payment'], description='Get a list of payment batches for a payment_group_payment_id and optional batch status.', ) @check_access @marshal_with( PaymentGroupPaymentBatchStatusSchema(many=True), code=HTTPStatus.OK, description=HTTPStatus.OK.phrase, ) def get_payment_group_payment_batches( payment_batch_status: str, payment_group_payment_id: int ): """GET a list of payment batches for a payment_group_payment_id and payment_batch_status. This endpoint returns all payment batches if payment_batch_status is not present in the URL, otherwise it returns payment batches according to status specified. Arg: payment_group_payment_id(int): id of the payment_group_payment payment_batch_status(str)(Optional): status of the payment batch is either failed, pending, or success """ # noqa: E501 batch_status = ( payment_batch_status.lower() if payment_batch_status else payment_batch_status ) return payment_batch_logic.get_payment_group_payment_batches( payment_group_payment_id, batch_status ), HTTPStatus.OK @payment_group_payment_api.route( '//payment-status-overview/', methods=['GET'] ) @doc( tags=['Payment Group Payment'], description='Payment status overview for a specified payment_group_payment', ) @check_access @marshal_with( PaymentGroupPaymentStatusOverviewSchema, code=HTTPStatus.OK, description=HTTPStatus.OK.phrase, ) def get_payment_status_overview(payment_group_payment_id: int) -> tuple[object, int]: """GET the payment status overview for a specified payment_group_payment. The endpoint returns the total count of - accounts payments succeeded/failed/rejected - accounts payments failed because of batch failure, Arg: payment_group_payment_id(int): id of the payment_group_payment """ return logic.get_payment_status_overview(payment_group_payment_id), HTTPStatus.OK @payment_group_payment_api.route( '/payment-status-overview/dataloader', methods=['POST'] ) @check_access @use_kwargs(DataloaderParamsPostSchema(), location='json') @marshal_with( PaymentGroupPaymentStatusOverviewDataloaderSchema(), code=HTTPStatus.OK, description=HTTPStatus.OK.phrase, ) @marshal_with( None, code=HTTPStatus.BAD_REQUEST, description=HTTPStatus.BAD_REQUEST.phrase, ) def payment_status_overview_by_payment_group_payment_id_dataloader( ids: List[int], ) -> Tuple[dict, int] | Response: """Dataloader endpoint.""" return logic.dataload_payment_status_overviews(ids), HTTPStatus.OK