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
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