Skip to content

Commit

Permalink
Add extra step to set transactions to REFUNDED if billable = 'f' (#1321)
Browse files Browse the repository at this point in the history
  • Loading branch information
seeker25 authored Nov 8, 2023
1 parent 1a1cb0c commit d1a7fea
Show file tree
Hide file tree
Showing 11 changed files with 29 additions and 14 deletions.
3 changes: 2 additions & 1 deletion pay-api/src/pay_api/services/base_payment_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ def get_payment_system_url_for_payment(self, payment: Payment, # pylint:disable
"""Return the payment system portal URL for payment."""
return None

def process_cfs_refund(self, invoice: InvoiceModel): # pylint:disable=unused-argument
def process_cfs_refund(self, invoice: InvoiceModel, # pylint:disable=unused-argument
payment_account: PaymentAccount): # pylint:disable=unused-argument
"""Process Refund if any."""
return None

Expand Down
3 changes: 2 additions & 1 deletion pay-api/src/pay_api/services/bcol_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ def get_payment_method_code(self):
"""Return CC as the method code."""
return PaymentMethod.DRAWDOWN.value

def process_cfs_refund(self, invoice: InvoiceModel):
def process_cfs_refund(self, invoice: InvoiceModel,
payment_account: PaymentAccount): # pylint:disable=unused-argument
"""Process refund in CFS."""
self._publish_refund_to_mailer(invoice)
payment: PaymentModel = PaymentModel.find_payment_for_invoice(invoice.id)
Expand Down
3 changes: 2 additions & 1 deletion pay-api/src/pay_api/services/direct_pay_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ def get_pay_system_reason_code(self, pay_response_url: str) -> str: # pylint:di
return pay_system_reason_code
return None

def process_cfs_refund(self, invoice: InvoiceModel):
def process_cfs_refund(self, invoice: InvoiceModel,
payment_account: PaymentAccount): # pylint:disable=unused-argument
"""Process refund in CFS."""
current_app.logger.debug('<process_cfs_refund creating automated refund for invoice: '
f'{invoice.id}, {invoice.invoice_status_code}')
Expand Down
5 changes: 4 additions & 1 deletion pay-api/src/pay_api/services/ejv_pay_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ def complete_post_invoice(self, invoice: Invoice, invoice_reference: InvoiceRefe
# Publish message to the queue with payment token, so that they can release records on their side.
self._release_payment(invoice=invoice)

def process_cfs_refund(self, invoice: InvoiceModel) -> str: # pylint:disable=unused-argument
def process_cfs_refund(self, invoice: InvoiceModel,
payment_account: PaymentAccount) -> str: # pylint:disable=unused-argument
"""Do nothing to process refund; as the refund is handled by CRON job.
Return the status after checking invoice status.
Expand All @@ -76,6 +77,8 @@ def process_cfs_refund(self, invoice: InvoiceModel) -> str: # pylint:disable=un
2.1 Return REFUND_REQUESTED
"""
current_app.logger.info(f'Received JV refund for invoice {invoice.id}, {invoice.invoice_status_code}')
if not payment_account.billable:
return InvoiceStatus.REFUNDED.value
if invoice.invoice_status_code == InvoiceStatus.APPROVED.value:
if InvoiceReference.find_active_reference_by_invoice_id(invoice.id):
return InvoiceStatus.REFUND_REQUESTED.value
Expand Down
3 changes: 2 additions & 1 deletion pay-api/src/pay_api/services/internal_pay_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ def get_default_invoice_status(self) -> str:
"""Return the default status for invoice when created."""
return InvoiceStatus.APPROVED.value

def process_cfs_refund(self, invoice: InvoiceModel):
def process_cfs_refund(self, invoice: InvoiceModel,
payment_account: PaymentAccount): # pylint:disable=unused-argument
"""Process refund in CFS."""
if invoice.total == 0:
raise BusinessException(Error.NO_FEE_REFUND)
Expand Down
3 changes: 2 additions & 1 deletion pay-api/src/pay_api/services/online_banking_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ def cancel_invoice(self, payment_account: PaymentAccount, inv_number: str):
current_app.logger.debug('<cancel_invoice %s, %s', payment_account, inv_number)
self.reverse_invoice(inv_number)

def process_cfs_refund(self, invoice: InvoiceModel):
def process_cfs_refund(self, invoice: InvoiceModel,
payment_account: PaymentAccount): # pylint:disable=unused-argument
"""Process refund in CFS."""
return super()._refund_and_create_credit_memo(invoice)
3 changes: 2 additions & 1 deletion pay-api/src/pay_api/services/pad_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ def complete_post_invoice(self, invoice: Invoice, # pylint: disable=unused-argu
# Publish message to the queue with payment token, so that they can release records on their side.
self._release_payment(invoice=invoice)

def process_cfs_refund(self, invoice: InvoiceModel):
def process_cfs_refund(self, invoice: InvoiceModel,
payment_account: PaymentAccount): # pylint:disable=unused-argument
"""Process refund in CFS."""
# Move invoice to CREDITED or CANCELLED. There are no refunds for PAD, just cancellation or credit.
# Credit memos don't return to the bank account.
Expand Down
3 changes: 2 additions & 1 deletion pay-api/src/pay_api/services/paybc_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@ def _get_receipt_by_number(self, access_token: str = None, receipt_url: str = No
receipt_url = receipt_url + f'{receipt_number}/'
return self.get(receipt_url, access_token, AuthHeaderType.BEARER, ContentType.JSON, True).json()

def process_cfs_refund(self, invoice: InvoiceModel):
def process_cfs_refund(self, invoice: InvoiceModel,
payment_account: PaymentAccount): # pylint:disable=unused-argument
"""Process refund in CFS."""
return super()._refund_and_create_credit_memo(invoice)

Expand Down
4 changes: 3 additions & 1 deletion pay-api/src/pay_api/services/refund.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from pay_api.models import Refund as RefundModel
from pay_api.models import RoutingSlip as RoutingSlipModel
from pay_api.services.base_payment_system import PaymentSystemService
from pay_api.services.payment_account import PaymentAccount
from pay_api.utils.constants import REFUND_SUCCESS_MESSAGES
from pay_api.utils.enums import InvoiceStatus, Role, RoutingSlipStatus
from pay_api.utils.errors import Error
Expand Down Expand Up @@ -266,7 +267,8 @@ def create_refund(cls, invoice_id: int, request: Dict[str, str], **kwargs) -> Di
pay_system_service: PaymentSystemService = PaymentSystemFactory.create_from_payment_method(
payment_method=invoice.payment_method_code
)
invoice_status = pay_system_service.process_cfs_refund(invoice)
payment_account = PaymentAccount.find_by_id(invoice.payment_account_id)
invoice_status = pay_system_service.process_cfs_refund(invoice, payment_account=payment_account)
refund.flush()
message = REFUND_SUCCESS_MESSAGES.get(f'{invoice.payment_method_code}.{invoice.invoice_status_code}')
# set invoice status
Expand Down
8 changes: 4 additions & 4 deletions pay-api/tests/unit/services/test_direct_pay_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ def test_process_cfs_refund_success(monkeypatch):

direct_pay_service = DirectPayService()

direct_pay_service.process_cfs_refund(invoice)
direct_pay_service.process_cfs_refund(invoice, payment_account)
assert True


Expand All @@ -208,7 +208,7 @@ def test_process_cfs_refund_bad_request():
invoice.save()
direct_pay_service = DirectPayService()
with pytest.raises(BusinessException) as excinfo:
direct_pay_service.process_cfs_refund(invoice)
direct_pay_service.process_cfs_refund(invoice, payment_account)
assert excinfo.value.code == Error.INVALID_REQUEST.name


Expand Down Expand Up @@ -241,7 +241,7 @@ def test_process_cfs_refund_duplicate_refund(monkeypatch):
]
}
with pytest.raises(HTTPError) as excinfo:
direct_pay_service.process_cfs_refund(invoice)
direct_pay_service.process_cfs_refund(invoice, payment_account)
assert invoice.invoice_status_code == InvoiceStatus.PAID.value

with patch('pay_api.services.oauth_service.requests.post') as mock_post:
Expand All @@ -257,5 +257,5 @@ def test_process_cfs_refund_duplicate_refund(monkeypatch):
'txnNumber': 'REGT00005433'
}
with pytest.raises(BusinessException) as excinfo:
direct_pay_service.process_cfs_refund(invoice)
direct_pay_service.process_cfs_refund(invoice, payment_account)
assert excinfo.value.code == Error.DIRECT_PAY_INVALID_RESPONSE.name
5 changes: 4 additions & 1 deletion pay-api/tests/unit/services/test_payment_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from pay_api.models import RoutingSlip as RoutingSlipModel
from pay_api.services import CFSService
from pay_api.services.internal_pay_service import InternalPayService
from pay_api.services.payment_account import PaymentAccount as PaymentAccountService
from pay_api.services.payment_service import PaymentService
from pay_api.utils.enums import InvoiceStatus, PaymentMethod, PaymentStatus, RoutingSlipStatus
from requests.exceptions import ConnectionError, ConnectTimeout, HTTPError
Expand Down Expand Up @@ -388,6 +389,8 @@ def test_internal_rs_back_active(session, public_user_mock):
assert rs.status == RoutingSlipStatus.COMPLETE.name

invoice = Invoice.find_by_id(invoice['id'])
InternalPayService().process_cfs_refund(invoice)
payment_account = PaymentAccountService()
payment_account._dao = account_model # pylint: disable=protected-access
InternalPayService().process_cfs_refund(invoice, payment_account)

assert rs.status == RoutingSlipStatus.ACTIVE.name

0 comments on commit d1a7fea

Please sign in to comment.