Exemplo n.º 1
0
async def _create_payment_record(amount, ejv_header, receipt_number):
    """Create payment record."""
    PaymentModel(payment_system_code=PaymentSystem.CGI.value,
                 payment_account_id=ejv_header.payment_account_id,
                 payment_method_code=PaymentMethod.EJV.value,
                 payment_status_code=PaymentStatus.COMPLETED.value,
                 receipt_number=receipt_number,
                 invoice_amount=amount,
                 paid_amount=amount,
                 completed_on=datetime.now()).flush()
Exemplo n.º 2
0
def _save_payment(
        payment_date,
        inv_number,
        invoice_amount,  # pylint: disable=too-many-arguments
        paid_amount,
        row,
        status,
        payment_method,
        receipt_number):
    # pylint: disable=import-outside-toplevel
    from pay_api.factory.payment_system_factory import PaymentSystemFactory

    payment_account = _get_payment_account(row)
    pay_service = PaymentSystemFactory.create_from_payment_method(
        payment_method)
    # If status is failed, which means NSF. We already have a COMPLETED payment record, find and update iit.
    payment: PaymentModel = None
    if status == PaymentStatus.FAILED.value:
        payment = _get_payment_by_inv_number_and_status(
            inv_number, PaymentStatus.COMPLETED.value)
        # Just to handle duplicate rows in settlement file,
        # pull out failed payment record if it exists and no COMPLETED payments are present.
        if not payment:
            payment = _get_payment_by_inv_number_and_status(
                inv_number, PaymentStatus.FAILED.value)
    elif status == PaymentStatus.COMPLETED.value:
        # if the payment status is COMPLETED, then make sure there are
        # no other COMPLETED payment for same invoice_number.If found, return. This is to avoid duplicate entries.
        payment = _get_payment_by_inv_number_and_status(
            inv_number, PaymentStatus.COMPLETED.value)
        if payment:
            return

    if not payment:
        payment = PaymentModel()
    payment.payment_method_code = pay_service.get_payment_method_code()
    payment.payment_status_code = status
    payment.payment_system_code = pay_service.get_payment_system_code()
    payment.invoice_number = inv_number
    payment.invoice_amount = invoice_amount
    payment.payment_account_id = payment_account.id
    payment.payment_date = payment_date
    payment.paid_amount = paid_amount
    payment.receipt_number = receipt_number
    db.session.add(payment)
Exemplo n.º 3
0
 def _dao(self):
     if not self.__dao:
         self.__dao = PaymentModel()
     return self.__dao
Exemplo n.º 4
0
    def create(cls, request_json: Dict[str, any], **kwargs):
        """Search for routing slip."""
        # 1. Create customer profile in CFS and store it in payment_account and cfs_accounts
        # 2. Create receipt in CFS
        # 3. Create routing slip and payment records.

        rs_number = request_json.get('number')
        # Validate Routing slip digits and if slip number is unique.
        if cls.validate_and_find_by_number(rs_number):
            raise BusinessException(Error.FAS_INVALID_ROUTING_SLIP_NUMBER)

        payment_methods: [str] = [payment.get('paymentMethod') for payment in request_json.get('payments')]
        # all the payment should have the same payment method
        if len(set(payment_methods)) != 1:
            raise BusinessException(Error.FAS_INVALID_PAYMENT_METHOD)

        # If payment method is cheque and then there is no payment date then raise error
        if payment_methods[0] == PaymentMethod.CHEQUE.value:
            for payment in request_json.get('payments'):
                if payment.get('paymentDate') is None:
                    raise BusinessException(Error.INVALID_REQUEST)

        pay_account: PaymentAccountModel = PaymentAccountModel(
            name=request_json.get('paymentAccount').get('accountName'),
            payment_method=payment_methods[0],
        ).flush()

        CfsAccountModel(
            account_id=pay_account.id,
            status=CfsAccountStatus.PENDING.value
        ).flush()

        total = get_quantized(sum(float(payment.get('paidAmount')) for payment in request_json.get('payments')))

        # Calculate Total USD
        total_usd = get_quantized(sum(float(payment.get('paidUsdAmount', 0))
                                      for payment in request_json.get('payments')))

        # Create a routing slip record.
        routing_slip: RoutingSlipModel = RoutingSlipModel(
            number=rs_number,
            payment_account_id=pay_account.id,
            status=RoutingSlipStatus.ACTIVE.value,
            total=total,
            remaining_amount=total,
            routing_slip_date=string_to_date(request_json.get('routingSlipDate')),
            total_usd=total_usd
        ).flush()

        for payment in request_json.get('payments'):
            PaymentModel(
                payment_system_code=PaymentSystem.FAS.value,
                payment_account_id=pay_account.id,
                payment_method_code=payment.get('paymentMethod'),
                payment_status_code=PaymentStatus.COMPLETED.value,
                receipt_number=rs_number,
                cheque_receipt_number=payment.get('chequeReceiptNumber'),
                is_routing_slip=True,
                paid_amount=payment.get('paidAmount'),
                payment_date=string_to_date(payment.get('paymentDate')) if payment.get('paymentDate') else None,
                created_by=kwargs['user'].user_name,
                paid_usd_amount=payment.get('paidUsdAmount', None)
            ).flush()

        routing_slip.commit()
        return cls.find_by_number(rs_number)
