Skip to content

Commit

Permalink
22655P2 - Fixes for consolidated invoices backend (#1748)
Browse files Browse the repository at this point in the history
  • Loading branch information
seeker25 authored Sep 16, 2024
1 parent ff47ad7 commit 8161642
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 8 deletions.
7 changes: 7 additions & 0 deletions pay-api/src/pay_api/services/eft_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,13 @@ def process_cfs_refund(self, invoice: InvoiceModel,
invoice.id, InvoiceReferenceStatus.ACTIVE.value) is None and not cils:
return InvoiceStatus.CANCELLED.value

inv_ref = InvoiceReferenceModel.find_by_invoice_id_and_status(invoice.id,
InvoiceReferenceStatus.COMPLETED.value)
if inv_ref and inv_ref.is_consolidated:
# We can't allow these, because they credit memo the account and don't actually refund.
# Also untested with EFT. We want to be able to refund back to the original payment method.
raise BusinessException(Error.INVALID_CONSOLIDATED_REFUND)

# 2. No EFT Credit Link - Job needs to reverse invoice in CFS
# (Invoice needs to be reversed, receipt doesn't exist.)
if not cils:
Expand Down
15 changes: 12 additions & 3 deletions pay-api/src/pay_api/services/oauth_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from collections.abc import Iterable
from typing import Dict

import re
import requests
from flask import current_app
from requests.adapters import HTTPAdapter # pylint:disable=ungrouped-imports
Expand Down Expand Up @@ -55,8 +56,10 @@ def post(endpoint, token, auth_header_type: AuthHeaderType, # pylint: disable=t
if content_type == ContentType.JSON:
data = json.dumps(data, cls=DecimalEncoder)

safe_headers = headers.copy()
safe_headers.pop('Authorization', None)
current_app.logger.debug(f'Endpoint : {endpoint}')
current_app.logger.debug(f'headers : {headers}')
current_app.logger.debug(f'headers : {safe_headers}')
current_app.logger.debug(f'data : {data}')
response = None
try:
Expand Down Expand Up @@ -91,7 +94,11 @@ def __log_response(response):
if response.headers and isinstance(response.headers, Iterable) and \
'Content-Type' in response.headers and \
response.headers['Content-Type'] == ContentType.JSON.value:
current_app.logger.info(f"response : {response.text if response else ''} ")
# Remove authentication from response
response_text = response.text if response is not None else ''
response_text = re.sub(r'"access_token"\s*:\s*"[^"]*",?\s*', '', response_text)
response_text = re.sub(r',\s*}', '}', response_text)
current_app.logger.info(f'response : {response_text}')

@staticmethod
def get(endpoint, token, auth_header_type: AuthHeaderType, # pylint:disable=too-many-arguments
Expand All @@ -109,8 +116,10 @@ def get(endpoint, token, auth_header_type: AuthHeaderType, # pylint:disable=too
if additional_headers is not None:
headers.update(additional_headers)

safe_headers = headers.copy()
safe_headers.pop('Authorization', None)
current_app.logger.debug(f'Endpoint : {endpoint}')
current_app.logger.debug(f'headers : {headers}')
current_app.logger.debug(f'headers : {safe_headers}')
session = requests.Session()
if retry_on_failure:
session.mount(endpoint, RETRY_ADAPTER)
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 @@ -102,6 +102,7 @@ class Error(Enum):
# Refund Errors
ROUTING_SLIP_REFUND = 'ROUTING_SLIP_REFUND', HTTPStatus.BAD_REQUEST
NO_FEE_REFUND = 'NO_FEE_REFUND', HTTPStatus.BAD_REQUEST
INVALID_CONSOLIDATED_REFUND = 'INVALID_CONSOLIDATED_REFUND', HTTPStatus.BAD_REQUEST

RS_ALREADY_A_PARENT = 'RS_ALREADY_A_PARENT', HTTPStatus.BAD_REQUEST
RS_ALREADY_LINKED = 'RS_ALREADY_LINKED', HTTPStatus.BAD_REQUEST
Expand Down
23 changes: 18 additions & 5 deletions pay-api/tests/unit/services/test_eft_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
from pay_api.models import EFTCreditInvoiceLink as EFTCreditInvoiceLinkModel
from pay_api.models import EFTShortnamesHistorical as EFTHistoryModel
from pay_api.services.eft_service import EftService
from pay_api.utils.enums import EFTCreditInvoiceStatus, EFTHistoricalTypes, InvoiceStatus, PaymentMethod
from pay_api.utils.enums import (
EFTCreditInvoiceStatus, EFTHistoricalTypes, InvoiceReferenceStatus, InvoiceStatus, PaymentMethod)
from pay_api.utils.errors import Error
from tests.utilities.base_test import (
factory_eft_credit, factory_eft_credit_invoice_link, factory_eft_file, factory_eft_shortname, factory_invoice,
Expand Down Expand Up @@ -119,7 +120,8 @@ def test_refund_eft_credits_exceed_balance(session):
('1_invoice_non_exist'),
('2_no_eft_credit_link'),
('3_pending_credit_link'),
('4_completed_credit_link')
('4_completed_credit_link'),
('5_consolidated_invoice_block')
])
def test_eft_invoice_refund(session, test_name):
"""Test various scenarios for eft_invoice_refund."""
Expand Down Expand Up @@ -162,9 +164,13 @@ def test_eft_invoice_refund(session, test_name):
eft_credit_id=eft_credit.id,
status_code=EFTCreditInvoiceStatus.PENDING.value,
link_group_id=3).save()
case '4_completed_credit_link':
factory_invoice_reference(invoice_id=invoice.id,
invoice_number='1234').save()
case '4_completed_credit_link' | '5_consolidated_invoice_block':
invoice_reference = factory_invoice_reference(invoice_id=invoice.id,
invoice_number='1234').save()
if test_name == '5_consolidated_invoice_block':
invoice_reference.is_consolidated = True
invoice_reference.status_code = InvoiceReferenceStatus.COMPLETED.value
invoice_reference.save()
# Filler rows to make sure COMPLETED is the highest ID
cil_1 = factory_eft_credit_invoice_link(invoice_id=invoice.id,
eft_credit_id=eft_credit.id,
Expand All @@ -190,6 +196,13 @@ def test_eft_invoice_refund(session, test_name):
case _:
raise NotImplementedError

if test_name == '5_consolidated_invoice_block':
with pytest.raises(BusinessException) as excinfo:
invoice.invoice_status_code = eft_service.process_cfs_refund(invoice, payment_account, None)
invoice.save()
assert excinfo.value.code == Error.INVALID_CONSOLIDATED_REFUND.name
return

invoice.invoice_status_code = eft_service.process_cfs_refund(invoice, payment_account, None)
invoice.save()

Expand Down

0 comments on commit 8161642

Please sign in to comment.