Skip to content

Commit

Permalink
nsf tweaks
Browse files Browse the repository at this point in the history
Adding cfs_account_id field to non_sufficient_funds, and adding the CSV reconciliation description to non_sufficient_funds
  • Loading branch information
rodrigo-barraza committed Jan 23, 2024
1 parent db88797 commit ba4aed4
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 11 deletions.
32 changes: 32 additions & 0 deletions pay-api/migrations/versions/2024_01_23_0b1f9c35b1fb_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""Add cfs_account_id and modify invoice_number to be non-nullable in non_sufficient_funds table
Revision ID: 0b1f9c35b1fb
Revises: fccdab259e05
Create Date: 2024-01-23 14:26:29.427462
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = '0b1f9c35b1fb'
down_revision = 'fccdab259e05'
branch_labels = None
depends_on = None


def upgrade():
op.add_column('non_sufficient_funds', sa.Column('cfs_account_id', sa.String(length=50), nullable=False, comment='CFS Account number'))
op.alter_column('non_sufficient_funds', 'invoice_number',
existing_type=sa.VARCHAR(length=50),
nullable=False,
existing_comment='CFS Invoice number')


def downgrade():
op.alter_column('non_sufficient_funds', 'invoice_number',
existing_type=sa.VARCHAR(length=50),
nullable=True,
existing_comment='CFS Invoice number')
op.drop_column('non_sufficient_funds', 'cfs_account_id')
9 changes: 6 additions & 3 deletions pay-api/src/pay_api/models/non_sufficient_funds.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@ class NonSufficientFundsModel(BaseModel): # pylint: disable=too-many-instance-a
__mapper_args__ = {
'include_properties': [
'id',
'cfs_account_id',
'description',
'invoice_id',
'invoice_number'
]
}

id = db.Column(db.Integer, primary_key=True, autoincrement=True)
cfs_account_id = db.Column(db.String(50), nullable=False, comment='CFS Account number')
description = db.Column(db.String(50), nullable=True)
invoice_id = db.Column(db.Integer, ForeignKey('invoices.id'), nullable=False)
invoice_number = db.Column(db.String(50), nullable=False, index=True, comment='CFS Invoice number')
Expand All @@ -55,15 +57,16 @@ class NonSufficientFundsSchema: # pylint: disable=too-few-public-methods
"""Used to search for NSF records."""

id: int
description: str
cfs_account_id: int
invoice_id: int
invoice_number: str
description: str

@classmethod
def from_row(cls, row: NonSufficientFundsModel):
"""From row is used so we don't tightly couple to our database class.
https://www.attrs.org/en/stable/init.html
"""
return cls(id=row.id, invoice_id=row.invoice_id, invoice_number=row.invoice_number,
description=row.description)
return cls(id=row.id, cfs_account_id=row.cfs_account_id, description=row.description,
invoice_id=row.invoice_id, invoice_number=row.invoice_number)
12 changes: 11 additions & 1 deletion pay-api/src/pay_api/services/non_sufficient_funds.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,25 @@ def save_non_sufficient_funds(invoice_id: int, invoice_number: str, description:
current_app.logger.debug('>save_non_sufficient_funds')
return NonSufficientFundsService.asdict(non_sufficient_funds_service)

@staticmethod
def exists_for_invoice_number(invoice_number: str) -> bool:
"""Return boolean if a row exists for the invoice number."""
return (db.session.query(NonSufficientFundsModel)
.filter(NonSufficientFundsModel.invoice_number == invoice_number)
.count()
) > 0


@staticmethod
def query_all_non_sufficient_funds_invoices(account_id: str):
"""Return all Non-Sufficient Funds invoices and their aggregate amounts."""
query = (db.session.query(
InvoiceModel, InvoiceReferenceModel)
.join(InvoiceReferenceModel, InvoiceReferenceModel.invoice_id == InvoiceModel.id)
.outerjoin(NonSufficientFundsModel, NonSufficientFundsModel.invoice_id == InvoiceModel.id)
.join(NonSufficientFundsModel, NonSufficientFundsModel.invoice_number == InvoiceReferenceModel.invoice_number)
.join(PaymentAccountModel, PaymentAccountModel.id == InvoiceModel.payment_account_id)
.filter(PaymentAccountModel.auth_account_id == account_id)
.distinct(InvoiceModel.id)
.group_by(InvoiceModel.id, InvoiceReferenceModel.id)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -452,10 +452,8 @@ def _process_failed_payments(row):
inv_number = _get_row_value(row, Column.TARGET_TXN_NO)
payment_account: PaymentAccountModel = _get_payment_account(row)

# If there is an NSF invoice with a remaining nsf_amount balance, it means it's a duplicate NSF event. Ignore it.
non_sufficient_funds = NonSufficientFundsService.find_all_non_sufficient_funds_invoices(
account_id=payment_account.auth_account_id)
if non_sufficient_funds['nsf_amount'] > 0:
# If there is an NSF row, it means it's a duplicate NSF event. Ignore it.
if NonSufficientFundsService.exists_for_invoice_number(inv_number):
logger.info('Ignoring duplicate NSF event for account: %s ', payment_account.auth_account_id)
return False

Expand Down Expand Up @@ -490,7 +488,8 @@ def _process_failed_payments(row):
invoice.paid = 0

# Create an invoice for NSF for this account
invoice = _create_nsf_invoice(cfs_account, inv_number, payment_account)
reason_description = _get_row_value(row, Column.REVERSAL_REASON_DESC)
invoice = _create_nsf_invoice(cfs_account, inv_number, payment_account, reason_description)
# Adjust CFS invoice
CFSService.add_nsf_adjustment(cfs_account=cfs_account, inv_number=inv_number, amount=invoice.total)
return True
Expand Down Expand Up @@ -718,7 +717,7 @@ def _get_row_value(row: Dict[str, str], key: Column) -> str:


def _create_nsf_invoice(cfs_account: CfsAccountModel, inv_number: str,
payment_account: PaymentAccountModel) -> InvoiceModel:
payment_account: PaymentAccountModel, reason_description: str) -> InvoiceModel:
"""Create Invoice, line item and invoice referwnce records."""
fee_schedule: FeeScheduleModel = FeeScheduleModel.find_by_filing_type_and_corp_type(corp_type_code='BCR',
filing_type_code='NSF')
Expand All @@ -738,7 +737,7 @@ def _create_nsf_invoice(cfs_account: CfsAccountModel, inv_number: str,
invoice = invoice.save()

NonSufficientFundsService.save_non_sufficient_funds(invoice_id=invoice.id, invoice_number=inv_number,
description='NSF')
cfs_account_id=cfs_account.id, description=reason_description)

distribution: DistributionCodeModel = DistributionCodeModel.find_by_active_for_fee_schedule(
fee_schedule.fee_schedule_id)
Expand Down

0 comments on commit ba4aed4

Please sign in to comment.