Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

21570 - Email / CAS Supplier Number #1749

Merged
merged 2 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""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))
ochiu marked this conversation as resolved.
Show resolved Hide resolved

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')
8 changes: 8 additions & 0 deletions pay-api/src/pay_api/models/eft_short_names.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,18 @@ class EFTShortnames(Versioned, BaseModel): # pylint: disable=too-many-instance-
__mapper_args__ = {
'include_properties': [
'id',
'cas_supplier_number',
'created_on',
'email',
'short_name'
]
}

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):
Expand All @@ -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
Expand All @@ -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)
Expand Down
21 changes: 20 additions & 1 deletion pay-api/src/pay_api/resources/v1/eft_short_names.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def get_eft_shortname_summaries():


@bp.route('/<int:short_name_id>', 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):
Expand All @@ -118,6 +118,25 @@ def get_eft_shortname(short_name_id: int):
return jsonify(response), status


@bp.route('/<int:short_name_id>', 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')
request_json = request.get_json()
valid_format, errors = schema_utils.validate(request_json, 'eft_short_name')
if not valid_format:
return error_to_response(Error.INVALID_REQUEST, invalid_params=schema_utils.serialize(errors))
try:
response, status = EFTShortnameService.patch_shortname(short_name_id, request_json), HTTPStatus.OK
except BusinessException as exception:
return exception.response()
current_app.logger.debug('>patch_eft_shortname')
return jsonify(response), status


@bp.route('/<int:short_name_id>/history', methods=['GET', 'OPTIONS'])
@cross_origin(origins='*', methods=['GET'])
@_jwt.requires_auth
Expand Down
26 changes: 14 additions & 12 deletions pay-api/src/pay_api/schemas/schemas/eft_short_name.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
]
}
}
Expand Down
19 changes: 19 additions & 0 deletions pay-api/src/pay_api/services/eft_short_names.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')
email = request.get('email', None)
cas_supplier_number = request.get('casSupplierNumber', None)
short_name = EFTShortnameModel.find_by_id(short_name_id)

if email is not None:
short_name.email = email.strip()
if cas_supplier_number is not None:
short_name.cas_supplier_number = cas_supplier_number.strip()
short_name.save()

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."""
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion pay-api/src/pay_api/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@
Development release segment: .devN
"""

__version__ = '1.22.0' # pylint: disable=invalid-name
__version__ = '1.22.1' # pylint: disable=invalid-name
2 changes: 1 addition & 1 deletion pay-api/tests/unit/api/test_cors_preflight.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'})
Expand Down
23 changes: 23 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 @@ -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']
4 changes: 4 additions & 0 deletions pay-api/tests/unit/models/test_eft_short_names.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Loading