Skip to content

Commit

Permalink
20419 - Short name linking status (#1540)
Browse files Browse the repository at this point in the history
- Handle basic unlinking for short name still in pending
- return whether associated account link has pending payments
  • Loading branch information
ochiu authored May 27, 2024
1 parent 594aef1 commit cd3901d
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 4 deletions.
4 changes: 3 additions & 1 deletion pay-api/src/pay_api/models/eft_short_name_links.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class EFTShortnameLinkSchema: # pylint: disable=too-few-public-methods
updated_by: str
updated_by_name: str
updated_on: datetime
has_pending_payment: bool

@classmethod
def from_row(cls, row: EFTShortnameLinks):
Expand All @@ -98,5 +99,6 @@ def from_row(cls, row: EFTShortnameLinks):
amount_owing=getattr(row, 'total_owing', None),
updated_by=row.updated_by,
updated_by_name=row.updated_by_name,
updated_on=row.updated_on
updated_on=row.updated_on,
has_pending_payment=bool(getattr(row, 'invoice_count', 0))
)
22 changes: 22 additions & 0 deletions pay-api/src/pay_api/resources/v1/eft_short_names.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,25 @@ def post_eft_shortname_link(short_name_id: int):

current_app.logger.debug('>post_eft_shortname_link')
return jsonify(response), status


@bp.route('/<int:short_name_id>/links/<int:short_name_link_id>', methods=['DELETE', 'OPTIONS'])
@cross_origin(origins='*', methods=['DELETE'])
@_jwt.has_one_of_roles([Role.SYSTEM.value, Role.MANAGE_EFT.value])
def delete_eft_shortname_link(short_name_id: int, short_name_link_id: int):
"""Delete EFT short name to account link."""
current_app.logger.info('<delete_eft_shortname_link')

try:
link = EFTShortnameService.find_link_by_id(short_name_link_id)
if not link or link['short_name_id'] != short_name_id:
response, status = {'message': 'The requested EFT short name could not be found.'}, \
HTTPStatus.NOT_FOUND
else:
EFTShortnameService.delete_shortname_link(short_name_link_id)
response, status = None, HTTPStatus.ACCEPTED
except BusinessException as exception:
return exception.response()

current_app.logger.debug('>delete_eft_shortname_link')
return jsonify(response), status
32 changes: 29 additions & 3 deletions pay-api/src/pay_api/services/eft_short_names.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,18 @@
from pay_api.exceptions import BusinessException
from pay_api.factory.payment_system_factory import PaymentSystemFactory
from pay_api.models import CfsAccount as CfsAccountModel
from pay_api.models import EFTShortnames as EFTShortnameModel
from pay_api.models import EFTCreditInvoiceLink as EFTCreditInvoiceLinkModel
from pay_api.models import EFTShortnameLinks as EFTShortnameLinksModel
from pay_api.models import EFTShortnameLinkSchema
from pay_api.models import EFTShortnames as EFTShortnameModel
from pay_api.models import EFTShortnameSchema
from pay_api.models import Invoice as InvoiceModel
from pay_api.models import PaymentAccount as PaymentAccountModel
from pay_api.models import Statement as StatementModel
from pay_api.models import StatementInvoices as StatementInvoicesModel
from pay_api.models import db
from pay_api.utils.converter import Converter
from pay_api.utils.enums import EFTShortnameStatus, InvoiceStatus, PaymentMethod
from pay_api.utils.enums import EFTCreditInvoiceStatus, EFTShortnameStatus, InvoiceStatus, PaymentMethod
from pay_api.utils.errors import Error
from pay_api.utils.user_context import user_context
from pay_api.utils.util import unstructure_schema_items
Expand Down Expand Up @@ -96,18 +97,33 @@ def create_shortname_link(cls, short_name_id: int, auth_account_id: str, **kwarg
current_app.logger.debug('>create_shortname_link')
return cls.find_link_by_id(eft_short_name_link.id)

@classmethod
def delete_shortname_link(cls, short_name_link_id: int):
"""Delete EFT short name auth account link."""
current_app.logger.debug('<delete_shortname_link')
short_name_link: EFTShortnameLinksModel = EFTShortnameLinksModel.find_by_id(short_name_link_id)

if short_name_link.status_code != EFTShortnameStatus.PENDING.value:
raise BusinessException(Error.EFT_SHORT_NAME_LINK_INVALID_STATUS)

short_name_link.delete()
current_app.logger.debug('>delete_shortname_link')

@classmethod
def get_shortname_links(cls, short_name_id: int) -> List[EFTShortnameLinksModel]:
"""Get EFT short name account links."""
current_app.logger.debug('<get_shortname_links')
statement_summary_query = cls.get_statement_summary_query().subquery()
invoice_count_query = cls.get_pending_payment_count()

query = db.session.query(EFTShortnameLinksModel.id.label('id'),
EFTShortnameLinksModel.eft_short_name_id,
EFTShortnameLinksModel.status_code,
EFTShortnameLinksModel.auth_account_id,
EFTShortnameLinksModel.updated_by,
EFTShortnameLinksModel.updated_by_name,
EFTShortnameLinksModel.updated_on) \
EFTShortnameLinksModel.updated_on,
invoice_count_query.label('invoice_count')) \
.join(
PaymentAccountModel,
PaymentAccountModel.auth_account_id == EFTShortnameLinksModel.auth_account_id)
Expand Down Expand Up @@ -267,6 +283,16 @@ def add_payment_account_name_columns(query):
), else_=PaymentAccountModel.name).label('account_name'),
PaymentAccountModel.branch_name.label('account_branch'))

