def apply_routing_slips_to_invoice(cls, # pylint: disable = too-many-arguments, too-many-locals routing_slip_payment_account: PaymentAccountModel, active_cfs_account: CfsAccountModel, parent_routing_slip: RoutingSlipModel, invoice: InvoiceModel, invoice_number: str) -> bool: """Apply routing slips (receipts in CFS) to invoice.""" has_errors = False child_routing_slips: List[RoutingSlipModel] = RoutingSlipModel.find_children(parent_routing_slip.number) # an invoice has to be applied to multiple receipts (incl. all linked RS); apply till the balance is zero for routing_slip in (parent_routing_slip, *child_routing_slips): try: # apply receipt now current_app.logger.debug(f'Apply receipt {routing_slip.number} on invoice {invoice_number} ' f'for routing slip {routing_slip.number}') receipt_number = routing_slip.number # For linked routing slips, new receipt numbers ends with 'L' if routing_slip.status == RoutingSlipStatus.LINKED.value: receipt_number = f'{routing_slip.number}L' # If balance of receipt is zero, continue to next receipt. receipt_balance_before_apply = float( CFSService.get_receipt(active_cfs_account, receipt_number).get('unapplied_amount') ) current_app.logger.debug(f'Current balance on {receipt_number} = {receipt_balance_before_apply}') if receipt_balance_before_apply == 0: continue current_app.logger.debug(f'Applying receipt {receipt_number} to {invoice_number}') receipt_response = CFSService.apply_receipt(active_cfs_account, receipt_number, invoice_number) # Create receipt. receipt = Receipt() receipt.receipt_number = receipt_response.json().get('receipt_number', None) receipt_amount = receipt_balance_before_apply - float(receipt_response.json().get('unapplied_amount')) receipt.receipt_amount = receipt_amount receipt.invoice_id = invoice.id receipt.receipt_date = datetime.now() receipt.flush() invoice_from_cfs = CFSService.get_invoice(active_cfs_account, invoice_number) if invoice_from_cfs.get('amount_due') == 0: break except Exception as e: # NOQA # pylint: disable=broad-except capture_message( f'Error on creating Routing Slip invoice: account id={routing_slip_payment_account.id}, ' f'routing slip : {routing_slip.id}, ERROR : {str(e)}', level='error') current_app.logger.error(e) has_errors = True continue return has_errors
def __save_receipt(invoice, receipt_details): receipt: Receipt = Receipt.find_by_invoice_id_and_receipt_number(invoice.id, receipt_details[0]) if not receipt.id: receipt: Receipt = Receipt() receipt.receipt_number = receipt_details[0] receipt.receipt_date = receipt_details[1] receipt.receipt_amount = receipt_details[2] receipt.invoice_id = invoice.id else: receipt.receipt_date = receipt_details[1] receipt.receipt_amount = receipt_details[2] # Save receipt details to DB. receipt.save() return receipt
def update_transaction( payment_identifier: int, transaction_id: uuid, # pylint: disable=too-many-locals receipt_number: str, jwt: JwtManager = None, skip_auth_check: bool = False): """Update transaction record. Does the following: 1. Find the payment record with the id 2. Find the invoice record using the payment identifier 3. Call the pay system service and get the receipt details 4. Save the receipt record 5. Change the status of Invoice 6. Change the status of Payment 7. Update the transaction record """ transaction_dao: PaymentTransactionModel = PaymentTransactionModel.find_by_id_and_payment_id( transaction_id, payment_identifier) if not transaction_dao: raise BusinessException(Error.PAY008) if transaction_dao.status_code == Status.COMPLETED.value: raise BusinessException(Error.PAY006) payment: Payment = Payment.find_by_id(payment_identifier, jwt=jwt, one_of_roles=[EDIT_ROLE], skip_auth_check=skip_auth_check) pay_system_service: PaymentSystemService = PaymentSystemFactory.create( payment_system=payment.payment_system_code) invoice = Invoice.find_by_payment_identifier(payment_identifier, jwt=jwt, skip_auth_check=True) payment_account = PaymentAccount.find_by_id(invoice.account_id) try: receipt_details = pay_system_service.get_receipt( payment_account, receipt_number, invoice.invoice_number) txn_reason_code = None except ServiceUnavailableException as exc: txn_reason_code = exc.status_code receipt_details = None if receipt_details: # Find if a receipt exists with same receipt_number for the invoice receipt: Receipt = Receipt.find_by_invoice_id_and_receipt_number( invoice.id, receipt_details[0]) if not receipt.id: receipt: Receipt = Receipt() receipt.receipt_number = receipt_details[0] receipt.receipt_date = receipt_details[1] receipt.receipt_amount = receipt_details[2] receipt.invoice_id = invoice.id else: receipt.receipt_date = receipt_details[1] receipt.receipt_amount = receipt_details[2] # Save receipt details to DB. receipt.save() invoice.paid = receipt.receipt_amount if invoice.paid == invoice.total: invoice.invoice_status_code = Status.COMPLETED.value payment.payment_status_code = Status.COMPLETED.value payment.save() elif 0 < invoice.paid < invoice.total: invoice.invoice_status_code = Status.PARTIAL.value invoice.save() transaction_dao.status_code = Status.COMPLETED.value else: transaction_dao.status_code = Status.FAILED.value transaction_dao.transaction_end_time = datetime.now() # Publish status to Queue PaymentTransaction.publish_status(transaction_dao, payment) transaction_dao = transaction_dao.save() transaction = PaymentTransaction() transaction._dao = transaction_dao # pylint: disable=protected-access transaction.pay_system_reason_code = txn_reason_code current_app.logger.debug('>update_transaction') return transaction
def update_transaction(payment_identifier: int, transaction_id: uuid, receipt_number: str): """Update transaction record. Does the following: 1. Find the payment record with the id 2. Find the invoice record using the payment identifier 3. Call the pay system service and get the receipt details 4. Save the receipt record 5. Change the status of Invoice 6. Change the status of Payment 7. Update the transaction record """ transaction_dao: PaymentTransactionModel = PaymentTransactionModel.find_by_id_and_payment_id( transaction_id, payment_identifier) if not transaction_dao: raise BusinessException(Error.PAY008) if transaction_dao.status_code == Status.COMPLETED.value: raise BusinessException(Error.PAY006) payment: Payment = Payment.find_by_id(payment_identifier) pay_system_service: PaymentSystemService = PaymentSystemFactory.create( payment_system=payment.payment_system_code) invoice = Invoice.find_by_payment_identifier(payment_identifier) payment_account = PaymentAccount.find_by_id(invoice.account_id) receipt_details = pay_system_service.get_receipt( payment_account, receipt_number, invoice.invoice_number) if receipt_details: # Find if a receipt exists with same receipt_number for the invoice receipt: Receipt = Receipt.find_by_invoice_id_and_receipt_number( invoice.id, receipt_details[0]) if not receipt.id: receipt: Receipt = Receipt() receipt.receipt_number = receipt_details[0] receipt.receipt_date = receipt_details[1] receipt.receipt_amount = receipt_details[2] receipt.invoice_id = invoice.id else: receipt.receipt_date = receipt_details[1] receipt.receipt_amount = receipt_details[2] # Save receipt details to DB. receipt.save() invoice.paid = receipt.receipt_amount if invoice.paid == invoice.total: invoice.invoice_status_code = Status.COMPLETED.value payment.payment_status_code = Status.COMPLETED.value payment.save() elif 0 < invoice.paid < invoice.total: invoice.invoice_status_code = Status.PARTIAL.value invoice.save() transaction_dao.transaction_end_time = datetime.now() transaction_dao.status_code = Status.COMPLETED.value transaction_dao = transaction_dao.save() transaction = PaymentTransaction() transaction._dao = transaction_dao # pylint: disable=protected-access current_app.logger.debug('>update_transaction') return transaction