Skip to content

Commit

Permalink
Changes for CFS_ACCOUNT.payment_method
Browse files Browse the repository at this point in the history
  • Loading branch information
seeker25 committed Jul 5, 2024
1 parent b8ea822 commit f692d77
Show file tree
Hide file tree
Showing 33 changed files with 139 additions and 168 deletions.
3 changes: 1 addition & 2 deletions jobs/payment-jobs/services/routing_slip.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ def create_cfs_account(cfs_account: CfsAccountModel, pay_account: PaymentAccount
routing_slip: RoutingSlipModel = RoutingSlipModel.find_by_payment_account_id(pay_account.id)
try:
# TODO add status check so that LINKED etc can be skipped.
# for RS , entity/business number=party name ; RS Number=site name
cfs_account_details: Dict[str, any] = CFSService.create_cfs_account(
identifier=pay_account.name,
contact_info={},
Expand All @@ -41,7 +40,7 @@ def create_cfs_account(cfs_account: CfsAccountModel, pay_account: PaymentAccount
cfs_account.cfs_party = cfs_account_details.get('party_number')
cfs_account.cfs_site = cfs_account_details.get('site_number')
cfs_account.status = CfsAccountStatus.ACTIVE.value
# Create receipt in CFS for the payment.
# for RS , entity/business number=party name ; RS Number=site name
CFSService.create_cfs_receipt(cfs_account=cfs_account,
rcpt_number=routing_slip.number,
rcpt_date=routing_slip.routing_slip_date.strftime('%Y-%m-%d'),
Expand Down
4 changes: 2 additions & 2 deletions jobs/payment-jobs/tasks/activate_pad_account_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def activate_pad_accounts(cls):
1. Find all accounts with pending PAD account activation status.
2. Activate them.
"""
pending_pad_activation_accounts: List[CfsAccountModel] = CfsAccountModel.find_all_accounts_with_status(
pending_pad_activation_accounts = CfsAccountModel.find_all_accounts_with_status(
status=CfsAccountStatus.PENDING_PAD_ACTIVATION.value)
current_app.logger.info(
f'Found {len(pending_pad_activation_accounts)} CFS Accounts to be pending PAD activation.')
Expand All @@ -54,7 +54,7 @@ def activate_pad_accounts(cls):
if is_activation_period_over:
pending_account.status = CfsAccountStatus.ACTIVE.value
pending_account.save()
# If account was in BCOL , change it to PAD
# If account was in another payment method, update it to pad
if pay_account.payment_method != PaymentMethod.PAD.value:
pay_account.payment_method = PaymentMethod.PAD.value
pay_account.save()
Expand Down
2 changes: 1 addition & 1 deletion jobs/payment-jobs/tasks/cfs_bank_name_updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def run_update(pay_account_id, num_records):
return

for payment_account in pad_accounts:
cfs_account: CfsAccountModel = CfsAccountModel.find_effective_by_account_id(payment_account.id)
cfs_account = CfsAccountModel.find_effective_by_payment_method(payment_account.id, PaymentMethod.PAD.value)
current_app.logger.info(
f'<<<< Running Update for account id :{payment_account.id} and cfs_account:{cfs_account.id} >>>>')
# payment_details = get_bank_info(cfs_account.cfs_party, cfs_account.cfs_account, cfs_account.cfs_site)
Expand Down
6 changes: 2 additions & 4 deletions jobs/payment-jobs/tasks/cfs_create_account_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def create_accounts(cls): # pylint: disable=too-many-locals
3. Publish a message to the queue if successful.
"""
# Pass payment method if offline account creation has be restricted based on payment method.
pending_accounts: List[CfsAccountModel] = CfsAccountModel.find_all_pending_accounts()
pending_accounts = CfsAccountModel.find_all_pending_accounts()
current_app.logger.info(f'Found {len(pending_accounts)} CFS Accounts to be created.')
if len(pending_accounts) == 0:
return
Expand Down Expand Up @@ -128,7 +128,6 @@ def _create_cfs_account(cls, pending_account: CfsAccountModel, pay_account: Paym
pending_account.cfs_party = cfs_account_details.get('party_number')

except Exception as e: # NOQA # pylint: disable=broad-except
# publish to mailer queue.
is_user_error = False
if pay_account.payment_method == PaymentMethod.PAD.value:
is_user_error = CreateAccountTask._check_user_error(e.response) # pylint: disable=no-member
Expand All @@ -146,8 +145,7 @@ def _create_cfs_account(cls, pending_account: CfsAccountModel, pay_account: Paym
pending_account.save()
return

# If the account has an activation time set ,
# before that it shud be set to the PENDING_PAD_ACTIVATION status.
# If the account has an activation time set it should have PENDING_PAD_ACTIVATION status.
is_account_in_pad_confirmation_period = pay_account.pad_activation_date is not None and \
pay_account.pad_activation_date > datetime.today()
pending_account.status = CfsAccountStatus.PENDING_PAD_ACTIVATION.value if \
Expand Down
83 changes: 15 additions & 68 deletions jobs/payment-jobs/tasks/cfs_create_invoice_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ def create_invoices(cls):
cls._create_online_banking_invoices()
current_app.logger.info('>> Done Online Banking Invoice Creation')

# Cancel invoice is the only non-creation of invoice in this job.
current_app.logger.info('<< Starting CANCEL Routing Slip Invoices')
cls._cancel_rs_invoices()
current_app.logger.info('>> Done CANCEL Routing Slip Invoices')
Expand All @@ -91,27 +90,24 @@ def _cancel_rs_invoices(cls):

current_app.logger.info(f'Found {len(invoices)} to be cancelled in CFS.')
for invoice in invoices:
# call unapply rcpts
# adjust invoice to zero
current_app.logger.debug(f'Calling the invoice {invoice.id}')
routing_slip = RoutingSlipModel.find_by_number(invoice.routing_slip)
routing_slip_payment_account: PaymentAccountModel = PaymentAccountModel.find_by_id(
routing_slip.payment_account_id)
cfs_account: CfsAccountModel = CfsAccountModel.find_effective_by_account_id(
routing_slip_payment_account.id)
cfs_account = CfsAccountModel.find_effective_by_payment_method(
routing_slip_payment_account.id, PaymentMethod.INTERNAL.value)
# Find COMPLETED invoice reference; as unapply has to be done only if invoice is created and applied in CFS.
invoice_reference = InvoiceReferenceModel. \
find_by_invoice_id_and_status(invoice.id, status_code=InvoiceReferenceStatus.COMPLETED.value)
if invoice_reference:
current_app.logger.debug(f'Found invoice reference - {invoice_reference.invoice_number}')
try:
# find receipts against the invoice and unapply
# apply receipt now
receipts: List[ReceiptModel] = ReceiptModel.find_all_receipts_for_invoice(invoice_id=invoice.id)
for receipt in receipts:
CFSService.unapply_receipt(cfs_account, receipt.receipt_number,
invoice_reference.invoice_number)

# Adjust to zero: -invoice.total + invoice.total = 0
adjustment_negative_amount = -invoice.total
CFSService.adjust_invoice(cfs_account=cfs_account,
inv_number=invoice_reference.invoice_number,
Expand Down Expand Up @@ -145,6 +141,7 @@ def _create_rs_invoices(cls): # pylint: disable=too-many-locals
.filter(InvoiceModel.payment_method_code == PaymentMethod.INTERNAL.value) \
.filter(InvoiceModel.invoice_status_code == InvoiceStatus.APPROVED.value) \
.filter(CfsAccountModel.status.in_([CfsAccountStatus.ACTIVE.value, CfsAccountStatus.FREEZE.value])) \
.filter(CfsAccountModel.payment_method == PaymentMethod.INTERNAL.value) \
.filter(InvoiceModel.routing_slip is not None) \
.order_by(InvoiceModel.created_on.asc()).all()

Expand All @@ -162,7 +159,8 @@ def _create_rs_invoices(cls): # pylint: disable=too-many-locals
routing_slip.payment_account_id)

# apply invoice to the active CFS_ACCOUNT which will be the parent routing slip
active_cfs_account = CfsAccountModel.find_effective_by_account_id(routing_slip_payment_account.id)
active_cfs_account = CfsAccountModel.find_effective_by_payment_method(routing_slip_payment_account.id,
PaymentMethod.INTERNAL.value)

try:
invoice_response = CFSService.create_account_invoice(transaction_number=invoice.id,
Expand Down Expand Up @@ -231,22 +229,19 @@ def _create_rs_invoices(cls): # pylint: disable=too-many-locals
@classmethod
def _create_pad_invoices(cls): # pylint: disable=too-many-locals
"""Create PAD invoices in to CFS system."""
# Find all accounts which have done a transaction with PAD transactions

inv_subquery = db.session.query(InvoiceModel.payment_account_id) \
.filter(InvoiceModel.payment_method_code == PaymentMethod.PAD.value) \
.filter(InvoiceModel.invoice_status_code == InvoiceStatus.APPROVED.value).subquery()

# Exclude the accounts which are in FREEZE state.
pad_accounts: List[PaymentAccountModel] = db.session.query(PaymentAccountModel) \
.join(CfsAccountModel, CfsAccountModel.account_id == PaymentAccountModel.id) \
.filter(CfsAccountModel.status != CfsAccountStatus.FREEZE.value) \
.filter(CfsAccountModel.payment_method == PaymentMethod.PAD.value) \
.filter(PaymentAccountModel.id.in_(select(inv_subquery))).all()

current_app.logger.info(f'Found {len(pad_accounts)} with PAD transactions.')

for account in pad_accounts:
# Find all PAD invoices for this account
account_invoices = db.session.query(InvoiceModel) \
.filter(InvoiceModel.payment_account_id == account.id) \
.filter(InvoiceModel.payment_method_code == PaymentMethod.PAD.value) \
Expand All @@ -261,21 +256,13 @@ def _create_pad_invoices(cls): # pylint: disable=too-many-locals
current_app.logger.debug(
f'Found {len(account_invoices)} invoices for account {payment_account.auth_account_id}')

cfs_account: CfsAccountModel = CfsAccountModel.find_effective_by_account_id(payment_account.id)
if cfs_account is None:
# Get the last cfs_account for it, as the account might have got upgraded from PAD to DRAWDOWN.
cfs_account: CfsAccountModel = CfsAccountModel.query.\
filter(CfsAccountModel.account_id == payment_account.id).order_by(CfsAccountModel.id.desc()).first()

# If the CFS Account status is not ACTIVE or INACTIVE (for above case), raise error and continue
cfs_account = CfsAccountModel.find_effective_or_latest_by_payment_method(payment_account.id,
PaymentMethod.PAD.value)
if cfs_account.status not in (CfsAccountStatus.ACTIVE.value, CfsAccountStatus.INACTIVE.value):
current_app.logger.info(f'CFS status for account {payment_account.auth_account_id} '
f'is {payment_account.cfs_account_status} skipping.')
continue

if not cls._verify_and_correct_receipt_method(cfs_account, payment_account, PaymentMethod.PAD.value):
continue

lines = []
invoice_total = Decimal('0')
for invoice in account_invoices:
Expand Down Expand Up @@ -348,6 +335,7 @@ def _return_eft_accounts(cls):
eft_accounts: List[PaymentAccountModel] = db.session.query(PaymentAccountModel) \
.join(CfsAccountModel, CfsAccountModel.account_id == PaymentAccountModel.id) \
.filter(CfsAccountModel.status != CfsAccountStatus.FREEZE.value) \
.filter(CfsAccountModel.payment_method == PaymentMethod.EFT.value) \
.filter(PaymentAccountModel.id.in_(select(invoice_subquery))).all()

current_app.logger.info(f'Found {len(eft_accounts)} with EFT transactions.')
Expand Down Expand Up @@ -398,22 +386,13 @@ def _create_eft_invoices(cls):
current_app.logger.debug(
f'Found {len(account_invoices)} invoices for account {payment_account.auth_account_id}')

cfs_account: CfsAccountModel = CfsAccountModel.find_effective_by_account_id(payment_account.id)

# If no CFS account then the payment method might have changed from EFT to DRAWDOWN
if not cfs_account:
cfs_account: CfsAccountModel = CfsAccountModel.query.\
filter(CfsAccountModel.account_id == payment_account.id).order_by(CfsAccountModel.id.desc()).first()

# If CFS account is not ACTIVE or INACTIVE (for above case), raise error and continue
cfs_account = CfsAccountModel.find_effective_or_latest_by_payment_method(payment_account.id,
PaymentMethod.EFT.value)
if cfs_account.status not in (CfsAccountStatus.ACTIVE.value, CfsAccountStatus.INACTIVE.value):
current_app.logger.info(f'CFS status for account {payment_account.auth_account_id} '
f'is {payment_account.cfs_account_status} skipping.')
continue

if not cls._verify_and_correct_receipt_method(cfs_account, payment_account, PaymentMethod.EFT.value):
continue

lines = []
invoice_total = Decimal('0')
for invoice in account_invoices:
Expand Down Expand Up @@ -482,16 +461,15 @@ def _create_single_invoice_per_purchase(cls, payment_method: PaymentMethod):
current_app.logger.info(f'Found {len(invoices)} to be created in CFS.')
for invoice in invoices:
payment_account: PaymentAccountService = PaymentAccountService.find_by_id(invoice.payment_account_id)
cfs_account: CfsAccountModel = CfsAccountModel.find_effective_by_account_id(payment_account.id)
# Adding this in for the future when we can switch between BCOL and ONLINE_BANKING.
cfs_account = CfsAccountModel.find_effective_or_latest_by_payment_method(payment_account.id,
PaymentMethod.ONLINE_BANKING.value)

if invoice.payment_method_code == PaymentMethod.ONLINE_BANKING.value:
corp_type: CorpTypeModel = CorpTypeModel.find_by_code(invoice.corp_type_code)
if not corp_type.is_online_banking_allowed:
continue

if not cls._verify_and_correct_receipt_method(cfs_account, payment_account, PaymentMethod.ONLINE_BANKING.value):
continue

current_app.logger.debug(f'Creating cfs invoice for invoice {invoice.id}')
try:
invoice_response = CFSService.create_account_invoice(transaction_number=invoice.id,
Expand All @@ -513,34 +491,3 @@ def _create_single_invoice_per_purchase(cls, payment_method: PaymentMethod):
invoice.invoice_status_code = InvoiceStatus.SETTLEMENT_SCHEDULED.value
invoice.save()

@classmethod
def _verify_and_correct_receipt_method(cls, cfs_account, payment_account, payment_method: str):
"""Verify and correct the receipt method site."""
try:
current_receipt_method = CFSService.get_site(cfs_account).get('receipt_method', None)
if current_receipt_method == RECEIPT_METHOD_PAD_STOP:
current_app.logger.error(f'Skipping the account as the receipt method is {RECEIPT_METHOD_PAD_STOP},'
' database is out of sync with CAS.')
return False

match payment_method:
case PaymentMethod.EFT.value:
new_receipt_method = CFS_RCPT_EFT_WIRE
case PaymentMethod.ONLINE_BANKING.value:
# According to the spec it should be "BCR Online Banking Payments", but in practice we use null.
new_receipt_method = None
case PaymentMethod.PAD.value:
new_receipt_method = RECEIPT_METHOD_PAD_DAILY
case _:
current_app.logging.error(f'Site switching for {payment_method} is not implemented.')
return False

if current_receipt_method != new_receipt_method:
current_app.logger.info('Switching site receipt_method from %s to %s',
current_receipt_method, new_receipt_method)
CFSService.update_site_receipt_method(cfs_account, receipt_method=new_receipt_method)
except Exception as e: # NO QA # pylint: disable=broad-except
capture_message(f'Error switching site for account id={cfs_account.account_id}, '
f'auth account : {payment_account.auth_account_id}, ERROR : {str(e)}', level='error')
return False
return True
Loading

0 comments on commit f692d77

Please sign in to comment.