From 37501004684f03adae3b29b9ea13adc5ab739e42 Mon Sep 17 00:00:00 2001 From: Odysseus Chiu Date: Mon, 16 Sep 2024 10:10:57 -0700 Subject: [PATCH 1/2] 21570-short-name-patch --- ...b0e78d8c_21570_short_name_supplier_info.py | 32 +++++++++++++++++++ pay-api/src/pay_api/models/eft_short_names.py | 8 +++++ .../pay_api/resources/v1/eft_short_names.py | 21 +++++++++++- .../schemas/schemas/eft_short_name.json | 26 ++++++++------- .../src/pay_api/services/eft_short_names.py | 19 +++++++++++ pay-api/src/pay_api/version.py | 2 +- pay-api/tests/unit/api/test_cors_preflight.py | 2 +- .../tests/unit/api/test_eft_short_names.py | 23 +++++++++++++ .../tests/unit/models/test_eft_short_names.py | 4 +++ 9 files changed, 122 insertions(+), 15 deletions(-) create mode 100644 pay-api/migrations/versions/2024_09_13_1fadb0e78d8c_21570_short_name_supplier_info.py diff --git a/pay-api/migrations/versions/2024_09_13_1fadb0e78d8c_21570_short_name_supplier_info.py b/pay-api/migrations/versions/2024_09_13_1fadb0e78d8c_21570_short_name_supplier_info.py new file mode 100644 index 000000000..55bdaf42d --- /dev/null +++ b/pay-api/migrations/versions/2024_09_13_1fadb0e78d8c_21570_short_name_supplier_info.py @@ -0,0 +1,32 @@ +"""21570-Short-name-supplier-info + +Revision ID: 1fadb0e78d8c +Revises: 2097573390f1 +Create Date: 2024-09-13 11:28:29.568578 + +""" +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 = '1fadb0e78d8c' +down_revision = '2097573390f1' +branch_labels = None +depends_on = None + + +def upgrade(): + with op.batch_alter_table('eft_short_names', schema=None) as batch_op: + batch_op.add_column(sa.Column('cas_supplier_number', sa.String(25), nullable=True)) + batch_op.add_column(sa.Column('email', sa.String(100), nullable=True)) + + +def downgrade(): + with op.batch_alter_table('eft_short_names', schema=None) as batch_op: + batch_op.drop_column('cas_supplier_number') + batch_op.drop_column('email') diff --git a/pay-api/src/pay_api/models/eft_short_names.py b/pay-api/src/pay_api/models/eft_short_names.py index 630c6fd07..a3fc477aa 100644 --- a/pay-api/src/pay_api/models/eft_short_names.py +++ b/pay-api/src/pay_api/models/eft_short_names.py @@ -40,7 +40,9 @@ class EFTShortnames(Versioned, BaseModel): # pylint: disable=too-many-instance- __mapper_args__ = { 'include_properties': [ 'id', + 'cas_supplier_number', 'created_on', + 'email', 'short_name' ] } @@ -48,6 +50,8 @@ class EFTShortnames(Versioned, BaseModel): # pylint: disable=too-many-instance- id = db.Column(db.Integer, primary_key=True, autoincrement=True) created_on = db.Column('created_on', db.DateTime, nullable=False, default=lambda: datetime.now(tz=timezone.utc)) short_name = db.Column('short_name', db.String, nullable=False, index=True) + email = db.Column(db.String(100), nullable=True) + cas_supplier_number = db.Column(db.String(), nullable=True) @classmethod def find_by_short_name(cls, short_name: str): @@ -65,6 +69,8 @@ class EFTShortnameSchema: # pylint: disable=too-few-public-methods account_branch: str amount_owing: Decimal created_on: datetime + email: str + cas_supplier_number: str short_name: str statement_id: int status_code: str @@ -83,6 +89,8 @@ def from_row(cls, row: EFTShortnames): amount_owing=getattr(row, 'total_owing', None), created_on=row.created_on, short_name=row.short_name, + email=getattr(row, 'email'), + cas_supplier_number=getattr(row, 'cas_supplier_number'), statement_id=getattr(row, 'latest_statement_id', None), status_code=getattr(row, 'status_code', None), cfs_account_status=getattr(row, 'cfs_account_status', None) diff --git a/pay-api/src/pay_api/resources/v1/eft_short_names.py b/pay-api/src/pay_api/resources/v1/eft_short_names.py index 2578190dc..4c2cf7da3 100644 --- a/pay-api/src/pay_api/resources/v1/eft_short_names.py +++ b/pay-api/src/pay_api/resources/v1/eft_short_names.py @@ -103,7 +103,7 @@ def get_eft_shortname_summaries(): @bp.route('/', methods=['GET', 'OPTIONS']) -@cross_origin(origins='*', methods=['GET']) +@cross_origin(origins='*', methods=['GET', 'PATCH']) @_jwt.requires_auth @_jwt.has_one_of_roles([Role.SYSTEM.value, Role.MANAGE_EFT.value]) def get_eft_shortname(short_name_id: int): @@ -118,6 +118,25 @@ def get_eft_shortname(short_name_id: int): return jsonify(response), status +@bp.route('/', methods=['PATCH']) +@cross_origin(origins='*') +@_jwt.requires_auth +@_jwt.has_one_of_roles([Role.SYSTEM.value, Role.MANAGE_EFT.value]) +def patch_eft_shortname(short_name_id: int): + """Patch EFT short name.""" + current_app.logger.info('patch_eft_shortname') + return jsonify(response), status + + @bp.route('//history', methods=['GET', 'OPTIONS']) @cross_origin(origins='*', methods=['GET']) @_jwt.requires_auth diff --git a/pay-api/src/pay_api/schemas/schemas/eft_short_name.json b/pay-api/src/pay_api/schemas/schemas/eft_short_name.json index 6ce6b9c9f..381d07c2a 100644 --- a/pay-api/src/pay_api/schemas/schemas/eft_short_name.json +++ b/pay-api/src/pay_api/schemas/schemas/eft_short_name.json @@ -2,25 +2,27 @@ "$schema": "http://json-schema.org/draft-07/schema#", "$id": "https://bcrs.gov.bc.ca/.well_known/schemas/eft_short_name", "type": "object", - "title": "EFT Short name response", - "required": [ - "shortName" - ], + "title": "EFT Short name patch request", "properties": { - "shortName": { - "$id": "#/properties/shortName", + "casSupplierNumber": { + "$id": "#/properties/casSupplierNumber", "type": "string", - "title": "EFT short name", + "title": "CAS Supplier Number", + "description": "EFT Short name associated CAS supplier number.", + "maxLength": 25, "examples": [ "ABC123" ] }, - "accountId": { - "$id": "#/properties/accountId", - "type": ["string", "null"], - "title": "BC Registries Account Number", + "email": { + "$id": "#/properties/email", + "type": "string", + "title": "Email", + "format": "email", + "description": "EFT Short name contact email.", + "maxLength": 100, "examples": [ - "1234" + "test@gmail.com" ] } } diff --git a/pay-api/src/pay_api/services/eft_short_names.py b/pay-api/src/pay_api/services/eft_short_names.py index 4f56ef319..3822210a6 100644 --- a/pay-api/src/pay_api/services/eft_short_names.py +++ b/pay-api/src/pay_api/services/eft_short_names.py @@ -359,6 +359,23 @@ def _send_reversed_payment_notification(cls, statement: StatementModel, reversed html_body=_render_payment_reversed_template(email_params), **kwargs) + @classmethod + def patch_shortname(cls, short_name_id: int, request: Dict): + """Patch EFT short name.""" + current_app.logger.debug('patch_shortname') + return cls.find_by_short_name_id(short_name_id) + @classmethod def patch_shortname_link(cls, link_id: int, request: Dict): """Patch EFT short name link.""" @@ -683,6 +700,8 @@ def get_search_query(cls, search_criteria: EFTShortnamesSearch, is_count: bool = query = db.session.query(EFTShortnameModel.id, EFTShortnameModel.short_name, + EFTShortnameModel.cas_supplier_number, + EFTShortnameModel.email, EFTShortnameModel.created_on) # Join payment information if this is NOT the count query diff --git a/pay-api/src/pay_api/version.py b/pay-api/src/pay_api/version.py index 6f7dcc57d..a323323b2 100644 --- a/pay-api/src/pay_api/version.py +++ b/pay-api/src/pay_api/version.py @@ -22,4 +22,4 @@ Development release segment: .devN """ -__version__ = '1.22.0' # pylint: disable=invalid-name +__version__ = '1.22.1' # pylint: disable=invalid-name diff --git a/pay-api/tests/unit/api/test_cors_preflight.py b/pay-api/tests/unit/api/test_cors_preflight.py index a3b7abe39..9b77e4f14 100644 --- a/pay-api/tests/unit/api/test_cors_preflight.py +++ b/pay-api/tests/unit/api/test_cors_preflight.py @@ -227,7 +227,7 @@ def test_preflight_eft_shortnames(app, client, jwt, session): rv = client.options('/api/v1/eft-shortnames/1', headers={'Access-Control-Request-Method': 'GET'}) assert rv.status_code == 200 - assert_access_control_headers(rv, '*', 'GET') + assert_access_control_headers(rv, '*', 'GET, PATCH') rv = client.options('/api/v1/eft-shortnames/summaries', headers={'Access-Control-Request-Method': 'GET'}) diff --git a/pay-api/tests/unit/api/test_eft_short_names.py b/pay-api/tests/unit/api/test_eft_short_names.py index c1676cf50..6c5a76f62 100755 --- a/pay-api/tests/unit/api/test_eft_short_names.py +++ b/pay-api/tests/unit/api/test_eft_short_names.py @@ -918,3 +918,26 @@ def test_post_shortname_refund_invalid_request(client, mocker, jwt, app): assert rv.status_code == 400 assert 'INVALID_REQUEST' in rv.json['type'] + + +def test_patch_shortname(session, client, jwt, app): + """Test patch EFT Short name.""" + data = {'email': 'invalid_email', 'casSupplierNumber': '1234567ABC'} + + short_name = factory_eft_shortname('TEST_SHORTNAME').save() + token = jwt.create_jwt(get_claims(roles=[Role.MANAGE_EFT.value]), token_header) + headers = {'Authorization': f'Bearer {token}', 'content-type': 'application/json'} + + rv = client.patch(f'/api/v1/eft-shortnames/{short_name.id}', headers=headers, json=data) + + assert rv.status_code == 400 + assert 'INVALID_REQUEST' in rv.json['type'], 'Expecting invalid email format.' + + data['email'] = 'test@test.com' + rv = client.patch(f'/api/v1/eft-shortnames/{short_name.id}', headers=headers, json=data) + + assert rv.status_code == 200 + result = rv.json + assert result is not None + assert result['casSupplierNumber'] == data['casSupplierNumber'] + assert result['email'] == data['email'] diff --git a/pay-api/tests/unit/models/test_eft_short_names.py b/pay-api/tests/unit/models/test_eft_short_names.py index 20f6091dc..77473e94d 100644 --- a/pay-api/tests/unit/models/test_eft_short_names.py +++ b/pay-api/tests/unit/models/test_eft_short_names.py @@ -25,8 +25,12 @@ def test_eft_short_name_model(session): """Assert eft short names are stored.""" eft_short_name = EFTShortnamesModel() eft_short_name.short_name = 'ABC' + eft_short_name.cas_supplier_number = '123456' + eft_short_name.email = 'test@test.com' eft_short_name.save() assert eft_short_name.id is not None assert eft_short_name.short_name == 'ABC' + assert eft_short_name.cas_supplier_number == '123456' + assert eft_short_name.email == 'test@test.com' assert eft_short_name.created_on.date() == datetime.now(tz=timezone.utc).date() From 068ef9a74dee4f357ca52437d552fe52498673ee Mon Sep 17 00:00:00 2001 From: Odysseus Chiu Date: Mon, 16 Sep 2024 10:29:16 -0700 Subject: [PATCH 2/2] update migration for history table --- ...4_09_13_1fadb0e78d8c_21570_short_name_supplier_info.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pay-api/migrations/versions/2024_09_13_1fadb0e78d8c_21570_short_name_supplier_info.py b/pay-api/migrations/versions/2024_09_13_1fadb0e78d8c_21570_short_name_supplier_info.py index 55bdaf42d..674a0e0fe 100644 --- a/pay-api/migrations/versions/2024_09_13_1fadb0e78d8c_21570_short_name_supplier_info.py +++ b/pay-api/migrations/versions/2024_09_13_1fadb0e78d8c_21570_short_name_supplier_info.py @@ -25,8 +25,16 @@ def upgrade(): batch_op.add_column(sa.Column('cas_supplier_number', sa.String(25), nullable=True)) batch_op.add_column(sa.Column('email', sa.String(100), nullable=True)) + with op.batch_alter_table('eft_short_names_history', schema=None) as batch_op: + batch_op.add_column(sa.Column('cas_supplier_number', sa.String(25), nullable=True)) + batch_op.add_column(sa.Column('email', sa.String(100), nullable=True)) + def downgrade(): with op.batch_alter_table('eft_short_names', schema=None) as batch_op: batch_op.drop_column('cas_supplier_number') batch_op.drop_column('email') + + with op.batch_alter_table('eft_short_names_history', schema=None) as batch_op: + batch_op.drop_column('cas_supplier_number') + batch_op.drop_column('email')