Example #1
0
    def link_routing_slips(cls):
        """Create invoice in CFS.

        Steps:
        1. Find all pending rs with pending status.
        1. Notify mailer
        """
        routing_slips = db.session.query(RoutingSlipModel) \
            .join(PaymentAccountModel, PaymentAccountModel.id == RoutingSlipModel.payment_account_id) \
            .join(CfsAccountModel, CfsAccountModel.account_id == PaymentAccountModel.id) \
            .filter(RoutingSlipModel.status == RoutingSlipStatus.LINKED.value) \
            .filter(CfsAccountModel.status == CfsAccountStatus.ACTIVE.value).all()

        for routing_slip in routing_slips:
            # 1.reverse the child routing slip
            # 2.create receipt to the parent
            # 3.change the payment account of child to parent
            # 4. change the status

            try:
                current_app.logger.debug(f'Linking Routing Slip: {routing_slip.number}')
                payment_account: PaymentAccountModel = PaymentAccountModel.find_by_id(
                    routing_slip.payment_account_id)
                cfs_account: CfsAccountModel = CfsAccountModel.find_effective_by_account_id(
                    payment_account.id)

                # reverse routing slip receipt
                CFSService.reverse_rs_receipt_in_cfs(cfs_account, routing_slip.number)
                cfs_account.status = CfsAccountStatus.INACTIVE.value

                # apply receipt to parent cfs account
                parent_rs: RoutingSlipModel = RoutingSlipModel.find_by_number(routing_slip.parent_number)
                parent_payment_account: PaymentAccountModel = PaymentAccountModel.find_by_id(
                    parent_rs.payment_account_id)
                parent_cfs_account: CfsAccountModel = CfsAccountModel.find_effective_by_account_id(
                    parent_payment_account.id)
                # For linked routing slip receipts, append 'L' to the number to avoid duplicate error
                receipt_number = f'{routing_slip.number}L'
                CFSService.create_cfs_receipt(cfs_account=parent_cfs_account,
                                              rcpt_number=receipt_number,
                                              rcpt_date=routing_slip.routing_slip_date.strftime('%Y-%m-%d'),
                                              amount=routing_slip.total,
                                              payment_method=parent_payment_account.payment_method,
                                              access_token=CFSService.get_fas_token().json().get('access_token'))

                # Add to the list if parent is NSF, to apply the receipts.
                if parent_rs.status == RoutingSlipStatus.NSF.value:
                    total_invoice_amount = cls._apply_routing_slips_to_pending_invoices(parent_rs)
                    current_app.logger.debug(f'Total Invoice Amount : {total_invoice_amount}')
                    # Update the parent routing slip status to ACTIVE
                    parent_rs.status = RoutingSlipStatus.ACTIVE.value
                    # linking routing slip balance is transferred ,so use the total
                    parent_rs.remaining_amount = float(routing_slip.total) - total_invoice_amount

                routing_slip.save()

            except Exception as e:  # NOQA # pylint: disable=broad-except
                capture_message(
                    f'Error on Linking Routing Slip number:={routing_slip.number}, '
                    f'routing slip : {routing_slip.id}, ERROR : {str(e)}', level='error')
                current_app.logger.error(e)
                continue
Example #2
0
    def process_nsf(cls):
        """Process NSF routing slips.

        Steps:
        1. Find all routing slips with NSF status.
        2. Reverse the receipt for the NSF routing slips.
        3. Add an invoice for NSF fees.
        """
        routing_slips: List[RoutingSlipModel] = db.session.query(RoutingSlipModel) \
            .join(PaymentAccountModel, PaymentAccountModel.id == RoutingSlipModel.payment_account_id) \
            .join(CfsAccountModel, CfsAccountModel.account_id == PaymentAccountModel.id) \
            .filter(RoutingSlipModel.status == RoutingSlipStatus.NSF.value) \
            .filter(CfsAccountModel.status == CfsAccountStatus.ACTIVE.value).all()

        current_app.logger.info(f'Found {len(routing_slips)} to process NSF.')
        for routing_slip in routing_slips:
            # 1. Reverse the routing slip receipt.
            # 2. Reverse all the child receipts.
            # 3. Change the CFS Account status to FREEZE.
            try:
                current_app.logger.debug(f'Reverse receipt {routing_slip.number}')
                payment_account: PaymentAccountModel = PaymentAccountModel.find_by_id(routing_slip.payment_account_id)
                cfs_account: CfsAccountModel = CfsAccountModel.find_effective_by_account_id(payment_account.id)

                # Find all child routing slip and reverse it, as all linked routing slips are also considered as NSF.
                child_routing_slips: List[RoutingSlipModel] = RoutingSlipModel.find_children(routing_slip.number)
                for rs in (routing_slip, *child_routing_slips):
                    receipt_number = rs.number
                    if rs.parent_number:
                        receipt_number = f'{receipt_number}L'
                    CFSService.reverse_rs_receipt_in_cfs(cfs_account, receipt_number, is_nsf=True)

                    for payment in db.session.query(PaymentModel) \
                            .filter(PaymentModel.receipt_number == receipt_number).all():
                        payment.payment_status_code = PaymentStatus.FAILED.value

                # Update the CFS Account status to FREEZE.
                cfs_account.status = CfsAccountStatus.FREEZE.value

                # Update all invoice status to CREATED.
                invoices: List[InvoiceModel] = db.session.query(InvoiceModel) \
                    .filter(InvoiceModel.routing_slip == routing_slip.number) \
                    .filter(InvoiceModel.invoice_status_code == InvoiceStatus.PAID.value) \
                    .all()
                for inv in invoices:
                    # Reset the statuses
                    inv.invoice_status_code = InvoiceStatus.CREATED.value
                    inv_ref = InvoiceReferenceModel.find_reference_by_invoice_id_and_status(
                        inv.id, InvoiceReferenceStatus.COMPLETED.value
                    )
                    inv_ref.status_code = InvoiceReferenceStatus.ACTIVE.value
                    # Delete receipts as receipts are reversed in CFS.
                    for receipt in ReceiptModel.find_all_receipts_for_invoice(inv.id):
                        db.session.delete(receipt)

                inv = cls._create_nsf_invoice(cfs_account, routing_slip.number, payment_account)
                # Reduce the NSF fee from remaining amount.
                routing_slip.remaining_amount = float(routing_slip.remaining_amount) - inv.total
                routing_slip.save()

            except Exception as e:  # NOQA # pylint: disable=broad-except
                capture_message(
                    f'Error on Processing NSF for :={routing_slip.number}, '
                    f'routing slip : {routing_slip.id}, ERROR : {str(e)}', level='error')
                current_app.logger.error(e)
                continue