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
Beispiel #2
0
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()