Exemplo n.º 5
0
async def test_credits(session, app, stan_server, event_loop, client_id,
                       events_stan, future, mock_publish, monkeypatch):
    """Test Reconciliations worker."""
    # Call back for the subscription
    from reconciliations.worker import cb_subscription_handler

    # Create a Credit Card Payment
    # register the handler to test it
    await subscribe_to_queue(
        events_stan,
        current_app.config.get('SUBSCRIPTION_OPTIONS').get('subject'),
        current_app.config.get('SUBSCRIPTION_OPTIONS').get('queue'),
        current_app.config.get('SUBSCRIPTION_OPTIONS').get('durable_name'),
        cb_subscription_handler)

    # 1. Create payment account.
    # 2. Create EFT/WIRE payment db record.
    # 3. Create a credit memo db record.
    # 4. Publish credit in settlement file.
    # 5. Mock CFS Response for the receipt and credit memo.
    # 6. Confirm the credit matches the records.
    cfs_account_number = '1234'
    pay_account: PaymentAccountModel = factory_create_online_banking_account(
        status=CfsAccountStatus.ACTIVE.value, cfs_account=cfs_account_number)
    pay_account_id = pay_account.id
    # invoice_number = '1234567890'

    # Create a payment for EFT Wire
    eft_wire_receipt = 'RCPT0012345'
    onac_amount = 100
    cm_identifier = 1000
    cm_amount = 100
    cm_used_amount = 50
    PaymentModel(payment_method_code=PaymentMethod.EFT.value,
                 payment_status_code=PaymentStatus.CREATED.value,
                 payment_system_code='PAYBC',
                 payment_account_id=pay_account.id,
                 completed_on=datetime.now(),
                 paid_amount=onac_amount,
                 receipt_number=eft_wire_receipt).save()

    credit = CreditModel(cfs_identifier=cm_identifier,
                         is_credit_memo=True,
                         amount=cm_amount,
                         remaining_amount=cm_amount,
                         account_id=pay_account_id).save()
    credit_id = credit.id

    # Mock up the Receipt look up
    def mock_receipt(cfs_account: CfsAccountModel, receipt_number: str):  # pylint: disable=unused-argument; mocks of library methods
        return {'receipt_amount': onac_amount}

    # Mock up the Receipt look up
    def mock_cms(cfs_account: CfsAccountModel, cms_number: str):  # pylint: disable=unused-argument; mocks of library methods
        return {'amount_due': cm_amount - cm_used_amount}

    monkeypatch.setattr('pay_api.services.cfs_service.CFSService.get_receipt',
                        mock_receipt)
    monkeypatch.setattr('pay_api.services.cfs_service.CFSService.get_cms',
                        mock_cms)

    # Create a settlement file and publish.
    file_name: str = 'cas_settlement_file.csv'

    # Settlement row
    date = datetime.now().strftime('%d-%b-%y')

    row = [
        RecordType.ONAC.value, SourceTransaction.EFT_WIRE.value,
        eft_wire_receipt, 100001, date, onac_amount, cfs_account_number,
        TargetTransaction.RECEIPT.value, eft_wire_receipt, onac_amount, 0,
        Status.ON_ACC.value
    ]

    create_and_upload_settlement_file(file_name, [row])
    await helper_add_event_to_queue(events_stan, file_name=file_name)

    # Look up credit file and make sure the credits are recorded.
    pay_account = PaymentAccountModel.find_by_id(pay_account_id)
    assert pay_account.credit == onac_amount + cm_amount - cm_used_amount
    credit = CreditModel.find_by_id(credit_id)
    assert credit.remaining_amount == cm_amount - cm_used_amount
