Skip to content

Commit

Permalink
24871 - Add route return valid payment method for product (#1866)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jxio authored Dec 24, 2024
1 parent 2ae38d1 commit 6dc698f
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""add payment_methods column to corp_types table, and insert payment methods based on product
Revision ID: 695a899f8a25
Revises: 4f3a44eeade8
Create Date: 2024-12-18 11:32:07.538729
"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
# Note you may see foreign keys with distribution_codes_history
# For disbursement_distribution_code_id, service_fee_distribution_code_id
# Please ignore those lines and don't include in migration.

revision = '695a899f8a25'
down_revision = '4f3a44eeade8'
branch_labels = None
depends_on = None


def upgrade():
op.add_column(
'corp_types',
sa.Column('payment_methods', sa.ARRAY(sa.String()), nullable=True)
)

op.execute("""
UPDATE corp_types
SET payment_methods =
CASE product
WHEN 'BUSINESS' THEN ARRAY['PAD', 'DIRECT_PAY', 'EFT', 'EJV', 'ONLINE_BANKING', 'DRAWDOWN', 'INTERNAL']
WHEN 'NRO' THEN ARRAY['DIRECT_PAY','PAD', 'DRAWDOWN', 'INTERNAL']
WHEN 'RPPR' THEN ARRAY['PAD', 'DRAWDOWN', 'INTERNAL']
WHEN 'VS' THEN ARRAY['DIRECT_PAY','PAD', 'DRAWDOWN', 'EFT', 'EJV', 'INTERNAL']
WHEN 'RPT' THEN ARRAY['PAD', 'DRAWDOWN', 'EFT', 'EJV', 'INTERNAL']
WHEN 'BUSINESS_SEARCH' THEN ARRAY['PAD', 'DIRECT_PAY', 'DRAWDOWN', 'EJV', 'EFT', 'INTERNAL']
WHEN 'CSO' THEN ARRAY['PAD', 'DRAWDOWN', 'EJV', 'INTERNAL']
WHEN 'ESRA' THEN ARRAY['PAD', 'DRAWDOWN', 'EJV', 'INTERNAL']
WHEN 'PPR' THEN ARRAY['PAD', 'DIRECT_PAY', 'DRAWDOWN', 'EFT', 'EJV', 'INTERNAL']
WHEN 'MHR' THEN ARRAY['PAD', 'DIRECT_PAY', 'DRAWDOWN', 'EFT', 'EJV', 'INTERNAL']
ELSE ARRAY['INTERNAL']
END
WHERE product IS NOT NULL
""")


def downgrade():
op.drop_column('corp_types', 'payment_methods')
2 changes: 2 additions & 0 deletions pay-api/src/pay_api/models/corp_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class CorpType(db.Model, CodeTable):
"description",
"has_partner_disbursements",
"is_online_banking_allowed",
"payment_methods",
"product",
]
}
Expand All @@ -61,6 +62,7 @@ class CorpType(db.Model, CodeTable):
has_partner_disbursements = db.Column(Boolean(), default=False)
batch_type = db.Column(db.String(2), nullable=True)
product = db.Column(db.String(20), nullable=True)
payment_methods = db.Column(db.ARRAY(db.String()), nullable=True)

def save(self):
"""Save corp type."""
Expand Down
8 changes: 8 additions & 0 deletions pay-api/src/pay_api/resources/v1/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,11 @@ def get_codes_by_type(code_type):
def get_code(code_type, code):
"""Return all codes based on code_type."""
return CodeService.find_code_value_by_type_and_code(code_type, code), HTTPStatus.OK


@bp.route("/valid_payment_methods", methods=["GET", "OPTIONS"])
@bp.route("/valid_payment_methods/<string:product_code>", methods=["GET", "OPTIONS"])
@cross_origin(origins="*", methods=["GET"])
def get_valid_payment_methods(product_code=None):
"""Return all valid payment methods based on product code."""
return CodeService.find_valid_payment_methods_by_product_code(product_code), HTTPStatus.OK
19 changes: 19 additions & 0 deletions pay-api/src/pay_api/services/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,22 @@ def find_code_value_by_type_and_code(cls, code_type: str, code: str):
code_response = schema.dump(codes_model, many=False)
current_app.logger.debug(">find_code_value_by_type_and_code")
return code_response

