Skip to content

Commit

Permalink
20787 - allow specific action overrides
Browse files Browse the repository at this point in the history
  • Loading branch information
ochiu committed Oct 2, 2024
1 parent 83380c1 commit 6a201a6
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 9 deletions.
8 changes: 5 additions & 3 deletions jobs/payment-jobs/invoke_jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,11 @@ def run(job_name, argument=None):
UnpaidInvoiceNotifyTask.notify_unpaid_invoices()
application.logger.info('<<<< Completed Sending notification for OB invoices >>>>')
case 'STATEMENTS_DUE':
action_date_override = argument[0] if len(argument) >= 1 else None
auth_account_override = argument[1] if len(argument) >= 2 else None
StatementDueTask.process_unpaid_statements(action_date_override=action_date_override,
action_override = argument[0] if len(argument) >= 1 else None
date_override = argument[0] if len(argument) >= 2 else None
auth_account_override = argument[1] if len(argument) >= 3 else None
StatementDueTask.process_unpaid_statements(action_override=action_override,
date_override=date_override,
auth_account_override=auth_account_override)
application.logger.info(
'<<<< Completed Sending notification for unpaid statements >>>>')
Expand Down
35 changes: 29 additions & 6 deletions jobs/payment-jobs/tasks/statement_due_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,23 +57,46 @@ class StatementDueTask: # pylint: disable=too-few-public-methods
statement_date_override = None

@classmethod
def process_unpaid_statements(cls, action_date_override=None,
def process_override_command(cls, action, date_override):
"""Process override action."""
if date_override is None:
current_app.logger.error(f'Expecting date override for action: {action}.')

date_override = datetime.strptime(date_override, '%Y-%m-%d')
match action:
case 'NOTIFICATION':
cls.action_date_override = date_override.date()
cls.statement_date_override = date_override
cls._notify_for_monthly()
case 'OVERDUE':
cls.action_date_override = date_override
cls._update_invoice_overdue_status()
case _:
current_app.logger.error(f'Unsupported action override: {action}.')

@classmethod
def process_unpaid_statements(cls,
action_override=None,
date_override=None,
auth_account_override=None, statement_date_override=None):
"""Notify for unpaid statements with an amount owing."""
eft_enabled = flags.is_on('enable-eft-payment-method', default=False)
if eft_enabled:
cls.action_date_override = action_date_override
cls.auth_account_override = auth_account_override
cls.statement_date_override = statement_date_override
cls._update_invoice_overdue_status()
cls._notify_for_monthly()

if action_override is not None and len(action_override.strip()) > 0:
cls.process_override_command(action_override, date_override)
else:
cls._update_invoice_overdue_status()
cls._notify_for_monthly()

@classmethod
def _update_invoice_overdue_status(cls):
"""Update the status of any invoices that are overdue."""
# Needs to be non timezone aware.
if cls.action_date_override:
now = datetime.strptime(cls.action_date_override, '%Y-%m-%d').replace(hour=8)
now = cls.action_date_override.replace(hour=8)
offset_hours = -now.astimezone(pytz.timezone('America/Vancouver')).utcoffset().total_seconds() / 60 / 60
now = now.replace(hour=int(offset_hours), minute=0, second=0)
else:
Expand Down Expand Up @@ -202,7 +225,7 @@ def _determine_action_and_due_date_by_invoice(cls, statement: StatementModel):

# Needs to be non timezone aware for comparison.
if cls.action_date_override:
now_date = datetime.strptime(cls.action_date_override, '%Y-%m-%d').date()
now_date = cls.action_date_override
else:
now_date = datetime.now(tz=timezone.utc).replace(tzinfo=None).date()

Expand Down
56 changes: 56 additions & 0 deletions jobs/payment-jobs/tests/jobs/test_statement_due_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,59 @@ def test_overdue_invoices_updated(setup, session):
StatementDueTask.process_unpaid_statements(auth_account_override=account.auth_account_id)
assert invoice.invoice_status_code == InvoiceStatus.OVERDUE.value
assert invoice2.invoice_status_code == InvoiceStatus.APPROVED.value


@pytest.mark.parametrize('test_name, date_override, action', [
('reminder', '2023-02-21', StatementNotificationAction.REMINDER),
('due', '2023-02-28', StatementNotificationAction.DUE),
('overdue', '2023-03-15', StatementNotificationAction.OVERDUE)
])
def test_statement_due_overrides_override(setup, session, test_name, date_override, action):
"""Assert payment reminder event is being sent."""
account, invoice, _, \
statement_recipient, _ = create_test_data(PaymentMethod.EFT.value,
datetime(2023, 1, 1, 8), # Hour 0 doesnt work for CI
StatementFrequency.MONTHLY.value,
351.50)
assert invoice.payment_method_code == PaymentMethod.EFT.value
assert invoice.overdue_date
assert account.payment_method == PaymentMethod.EFT.value

# Generate statements runs at 8:01 UTC, currently set to 7:01 UTC, should be moved.
with freeze_time(datetime(2023, 2, 1, 8, 0, 1)):
StatementTask.generate_statements()

statements = StatementService.get_account_statements(auth_account_id=account.auth_account_id, page=1, limit=100)
assert statements is not None
assert len(statements) == 2 # items results and page total
assert len(statements[0]) == 1 # items
invoices = StatementInvoicesModel.find_all_invoices_for_statement(statements[0][0].id)
assert invoices is not None
assert invoices[0].invoice_id == invoice.id

summary = StatementService.get_summary(account.auth_account_id, statements[0][0].id)
total_amount_owing = summary['total_due']

with patch('utils.auth_event.AuthEvent.publish_lock_account_event') as mock_auth_event:
with patch('tasks.statement_due_task.publish_payment_notification') as mock_mailer:
# Statement due task looks at the month before.
if test_name == 'overdue':
StatementDueTask.process_unpaid_statements(action_override='OVERDUE',
date_override=date_override)

StatementDueTask.process_unpaid_statements(action_override='NOTIFICATION',
date_override=date_override)
if action == StatementNotificationAction.OVERDUE:
mock_auth_event.assert_called()
assert statements[0][0].overdue_notification_date
assert NonSufficientFundsModel.find_by_invoice_id(invoice.id)
assert account.has_overdue_invoices
else:
due_date = statements[0][0].to_date + relativedelta(months=1)
mock_mailer.assert_called_with(StatementNotificationInfo(auth_account_id=account.auth_account_id,
statement=statements[0][0],
action=action,
due_date=due_date,
emails=statement_recipient.email,
total_amount_owing=total_amount_owing,
short_name_links_count=0))

0 comments on commit 6a201a6

Please sign in to comment.