Exemplo n.º 6
0
async def test_eft_wire_reconciliations(session, app, stan_server, event_loop,
                                        client_id, events_stan, future,
                                        mock_publish):
    """Test Reconciliations worker."""
    # Call back for the subscription
    from reconciliations.worker import cb_subscription_handler

    # Create a Credit Card Payment
    # register the handler to test it
    await subscribe_to_queue(
        events_stan,
        current_app.config.get('SUBSCRIPTION_OPTIONS').get('subject'),
        current_app.config.get('SUBSCRIPTION_OPTIONS').get('queue'),
        current_app.config.get('SUBSCRIPTION_OPTIONS').get('durable_name'),
        cb_subscription_handler)

    # 1. Create payment account
    # 2. Create invoice and related records
    # 3. Create CFS Invoice records
    # 4. Create a CFS settlement file, and verify the records
    cfs_account_number = '1234'
    pay_account: PaymentAccountModel = factory_create_online_banking_account(
        status=CfsAccountStatus.ACTIVE.value, cfs_account=cfs_account_number)

    invoice: InvoiceModel = factory_invoice(
        payment_account=pay_account,
        total=100,
        service_fees=10.0,
        payment_method_code=PaymentMethod.ONLINE_BANKING.value)
    factory_payment_line_item(invoice_id=invoice.id,
                              filing_fees=90.0,
                              service_fees=10.0,
                              total=90.0)
    invoice_number = '1234567890'
    factory_invoice_reference(invoice_id=invoice.id,
                              invoice_number=invoice_number)
    invoice.invoice_status_code = InvoiceStatus.SETTLEMENT_SCHEDULED.value
    invoice = invoice.save()
    invoice_id = invoice.id
    total = invoice.total

    # Create a payment for EFT Wire
    eft_wire_receipt = 'RCPT0012345'
    paid_amount = 100
    PaymentModel(payment_method_code=PaymentMethod.EFT.value,
                 payment_status_code=PaymentStatus.CREATED.value,
                 payment_system_code='PAYBC',
                 payment_account_id=pay_account.id,
                 completed_on=datetime.now(),
                 paid_amount=paid_amount,
                 receipt_number=eft_wire_receipt).save()

    # Create a settlement file and publish.
    file_name: str = 'cas_settlement_file.csv'

    # Settlement row
    date = datetime.now().strftime('%d-%b-%y')

    row = [
        RecordType.EFTP.value, SourceTransaction.EFT_WIRE.value,
        eft_wire_receipt, 100001, date, total, cfs_account_number,
        TargetTransaction.INV.value, invoice_number, total, 0,
        Status.PAID.value
    ]
    create_and_upload_settlement_file(file_name, [row])
    await helper_add_event_to_queue(events_stan, file_name=file_name)

    # The invoice should be in PAID status and Payment should be completed
    updated_invoice = InvoiceModel.find_by_id(invoice_id)
    assert updated_invoice.invoice_status_code == InvoiceStatus.PAID.value

    payment: PaymentModel = PaymentModel.find_payment_by_receipt_number(
        eft_wire_receipt)
    assert payment.payment_status_code == PaymentStatus.COMPLETED.value
    assert payment.paid_amount == paid_amount
    assert payment.receipt_number == eft_wire_receipt