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

19336 - EFT Payment details #1389

Merged
merged 5 commits into from
Jan 30, 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,30 @@
"""Update eft_transactions table to track dates from TDI17

Revision ID: a9bf3eaeda7b
Revises: 81c6a133a84a
Create Date: 2024-01-25 13:42:55.428494

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = 'a9bf3eaeda7b'
down_revision = '81c6a133a84a'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('eft_transactions', sa.Column('deposit_date', sa.DateTime(), nullable=True))
op.add_column('eft_transactions', sa.Column('transaction_date', sa.DateTime(), nullable=True))
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('eft_transactions', 'transaction_date')
op.drop_column('eft_transactions', 'deposit_date')
# ### end Alembic commands ###
2 changes: 1 addition & 1 deletion pay-api/src/pay_api/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from .eft_gl_transfers import EFTGLTransfer
from .eft_process_status_code import EFTProcessStatusCode
from .eft_short_names import EFTShortnames, EFTShortnameSchema
from .eft_transaction import EFTTransaction
from .eft_transaction import EFTTransaction, EFTTransactionSchema
from .ejv_file import EjvFile
from .ejv_header import EjvHeader
from .ejv_invoice_link import EjvInvoiceLink
Expand Down
10 changes: 8 additions & 2 deletions pay-api/src/pay_api/models/custom_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,26 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Custom Query class to extend BaseQuery class functionality."""
from datetime import datetime
from datetime import date, datetime
from flask_sqlalchemy import BaseQuery
from sqlalchemy import func


class CustomQuery(BaseQuery):
"""Custom Query class to extend the base query class for helper functionality."""

def filter_conditionally(self, search_criteria, model_attribute):
def filter_conditionally(self, search_criteria, model_attribute, is_like: bool = False):
"""Add query filter if present."""
if search_criteria is None:
return self

if isinstance(search_criteria, datetime):
return self.filter(func.DATE(model_attribute) == search_criteria.date())
if isinstance(search_criteria, date):
return self.filter(func.DATE(model_attribute) == search_criteria)
if is_like:
# Ensure any updates for this kind of LIKE searches are using SQL Alchemy functions as it uses
# bind variables to mitigate SQL Injection
return self.filter(func.lower(model_attribute).ilike(f'%{search_criteria}%'))

return self.filter(model_attribute == search_criteria)
28 changes: 14 additions & 14 deletions pay-api/src/pay_api/models/eft_short_names.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Model to handle EFT TDI17 short name to BCROS account mapping."""

from datetime import datetime
from _decimal import Decimal
from attrs import define


from .base_model import VersionedModel
from .db import db
from ..utils.util import cents_to_decimal


class EFTShortnames(VersionedModel): # pylint: disable=too-many-instance-attributes
Expand Down Expand Up @@ -54,18 +55,6 @@ def find_by_short_name(cls, short_name: str):
"""Find by eft short name."""
return cls.query.filter_by(short_name=short_name).one_or_none()

@classmethod
def find_all_short_names(cls, include_all: bool, page: int, limit: int):
"""Return eft short names."""
query = db.session.query(EFTShortnames)

if not include_all:
query = query.filter(EFTShortnames.auth_account_id.is_(None))

query = query.order_by(EFTShortnames.short_name.asc())
pagination = query.paginate(per_page=limit, page=page)
return pagination.items, pagination.total


@define
class EFTShortnameSchema: # pylint: disable=too-few-public-methods
Expand All @@ -75,11 +64,22 @@ class EFTShortnameSchema: # pylint: disable=too-few-public-methods
short_name: str
account_id: str
created_on: datetime
transaction_id: int
transaction_date: datetime
deposit_date: datetime
deposit_amount: Decimal

@classmethod
def from_row(cls, row: EFTShortnames):
"""From row is used so we don't tightly couple to our database class.

https://www.attrs.org/en/stable/init.html
"""
return cls(id=row.id, short_name=row.short_name, account_id=row.auth_account_id, created_on=row.created_on)
return cls(id=row.id,
short_name=row.short_name,
account_id=row.auth_account_id,
created_on=row.created_on,
transaction_id=getattr(row, 'transaction_id', None),
transaction_date=getattr(row, 'transaction_date', None),
deposit_date=getattr(row, 'deposit_date', None),
deposit_amount=cents_to_decimal(getattr(row, 'deposit_amount', None)))
33 changes: 31 additions & 2 deletions pay-api/src/pay_api/models/eft_transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Model to handle EFT file processing."""

from datetime import datetime
from _decimal import Decimal
from attrs import define

from sqlalchemy import ForeignKey, String
from sqlalchemy.dialects.postgresql import ARRAY

from .base_model import BaseModel
from .db import db
from ..utils.util import cents_to_decimal


