From 65acc3ce093fef1cc8c0cb9011a52d0867b38c4f Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Fri, 12 May 2023 13:39:14 +0900 Subject: [PATCH] =?UTF-8?q?style:=20format=E9=81=A9=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ecs/jskult-webapp/src/aws/cognito.py | 6 ++-- ecs/jskult-webapp/src/aws/s3.py | 16 +++++----- ecs/jskult-webapp/src/controller/bio.py | 12 ++++--- .../src/controller/bio_download.py | 31 ++++++++++++------- .../src/controller/healthcheck.py | 2 ++ ecs/jskult-webapp/src/controller/login.py | 28 ++++++++++------- ecs/jskult-webapp/src/controller/logout.py | 10 +++--- ecs/jskult-webapp/src/controller/menu.py | 8 +++-- ecs/jskult-webapp/src/core/tasks.py | 2 +- ecs/jskult-webapp/src/db/sql_condition.py | 7 +++-- ecs/jskult-webapp/src/depends/auth.py | 12 ++++--- ecs/jskult-webapp/src/depends/database.py | 2 +- ecs/jskult-webapp/src/depends/services.py | 5 ++- ecs/jskult-webapp/src/error/exceptions.py | 4 +++ ecs/jskult-webapp/src/model/db/hdke_tbl.py | 1 - ecs/jskult-webapp/src/model/db/user_master.py | 4 +-- .../src/model/internal/jwt_token.py | 18 +++++------ .../src/model/internal/session.py | 8 ++--- ecs/jskult-webapp/src/model/request/bio.py | 5 ++- .../src/model/request/bio_download.py | 4 +-- ecs/jskult-webapp/src/model/request/login.py | 2 +- .../src/model/view/bio_disp_model.py | 4 +-- .../src/model/view/bio_view_model.py | 22 +++++++------ .../src/model/view/logout_view_model.py | 2 +- .../src/model/view/user_view_model.py | 6 ++-- .../src/repositories/base_repository.py | 6 ++-- .../repositories/bio_sales_view_repository.py | 5 ++- .../src/repositories/hdke_tbl_repository.py | 1 - .../pharmacy_product_master_repository.py | 8 ++--- .../repositories/user_master_repository.py | 3 +- .../wholesaler_master_repository.py | 4 +-- .../src/router/session_router.py | 12 +++++-- .../src/services/base_service.py | 1 + .../src/services/batch_status_service.py | 2 +- .../src/services/bio_view_service.py | 21 +++++++------ .../src/services/login_service.py | 6 ++-- .../src/services/session_service.py | 1 + .../src/system_var/environment.py | 2 +- 38 files changed, 163 insertions(+), 130 deletions(-) diff --git a/ecs/jskult-webapp/src/aws/cognito.py b/ecs/jskult-webapp/src/aws/cognito.py index c80f5bac..ee93f7ae 100644 --- a/ecs/jskult-webapp/src/aws/cognito.py +++ b/ecs/jskult-webapp/src/aws/cognito.py @@ -7,9 +7,9 @@ from src.system_var import environment class CognitoClient(AWSAPIClient): def __init__(self) -> None: self.__client = boto3.client('cognito-idp') - + def login_by_user_password_flow(self, username: str, password: str, secret_hash: str): - + auth_response = self.__client.admin_initiate_auth( UserPoolId=environment.COGNITO_USER_POOL_ID, ClientId=environment.COGNITO_CLIENT_ID, @@ -21,5 +21,5 @@ class CognitoClient(AWSAPIClient): }, ) authentication_result = auth_response['AuthenticationResult'] - + return authentication_result['IdToken'], authentication_result['RefreshToken'], diff --git a/ecs/jskult-webapp/src/aws/s3.py b/ecs/jskult-webapp/src/aws/s3.py index 852c7ceb..de11949c 100644 --- a/ecs/jskult-webapp/src/aws/s3.py +++ b/ecs/jskult-webapp/src/aws/s3.py @@ -7,16 +7,16 @@ from src.aws.aws_api_client import AWSAPIClient class S3Client(AWSAPIClient): __s3_client = boto3.client('s3') - + def upload_file(self, local_file_path: str, bucket_name: str, file_key: str): self.__s3_client.upload_file( - local_file_path, - Bucket=bucket_name, - Key=file_key - ) + local_file_path, + Bucket=bucket_name, + Key=file_key + ) - def generate_presigned_url(self, bucket_name: str, file_key: str, download_filename: str=''): - # presigned_urlを生成 + def generate_presigned_url(self, bucket_name: str, file_key: str, download_filename: str = ''): + # presigned_urlを生成 presigned_url = self.__s3_client.generate_presigned_url( 'get_object', Params={ @@ -28,5 +28,5 @@ class S3Client(AWSAPIClient): # 有効期限20分 ExpiresIn=1200 ) - + return presigned_url diff --git a/ecs/jskult-webapp/src/controller/bio.py b/ecs/jskult-webapp/src/controller/bio.py index a54909bd..188560fb 100644 --- a/ecs/jskult-webapp/src/controller/bio.py +++ b/ecs/jskult-webapp/src/controller/bio.py @@ -1,7 +1,6 @@ from typing import Optional from fastapi import APIRouter, Depends, HTTPException, Request -from fastapi.exceptions import HTTPException from starlette import status from src.depends.services import get_service @@ -21,11 +20,13 @@ router.route_class = AuthenticatedRoute ######################### # Views # ######################### + + @router.get('/BioSearchList') def bio_view( request: Request, - batch_status_service:BatchStatusService=Depends(get_service(BatchStatusService)), - bio_service: BioViewService=Depends(get_service(BioViewService)) + batch_status_service: BatchStatusService = Depends(get_service(BatchStatusService)), + bio_service: BioViewService = Depends(get_service(BioViewService)) ): session: UserSession = request.session # バッチ処理中の場合、機能を利用させない @@ -50,12 +51,13 @@ def bio_view( ) return templates_response + @router.post('/BioSearchList') def search_bio( request: Request, bio_form: Optional[BioModel] = Depends(BioModel.as_form), - bio_service: BioViewService=Depends(get_service(BioViewService)), - batch_status_service:BatchStatusService=Depends(get_service(BatchStatusService)) + bio_service: BioViewService = Depends(get_service(BioViewService)), + batch_status_service: BatchStatusService = Depends(get_service(BatchStatusService)) ): # error_log(date("Y/m/d H:i:s") . " [INFO] UserId:" . $UserId . "\r\n", 3, "$execLog"); session: UserSession = request.session diff --git a/ecs/jskult-webapp/src/controller/bio_download.py b/ecs/jskult-webapp/src/controller/bio_download.py index 67593fb7..0d172e8a 100644 --- a/ecs/jskult-webapp/src/controller/bio_download.py +++ b/ecs/jskult-webapp/src/controller/bio_download.py @@ -3,7 +3,6 @@ from datetime import datetime from typing import Union from fastapi import APIRouter, Depends, HTTPException -from fastapi.exceptions import HTTPException from fastapi.responses import JSONResponse from starlette import status @@ -23,14 +22,16 @@ router = APIRouter() ######################### # APIs # ######################### + + @router.post('/download') async def download_bio_data( - search_param: BioModel=Depends(BioModel.as_body), - download_param: BioDownloadModel=Depends(BioDownloadModel.as_body), + search_param: BioModel = Depends(BioModel.as_body), + download_param: BioDownloadModel = Depends(BioDownloadModel.as_body), bio_service: BioViewService = Depends(get_service(BioViewService)), batch_status_service: BatchStatusService = Depends(get_service(BatchStatusService)), - session: Union[UserSession, None]=Depends(verify_session) - ): + session: Union[UserSession, None] = Depends(verify_session) +): # 通常のビューとはルーティングの扱いを変えるために、個別のルーターで登録する # error_log(date("Y/m/d H:i:s") . " [INFO] getBioData start" . "\r\n", 3, "$execLog"); # 改修後のパラメータを打ち出すようにする @@ -68,14 +69,18 @@ async def download_bio_data( # 値を変換 # データ種別の正式名を設定 - extract_df.loc[:, 'slip_org_kbn'] = extract_df['slip_org_kbn'].apply(lambda key: constants.SLIP_ORG_KBN_FULL_NAME.get(key)) + extract_df.loc[:, 'slip_org_kbn'] = extract_df['slip_org_kbn'].apply( + lambda key: constants.SLIP_ORG_KBN_FULL_NAME.get(key)) # データ区分の区分の日本語名を設定 extract_df.loc[:, 'data_kbn'] = extract_df['data_kbn'].apply(lambda key: constants.DATA_KBN_JP_NAME.get(key)) # ロット番号エラーフラグの日本語名を設定 - extract_df.loc[:, 'lot_no_err_flg'] = extract_df['lot_no_err_flg'].apply(lambda key: constants.LOT_NO_ERR_FLG_JP_NAME.get(key)) - # 訂正前伝票管理番号がセットされているときのみ修正日時、修正者、エラー詳細種別をセット - extract_df.loc[:, 'ins_dt'] = extract_df['bef_slip_mgt_no'].apply(lambda bef_slip_mgt_no:extract_df['ins_dt'] if bef_slip_mgt_no is not None else '') - extract_df.loc[:, 'ins_usr'] = extract_df['bef_slip_mgt_no'].apply(lambda bef_slip_mgt_no:extract_df['ins_usr'] if bef_slip_mgt_no is not None else '') + extract_df.loc[:, 'lot_no_err_flg'] = extract_df['lot_no_err_flg'].apply( + lambda key: constants.LOT_NO_ERR_FLG_JP_NAME.get(key)) + # 訂正前伝票管理番号がセットされているときのみ修正日時、修正者、エラー詳細種別をセット + extract_df.loc[:, 'ins_dt'] = extract_df['bef_slip_mgt_no'].apply( + lambda bef_slip_mgt_no: extract_df['ins_dt'] if bef_slip_mgt_no is not None else '') + extract_df.loc[:, 'ins_usr'] = extract_df['bef_slip_mgt_no'].apply( + lambda bef_slip_mgt_no: extract_df['ins_usr'] if bef_slip_mgt_no is not None else '') # 種別によって出力を変える local_file_path = '' @@ -84,12 +89,14 @@ async def download_bio_data( local_file_path = bio_service.write_excel_file(extract_df, download_param.user_id, timestamp=now) elif download_param.kind == 'csv': # error_log(date("Y/m/d H:i:s") . " [INFO] 今回はCSVファイルに出力する" . "\r\n", 3, "$execLog"); - local_file_path = bio_service.write_csv_file(extract_df, download_param.user_id, header=constants.BIO_CSV_HEADER, timestamp=now) + local_file_path = bio_service.write_csv_file( + extract_df, download_param.user_id, header=constants.BIO_CSV_HEADER, timestamp=now) # ローカルファイルからS3にアップロードし、ダウンロード用URLを取得する try: bio_service.upload_bio_data_file(local_file_path) - download_file_url = bio_service.generate_download_file_url(local_file_path, download_param.user_id, download_param.kind) + download_file_url = bio_service.generate_download_file_url( + local_file_path, download_param.user_id, download_param.kind) except Exception as e: print('S3 access error', e.args) raise HTTPException( diff --git a/ecs/jskult-webapp/src/controller/healthcheck.py b/ecs/jskult-webapp/src/controller/healthcheck.py index bd571edd..cdb8f00e 100644 --- a/ecs/jskult-webapp/src/controller/healthcheck.py +++ b/ecs/jskult-webapp/src/controller/healthcheck.py @@ -5,6 +5,8 @@ router = APIRouter() ######################### # Views # ######################### + + @router.get('/') def healthcheck(): return {'status': 'OK'} diff --git a/ecs/jskult-webapp/src/controller/login.py b/ecs/jskult-webapp/src/controller/login.py index a7bc6808..e8246322 100644 --- a/ecs/jskult-webapp/src/controller/login.py +++ b/ecs/jskult-webapp/src/controller/login.py @@ -1,4 +1,3 @@ -import os.path as path import secrets import urllib.parse as parse from typing import Union @@ -25,6 +24,8 @@ router.route_class = AfterSetCookieSessionRoute ######################### # Views # ######################### + + @router.get('/userlogin') def login_user_redirect_view(): auth_query_string = parse.urlencode( @@ -39,6 +40,7 @@ def login_user_redirect_view(): return RedirectResponse(url=authorize_endpoint_url, status_code=status.HTTP_303_SEE_OTHER) + @router.get('/maintlogin') def login_maintenance_view(request: Request): mainte_login = MainteLoginViewModel() @@ -53,20 +55,22 @@ def login_maintenance_view(request: Request): ######################### # APIs # ######################### + + @router.post('/maintlogin') def login( - response: Response, - request: LoginModel = Depends(LoginModel.as_form), - login_service: LoginService = Depends(get_service(LoginService)) - ): + response: Response, + request: LoginModel = Depends(LoginModel.as_form), + login_service: LoginService = Depends(get_service(LoginService)) +): try: jwt_token = login_service.login(request.username, request.password) except NotAuthorizeException as e: print(e) raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=constants.LOGOUT_REASON_LOGIN_ERROR) - except JWTTokenVerifyException as e: + except JWTTokenVerifyException: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=constants.LOGOUT_REASON_SESSION_EXPIRED) - + verified_token = jwt_token.verify_token() # 普通の認証だと、`cognito:username`に入る。 user_id = verified_token.user_id @@ -92,7 +96,7 @@ def login( user_flg=user_record.mntuser_flg ) session_key = set_session(session_model) - + response = RedirectResponse( url='/menu', status_code=status.HTTP_303_SEE_OTHER, @@ -103,9 +107,9 @@ def login( @router.get('/authorize') def sso_authorize( - code:Union[str, None]=Depends(code_security), - login_service: LoginService=Depends(get_service(LoginService)) - ) -> Response: + code: Union[str, None] = Depends(code_security), + login_service: LoginService = Depends(get_service(LoginService)) +) -> Response: if not code: raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=constants.LOGOUT_REASON_NOT_LOGIN) @@ -114,7 +118,7 @@ def sso_authorize( try: # トークン検証 verified_token = jwt_token.verify_token() - except JWTTokenVerifyException as e: + except JWTTokenVerifyException: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=constants.LOGOUT_REASON_SESSION_EXPIRED) # トークンからユーザーIDを取得 diff --git a/ecs/jskult-webapp/src/controller/logout.py b/ecs/jskult-webapp/src/controller/logout.py index 8cad1b5f..79de281c 100644 --- a/ecs/jskult-webapp/src/controller/logout.py +++ b/ecs/jskult-webapp/src/controller/logout.py @@ -14,12 +14,14 @@ router = APIRouter() ######################### # Views # ######################### + + @router.get('/', response_class=HTMLResponse) def logout_view( - request: Request, - reason: Optional[str] = None, - session: Union[UserSession, None]=Depends(verify_session) - ): + request: Request, + reason: Optional[str] = None, + session: Union[UserSession, None] = Depends(verify_session) +): redirect_to = '/login/userlogin' link_text = 'MeDaCA機能メニューへ' if session is not None and session.user_flg == '1': diff --git a/ecs/jskult-webapp/src/controller/menu.py b/ecs/jskult-webapp/src/controller/menu.py index a9e450bb..27065dc7 100644 --- a/ecs/jskult-webapp/src/controller/menu.py +++ b/ecs/jskult-webapp/src/controller/menu.py @@ -16,11 +16,13 @@ router.route_class = AuthenticatedRoute ######################### # Views # ######################### + + @router.get('/', response_class=HTMLResponse) def menu_view( - request: Request, - batch_status_service:BatchStatusService=Depends(get_service(BatchStatusService)) - ): + request: Request, + batch_status_service: BatchStatusService = Depends(get_service(BatchStatusService)) +): session: UserSession = request.session # 日付マスターからバッチ情報を取得する hdke_tbl_record = batch_status_service.hdke_table_record diff --git a/ecs/jskult-webapp/src/core/tasks.py b/ecs/jskult-webapp/src/core/tasks.py index 42352465..93f4c8f5 100644 --- a/ecs/jskult-webapp/src/core/tasks.py +++ b/ecs/jskult-webapp/src/core/tasks.py @@ -18,4 +18,4 @@ def create_stop_app_handler(app: FastAPI) -> Callable: def stop_app() -> None: close_db(app) - return stop_app \ No newline at end of file + return stop_app diff --git a/ecs/jskult-webapp/src/db/sql_condition.py b/ecs/jskult-webapp/src/db/sql_condition.py index dfd73858..d0d645c7 100644 --- a/ecs/jskult-webapp/src/db/sql_condition.py +++ b/ecs/jskult-webapp/src/db/sql_condition.py @@ -16,13 +16,14 @@ class SQLCondition: self.column = column self.operator = operator self.param = param - self.literal=literal - + self.literal = literal + def apply(self): # literalがFalseならプレースホルダー。Trueだったならは固定値。 param = f':{self.param}' if self.literal is False else self.param return f' {self.column} {self.operator} {param}' + # 定数 EQ = '=' NE = '<>' @@ -32,4 +33,4 @@ GE = '>=' LE = '<=' LIKE = 'LIKE' IS = 'IS' -IS_NOT = 'IS NOT' \ No newline at end of file +IS_NOT = 'IS NOT' diff --git a/ecs/jskult-webapp/src/depends/auth.py b/ecs/jskult-webapp/src/depends/auth.py index 3310df6f..893c95e4 100644 --- a/ecs/jskult-webapp/src/depends/auth.py +++ b/ecs/jskult-webapp/src/depends/auth.py @@ -17,26 +17,28 @@ code_security = APIKeyQuery(name='code', auto_error=False) def get_current_session(session_key=Depends(cookie_security)): if session_key is None: return None - + session = get_session(session_key) # sessionが存在しない場合はNoneが返る return session -def check_session_expired(session:Union[UserSession, None]=Depends(get_current_session)): +def check_session_expired(session: Union[UserSession, None] = Depends(get_current_session)): """セッションの最後にアクセスした時間が、セッション有効期限切れであるかどうかをチェックする""" if session is None: return None last_access_time = session.last_access_time - session_expired_period = datetime.datetime.fromtimestamp(last_access_time) + datetime.timedelta(minutes=environment.SESSION_EXPIRE_MINUTE) + session_expired_period = datetime.datetime.fromtimestamp( + last_access_time) + datetime.timedelta(minutes=environment.SESSION_EXPIRE_MINUTE) if session_expired_period < datetime.datetime.now(): return None - + return session -def verify_session(session:Union[UserSession, None]=Depends(check_session_expired)): + +def verify_session(session: Union[UserSession, None] = Depends(check_session_expired)): if session is None: return None jwt_token = JWTToken(session.id_token, session.refresh_token) diff --git a/ecs/jskult-webapp/src/depends/database.py b/ecs/jskult-webapp/src/depends/database.py index f764d5c5..c5b28042 100644 --- a/ecs/jskult-webapp/src/depends/database.py +++ b/ecs/jskult-webapp/src/depends/database.py @@ -14,4 +14,4 @@ def get_database(request: Request) -> Database: def get_repository(Repo_type: Type[BaseRepository]) -> Callable: def get_repo(db: Database = Depends(get_database)) -> Type[BaseRepository]: return Repo_type(db) - return get_repo \ No newline at end of file + return get_repo diff --git a/ecs/jskult-webapp/src/depends/services.py b/ecs/jskult-webapp/src/depends/services.py index d93a0c97..40bf31cf 100644 --- a/ecs/jskult-webapp/src/depends/services.py +++ b/ecs/jskult-webapp/src/depends/services.py @@ -1,7 +1,6 @@ from typing import Callable, Type from fastapi import Depends -from starlette.requests import Request from src.db.database import Database from src.depends.database import get_database @@ -9,8 +8,8 @@ from src.services.base_service import BaseService def get_service(Service_type: Type[BaseService]) -> Callable: - def get_service(db: Database=Depends(get_database)) -> Type[BaseService]: + def get_service(db: Database = Depends(get_database)) -> Type[BaseService]: repositories = {key: repository(db) for key, repository in Service_type.REPOSITORIES.items()} clients = {key: client() for key, client in Service_type.CLIENTS.items()} return Service_type(repositories=repositories, clients=clients) - return get_service \ No newline at end of file + return get_service diff --git a/ecs/jskult-webapp/src/error/exceptions.py b/ecs/jskult-webapp/src/error/exceptions.py index 53b299db..4e73515c 100644 --- a/ecs/jskult-webapp/src/error/exceptions.py +++ b/ecs/jskult-webapp/src/error/exceptions.py @@ -7,18 +7,22 @@ class MeDaCaException(Exception): """Webアプリの共通例外""" pass + class NotAuthorizeException(MeDaCaException): """認証失敗の例外""" pass + class JWTTokenVerifyException(MeDaCaException): """トークン検証失敗の例外""" pass + class DBException(MeDaCaException): """DB関連の例外""" pass + class UnexpectedException(MeDaCaException): """予期しない例外""" diff --git a/ecs/jskult-webapp/src/model/db/hdke_tbl.py b/ecs/jskult-webapp/src/model/db/hdke_tbl.py index 920cb2e3..944581d5 100644 --- a/ecs/jskult-webapp/src/model/db/hdke_tbl.py +++ b/ecs/jskult-webapp/src/model/db/hdke_tbl.py @@ -1,4 +1,3 @@ -from datetime import datetime from typing import Optional from src.model.db.base_db_model import BaseDBModel diff --git a/ecs/jskult-webapp/src/model/db/user_master.py b/ecs/jskult-webapp/src/model/db/user_master.py index 5b55c014..82fe50f9 100644 --- a/ecs/jskult-webapp/src/model/db/user_master.py +++ b/ecs/jskult-webapp/src/model/db/user_master.py @@ -28,9 +28,9 @@ class UserMasterModel(BaseDBModel): def is_enable_user(self): return self.enabled_flg == 'Y' - + def is_maintenance_user(self): return self.mntuser_flg == '1' - + def is_groupware_user(self): return self.mntuser_flg == '0' diff --git a/ecs/jskult-webapp/src/model/internal/jwt_token.py b/ecs/jskult-webapp/src/model/internal/jwt_token.py index a10635ad..d7544125 100644 --- a/ecs/jskult-webapp/src/model/internal/jwt_token.py +++ b/ecs/jskult-webapp/src/model/internal/jwt_token.py @@ -15,11 +15,11 @@ class JWTToken: refresh_token: str verified_jwt: Optional[dict] - def __init__(self, id_token: str, refresh_token: str, verified_jwt: dict=None) -> None: + def __init__(self, id_token: str, refresh_token: str, verified_jwt: dict = None) -> None: self.id_token = id_token self.refresh_token = refresh_token self.verified_jwt = verified_jwt - + @property def verified_token(self): if self.verified_jwt is None: @@ -29,7 +29,7 @@ class JWTToken: @property def user_id(self): verified_token = self.verified_token - + user_id: str = None identities: dict = verified_token.get('identities') if identities is not None: @@ -63,7 +63,7 @@ class JWTToken: 'code': code, 'redirect_uri': environment.COGNITO_REDIRECT_URI } - + message = bytes(f'{environment.COGNITO_CLIENT_ID}:{environment.COGNITO_CLIENT_SECRET}', 'utf8') auth_header_value = base64.b64encode(message).decode() request_headers = { @@ -76,7 +76,7 @@ class JWTToken: raise JWTTokenVerifyException(res.text) token_response = json.loads(res.text) - + return cls(id_token=token_response['id_token'], refresh_token=token_response['refresh_token']) @classmethod @@ -99,7 +99,7 @@ class JWTToken: 'refresh_token': refresh_token, 'redirect_uri': environment.COGNITO_REDIRECT_URI } - + message = bytes(f'{environment.COGNITO_CLIENT_ID}:{environment.COGNITO_CLIENT_SECRET}', 'utf8') auth_header_value = base64.b64encode(message).decode() request_headers = { @@ -117,13 +117,13 @@ class JWTToken: def verify_token(self): if self.id_token is None: raise Exception('アクセストークンがない') - + issuer = f'https://cognito-idp.{environment.AWS_REGION}.amazonaws.com/{environment.COGNITO_USER_POOL_ID}' jwks_url = f'{issuer}/.well-known/jwks.json' - + jwks_client = jwt.PyJWKClient(jwks_url) signing_key = jwks_client.get_signing_key_from_jwt(self.id_token) - + try: verified_jwt = jwt.decode( self.id_token, diff --git a/ecs/jskult-webapp/src/model/internal/session.py b/ecs/jskult-webapp/src/model/internal/session.py index 5235d0f3..15739c28 100644 --- a/ecs/jskult-webapp/src/model/internal/session.py +++ b/ecs/jskult-webapp/src/model/internal/session.py @@ -27,7 +27,7 @@ class UserSession(DynamoDBTableModel): @classmethod def new_last_access_time(cls): return datetime.datetime.now().timestamp() - + @classmethod def new_record_expiration_time(cls, expire=environment.SESSION_EXPIRE_MINUTE): last_access_time = datetime.datetime.fromtimestamp(cls.new_last_access_time()) @@ -35,8 +35,8 @@ class UserSession(DynamoDBTableModel): @classmethod def new( - cls, user_id, id_token, refresh_token, csrf_token, doc_flg, inst_flg, bio_flg, master_mainte_flg, user_flg - ): + cls, user_id, id_token, refresh_token, csrf_token, doc_flg, inst_flg, bio_flg, master_mainte_flg, user_flg + ): return cls( session_key=str(uuid.uuid4()), user_id=user_id, @@ -47,7 +47,7 @@ class UserSession(DynamoDBTableModel): inst_flg=inst_flg, bio_flg=bio_flg, master_mainte_flg=master_mainte_flg, - user_flg=user_flg, + user_flg=user_flg, last_access_time=cls.new_last_access_time(), record_expiration_time=cls.new_record_expiration_time() ) diff --git a/ecs/jskult-webapp/src/model/request/bio.py b/ecs/jskult-webapp/src/model/request/bio.py index a32bb2f2..63994e07 100644 --- a/ecs/jskult-webapp/src/model/request/bio.py +++ b/ecs/jskult-webapp/src/model/request/bio.py @@ -50,7 +50,7 @@ class BioModel(BaseModel): ctrl_rev_hsdnymd_srk_to, ikoFlg ) - + @classmethod def as_body( cls, @@ -79,7 +79,6 @@ class BioModel(BaseModel): ctrl_rev_hsdnymd_srk_to, ikoFlg ) - def __convert_request_param( cls, @@ -134,4 +133,4 @@ class BioModel(BaseModel): rev_hsdnymd_srk_from=rev_hsdnymd_srk_from, rev_hsdnymd_srk_to=rev_hsdnymd_srk_to, ikoFlg=ikoFlg - ) \ No newline at end of file + ) diff --git a/ecs/jskult-webapp/src/model/request/bio_download.py b/ecs/jskult-webapp/src/model/request/bio_download.py index 8b4b5ae9..51bea2e3 100644 --- a/ecs/jskult-webapp/src/model/request/bio_download.py +++ b/ecs/jskult-webapp/src/model/request/bio_download.py @@ -1,5 +1,3 @@ -from typing import Optional - from fastapi import Body from pydantic import BaseModel @@ -7,7 +5,7 @@ from pydantic import BaseModel class BioDownloadModel(BaseModel): user_id: str kind: str - + @classmethod def as_body( cls, diff --git a/ecs/jskult-webapp/src/model/request/login.py b/ecs/jskult-webapp/src/model/request/login.py index f0c431ab..0e7710cb 100644 --- a/ecs/jskult-webapp/src/model/request/login.py +++ b/ecs/jskult-webapp/src/model/request/login.py @@ -5,7 +5,7 @@ from pydantic import BaseModel class LoginModel(BaseModel): username: str password: str - + @classmethod def as_form( cls, diff --git a/ecs/jskult-webapp/src/model/view/bio_disp_model.py b/ecs/jskult-webapp/src/model/view/bio_disp_model.py index 0f1a11fd..42bd0f42 100644 --- a/ecs/jskult-webapp/src/model/view/bio_disp_model.py +++ b/ecs/jskult-webapp/src/model/view/bio_disp_model.py @@ -7,12 +7,12 @@ from src.util.sanitize import sanitize class BisDisplayModel(BioSalesViewModel): def __init__(self, param: BioSalesViewModel) -> None: super().__init__(**param.dict()) - + # 区分・フラグの正式名称を設定 self.slip_org_kbn = constants.SLIP_ORG_KBN_FULL_NAME.get(self.slip_org_kbn) self.data_kbn = constants.DATA_KBN_JP_NAME.get(self.data_kbn) self.lot_no_err_flg = constants.LOT_NO_ERR_FLG_JP_NAME.get(self.lot_no_err_flg) - + # 訂正前伝票管理番号がセットされているときのみ修正日時、修正者、エラー詳細種別をセット if (self.bef_slip_mgt_no is None): self.ins_dt = "" diff --git a/ecs/jskult-webapp/src/model/view/bio_view_model.py b/ecs/jskult-webapp/src/model/view/bio_view_model.py index 0657bd3c..1c6c98e3 100644 --- a/ecs/jskult-webapp/src/model/view/bio_view_model.py +++ b/ecs/jskult-webapp/src/model/view/bio_view_model.py @@ -20,7 +20,7 @@ class BioViewModel(BaseModel): phm_models: list[PharmacyProductMasterModel] bio_data: Optional[list[BisDisplayModel]] = [] form_data: Optional[BioModel] - + def display_wholesaler_names(self): display_names = [ f'{whs_model.rec_whs_cd}-{whs_model.rec_whs_sub_cd}:{whs_model.nm}' @@ -41,7 +41,7 @@ class BioViewModel(BaseModel): def display_data_kbn(self): return OrderedDict( { - '' : '', + '': '', '0': '正常', '1': 'ロットエラー', '3': 'ロット不明', @@ -59,14 +59,16 @@ class BioViewModel(BaseModel): if not self.is_form_submitted(): return '' - form_wholesaler_full_name = f'{self.form_data.wholesaler_code}-{self.form_data.wholesaler_sub_code}:{self.form_data.wholesaler_name}' + form_wholesaler_full_name = \ + f'{self.form_data.wholesaler_code}-{self.form_data.wholesaler_sub_code}:{self.form_data.wholesaler_name}' + return self._selected_value(form_wholesaler_full_name, selected_wholesaler) def is_selected_org_kbn(self, selected_org_kbn): if not self.is_form_submitted(): return '' return self._selected_value(self.form_data.org_kbn, selected_org_kbn) - + def is_input_rec_ymd_from(self): if not self.is_form_submitted(): return '' @@ -84,17 +86,17 @@ class BioViewModel(BaseModel): return '' return self.form_data.rec_lot_num or '' - + def is_selected_data_kbn(self, selected_data_kbn): if not self.is_form_submitted(): return '' - + return self._selected_value(self.form_data.data_kbn, selected_data_kbn) def is_selected_maker_cd(self, selected_maker_cd): if not self.is_form_submitted(): return '' - + return self._selected_value(self.form_data.maker_cd, selected_maker_cd) def is_input_rev_hsdnymd_srk_from(self): @@ -108,13 +110,13 @@ class BioViewModel(BaseModel): return '' return self._format_date_string(self.form_data.rev_hsdnymd_srk_to) - + def is_checked_iko_flg(self): if not self.is_form_submitted(): return '' return 'checked' if self.form_data.ikoFlg else '' - + def disabled_button(self): return 'disabled' if self.is_data_empty() or self.is_data_overflow_max_length() else '' @@ -123,7 +125,7 @@ class BioViewModel(BaseModel): def is_data_empty(self): return len(self.bio_data) == 0 - + def is_data_overflow_max_length(self): return len(self.bio_data) >= environment.BIO_SEARCH_RESULT_MAX_COUNT diff --git a/ecs/jskult-webapp/src/model/view/logout_view_model.py b/ecs/jskult-webapp/src/model/view/logout_view_model.py index b219918a..6935a309 100644 --- a/ecs/jskult-webapp/src/model/view/logout_view_model.py +++ b/ecs/jskult-webapp/src/model/view/logout_view_model.py @@ -7,4 +7,4 @@ class LogoutViewModel(BaseModel): subtitle: str = 'MeDaCA Logout' redirect_to: Optional[str] reason: Optional[str] - link_text:Optional[str] + link_text: Optional[str] diff --git a/ecs/jskult-webapp/src/model/view/user_view_model.py b/ecs/jskult-webapp/src/model/view/user_view_model.py index 7d36fba2..3ef9ca12 100644 --- a/ecs/jskult-webapp/src/model/view/user_view_model.py +++ b/ecs/jskult-webapp/src/model/view/user_view_model.py @@ -7,9 +7,9 @@ class UserViewModel(BaseModel): bio_flg: str # AUTH_FLG1 doc_flg: str # AUTH_FLG2 inst_flg: str # AUTH_FLG3 - master_mainte_flg: str # AUTH_FLG4 + master_mainte_flg: str # AUTH_FLG4 user_flg: Optional[str] # MNTUSER_FLG - + def has_ult_doctor_permission(self): return self.doc_flg == '1' @@ -21,6 +21,6 @@ class UserViewModel(BaseModel): def has_master_maintenance_permission(self): return self.master_mainte_flg == '1' - + def is_maintenance_user(self): return self.user_flg == '1' diff --git a/ecs/jskult-webapp/src/repositories/base_repository.py b/ecs/jskult-webapp/src/repositories/base_repository.py index 60f9ba33..20aac09f 100644 --- a/ecs/jskult-webapp/src/repositories/base_repository.py +++ b/ecs/jskult-webapp/src/repositories/base_repository.py @@ -8,8 +8,9 @@ from src.model.db.base_db_model import BaseDBModel class BaseRepository(metaclass=ABCMeta): - + _database: Database + def __init__(self, db: Database) -> None: self._database = db @@ -29,10 +30,9 @@ class BaseRepository(metaclass=ABCMeta): """DBの取得結果をデータフレームにして返す""" pass - def _to_data_frame(self, query, parameter: BaseDBModel): """DBの取得結果をデータフレームに変換する""" - params = params=parameter.dict() + params = params = parameter.dict() sql_query = pd.read_sql( text(query), diff --git a/ecs/jskult-webapp/src/repositories/bio_sales_view_repository.py b/ecs/jskult-webapp/src/repositories/bio_sales_view_repository.py index 69e50783..c9a60c30 100644 --- a/ecs/jskult-webapp/src/repositories/bio_sales_view_repository.py +++ b/ecs/jskult-webapp/src/repositories/bio_sales_view_repository.py @@ -55,7 +55,6 @@ class BioSalesViewRepository(BaseRepository): finally: self._database.disconnect() - def fetch_as_data_frame(self, parameter: BioModel): try: self._database.connect() @@ -95,7 +94,7 @@ class BioSalesViewRepository(BaseRepository): if is_not_empty(parameter.rec_lot_num): rec_lot_num = parameter.rec_lot_num # あいまい検索文字列('%')が含まれる場合は'LIKE'、でなければ'='で検索 - rec_lot_num_comparator = condition.LIKE if rec_lot_num in '%' else condition.EQ + rec_lot_num_comparator = condition.LIKE if rec_lot_num in '%' else condition.EQ where_clauses.append(SQLCondition('rec_lot_num', rec_lot_num_comparator, 'rec_lot_num')) # データ区分 if is_not_empty(parameter.data_kbn): @@ -112,7 +111,7 @@ class BioSalesViewRepository(BaseRepository): # 移行フラグ # チェックが入っていない場合、移行対象(IKO_FLG = '*')を省く if parameter.ikoFlg is None: - where_clauses.append(SQLCondition('iko_flg', condition.IS, 'NULL', literal=True)) + where_clauses.append(SQLCondition('iko_flg', condition.IS, 'NULL', literal=True)) # 固定条件 # Viewで返されるロット番号9件をNull以外で抽出 where_clauses.append(SQLCondition('LENGTH(TRIM(rec_lot_num))', condition.GT, '0', literal=True)) diff --git a/ecs/jskult-webapp/src/repositories/hdke_tbl_repository.py b/ecs/jskult-webapp/src/repositories/hdke_tbl_repository.py index e3a72f23..6927533b 100644 --- a/ecs/jskult-webapp/src/repositories/hdke_tbl_repository.py +++ b/ecs/jskult-webapp/src/repositories/hdke_tbl_repository.py @@ -1,5 +1,4 @@ from src.model.db.hdke_tbl import HdkeTblModel -from src.model.request.bio import BioModel from src.repositories.base_repository import BaseRepository diff --git a/ecs/jskult-webapp/src/repositories/pharmacy_product_master_repository.py b/ecs/jskult-webapp/src/repositories/pharmacy_product_master_repository.py index f6523612..2720955f 100644 --- a/ecs/jskult-webapp/src/repositories/pharmacy_product_master_repository.py +++ b/ecs/jskult-webapp/src/repositories/pharmacy_product_master_repository.py @@ -3,15 +3,15 @@ from src.repositories.base_repository import BaseRepository class PharmacyProductMasterRepository(BaseRepository): - + FETCH_SQL = """\ - SELECT + SELECT CONCAT(IFNULL(mkr_cd, ''), ' ', IFNULL(mkr_inf_1, '')) AS mkr_cd_nm FROM src05.phm_prd_mst_v t1 - INNER JOIN + INNER JOIN ( - SELECT + SELECT prd_cd,MAX(sub_no) AS sno FROM src05.phm_prd_mst_v diff --git a/ecs/jskult-webapp/src/repositories/user_master_repository.py b/ecs/jskult-webapp/src/repositories/user_master_repository.py index e5e1ba41..60228074 100644 --- a/ecs/jskult-webapp/src/repositories/user_master_repository.py +++ b/ecs/jskult-webapp/src/repositories/user_master_repository.py @@ -1,5 +1,4 @@ from src.model.db.user_master import UserMasterModel -from src.model.request.bio import BioModel from src.repositories.base_repository import BaseRepository @@ -27,4 +26,4 @@ class UserMasterRepository(BaseRepository): print(f"[ERROR] DB Error : Exception={e.args}") raise e finally: - self._database.disconnect() \ No newline at end of file + self._database.disconnect() diff --git a/ecs/jskult-webapp/src/repositories/wholesaler_master_repository.py b/ecs/jskult-webapp/src/repositories/wholesaler_master_repository.py index 0f625bc7..246eea5e 100644 --- a/ecs/jskult-webapp/src/repositories/wholesaler_master_repository.py +++ b/ecs/jskult-webapp/src/repositories/wholesaler_master_repository.py @@ -3,7 +3,7 @@ from src.repositories.base_repository import BaseRepository class WholesalerMasterRepository(BaseRepository): - + FETCH_SQL = """\ SELECT DISTINCT b.rec_whs_cd, @@ -17,7 +17,7 @@ class WholesalerMasterRepository(BaseRepository): FROM src05.whs_mst_v WHERE (SELECT STR_TO_DATE(syor_date, '%Y%m%d') FROM src05.hdke_tbl) BETWEEN start_date AND end_date ) v2 - ON b.v_whs_cd = v2.v_whs_cd + ON b.v_whs_cd = v2.v_whs_cd AND v2.rec_sts_kbn <> '9' ORDER BY b.rec_whs_cd, b.rec_whs_sub_cd , b.whs_nm DESC """ diff --git a/ecs/jskult-webapp/src/router/session_router.py b/ecs/jskult-webapp/src/router/session_router.py index 7a4ada09..e2699784 100644 --- a/ecs/jskult-webapp/src/router/session_router.py +++ b/ecs/jskult-webapp/src/router/session_router.py @@ -13,12 +13,14 @@ from src.system_var import constants, environment logger = logging.getLogger('uvicorn') + class MeDaCaRoute(APIRoute): """アプリケーションのカスタムルーター Args: APIRoute (APIRoute): FastAPIの標準APIRoute """ + def get_route_handler(self) -> Callable: """前後処理を付加するルートハンドラーを返す @@ -60,6 +62,7 @@ class MeDaCaRoute(APIRoute): Request: 加工後のRequestインスタンス """ return request + async def post_process_route(self, request: Request, response: Response) -> Response: """ルートハンドラーの事後処理 @@ -71,6 +74,7 @@ class MeDaCaRoute(APIRoute): """ return response + class BeforeCheckSessionRoute(MeDaCaRoute): """事前処理として、セッションチェックを行うルートハンドラー @@ -86,12 +90,14 @@ class BeforeCheckSessionRoute(MeDaCaRoute): verified_session = verify_session(checked_session) # セッションが有効でない場合、エラーにする if verified_session is None: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=constants.LOGOUT_REASON_SESSION_EXPIRED) + raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, + detail=constants.LOGOUT_REASON_SESSION_EXPIRED) scope = request.scope scope['session'] = verified_session session_request = Request(receive=request.receive, scope=scope) return session_request + class AfterSetCookieSessionRoute(MeDaCaRoute): """事後処理として、セッションキーをcookieに設定するカスタムルートハンドラー @@ -110,16 +116,18 @@ class AfterSetCookieSessionRoute(MeDaCaRoute): response.set_cookie( key='session', value=session_key, - max_age=environment.SESSION_EXPIRE_MINUTE * 60, # cookieの有効期限は秒数指定なので、60秒をかける + max_age=environment.SESSION_EXPIRE_MINUTE * 60, # cookieの有効期限は秒数指定なので、60秒をかける secure=True, httponly=True ) return response + class AuthenticatedRoute(BeforeCheckSessionRoute, AfterSetCookieSessionRoute): async def pre_process_route(self, request: Request): request = await super().pre_process_route(request) return request + async def post_process_route(self, request: Request, response: Response): response = await super().post_process_route(request, response) return response diff --git a/ecs/jskult-webapp/src/services/base_service.py b/ecs/jskult-webapp/src/services/base_service.py index a2669225..7fd71b3b 100644 --- a/ecs/jskult-webapp/src/services/base_service.py +++ b/ecs/jskult-webapp/src/services/base_service.py @@ -9,5 +9,6 @@ class BaseService(metaclass=ABCMeta): REPOSITORIES: dict[str, BaseRepository] = {} # 各サービスが依存するAWS APIクライアントクラスのマップ CLIENTS: dict[str, AWSAPIClient] = {} + def __init__(self, repositories: dict[str, BaseRepository], clients: dict[str, AWSAPIClient]) -> None: pass diff --git a/ecs/jskult-webapp/src/services/batch_status_service.py b/ecs/jskult-webapp/src/services/batch_status_service.py index e30f0bed..c9f6c6a7 100644 --- a/ecs/jskult-webapp/src/services/batch_status_service.py +++ b/ecs/jskult-webapp/src/services/batch_status_service.py @@ -13,6 +13,7 @@ class BatchStatusService(BaseService): } hdke_table_repository: HdkeTblRepository __hdke_table_record: list[HdkeTblModel] = [] + def __init__(self, repositories: dict[str, BaseRepository], clients: dict[str, AWSAPIClient]) -> None: super().__init__(repositories, clients) self.hdke_table_repository = repositories['hdke_table_repository'] @@ -38,4 +39,3 @@ class BatchStatusService(BaseService): # 日付マスタのレコードがない場合は例外とする if len(self.__hdke_table_record) == 0: raise DBException('日付テーブルのレコードが存在しません') - diff --git a/ecs/jskult-webapp/src/services/bio_view_service.py b/ecs/jskult-webapp/src/services/bio_view_service.py index 99726d23..8fa05778 100644 --- a/ecs/jskult-webapp/src/services/bio_view_service.py +++ b/ecs/jskult-webapp/src/services/bio_view_service.py @@ -26,15 +26,16 @@ class BioViewService(BaseService): 'phm_repository': PharmacyProductMasterRepository, 'bio_sales_repository': BioSalesViewRepository } - + CLIENTS = { 's3_client': S3Client } - + whs_repository: WholesalerMasterRepository phm_repository: PharmacyProductMasterRepository bio_sales_repository: BioSalesViewRepository s3_client: S3Client + def __init__(self, repositories: dict[str, BaseRepository], clients: dict[str, AWSAPIClient]) -> None: super().__init__(repositories, clients) self.whs_repository = repositories['whs_repository'] @@ -45,7 +46,7 @@ class BioViewService(BaseService): def prepare_bio_view( self, session: UserSession - ) ->BioViewModel: + ) -> BioViewModel: # 卸リストを取得 wholesalers = self.whs_repository.fetch_all() # 製品リストを取得 @@ -72,7 +73,8 @@ class BioViewService(BaseService): def write_excel_file(self, data_frame: pd.DataFrame, user_id: str, timestamp: datetime): # Excelに書き込み - output_file_path = path.join(constants.BIO_TEMPORARY_FILE_DIR_PATH, f'Result_{user_id}_{timestamp:%Y%m%d%H%M%S%f}.xlsx') + output_file_path = path.join(constants.BIO_TEMPORARY_FILE_DIR_PATH, + f'Result_{user_id}_{timestamp:%Y%m%d%H%M%S%f}.xlsx') # テンプレートファイルをコピーして出力ファイルの枠だけを作る shutil.copyfile( @@ -87,12 +89,13 @@ class BioViewService(BaseService): # DF内のヘッダと連番を書き込みたくない場合、`header`と`index`をFalseに指定する。 # `startrow`と`startcol`で、Excelの書き込み位置を決定する。省略した場合はA1セルから書く。 data_frame.to_excel(writer, header=False, index=False, startrow=1, startcol=0) - + return output_file_path def write_csv_file(self, data_frame: pd.DataFrame, user_id: str, header: list[str], timestamp: datetime): # csvに書き込み - output_file_path = path.join(constants.BIO_TEMPORARY_FILE_DIR_PATH, f'Result_{user_id}_{timestamp:%Y%m%d%H%M%S%f}.csv') + output_file_path = path.join(constants.BIO_TEMPORARY_FILE_DIR_PATH, + f'Result_{user_id}_{timestamp:%Y%m%d%H%M%S%f}.csv') # 横長のDataFrameとするため、ヘッダーの加工処理 header_data = {} for df_column, header_column in zip(data_frame.columns, header): @@ -108,10 +111,10 @@ class BioViewService(BaseService): def upload_bio_data_file(self, local_file_path: str) -> None: bucket_name = environment.BIO_ACCESS_LOG_BUCKET # TODO: フォルダを変える - file_key =f'bio/{path.basename(local_file_path)}' + file_key = f'bio/{path.basename(local_file_path)}' self.s3_client.upload_file(local_file_path, bucket_name, file_key) - - def generate_download_file_url(self, local_file_path:str, user_id: str, kind: str) -> str: + + def generate_download_file_url(self, local_file_path: str, user_id: str, kind: str) -> str: bucket_name = environment.BIO_ACCESS_LOG_BUCKET # TODO: フォルダを変える file_key = f'bio/{path.basename(local_file_path)}' diff --git a/ecs/jskult-webapp/src/services/login_service.py b/ecs/jskult-webapp/src/services/login_service.py index 6442c82a..aa1f37fd 100644 --- a/ecs/jskult-webapp/src/services/login_service.py +++ b/ecs/jskult-webapp/src/services/login_service.py @@ -17,7 +17,7 @@ class LoginService(BaseService): REPOSITORIES = { 'user_repository': UserMasterRepository } - + CLIENTS = { 'cognito_client': CognitoClient } @@ -41,10 +41,10 @@ class LoginService(BaseService): raise e return JWTToken(id_token, refresh_token) - + def login_with_security_code(self, code: str) -> JWTToken: return JWTToken.request(code) - + def logged_in_user(self, user_id): user_record: UserMasterModel = self.user_repository.fetch_one({'user_id': user_id}) return user_record diff --git a/ecs/jskult-webapp/src/services/session_service.py b/ecs/jskult-webapp/src/services/session_service.py index 92a7a193..e93d9dde 100644 --- a/ecs/jskult-webapp/src/services/session_service.py +++ b/ecs/jskult-webapp/src/services/session_service.py @@ -6,6 +6,7 @@ def set_session(session: UserSession) -> str: session.save() return session.session_key + def get_session(key: str) -> UserSession: try: session = UserSession.get(hash_key=key, consistent_read=True) diff --git a/ecs/jskult-webapp/src/system_var/environment.py b/ecs/jskult-webapp/src/system_var/environment.py index aed9916c..7d82d560 100644 --- a/ecs/jskult-webapp/src/system_var/environment.py +++ b/ecs/jskult-webapp/src/system_var/environment.py @@ -19,4 +19,4 @@ DB_PASSWORD = os.environ['DB_PASSWORD'] DB_SCHEMA = os.environ['DB_SCHEMA'] BIO_SEARCH_RESULT_MAX_COUNT = int(os.environ['BIO_SEARCH_RESULT_MAX_COUNT']) -SESSION_EXPIRE_MINUTE=int(os.environ['SESSION_EXPIRE_MINUTE']) \ No newline at end of file +SESSION_EXPIRE_MINUTE = int(os.environ['SESSION_EXPIRE_MINUTE'])