@staticmethod
def get_pending_payment_count():
"""Get count of pending EFT Credit Invoice Links."""
return (db.session.query(db.func.count(InvoiceModel.id).label('invoice_count'))
.join(EFTCreditInvoiceLinkModel, EFTCreditInvoiceLinkModel.invoice_id == InvoiceModel.id)
.filter(InvoiceModel.payment_account_id == PaymentAccountModel.id)
.filter(EFTCreditInvoiceLinkModel.status_code.in_([EFTCreditInvoiceStatus.PENDING.value]))
.correlate(PaymentAccountModel)
.as_scalar())

@classmethod
def get_search_query(cls, search_criteria: EFTShortnamesSearch, is_count: bool = False):
"""Query for short names based on search criteria."""
Expand Down
1 change: 1 addition & 0 deletions pay-api/src/pay_api/utils/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class Error(Enum):
EFT_SHORT_NAME_EXISTS = 'EFT_SHORT_NAME_EXISTS', HTTPStatus.BAD_REQUEST
EFT_SHORT_NAME_ACCOUNT_ID_REQUIRED = 'EFT_SHORT_NAME_ACCOUNT_ID_REQUIRED', HTTPStatus.BAD_REQUEST
EFT_SHORT_NAME_ALREADY_MAPPED = 'EFT_SHORT_NAME_ALREADY_MAPPED', HTTPStatus.BAD_REQUEST
EFT_SHORT_NAME_LINK_INVALID_STATUS = 'EFT_SHORT_NAME_LINK_INVALID_STATUS', HTTPStatus.BAD_REQUEST

# FAS Errors
FAS_INVALID_PAYMENT_METHOD = 'FAS_INVALID_PAYMENT_METHOD', HTTPStatus.BAD_REQUEST
Expand Down
33 changes: 33 additions & 0 deletions pay-api/tests/unit/api/test_eft_short_names.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from pay_api.models import EFTCredit as EFTCreditModel
from pay_api.models import EFTFile as EFTFileModel
from pay_api.models import EFTShortnames as EFTShortnamesModel
from pay_api.models import EFTShortnameLinks as EFTShortnameLinksModel
from pay_api.models import EFTTransaction as EFTTransactionModel
from pay_api.models import Payment as PaymentModel
from pay_api.models import PaymentAccount as PaymentAccountModel
Expand Down Expand Up @@ -95,6 +96,38 @@ def test_create_eft_short_name_link_validation(session, client, jwt, app):
assert link_dict['type'] == 'EFT_SHORT_NAME_ALREADY_MAPPED'


def test_eft_short_name_unlink(session, client, jwt, app):
"""Assert that an EFT short name unlinking and basic state validation."""
token = jwt.create_jwt(get_claims(roles=[Role.MANAGE_EFT.value],
username='IDIR/JSMITH'), token_header)
headers = {'Authorization': f'Bearer {token}', 'content-type': 'application/json'}
account = factory_payment_account(payment_method_code=PaymentMethod.EFT.value,
auth_account_id='1234').save()

short_name = factory_eft_shortname(short_name='TESTSHORTNAME').save()
short_name_link = EFTShortnameLinksModel(
eft_short_name_id=short_name.id,
status_code=EFTShortnameStatus.LINKED.value,
auth_account_id=account.auth_account_id
).save()

# Assert cannot unlink an account not in PENDING status
rv = client.delete(f'/api/v1/eft-shortnames/{short_name.id}/links/{short_name_link.id}',
headers=headers)

link_dict = rv.json
assert rv.status_code == 400
assert link_dict['type'] == 'EFT_SHORT_NAME_LINK_INVALID_STATUS'

short_name_link.status_code = EFTShortnameStatus.PENDING.value
short_name_link.save()

# Assert we can delete a short name link that is pending
rv = client.delete(f'/api/v1/eft-shortnames/{short_name.id}/links/{short_name_link.id}',
headers=headers)
assert rv.status_code == 202


def test_get_eft_short_name_links(session, client, jwt, app):
"""Assert that short name links can be retrieved."""
token = jwt.create_jwt(get_claims(roles=[Role.MANAGE_EFT.value],
Expand Down

0 comments on commit cd3901d

Please sign in to comment.