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 _sync_credit_records(): """Sync credit records with CFS.""" # 1. Get all credit records with balance > 0 # 2. If it's on account receipt call receipt endpoint and calculate balance. # 3. If it's credit memo, call credit memo endpoint and calculate balance. # 4. Roll up the credits to credit field in payment_account. active_credits: List[CreditModel] = db.session.query(CreditModel).filter( CreditModel.remaining_amount > 0).all() logger.info('Found %s credit records', len(active_credits)) account_ids: List[int] = [] for credit in active_credits: account_ids.append(credit.account_id) cfs_account: CfsAccountModel = CfsAccountModel.find_effective_by_account_id( credit.account_id) if credit.is_credit_memo: credit_memo = CFSService.get_cms(cfs_account=cfs_account, cms_number=credit.cfs_identifier) credit.remaining_amount = abs(float(credit_memo.get('amount_due'))) else: receipt = CFSService.get_receipt( cfs_account=cfs_account, receipt_number=credit.cfs_identifier) receipt_amount = float(receipt.get('receipt_amount')) applied_amount: float = 0 for invoice in receipt.get('invoices', []): applied_amount += float(invoice.get('amount_applied')) credit.remaining_amount = receipt_amount - applied_amount credit.save() # Roll up the credits and add up to credit in payment_account. for account_id in set(account_ids): account_credits: List[CreditModel] = db.session.query( CreditModel).filter(CreditModel.remaining_amount > 0).filter( CreditModel.account_id == account_id).all() credit_total: float = 0 for account_credit in account_credits: credit_total += account_credit.remaining_amount pay_account: PaymentAccountModel = PaymentAccountModel.find_by_id( account_id) pay_account.credit = credit_total pay_account.save()