class EFTTransaction(BaseModel): # pylint: disable=too-many-instance-attributes
Expand All @@ -43,6 +45,7 @@ class EFTTransaction(BaseModel): # pylint: disable=too-many-instance-attributes
'completed_on',
'created_on',
'deposit_amount_cents',
'deposit_date',
'error_messages',
'file_id',
'last_updated_on',
Expand All @@ -52,7 +55,8 @@ class EFTTransaction(BaseModel): # pylint: disable=too-many-instance-attributes
'jv_number',
'sequence_number',
'short_name_id',
'status_code'
'status_code',
'transaction_date'
]
}

Expand All @@ -71,3 +75,28 @@ class EFTTransaction(BaseModel): # pylint: disable=too-many-instance-attributes
short_name_id = db.Column(db.Integer, ForeignKey('eft_short_names.id'), nullable=True)
status_code = db.Column(db.String, ForeignKey('eft_process_status_codes.code'), nullable=False)
deposit_amount_cents = db.Column('deposit_amount_cents', db.BigInteger, nullable=True)
deposit_date = db.Column('deposit_date', db.DateTime, nullable=True)
transaction_date = db.Column('transaction_date', db.DateTime, nullable=True)


@define
class EFTTransactionSchema: # pylint: disable=too-few-public-methods
"""Main schema used to serialize a EFT Transaction."""

id: int
short_name_id: int
transaction_date: datetime
deposit_date: datetime
deposit_amount: Decimal

@classmethod
def from_row(cls, row: EFTTransaction):
"""From row is used so we don't tightly couple to our database class.

https://www.attrs.org/en/stable/init.html
"""
return cls(id=row.id,
short_name_id=row.short_name_id,
transaction_date=getattr(row, 'transaction_date', None),
deposit_date=getattr(row, 'deposit_date', None),
deposit_amount=cents_to_decimal(getattr(row, 'deposit_amount_cents', None)))
40 changes: 38 additions & 2 deletions pay-api/src/pay_api/resources/v1/eft_short_names.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,23 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Resource for EFT Short name."""
from decimal import Decimal
from http import HTTPStatus

from flask import Blueprint, current_app, jsonify, request
from flask_cors import cross_origin

from pay_api.exceptions import BusinessException
from pay_api.services.eft_short_names import EFTShortnames as EFTShortnameService
from pay_api.services.eft_short_names import EFTShortnamesSearch
from pay_api.services.eft_transactions import EFTTransactions as EFTTransactionService
from pay_api.services.eft_transactions import EFTTransactionSearch
from pay_api.utils.auth import jwt as _jwt
from pay_api.utils.endpoints_enums import EndpointEnum
from pay_api.utils.enums import Role
from pay_api.utils.trace import tracing as _tracing
from pay_api.utils.util import string_to_date


bp = Blueprint('EFT_SHORT_NAMES', __name__, url_prefix=f'{EndpointEnum.API_V1.value}/eft-shortnames')

Expand All @@ -35,11 +41,22 @@ def get_eft_shortnames():
"""Get all eft short name records."""
current_app.logger.info('<get_eft_shortnames')

include_all = bool(request.args.get('includeAll', 'false').lower() == 'true')
state = request.args.get('state', None)
page: int = int(request.args.get('page', '1'))
limit: int = int(request.args.get('limit', '10'))
transaction_date = request.args.get('transactionDate', None)
deposit_amount = request.args.get('depositAmount', None)
deposit_date = request.args.get('depositDate', None)
short_name = request.args.get('shortName', None)

response, status = EFTShortnameService.search(include_all, page, limit), HTTPStatus.OK
response, status = EFTShortnameService.search(EFTShortnamesSearch(
deposit_date=string_to_date(deposit_date),
deposit_amount=Decimal(deposit_amount) * Decimal(100) if deposit_amount else None,
short_name=short_name,
transaction_date=string_to_date(transaction_date),
state=state,
page=page,
limit=limit)), HTTPStatus.OK
current_app.logger.debug('>get_eft_shortnames')
return jsonify(response), status

Expand Down Expand Up @@ -83,3 +100,22 @@ def patch_eft_shortname(short_name_id: int):

current_app.logger.debug('>patch_eft_shortname')
return jsonify(response), status


@bp.route('/<int:short_name_id>/transactions', methods=['GET', 'OPTIONS'])
@cross_origin(origins='*', methods=['GET'])
@_tracing.trace()
@_jwt.requires_auth
@_jwt.has_one_of_roles([Role.SYSTEM.value, Role.STAFF.value])
def get_eft_shortname_transactions(short_name_id: int):
"""Get EFT short name transactions."""
current_app.logger.info('<get_eft_shortname_transactions')

page: int = int(request.args.get('page', '1'))
limit: int = int(request.args.get('limit', '10'))

response, status = EFTTransactionService.search(short_name_id,
EFTTransactionSearch(page=page, limit=limit)), HTTPStatus.OK

current_app.logger.debug('>get_eft_shortname_transactions')
return jsonify(response), status
Loading
Loading