-
Notifications
You must be signed in to change notification settings - Fork 40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
20719- Interim Statements Settings Fix #1584
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,36 +33,43 @@ class StatementTask: # pylint:disable=too-few-public-methods | |
"""Task to generate statements.""" | ||
|
||
has_date_override: bool = False | ||
has_account_override: bool = False | ||
|
||
@classmethod | ||
def generate_statements(cls, date_override=None): | ||
def generate_statements(cls, arguments=None): | ||
"""Generate statements. | ||
|
||
Steps: | ||
1. Get all payment accounts and it's active statement settings. | ||
""" | ||
date_override = arguments[0] if arguments and len(arguments) > 0 else None | ||
auth_account_override = arguments[1] if arguments and len(arguments) > 1 else None | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. allow a specific account number to be filtered on. This allows us to generate a monthly statement using the interim statement settings before the month is up without affecting other accounts There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great idea, I was thinking about this the other day, when I had to regenerate statements for a client |
||
|
||
target_time = get_local_time(datetime.now()) if date_override is None \ | ||
else datetime.strptime(date_override, '%Y-%m-%d') + timedelta(days=1) | ||
cls.has_date_override = date_override is not None | ||
cls.has_account_override = auth_account_override is not None | ||
if date_override: | ||
current_app.logger.debug(f'Generating statements for: {date_override} using date override.') | ||
if auth_account_override: | ||
current_app.logger.debug(f'Generating statements for: {auth_account_override} using account override.') | ||
# If today is sunday - generate all weekly statements for pervious week | ||
# If today is month beginning - generate all monthly statements for previous month | ||
# For every day generate all daily statements for previous day | ||
generate_weekly = target_time.weekday() == 6 # Sunday is 6 | ||
generate_monthly = target_time.day == 1 | ||
|
||
cls._generate_daily_statements(target_time) | ||
cls._generate_daily_statements(target_time, auth_account_override) | ||
if generate_weekly: | ||
cls._generate_weekly_statements(target_time) | ||
cls._generate_weekly_statements(target_time, auth_account_override) | ||
if generate_monthly: | ||
cls._generate_monthly_statements(target_time) | ||
cls._generate_monthly_statements(target_time, auth_account_override) | ||
|
||
# Commit transaction | ||
db.session.commit() | ||
|
||
@classmethod | ||
def _generate_daily_statements(cls, target_time: datetime): | ||
def _generate_daily_statements(cls, target_time: datetime, account_override: str): | ||
"""Generate daily statements for all accounts with settings to generate daily.""" | ||
previous_day = get_previous_day(target_time) | ||
statement_settings = StatementSettingsModel.find_accounts_settings_by_frequency(previous_day, | ||
|
@@ -74,10 +81,10 @@ def _generate_daily_statements(cls, target_time: datetime): | |
'endDate': previous_day.strftime('%Y-%m-%d') | ||
} | ||
} | ||
cls._create_statement_records(search_filter, statement_settings) | ||
cls._create_statement_records(search_filter, statement_settings, account_override) | ||
|
||
@classmethod | ||
def _generate_weekly_statements(cls, target_time: datetime): | ||
def _generate_weekly_statements(cls, target_time: datetime, account_override: str): | ||
"""Generate weekly statements for all accounts with settings to generate weekly.""" | ||
previous_day = get_previous_day(target_time) | ||
statement_settings = StatementSettingsModel.find_accounts_settings_by_frequency(previous_day, | ||
|
@@ -91,10 +98,10 @@ def _generate_weekly_statements(cls, target_time: datetime): | |
} | ||
} | ||
|
||
cls._create_statement_records(search_filter, statement_settings) | ||
cls._create_statement_records(search_filter, statement_settings, account_override) | ||
|
||
@classmethod | ||
def _generate_monthly_statements(cls, target_time: datetime): | ||
def _generate_monthly_statements(cls, target_time: datetime, account_override: str): | ||
"""Generate monthly statements for all accounts with settings to generate monthly.""" | ||
previous_day = get_previous_day(target_time) | ||
statement_settings = StatementSettingsModel.find_accounts_settings_by_frequency(previous_day, | ||
|
@@ -108,10 +115,10 @@ def _generate_monthly_statements(cls, target_time: datetime): | |
} | ||
} | ||
|
||
cls._create_statement_records(search_filter, statement_settings) | ||
cls._create_statement_records(search_filter, statement_settings, account_override) | ||
|
||
@classmethod | ||
def _create_statement_records(cls, search_filter, statement_settings): | ||
def _create_statement_records(cls, search_filter, statement_settings, account_override: str): | ||
statement_from = None | ||
statement_to = None | ||
if search_filter.get('dateFilter', None): | ||
|
@@ -125,7 +132,12 @@ def _create_statement_records(cls, search_filter, statement_settings): | |
statement_from, statement_to = get_first_and_last_dates_of_month( | ||
search_filter.get('monthFilter').get('month'), search_filter.get('monthFilter').get('year')) | ||
current_app.logger.debug(f'Statements for month: {statement_from.date()} to {statement_to.date()}') | ||
auth_account_ids = [pay_account.auth_account_id for _, pay_account in statement_settings] | ||
if cls.has_account_override: | ||
auth_account_ids = [account_override] | ||
statement_settings = cls._filter_settings_by_override(statement_settings, account_override) | ||
current_app.logger.debug(f'Override Filtered to {len(statement_settings)} accounts to generate statements.') | ||
else: | ||
auth_account_ids = [pay_account.auth_account_id for _, pay_account in statement_settings] | ||
search_filter['authAccountIds'] = auth_account_ids | ||
# Force match on these methods where if the payment method is in matchPaymentMethods, the invoice payment method | ||
# must match the account payment method. Used for EFT so the statements only show EFT invoices and interim | ||
|
@@ -136,15 +148,15 @@ def _create_statement_records(cls, search_filter, statement_settings): | |
cls._clean_up_old_statements(statement_settings, statement_from, statement_to) | ||
current_app.logger.debug('Inserting statements.') | ||
statements = [StatementModel( | ||
frequency=setting.frequency, | ||
statement_settings_id=setting.id, | ||
payment_account_id=pay_account.id, | ||
created_on=get_local_time(datetime.now()), | ||
from_date=statement_from, | ||
to_date=statement_to, | ||
notification_status_code=NotificationStatus.PENDING.value | ||
if pay_account.statement_notification_enabled is True and cls.has_date_override is False | ||
else NotificationStatus.SKIP.value | ||
frequency=setting.frequency, | ||
statement_settings_id=setting.id, | ||
payment_account_id=pay_account.id, | ||
created_on=get_local_time(datetime.now()), | ||
from_date=statement_from, | ||
to_date=statement_to, | ||
notification_status_code=NotificationStatus.PENDING.value | ||
if pay_account.statement_notification_enabled is True and cls.has_date_override is False | ||
else NotificationStatus.SKIP.value | ||
) for setting, pay_account in statement_settings] | ||
# Return defaults which returns the id. | ||
db.session.bulk_save_objects(statements, return_defaults=True) | ||
|
@@ -182,3 +194,10 @@ def _clean_up_old_statements(cls, statement_settings, statement_from, statement_ | |
db.session.flush() | ||
delete_statement = delete(StatementModel).where(StatementModel.id.in_(remove_statements_ids)) | ||
db.session.execute(delete_statement) | ||
|
||
@classmethod | ||
def _filter_settings_by_override(cls, statement_settings, auth_account_id: str): | ||
"""Return filtered Statement settings by payment account.""" | ||
return [settings | ||
for settings in statement_settings | ||
if settings.PaymentAccount.auth_account_id == auth_account_id] |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,8 +16,7 @@ | |
|
||
Test-Suite to ensure that the Statement Service is working as expected. | ||
""" | ||
from datetime import datetime, timezone | ||
|
||
from datetime import datetime, timedelta, timezone | ||
from dateutil.relativedelta import relativedelta | ||
from unittest.mock import patch | ||
|
||
|
@@ -322,6 +321,114 @@ def test_get_monthly_interim_statement(session, admin_users_mock): | |
assert monthly_invoices[0].invoice_id == monthly_invoice.id | ||
|
||
|
||
def test_interim_statement_settings_eft(db, session, admin_users_mock): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ken found some anomalies which was more prevalent when swapping payment methods within the same day. |
||
"""Assert statement setting properly generated when transitioning to and from EFT payment method.""" | ||
account_create_date = datetime(2024, 5, 30, 12, 0) | ||
with freeze_time(account_create_date): | ||
account: PaymentAccountService = PaymentAccountService.create( | ||
get_premium_account_payload(payment_method=PaymentMethod.DRAWDOWN.value)) | ||
|
||
assert account is not None | ||
assert account.payment_method == PaymentMethod.DRAWDOWN.value | ||
|
||
# Confirm initial default settings when account is created | ||
initial_settings: StatementSettingsModel = StatementSettingsModel \ | ||
.find_active_settings(str(account.auth_account_id), datetime.today()) | ||
|
||
assert initial_settings is not None | ||
assert initial_settings.frequency == StatementFrequency.WEEKLY.value | ||
assert initial_settings.from_date == account_create_date.date() | ||
assert initial_settings.to_date is None | ||
|
||
update_date = localize_date(datetime(2024, 6, 13, 12, 0)) | ||
with freeze_time(update_date): | ||
account = PaymentAccountService.update(account.auth_account_id, | ||
get_eft_enable_account_payload(payment_method=PaymentMethod.EFT.value, | ||
account_id=account.auth_account_id)) | ||
# Assert initial settings are properly end dated | ||
assert initial_settings is not None | ||
assert initial_settings.frequency == StatementFrequency.WEEKLY.value | ||
assert initial_settings.from_date == account_create_date.date() | ||
assert initial_settings.to_date == update_date.date() | ||
|
||
# Assert new EFT Monthly settings are created | ||
latest_statement_settings: StatementSettingsModel = StatementSettingsModel \ | ||
.find_latest_settings(account.auth_account_id) | ||
|
||
assert latest_statement_settings is not None | ||
assert latest_statement_settings.id != initial_settings.id | ||
assert latest_statement_settings.frequency == StatementFrequency.MONTHLY.value | ||
assert latest_statement_settings.from_date == (update_date + timedelta(days=1)).date() | ||
assert latest_statement_settings.to_date is None | ||
|
||
# Same day payment method change back to DRAWDOWN | ||
update_date = localize_date(datetime(2024, 6, 13, 12, 5)) | ||
with freeze_time(update_date): | ||
account = PaymentAccountService.update(account.auth_account_id, | ||
get_premium_account_payload(payment_method=PaymentMethod.DRAWDOWN.value)) | ||
|
||
latest_statement_settings: StatementSettingsModel = StatementSettingsModel \ | ||
.find_latest_settings(account.auth_account_id) | ||
|
||
assert latest_statement_settings is not None | ||
assert latest_statement_settings.id != initial_settings.id | ||
assert latest_statement_settings.frequency == StatementFrequency.WEEKLY.value | ||
assert latest_statement_settings.from_date == (update_date + timedelta(days=1)).date() | ||
assert latest_statement_settings.to_date is None | ||
|
||
# Same day payment method change back to EFT | ||
update_date = localize_date(datetime(2024, 6, 13, 12, 6)) | ||
with freeze_time(update_date): | ||
account = PaymentAccountService.update(account.auth_account_id, | ||
get_eft_enable_account_payload(payment_method=PaymentMethod.EFT.value, | ||
account_id=account.auth_account_id)) | ||
|
||
latest_statement_settings: StatementSettingsModel = StatementSettingsModel \ | ||
.find_latest_settings(account.auth_account_id) | ||
|
||
assert latest_statement_settings is not None | ||
assert latest_statement_settings.id != initial_settings.id | ||
assert latest_statement_settings.frequency == StatementFrequency.MONTHLY.value | ||
assert latest_statement_settings.from_date == (update_date + timedelta(days=1)).date() | ||
assert latest_statement_settings.to_date is None | ||
|
||
all_settings = (db.session.query(StatementSettingsModel) | ||
.filter(StatementSettingsModel.payment_account_id == account.id) | ||
.order_by(StatementSettingsModel.id)).all() | ||
|
||
assert all_settings is not None | ||
assert len(all_settings) == 2 | ||
|
||
expected_from_date = latest_statement_settings.from_date | ||
|
||
# Change payment method to DRAWDOWN 1 day later - should create a new statement settings record | ||
update_date = localize_date(datetime(2024, 6, 14, 12, 6)) | ||
with freeze_time(update_date): | ||
account = PaymentAccountService.update(account.auth_account_id, | ||
get_premium_account_payload(payment_method=PaymentMethod.DRAWDOWN.value)) | ||
|
||
latest_statement_settings: StatementSettingsModel = StatementSettingsModel \ | ||
.find_latest_settings(account.auth_account_id) | ||
|
||
assert latest_statement_settings is not None | ||
assert latest_statement_settings.id != initial_settings.id | ||
assert latest_statement_settings.frequency == StatementFrequency.WEEKLY.value | ||
assert latest_statement_settings.from_date == (update_date + timedelta(days=1)).date() | ||
assert latest_statement_settings.to_date is None | ||
|
||
all_settings = (db.session.query(StatementSettingsModel) | ||
.filter(StatementSettingsModel.payment_account_id == account.id) | ||
.order_by(StatementSettingsModel.id)).all() | ||
|
||
assert all_settings is not None | ||
assert len(all_settings) == 3 | ||
|
||
# Assert previous settings properly end dated | ||
assert all_settings[1].frequency == StatementFrequency.MONTHLY.value | ||
assert all_settings[1].from_date == expected_from_date | ||
assert all_settings[1].to_date == update_date.date() | ||
|
||
|
||
def get_statement_date_string(datetime_value: datetime) -> str: | ||
"""Get formatted date string for report input.""" | ||
date_format = '%Y-%m-%d' | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update to allow any number of parameters to be passed in when running a job.