@classmethod
def find_valid_payment_methods_by_product_code(cls, product_code: str | None = None) -> dict:
"""Find payment methods for a product."""
if not product_code:
corp_types = (
CorpType.query.with_entities(CorpType.product, CorpType.payment_methods)
.filter(CorpType.product.isnot(None)) # Exclude None at the query level
.distinct()
.all()
)
return dict(corp_types)

corp_type = (
CorpType.query.with_entities(CorpType.product, CorpType.payment_methods)
.filter_by(product=product_code)
.first()
)
return {corp_type.product: corp_type.payment_methods} if corp_type else {}
15 changes: 15 additions & 0 deletions pay-api/tests/unit/api/test_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,18 @@ def test_find_codes(session, client, jwt, app, code: Code):
"""Assert that the endpoint returns 200."""
rv = client.get(f"/api/v1/codes/{code.value}", headers={})
assert rv.status_code == 200


def test_get_valid_payment_methods(session, client, jwt, app):
"""Assert that the valid payment methods endpoint works."""
rv = client.get("/api/v1/codes/valid_payment_methods", headers={})
assert rv.status_code == 200
assert isinstance(rv.json, dict)

rv = client.get("/api/v1/codes/valid_payment_methods/VS", headers={})
assert rv.status_code == 200
assert isinstance(rv.json, dict)

rv = client.get("/api/v1/codes/valid_payment_methods/INVALID", headers={})
assert rv.status_code == 200
assert rv.json == {}
25 changes: 23 additions & 2 deletions pay-api/tests/unit/models/test_corp_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,14 @@
from pay_api.models import CorpType


def factory_corp_type(corp_type_code: str, corp_description: str):
def factory_corp_type(corp_type_code: str, corp_description: str, product: str = None, payment_methods: list = None):
"""Return a valid Corp Type object."""
return CorpType(code=corp_type_code, description=corp_description)
corp_type = CorpType(code=corp_type_code, description=corp_description)
if product:
corp_type.product = product
if payment_methods:
corp_type.payment_methods = payment_methods
return corp_type


def test_corp_type(session):
Expand Down Expand Up @@ -54,3 +59,19 @@ def test_corp_type_by_invalid_code(session):

b = CorpType.find_by_code("AB")
assert b is None


def test_payment_methods(session):
"""Assert that payment methods are stored and retrieved correctly."""
business_corp = factory_corp_type(
"XX",
"Business",
product="BUSINESS",
payment_methods=['PAD', 'DIRECT_PAY', 'ONLINE_BANKING', 'DRAWDOWN']
)
session.add(business_corp)
session.commit()

retrieved_corp = CorpType.find_by_code("XX")
assert retrieved_corp is not None
assert retrieved_corp.payment_methods == ['PAD', 'DIRECT_PAY', 'ONLINE_BANKING', 'DRAWDOWN']
15 changes: 15 additions & 0 deletions pay-api/tests/unit/services/test_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,18 @@ def test_find_payment_types_code_values(session):
codes = CodeService.find_code_values_by_type(Code.INVOICE_STATUS.value)
assert codes is not None
assert len(codes) > 0


def test_find_valid_payment_methods_by_product_code(session):
"""Assert that valid payment methods are returned for products."""
payment_methods = CodeService.find_valid_payment_methods_by_product_code()
assert payment_methods is not None
assert isinstance(payment_methods, dict)

business_payment_methods = CodeService.find_valid_payment_methods_by_product_code('BUSINESS')
assert business_payment_methods is not None
assert 'BUSINESS' in business_payment_methods
assert isinstance(business_payment_methods['BUSINESS'], list)

invalid_payment_methods = CodeService.find_valid_payment_methods_by_product_code('INVALID')
assert invalid_payment_methods == {}

0 comments on commit 6dc698f

Please sign in to comment.