"""DP Payment handlers.""" from http import HTTPStatus from typing import Optional from flask import Response from flask.typing import ResponseReturnValue from flask_pydantic import validate from collaborator.api import app from collaborator.constants import error from collaborator.constants.features import ( ABACUS_COLLABORATORS, ABACUS_COLLABORATORS_PAYONEER_API_INTEGRATION, ) from collaborator.logic import dp_payment from collaborator.models.rds.dp_payment import ( PayoneerEventType, PayoneerPaymentStatus, ) from collaborator.schemas import BaseSchema, SortableRequestMixin from collaborator.schemas.abacus_statement_period import ( GetDpPaymentsForAbacusStatementPeriodResponseSchema, ) from collaborator.utils import features from collaborator.utils import handlers as handler_utils from collaborator.utils.error import OwsError class GetDpPaymentsQuery(BaseSchema, SortableRequestMixin): """Query parameters for GET /dp-payments.""" abacus_statement_period_id: Optional[int] = None collaborator_id: Optional[int] = None account_id: Optional[int] = None payoneer_program_id: Optional[str] = None payoneer_status: Optional[PayoneerPaymentStatus] = None class PayoneerWebhookBody(BaseSchema): """Event received from Abacus Payoneer lambda.""" client_reference_id: str event_type: PayoneerEventType amount: Optional[str] = None currency_code: Optional[str] = None reason_description: Optional[str] = None @app.route("/dp-payment/payoneer-webhook", methods=["POST"]) @validate() @handler_utils.fetch_authorized_resources def dp_payment_payoneer_webhook( authorized_resources, user, body: PayoneerWebhookBody ) -> ResponseReturnValue: """Handle webhook events from Abacus Payoneer lambda.""" payment = dp_payment.get_by_payoneer_payment_id(body.client_reference_id) if not payment: raise OwsError.not_found( code=error.ERROR_CODE_DP_PAYMENT_NOT_FOUND, message=error.ERROR_MESSAGE_DP_PAYMENT_NOT_FOUND, ) if not features.is_feature_enabled_for_account( ABACUS_COLLABORATORS_PAYONEER_API_INTEGRATION, payment.account_id ): return Response(status=HTTPStatus.NO_CONTENT) dp_payment.update_payoneer_status( payment.dp_payment_id, body.event_type, reason=body.reason_description, user=user, ) dp_payment.handle_payment_event(payment, user, body.event_type) return Response(status=HTTPStatus.NO_CONTENT) @app.route("/dp-payments", methods=["GET"]) @validate() def get_dp_payments(query: GetDpPaymentsQuery) -> ResponseReturnValue: """Handle GET DP payments with an optional statement-period filter. Accepts an optional `abacus_statement_period_id` query parameter. When omitted, payments for all statement periods are returned. """ if not features.is_feature_enabled(ABACUS_COLLABORATORS): raise OwsError.forbidden( code=error.ERROR_CODE_AUTHORIZATION, message=error.ERROR_MESSAGE_FORBIDDEN_USER, ) payments, total_amount = dp_payment.get_dp_payments( abacus_statement_period_id=query.abacus_statement_period_id, collaborator_id=query.collaborator_id, account_id=query.account_id, payoneer_program_id=query.payoneer_program_id, payoneer_status=query.payoneer_status, sort_key=query.sort_key, sort_direction=query.sort_direction, ) return GetDpPaymentsForAbacusStatementPeriodResponseSchema( currency_agnostic_total_amount=total_amount, total_count=len(payments), payments=payments, ).dump()