Merge pull request #229 feature-NEWDWH2021-1069 into develop

This commit is contained in:
下田雅人 2023-07-28 09:07:05 +09:00
commit 9377627f56
23 changed files with 2584 additions and 58 deletions

View File

@ -10,6 +10,7 @@ COGNITO_CLIENT_SECRET=******************************
SESSION_TABLE_NAME=***********************
##S3
BIO_ACCESS_LOG_BUCKET=*******************
MASTER_MAINTENANCE_BUCKET=mbj-newdwh2021-staging-jskult-master-maintenance
#MySQL
DB_HOST=************
DB_PORT=************

View File

@ -1,8 +1,11 @@
from io import BytesIO, TextIOWrapper
from typing import Optional
from fastapi import APIRouter, Depends, HTTPException, Request
from fastapi.responses import HTMLResponse
from starlette import status
from src.depends.services import get_service
from src.logging.get_logger import get_logger
from src.model.internal.session import UserSession
from src.model.view.inst_emp_csv_download_view_model import \
InstEmpCsvDownloadViewModel
@ -13,9 +16,15 @@ from src.model.view.master_mainte_menu_view_model import \
from src.model.view.table_override_view_model import TableOverrideViewModel
from src.router.session_router import AuthenticatedRoute
from src.services.batch_status_service import BatchStatusService
from src.services.master_mainte_service import MasterMainteService
from src.services.session_service import set_session
from src.system_var import constants
from src.templates import templates
from src.model.request.master_mainte_csvup import MasterMainteCsvUpModel
from src.model.request.master_mainte_csvdl import MasterMainteCsvDlModel
logger = get_logger('マスターメンテ')
router = APIRouter()
router.route_class = AuthenticatedRoute
@ -85,7 +94,7 @@ def inst_emp_csv_upload_view(
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=constants.LOGOUT_REASON_BACKUP_PROCESSING)
# 画面表示用のモデル
view_model = InstEmpCsvUploadViewModel()
mainte_csv_up = InstEmpCsvUploadViewModel()
# セッション書き換え
session.update(
actions=[
@ -98,14 +107,118 @@ def inst_emp_csv_upload_view(
'instEmpCsvUL.html',
{
'request': request,
'view': view_model
'mainte_csv_up': mainte_csv_up
},
headers={'session_key': session.session_key}
)
return templates_response
@router.get('/instEmpCsvDL', response_class=HTMLResponse)
@router.post('/instEmpCsvUL', response_class=HTMLResponse)
async def inst_emp_csv_upload(
request: Request,
csv_upload_form: Optional[MasterMainteCsvUpModel] = Depends(MasterMainteCsvUpModel.as_form),
master_mainte_service: MasterMainteService = Depends(get_service(MasterMainteService)),
batch_status_service: BatchStatusService = Depends(get_service(BatchStatusService))
):
session: UserSession = request.session
# マスタメンテメニューへのアクセス権がない場合、ログアウトさせる
if session.master_mainte_flg != '1':
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)
# バッチ処理中の場合、ログアウトさせる
if batch_status_service.is_batch_processing():
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN,
detail=constants.LOGOUT_REASON_BATCH_PROCESSING_FOR_MAINTE)
# dump処理中の場合、ログアウトさせる
if batch_status_service.is_dump_processing():
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=constants.LOGOUT_REASON_BACKUP_PROCESSING)
# 画面表示用のモデル
error_message_list = []
content_type: str = csv_upload_form.csv_file.content_type.strip()
if csv_upload_form.csv_file.size == 0:
error_message_list.append('選択されたファイルが見つかりませんでした。')
elif content_type != 'text/csv' and content_type != 'application/vnd.ms-excel' and content_type != 'application/octet-stream':
error_message_list.append('選択されたファイル形式が"csv"ではありません。')
elif csv_upload_form.csv_file.size >= constants.MENTE_CSV_UPLOAD_MAX_FILE_SIZE_BYTE:
error_message_list.append('選択されたCSVファイルサイズが大きいです。100MB未満にしてください。')
else:
mainte_csv_up = master_mainte_service.prepare_mainte_csv_up_view(
TextIOWrapper(BytesIO(await csv_upload_form.csv_file.read()), encoding='utf-8'),
csv_upload_form.csv_file.filename,
csv_upload_form)
if len(error_message_list) > 0:
mainte_csv_up = InstEmpCsvUploadViewModel(
is_verified=True,
error_message_list=error_message_list,
select_function=csv_upload_form.select_function,
select_table=csv_upload_form.select_table)
# セッション書き換え
session.update(
actions=[
UserSession.last_access_time.set(UserSession.new_last_access_time()),
UserSession.record_expiration_time.set(UserSession.new_record_expiration_time()),
]
)
set_session(session)
templates_response = templates.TemplateResponse(
'instEmpCsvUL.html',
{
'request': request,
'mainte_csv_up': mainte_csv_up
},
headers={'session_key': session.session_key}
)
return templates_response
@router.post('/newInst', response_class=HTMLResponse)
def new_inst_result_view(
request: Request,
csv_upload_form: Optional[MasterMainteCsvUpModel] = Depends(MasterMainteCsvUpModel.as_form),
master_mainte_service: MasterMainteService = Depends(get_service(MasterMainteService)),
batch_status_service: BatchStatusService = Depends(get_service(BatchStatusService))
):
session: UserSession = request.session
# マスタメンテメニューへのアクセス権がない場合、ログアウトさせる
if session.master_mainte_flg != '1':
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)
# バッチ処理中の場合、ログアウトさせる
if batch_status_service.is_batch_processing():
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN,
detail=constants.LOGOUT_REASON_BATCH_PROCESSING_FOR_MAINTE)
# dump処理中の場合、ログアウトさせる
if batch_status_service.is_dump_processing():
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=constants.LOGOUT_REASON_BACKUP_PROCESSING)
# 画面表示用のモデル
mainte_csv_up = master_mainte_service.prepare_mainte_new_inst_view(session.user_id, csv_upload_form)
# セッション書き換え
session.update(
actions=[
UserSession.last_access_time.set(UserSession.new_last_access_time()),
UserSession.record_expiration_time.set(UserSession.new_record_expiration_time()),
]
)
set_session(session)
templates_response = templates.TemplateResponse(
'instEmpCsvUL.html',
{
'request': request,
'mainte_csv_up': mainte_csv_up
},
headers={'session_key': session.session_key}
)
return templates_response
@ router.get('/instEmpCsvDL', response_class=HTMLResponse)
def inst_emp_csv_download_view(
request: Request,
batch_status_service: BatchStatusService = Depends(get_service(BatchStatusService))
@ -125,7 +238,9 @@ def inst_emp_csv_download_view(
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=constants.LOGOUT_REASON_BACKUP_PROCESSING)
# 画面表示用のモデル
view_model = InstEmpCsvDownloadViewModel()
mainte_csv_dl = InstEmpCsvDownloadViewModel(
is_search=False
)
# セッション書き換え
session.update(
actions=[
@ -138,7 +253,77 @@ def inst_emp_csv_download_view(
'instEmpCsvDL.html',
{
'request': request,
'view': view_model
'mainte_csv_dl': mainte_csv_dl
},
headers={'session_key': session.session_key}
)
return templates_response
@router.post('/download', response_class=HTMLResponse)
async def inst_emp_csv_download(
request: Request,
csv_download_form: Optional[MasterMainteCsvDlModel] = Depends(MasterMainteCsvDlModel.as_form),
master_mainte_service: MasterMainteService = Depends(get_service(MasterMainteService)),
batch_status_service: BatchStatusService = Depends(get_service(BatchStatusService))
):
session: UserSession = request.session
# マスタメンテメニューへのアクセス権がない場合、ログアウトさせる
if session.master_mainte_flg != '1':
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)
# バッチ処理中の場合、ログアウトさせる
if batch_status_service.is_batch_processing():
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN,
detail=constants.LOGOUT_REASON_BATCH_PROCESSING_FOR_MAINTE)
# dump処理中の場合、ログアウトさせる
if batch_status_service.is_dump_processing():
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=constants.LOGOUT_REASON_BACKUP_PROCESSING)
search_result_df = master_mainte_service.search_emp_chg_inst_data(csv_download_form)
(result_msg, download_file_url) = master_mainte_service.upload_emp_chg_inst_data_file(
search_result_df,
session.user_id,
csv_download_form.select_table)
# 画面表示用のモデル
mainte_csv_dl = InstEmpCsvDownloadViewModel(
is_search=True,
ta_cd=csv_download_form.ta_cd,
inst_cd=csv_download_form.inst_cd,
emp_cd=csv_download_form.emp_cd,
apply_date_from=csv_download_form.apply_date_from,
start_date_from=csv_download_form.start_date_from,
start_date_to=csv_download_form.start_date_to,
end_date_from=csv_download_form.end_date_from,
end_date_to=csv_download_form.end_date_to,
create_date_from=csv_download_form.create_date_from,
create_date_to=csv_download_form.create_date_to,
update_date_from=csv_download_form.update_date_from,
update_date_to=csv_download_form.update_date_to,
select_table=csv_download_form.select_table,
data_count=search_result_df.shape[0],
download_file_url=download_file_url,
file_name=constants.MENTE_CSV_DOWNLOAD_FILE_NAME,
result_msg=result_msg
)
# セッション書き換え
session.update(
actions=[
UserSession.last_access_time.set(UserSession.new_last_access_time()),
UserSession.record_expiration_time.set(UserSession.new_record_expiration_time()),
]
)
set_session(session)
templates_response = templates.TemplateResponse(
'instEmpCsvDL.html',
{
'request': request,
'mainte_csv_dl': mainte_csv_dl
},
headers={'session_key': session.session_key}
)
@ -165,7 +350,7 @@ def table_override_view(
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=constants.LOGOUT_REASON_BACKUP_PROCESSING)
# 画面表示用のモデル
view_model = TableOverrideViewModel()
table_override = TableOverrideViewModel()
# セッション書き換え
session.update(
actions=[
@ -178,7 +363,49 @@ def table_override_view(
'tableOverride.html',
{
'request': request,
'view': view_model
'table_override': table_override
},
headers={'session_key': session.session_key}
)
return templates_response
@router.post('/tableOverride', response_class=HTMLResponse)
def table_override_result_view(
request: Request,
master_mainte_service: MasterMainteService = Depends(get_service(MasterMainteService)),
batch_status_service: BatchStatusService = Depends(get_service(BatchStatusService))
):
session: UserSession = request.session
# マスタメンテメニューへのアクセス権がない場合、ログアウトさせる
if session.master_mainte_flg != '1':
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN)
# バッチ処理中の場合、ログアウトさせる
if batch_status_service.is_batch_processing():
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN,
detail=constants.LOGOUT_REASON_BATCH_PROCESSING_FOR_MAINTE)
# dump処理中の場合、ログアウトさせる
if batch_status_service.is_dump_processing():
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=constants.LOGOUT_REASON_BACKUP_PROCESSING)
# 画面表示用のモデル
table_override = master_mainte_service.copy_data_real_to_dummy()
# セッション書き換え
session.update(
actions=[
UserSession.last_access_time.set(UserSession.new_last_access_time()),
UserSession.record_expiration_time.set(UserSession.new_record_expiration_time()),
]
)
set_session(session)
templates_response = templates.TemplateResponse(
'tableOverride.html',
{
'request': request,
'table_override': table_override
},
headers={'session_key': session.session_key}
)

View File

@ -0,0 +1,9 @@
from typing import Optional
from src.model.db.base_db_model import BaseDBModel
from src.util.sanitize import sanitize
@sanitize
class MasterMenteCountModel(BaseDBModel):
count: Optional[int]

View File

@ -0,0 +1,572 @@
import csv
import json
from io import TextIOWrapper
from datetime import datetime
from abc import ABCMeta, abstractmethod
from src.system_var import constants
from src.util.string_util import is_not_empty
from src.repositories.mst_inst_repository import MstInstRepository
from src.repositories.bu_master_cd_repository import BuMasterRepository
from src.repositories.emp_master_repository import EmpMasterRepository
from src.repositories.emp_chg_inst_repository import EmpChgInstRepository
from src.logging.get_logger import get_logger
logger = get_logger('マスターメンテ')
class MasterMainteCSVItem(metaclass=ABCMeta):
csv_row: list[str]
table_name: str
line_num: str
mst_inst_repository: MstInstRepository
emp_master_repository: EmpMasterRepository
bu_master_repository: BuMasterRepository
emp_chginst_repository: EmpChgInstRepository
def __init__(
self,
csv_row: list[str],
table_name: str,
line_num: str,
mst_inst_repository: MstInstRepository,
emp_master_repository: EmpMasterRepository,
bu_master_repository: BuMasterRepository,
emp_chginst_repository: EmpChgInstRepository
):
self.csv_row = csv_row
self.table_name = table_name
self.line_num = line_num
self.mst_inst_repository = mst_inst_repository
self.emp_master_repository = emp_master_repository
self.bu_master_repository = bu_master_repository
self.emp_chginst_repository = emp_chginst_repository
def validate(self) -> list[str]:
"""
項目のバリデーションを行うテンプレートメソッド\n
各チェックロジックはサブクラスで実装する
エラーが有る場合[行数項目名: エラー内容]のリストを返す
"""
error_list = []
# 項目数チェック
error_list.extend(self.check_item_count())
if len(error_list) == 0:
# 必須チェック 及び コメントエラーチェック
error_list.extend(self.check_require())
# 施設コード存在チェック
error_list.extend(self.check_inst_cd_exists())
# MUID存在チェック
error_list.extend(self.check_emp_cd_exists())
# BuCd存在チェック
error_list.extend(self.check_bu_cd_exists())
# 適用開始日 < 適用終了日、実在日チェック
error_list.extend(self.check_existing_date())
# データ存在チェック
error_list.extend(self.check_data_exists())
# エラーのないリストを省いて返す
error_list = [error for error in error_list if len(error) != 0]
return error_list
def check_csv_item_count(self, item_count: int) -> list[str]:
error_list = []
if not len(self.csv_row) == item_count:
error_list.append(f'{self.line_num}行目の項目数が一致しません。項目数を確認してください。')
return error_list
def emp_chg_inst_count(self, start_date: str):
return self.emp_chginst_repository.fetch_count(self.inst_cd, self.ta_cd, start_date, self.table_name)
def is_exist_emp_cd(self, start_date: str) -> bool:
if start_date is None or len(start_date) == 0:
return False
if self.emp_master_repository.fetch_count(self.emp_cd, start_date) == 0:
return True
return False
def is_exist_inst_cd(self) -> bool:
return True if self.mst_inst_repository.fetch_count(self.inst_cd) > 0 else False
def is_exist_bu_cd(self) -> bool:
return True if self.bu_master_repository.fetch_count(self.bu_cd) > 0 else False
def make_require_error_message(self, line_num: str, col_name: str) -> str:
return f'{line_num}行目の{col_name}が入力されておりません。'
def __parse_str_to_date(self, check_date: str) -> tuple[bool, datetime]:
try:
check_date_time: datetime = datetime.strptime(check_date, '%Y%m%d')
except Exception as e:
logger.debug(f'適用期間の日付が不正{e}')
return (False, None)
try:
reverse_check_date: str = check_date_time.strftime('%Y%m%d')
except Exception as e:
logger.debug(f'適用期間の日付が不正{e}')
return (False, None)
if check_date != reverse_check_date:
return (False, None)
return (True, check_date_time)
def check_term_date(self,
start_date: str,
end_date: str,
start_date_col_name: str,
end_date_col_name: str) -> tuple[list[str], datetime, datetime]:
error_list = []
start_date_time: datetime = None
end_date_time: datetime = None
if is_not_empty(start_date):
(result, start_date_time) = self.__parse_str_to_date(start_date)
if result is False:
error_list.append(f'{self.line_num}行目の{start_date_col_name}が実在しない日付になっています。')
if is_not_empty(end_date):
(result, end_date_time) = self.__parse_str_to_date(end_date)
if result is False:
error_list.append(f'{self.line_num}行目の{end_date_col_name}が実在しない日付になっています。')
return (error_list, start_date_time, end_date_time)
def get_csv_value(self, column_no: int):
try:
column_value = self.csv_row[column_no]
except IndexError:
column_value = ''
return column_value
@abstractmethod
def csv_row_data(self) -> dict:
pass
...
@abstractmethod
def check_require(self) -> list[str]:
"""必須チェック"""
pass
...
@abstractmethod
def check_inst_cd_exists(self) -> list[str]:
"""InstCD存在チェック"""
pass
...
@abstractmethod
def check_emp_cd_exists(self) -> list[str]:
"""MUID存在チェック"""
pass
...
@abstractmethod
def check_bu_cd_exists(self) -> list[str]:
"""BuCd存在チェック"""
pass
...
@abstractmethod
def check_existing_date(self) -> list[str]:
"""適用開始日 < 適用終了日、実在日チェック"""
@abstractmethod
def check_item_count(self) -> list[str]:
"""項目数チェック"""
pass
...
@abstractmethod
def check_data_exists(self) -> list[str]:
"""データ存在チェック"""
pass
...
class MasterMainteNewInstEmpCSVItem(MasterMainteCSVItem):
"""新規施設担当者登録CSV"""
inst_name: str
emp_name_family: str
emp_name_first: str
start_date: str
end_date: str
def __init__(
self,
csv_row: list[str],
table_name: str,
line_num: str,
mst_inst_repository: MstInstRepository,
emp_master_repository: EmpMasterRepository,
bu_master_repository: BuMasterRepository,
emp_chginst_repository: EmpChgInstRepository
):
super().__init__(
csv_row,
table_name,
line_num,
mst_inst_repository,
emp_master_repository,
bu_master_repository,
emp_chginst_repository
)
self.inst_cd = super().get_csv_value(constants.CSV_NEW_INST_CD_COL_NO)
self.inst_name = super().get_csv_value(constants.CSV_NEW_INST_NAME_COL_NO)
self.ta_cd = super().get_csv_value(constants.CSV_NEW_TA_CD_COL_NO)
self.emp_cd = super().get_csv_value(constants.CSV_NEW_EMP_CD_COL_NO)
self.emp_name_family = super().get_csv_value(constants.CSV_NEW_EMP_NAME_FAMILY_COL_NO)
self.emp_name_first = super().get_csv_value(constants.CSV_NEW_EMP_NAME_FIRST_COL_NO)
self.bu_cd = super().get_csv_value(constants.CSV_NEW_BU_CD_COL_NO)
self.start_date = super().get_csv_value(constants.CSV_NEW_START_DATE)
self.end_date = super().get_csv_value(constants.CSV_NEW_END_DATE)
def csv_row_data(self) -> dict:
return {constants.NEW_INST_EMP_CSV_LOGICAL_NAMES[i]: self.csv_row[i] for i in range(len(self.csv_row))}
def check_require(self) -> list[str]:
error_list = []
if len(self.inst_cd) == 0:
error_list.append(self.make_require_error_message(
self.line_num, constants.NEW_INST_EMP_CSV_LOGICAL_NAMES[constants.CSV_NEW_INST_CD_COL_NO]))
if len(self.ta_cd) == 0:
error_list.append(self.make_require_error_message(
self.line_num, constants.NEW_INST_EMP_CSV_LOGICAL_NAMES[constants.CSV_NEW_TA_CD_COL_NO]))
if len(self.emp_cd) == 0:
error_list.append(self.make_require_error_message(
self.line_num, constants.NEW_INST_EMP_CSV_LOGICAL_NAMES[constants.CSV_NEW_EMP_CD_COL_NO]))
if len(self.bu_cd) == 0:
error_list.append(self.make_require_error_message(
self.line_num, constants.NEW_INST_EMP_CSV_LOGICAL_NAMES[constants.CSV_NEW_BU_CD_COL_NO]))
if len(self.start_date) == 0:
error_list.append(self.make_require_error_message(
self.line_num, constants.NEW_INST_EMP_CSV_LOGICAL_NAMES[constants.CSV_NEW_START_DATE]))
if len(self.end_date) == 0:
error_list.append(self.make_require_error_message(
self.line_num, constants.NEW_INST_EMP_CSV_LOGICAL_NAMES[constants.CSV_NEW_END_DATE]))
return error_list
def check_inst_cd_exists(self) -> list[str]:
error_list = []
if is_not_empty(self.inst_cd) and super().is_exist_inst_cd() is False:
error_list.append(
f'{self.line_num}行目の{constants.NEW_INST_EMP_CSV_LOGICAL_NAMES[constants.CSV_NEW_INST_CD_COL_NO]}\
は施設マスタに存在しないコードです')
return error_list
def check_emp_cd_exists(self) -> list[str]:
error_list = []
if not self.start_date or not self.emp_cd:
return error_list
if super().is_exist_emp_cd(self.start_date) is True:
error_list.append(f'{self.line_num}行目の{constants.NEW_INST_EMP_CSV_LOGICAL_NAMES[constants.CSV_NEW_EMP_CD_COL_NO]}\
は従業員マスタに存在しない もしくは 適用期間外のIDです')
return error_list
def check_bu_cd_exists(self) -> list[str]:
error_list = []
if is_not_empty(self.bu_cd) and super().is_exist_bu_cd() is False:
error_list.append(f'{self.line_num}行目の{constants.NEW_INST_EMP_CSV_LOGICAL_NAMES[constants.CSV_NEW_BU_CD_COL_NO]}\
はビジネスユニットマスタに存在しないコードです')
return error_list
def check_existing_date(self) -> list[str]:
error_list = []
if not self.start_date or not self.end_date:
return error_list
(error_list, start_date_time, end_date_time) = super().check_term_date(
self.start_date,
self.end_date,
constants.NEW_INST_EMP_CSV_LOGICAL_NAMES[constants.CSV_NEW_START_DATE],
constants.NEW_INST_EMP_CSV_LOGICAL_NAMES[constants.CSV_NEW_END_DATE])
if len(error_list) > 0:
return error_list
if start_date_time > end_date_time:
error_list.append(f'{self.line_num}行目の{constants.NEW_INST_EMP_CSV_LOGICAL_NAMES[constants.CSV_NEW_START_DATE]}\
{constants.NEW_INST_EMP_CSV_LOGICAL_NAMES[constants.CSV_NEW_END_DATE]}よりも後の日付になっています')
return error_list
def check_item_count(self) -> list[str]:
return super().check_csv_item_count(len(constants.NEW_INST_EMP_CSV_LOGICAL_NAMES))
def check_data_exists(self) -> list[str]:
error_list = []
if super().emp_chg_inst_count(self.start_date) > 0:
error_list.append(f'{self.line_num}行目の施設コード、領域コード、適用開始日がすべて同一のデータが既に登録されています。')
return error_list
class MasterMainteChangeInstEmpCSVItem(MasterMainteCSVItem):
"""施設担当者変更登録CSV"""
bu_name: str
org_cd: str
org_short_name: str
inst_name: str
explain: str
emp_full_name: str
inst_emp_start_date: str
inst_emp_end_date: str
change_end_date: str
comment: str
def __init__(
self,
csv_row: list[str],
table_name: str,
line_num: str,
mst_inst_repository: MstInstRepository,
emp_master_repository: EmpMasterRepository,
bu_master_repository: BuMasterRepository,
emp_chginst_repository: EmpChgInstRepository
):
super().__init__(
csv_row,
table_name,
line_num,
mst_inst_repository,
emp_master_repository,
bu_master_repository,
emp_chginst_repository
)
self.bu_cd = super().get_csv_value(constants.CSV_CHANGE_BU_CD_COL_NO)
self.bu_name = super().get_csv_value(constants.CSV_CHANGE_BU_NAME_COL_NO)
self.org_cd = super().get_csv_value(constants.CSV_CHANGE_ORG_CD_COL_NO)
self.org_short_name = super().get_csv_value(constants.CSV_CHANGE_ORG_SHORT_NAME_COL_NO)
self.inst_cd = super().get_csv_value(constants.CSV_CHANGE_INST_CD_COL_NO)
self.inst_name = super().get_csv_value(constants.CSV_CHANGE_INST_NAME_COL_NO)
self.ta_cd = super().get_csv_value(constants.CSV_CHANGE_TA_CD_COL_NO)
self.explain = super().get_csv_value(constants.CSV_CHANGE_EXPLAIN_COL_NO)
self.emp_cd = super().get_csv_value(constants.CSV_CHANGE_EMP_CD_COL_NO)
self.emp_full_name = super().get_csv_value(constants.CSV_CHANGE_EMP_FULL_NAME_COL_NO)
self.inst_emp_start_date = super().get_csv_value(constants.CSV_CHANGE_INST_EMP_START_DATE_COL_NO)
self.inst_emp_end_date = super().get_csv_value(constants.CSV_CHANGE_INST_EMP_END_DATE_COL_NO)
self.change_end_date = super().get_csv_value(constants.CSV_CHANGE_CHANGE_END_DATE_COL_NO)
self.comment = super().get_csv_value(constants.CSV_CHANGE_COMMENT)
def csv_row_data(self) -> dict:
return {constants.CHANGE_INST_CSV_LOGICAL_NAMES[i]: self.csv_row[i] for i in range(len(self.csv_row))}
def check_require(self) -> list[str]:
error_list = []
if self.comment == '追加':
if len(self.bu_cd) == 0:
error_list.append(self.make_require_error_message(
self.line_num, constants.CHANGE_INST_CSV_LOGICAL_NAMES[constants.CSV_CHANGE_BU_CD_COL_NO]))
if len(self.inst_cd) == 0:
error_list.append(self.make_require_error_message(
self.line_num, constants.CHANGE_INST_CSV_LOGICAL_NAMES[constants.CSV_CHANGE_INST_CD_COL_NO]))
if len(self.ta_cd) == 0:
error_list.append(self.make_require_error_message(
self.line_num, constants.CHANGE_INST_CSV_LOGICAL_NAMES[constants.CSV_CHANGE_TA_CD_COL_NO]))
if len(self.emp_cd) == 0:
error_list.append(self.make_require_error_message(
self.line_num, constants.CHANGE_INST_CSV_LOGICAL_NAMES[constants.CSV_CHANGE_EMP_CD_COL_NO]))
if len(self.inst_emp_start_date) == 0:
error_list.append(self.make_require_error_message(
self.line_num, constants.CHANGE_INST_CSV_LOGICAL_NAMES[
constants.CSV_CHANGE_INST_EMP_START_DATE_COL_NO]))
if len(self.inst_emp_end_date) == 0:
error_list.append(self.make_require_error_message(
self.line_num, constants.CHANGE_INST_CSV_LOGICAL_NAMES[
constants.CSV_CHANGE_INST_EMP_END_DATE_COL_NO]))
elif self.comment == '終了':
if len(self.inst_cd) == 0:
error_list.append(self.make_require_error_message(
self.line_num, constants.CHANGE_INST_CSV_LOGICAL_NAMES[constants.CSV_CHANGE_INST_CD_COL_NO]))
if len(self.ta_cd) == 0:
error_list.append(self.make_require_error_message(
self.line_num, constants.CHANGE_INST_CSV_LOGICAL_NAMES[constants.CSV_CHANGE_TA_CD_COL_NO]))
if len(self.inst_emp_start_date) == 0:
error_list.append(self.make_require_error_message(
self.line_num,
constants.CHANGE_INST_CSV_LOGICAL_NAMES[constants.CSV_CHANGE_INST_EMP_START_DATE_COL_NO]))
if len(self.change_end_date) == 0:
error_list.append(self.make_require_error_message(self.line_num,
constants.CHANGE_INST_CSV_LOGICAL_NAMES[
constants.CSV_CHANGE_CHANGE_END_DATE_COL_NO]))
elif self.comment == '担当者修正':
if len(self.inst_cd) == 0:
error_list.append(self.make_require_error_message(
self.line_num, constants.CHANGE_INST_CSV_LOGICAL_NAMES[constants.CSV_CHANGE_INST_CD_COL_NO]))
if len(self.ta_cd) == 0:
error_list.append(self.make_require_error_message(
self.line_num, constants.CHANGE_INST_CSV_LOGICAL_NAMES[constants.CSV_CHANGE_TA_CD_COL_NO]))
if len(self.emp_cd) == 0:
error_list.append(self.make_require_error_message(
self.line_num, constants.CHANGE_INST_CSV_LOGICAL_NAMES[constants.CSV_CHANGE_EMP_CD_COL_NO]))
if len(self.inst_emp_start_date) == 0:
error_list.append(self.make_require_error_message(self.line_num,
constants.CHANGE_INST_CSV_LOGICAL_NAMES[
constants.CSV_CHANGE_INST_EMP_START_DATE_COL_NO]))
else:
error_list.append(f'{self.line_num}行目のコメントが不正です。 「追加」「終了」「担当者修正」のいずれかを入力してください。')
return error_list
def check_inst_cd_exists(self) -> list[str]:
error_list = []
if is_not_empty(self.inst_cd) and super().is_exist_inst_cd() is False:
error_list.append(f'{self.line_num}行目の{constants.CHANGE_INST_CSV_LOGICAL_NAMES[constants.CSV_CHANGE_INST_CD_COL_NO]}\
は施設マスタに存在しないコードです')
return error_list
def check_emp_cd_exists(self) -> list[str]:
error_list = []
if not self.inst_emp_start_date or not self.emp_cd:
return error_list
if self.comment != '追加' and self.comment != '担当者修正':
return error_list
if super().is_exist_emp_cd(self.inst_emp_start_date) is True:
error_list.append(f'{self.line_num}行目の{constants.CHANGE_INST_CSV_LOGICAL_NAMES[constants.CSV_CHANGE_EMP_CD_COL_NO]}\
は従業員マスタに存在しない もしくは 適用期間外のIDです')
return error_list
def check_bu_cd_exists(self) -> list[str]:
error_list = []
if is_not_empty(self.bu_cd) and self.comment == '追加'\
and super().is_exist_bu_cd() is False:
error_list.append(f'{self.line_num}行目の{constants.CHANGE_INST_CSV_LOGICAL_NAMES[constants.CSV_CHANGE_BU_CD_COL_NO]}\
はビジネスユニットマスタに存在しないコードです')
return error_list
def check_existing_date(self) -> list[str]:
error_list = []
start_date = self.inst_emp_start_date
if self.comment == '追加' or self.comment == '終了':
if self.comment == '追加':
end_date = self.inst_emp_end_date
end_date_col_name = constants.CHANGE_INST_CSV_LOGICAL_NAMES[
constants.CSV_CHANGE_INST_EMP_END_DATE_COL_NO]
compare_error_message = f'\
{constants.CHANGE_INST_CSV_LOGICAL_NAMES[constants.CSV_CHANGE_INST_EMP_START_DATE_COL_NO]}\
{end_date_col_name}よりも後の日付になっています'
else:
end_date = self.change_end_date
end_date_col_name = constants.CHANGE_INST_CSV_LOGICAL_NAMES[constants.CSV_CHANGE_CHANGE_END_DATE_COL_NO]
compare_error_message = f'\
{constants.CHANGE_INST_CSV_LOGICAL_NAMES[constants.CSV_CHANGE_INST_EMP_START_DATE_COL_NO]}\
{end_date_col_name}よりも後の日付になっています'
if not start_date or not end_date:
return error_list
(error_list, start_date_time, end_date_time) = super().check_term_date(
start_date,
end_date,
constants.CHANGE_INST_CSV_LOGICAL_NAMES[constants.CSV_CHANGE_INST_EMP_START_DATE_COL_NO],
end_date_col_name)
if len(error_list) > 0:
return error_list
if start_date_time > end_date_time:
error_list.append(f'{self.line_num}行目の{compare_error_message}')
return error_list
def check_item_count(self) -> list[str]:
return super().check_csv_item_count(len(constants.CHANGE_INST_CSV_LOGICAL_NAMES))
def check_data_exists(self) -> list[str]:
error_list = []
emp_chg_inst_count = super().emp_chg_inst_count(self.inst_emp_start_date)
if self.comment == '追加' and emp_chg_inst_count > 0:
error_list.append(f'{self.line_num}行目の施設コード、領域コード、施設担当_開始日がすべて同一のデータが既に登録されています。')
elif (self.comment == '終了' or self.comment == '担当者修正') and emp_chg_inst_count == 0:
error_list.append(f'{self.line_num}行目の施設コード、領域コード、施設担当_開始日がすべて同一のデータが存在しないため更新できません。')
return error_list
class MasterMainteCSVItems:
"""施設担当者CSVをループで回すためのもの"""
lines: list[MasterMainteCSVItem]
__i: int = 0
def to_json(self):
# CSVをjsonに変換
csv_row_dict_list: list[dict] = self.to_dict()
# json作成
return json.dumps(csv_row_dict_list, ensure_ascii=False)
def to_dict(self):
return [row_item.csv_row_data() for row_item in self.lines]
def __iter__(self):
return self
def __next__(self) -> MasterMainteCSVItem:
if self.__i == len(self.lines):
raise StopIteration()
line = self.lines[self.__i]
self.__i += 1
return line
def __init__(
self,
file: TextIOWrapper,
select_function: str,
table_name: str,
mst_inst_repository: MstInstRepository,
emp_master_repository: EmpMasterRepository,
bu_master_repository: BuMasterRepository,
emp_chginst_repository: EmpChgInstRepository
) -> None:
reader = csv.reader(file)
csv_rows = []
for line_num, row in enumerate(reader, start=0):
if line_num == 0:
continue
csv_rows.append(self.__select_function(
select_function,
row,
table_name,
line_num,
mst_inst_repository,
emp_master_repository,
bu_master_repository,
emp_chginst_repository))
self.lines = csv_rows
def __select_function(self,
function_type: str,
row: list[str],
table_name: str,
line_num: int,
mst_inst_repository: MstInstRepository,
emp_master_repository: EmpMasterRepository,
bu_master_repository: BuMasterRepository,
emp_chginst_repository: EmpChgInstRepository) -> MasterMainteCSVItem:
if function_type == 'new':
return MasterMainteNewInstEmpCSVItem(
row,
table_name,
str(line_num),
mst_inst_repository,
emp_master_repository,
bu_master_repository,
emp_chginst_repository)
elif function_type == 'change':
return MasterMainteChangeInstEmpCSVItem(
row,
table_name,
str(line_num),
mst_inst_repository,
emp_master_repository,
bu_master_repository,
emp_chginst_repository)

View File

@ -0,0 +1,165 @@
from abc import ABCMeta, abstractmethod
from src.repositories.emp_chg_inst_repository import EmpChgInstRepository
from src.logging.get_logger import get_logger
logger = get_logger('マスターメンテ')
class MasterMainteEmpChgInstFunction(metaclass=ABCMeta):
insert_data: list[dict]
table_name: str
select_table_message: str
user_name: str
emp_chginst_repository: EmpChgInstRepository
def __init__(
self,
insert_data,
table_name: str,
select_table_message: str,
user_name: str,
emp_chginst_repository: EmpChgInstRepository
):
self.insert_data = insert_data
self.table_name = table_name
self.select_table_message = select_table_message
self.user_name = user_name
self.emp_chginst_repository = emp_chginst_repository
def save(self):
error_list = []
try:
self.emp_chginst_repository.connect()
self.emp_chginst_repository.begin()
(result_message, error_list) = self.write_emp_chg_inst_table()
if len(error_list) > 0:
self.emp_chginst_repository.rollback()
else:
self.emp_chginst_repository.commit()
except Exception as e:
self.emp_chginst_repository.rollback()
raise e
finally:
self.emp_chginst_repository.disconnect()
return (result_message, error_list)
def add_emp_chg_inst_table(self, data, start_date, end_date):
self.emp_chginst_repository.insert_emp_chg_inst(
data['施設コード'],
data['領域コード'],
data['MUID'],
data['ビジネスユニットコード'],
start_date,
end_date,
self.user_name,
self.table_name)
@abstractmethod
def write_emp_chg_inst_table(self):
pass
class NewEmpChgInstFunction(MasterMainteEmpChgInstFunction):
def __init__(
self,
insert_data_list: list[dict],
table_name: str,
select_table_message: str,
user_name: str,
emp_chginst_repository: EmpChgInstRepository
):
super().__init__(
insert_data_list,
table_name,
select_table_message,
user_name,
emp_chginst_repository
)
def write_emp_chg_inst_table(self):
error_list = []
add_count = 0
for row_no, data in enumerate(self.insert_data, start=1):
try:
self.add_emp_chg_inst_table(data, data['適用開始日'], data['適用終了日'])
add_count += 1
except Exception as e:
error_list.append(f'{str(row_no)}行目がSQL実行エラーです。CSVファイルを確認してください。')
logger.info(f'新規施設登録時に{row_no}行目でエラーが発生しました: {e}')
result_message_list = []
if len(error_list) == 0:
result_message_list.append('新規施設登録を行いました')
result_message_list.append('対象:' + self.select_table_message)
result_message_list.append('追加:' + str(add_count) + '')
return (result_message_list, error_list)
class ChangeEmpChgInstFunction(MasterMainteEmpChgInstFunction):
def __init__(
self,
insert_data: list[dict],
table_name: str,
select_table_message: str,
user_name: str,
emp_chginst_repository: EmpChgInstRepository
):
super().__init__(
insert_data,
table_name,
select_table_message,
user_name,
emp_chginst_repository
)
def write_emp_chg_inst_table(self):
add_count = 0
end_count = 0
modify_count = 0
error_list = []
for row_no, data in enumerate(self.insert_data, start=1):
try:
if data['コメント'] == '追加':
self.add_emp_chg_inst_table(data, data['施設担当_開始日'], data['施設担当_終了日'])
add_count += 1
elif data['コメント'] == '終了':
self.__end_emp_chg_inst(data)
end_count += 1
elif data['コメント'] == '担当者修正':
self.__modify_emp_chg_inst(data)
modify_count += 1
except Exception as e:
error_list.append(f'{str(row_no)}行目がSQL実行エラーです。CSVファイルを確認してください。')
logger.info(f'施設担当者変更時に{row_no}行目でエラーが発生しました: {e}')
result_message_list = []
if len(error_list) == 0:
result_message_list.append('施設担当者変更を行いました')
result_message_list.append('対象:' + self.select_table_message)
result_message_list.append('追加:' + str(add_count) + '')
result_message_list.append('修正:' + str(modify_count) + '')
result_message_list.append('終了:' + str(end_count) + '')
return (result_message_list, error_list)
def __end_emp_chg_inst(self, data: dict):
self.emp_chginst_repository.end_emp_chg_inst(
data['施設コード'],
data['領域コード'],
data['施設担当_開始日'],
data['終了日の変更'],
self.user_name,
self.table_name)
def __modify_emp_chg_inst(self, data: dict):
self.emp_chginst_repository.modify_emp_chg_inst(
data['施設コード'],
data['領域コード'],
data['施設担当_開始日'],
data['MUID'],
self.user_name,
self.table_name)

View File

@ -0,0 +1,169 @@
from typing import Optional
from fastapi import Form
from src.util.sanitize import sanitize
from src.model.request.request_base_model import RequestBaseModel
from src.util.string_util import is_not_empty
@sanitize
class MasterMainteCsvDlModel(RequestBaseModel):
ta_cd: Optional[str]
adapt_ta_cd: Optional[str]
inst_cd: Optional[str]
adapt_inst_cd: Optional[str]
emp_cd: Optional[str]
adapt_emp_cd: Optional[str]
apply_date_from: Optional[str]
adapt_apply_date_from: Optional[str]
start_date_from: Optional[str]
adapt_start_date_from: Optional[str]
start_date_to: Optional[str]
adapt_start_date_to: Optional[str]
end_date_from: Optional[str]
adapt_end_date_from: Optional[str]
end_date_to: Optional[str]
adapt_end_date_to: Optional[str]
select_table: Optional[str]
create_date_from: Optional[str]
adapt_create_date_from: Optional[str]
create_date_to: Optional[str]
adapt_create_date_to: Optional[str]
update_date_from: Optional[str]
adapt_update_date_from: Optional[str]
update_date_to: Optional[str]
adapt_update_date_to: Optional[str]
@classmethod
def as_form(
cls,
ctrl_ta_cd: Optional[str] = Form(None),
ctrl_inst_cd: Optional[str] = Form(None),
ctrl_emp_cd: Optional[str] = Form(None),
ctrl_apply_date_from: Optional[str] = Form(None),
ctrl_start_date_from: Optional[str] = Form(None),
ctrl_start_date_to: Optional[str] = Form(None),
ctrl_end_date_from: Optional[str] = Form(None),
ctrl_end_date_to: Optional[str] = Form(None),
radio_select_table: Optional[str] = Form(None),
ctrl_create_date_from: Optional[str] = Form(None),
ctrl_create_date_to: Optional[str] = Form(None),
ctrl_update_date_from: Optional[str] = Form(None),
ctrl_update_date_to: Optional[str] = Form(None)
):
return cls.__convert_request_param(
cls,
ctrl_ta_cd,
ctrl_inst_cd,
ctrl_emp_cd,
ctrl_apply_date_from,
ctrl_start_date_from,
ctrl_start_date_to,
ctrl_end_date_from,
ctrl_end_date_to,
radio_select_table,
ctrl_create_date_from,
ctrl_create_date_to,
ctrl_update_date_from,
ctrl_update_date_to
)
def __convert_request_param(
cls,
ctrl_ta_cd: str,
ctrl_inst_cd: str,
ctrl_emp_cd: str,
ctrl_apply_date_from: str,
ctrl_start_date_from: str,
ctrl_start_date_to: str,
ctrl_end_date_from: str,
ctrl_end_date_to: str,
radio_select_table: str,
ctrl_create_date_from: str,
ctrl_create_date_to: str,
ctrl_update_date_from: str,
ctrl_update_date_to: str
):
ctrl_ta_cd = ctrl_ta_cd if is_not_empty(ctrl_ta_cd) else ''
ctrl_inst_cd = ctrl_inst_cd if is_not_empty(ctrl_inst_cd) else ''
ctrl_emp_cd = ctrl_emp_cd if is_not_empty(ctrl_emp_cd) else ''
adapt_apply_date_from = ''
if is_not_empty(ctrl_apply_date_from):
adapt_apply_date_from = ctrl_apply_date_from.replace('/', '')
else:
ctrl_apply_date_from = ''
adapt_start_date_from = ''
adapt_start_date_to = ''
if is_not_empty(ctrl_start_date_from):
adapt_start_date_from = ctrl_start_date_from.replace('/', '')
else:
ctrl_start_date_from = ''
if is_not_empty(ctrl_start_date_to):
adapt_start_date_to = ctrl_start_date_to.replace('/', '')
else:
ctrl_start_date_to = ''
adapt_end_date_from = ''
adapt_end_date_to = ''
if is_not_empty(ctrl_end_date_from):
adapt_end_date_from = ctrl_end_date_from.replace('/', '')
else:
ctrl_end_date_from = ''
if is_not_empty(ctrl_end_date_to):
adapt_end_date_to = ctrl_end_date_to.replace('/', '')
else:
ctrl_end_date_to = ''
adapt_create_date_from = ''
adapt_create_date_to = ''
if is_not_empty(ctrl_create_date_from):
adapt_create_date_from = ctrl_create_date_from.replace('/', '-') + ' 00:00:00'
else:
ctrl_create_date_from = ''
if is_not_empty(ctrl_create_date_to):
adapt_create_date_to = ctrl_create_date_to.replace('/', '-') + ' 23:59:59'
else:
ctrl_create_date_to = ''
adapt_update_date_from = ''
adapt_update_date_to = ''
if is_not_empty(ctrl_update_date_from):
adapt_update_date_from = ctrl_update_date_from.replace('/', '-') + ' 00:00:00'
else:
ctrl_update_date_from = ''
if is_not_empty(ctrl_update_date_to):
adapt_update_date_to = ctrl_update_date_to.replace('/', '-') + ' 23:59:59'
else:
ctrl_update_date_to = ''
return cls(
ta_cd=ctrl_ta_cd,
adapt_ta_cd=ctrl_ta_cd,
inst_cd=ctrl_inst_cd,
adapt_inst_cd=ctrl_inst_cd,
emp_cd=ctrl_emp_cd,
adapt_emp_cd=ctrl_emp_cd,
apply_date_from=ctrl_apply_date_from,
adapt_apply_date_from=adapt_apply_date_from,
start_date_from=ctrl_start_date_from,
adapt_start_date_from=adapt_start_date_from,
start_date_to=ctrl_start_date_to,
adapt_start_date_to=adapt_start_date_to,
select_table=radio_select_table,
end_date_from=ctrl_end_date_from,
adapt_end_date_from=adapt_end_date_from,
end_date_to=ctrl_end_date_to,
adapt_end_date_to=adapt_end_date_to,
create_date_from=ctrl_create_date_from,
adapt_create_date_from=adapt_create_date_from,
create_date_to=ctrl_create_date_to,
adapt_create_date_to=adapt_create_date_to,
update_date_from=ctrl_update_date_from,
adapt_update_date_from=adapt_update_date_from,
update_date_to=ctrl_update_date_to,
adapt_update_date_to=adapt_update_date_to
)

View File

@ -0,0 +1,31 @@
from typing import Optional, Annotated
from fastapi import Form
from src.util.sanitize import sanitize
from fastapi import File, UploadFile
from src.model.request.request_base_model import RequestBaseModel
@sanitize
class MasterMainteCsvUpModel(RequestBaseModel):
csv_file: Optional[Annotated[UploadFile, File()]]
select_function: Optional[str]
select_table: Optional[str]
json_upload_data: Optional[str]
@classmethod
def as_form(
cls,
ctrl_csv_file: UploadFile = Form(None),
ctrl_select_function: Optional[str] = Form(None),
ctrl_select_table: Optional[str] = Form(None),
ctrl_json_upload_data: Optional[str] = Form(None)
):
return cls(
csv_file=ctrl_csv_file,
select_function=ctrl_select_function,
select_table=ctrl_select_table,
json_upload_data=ctrl_json_upload_data
)

View File

@ -1,5 +1,31 @@
from pydantic import BaseModel
from typing import Optional
from src.util.string_util import is_not_empty
class InstEmpCsvDownloadViewModel(BaseModel):
subtitle: str = '施設担当者データCSVダウンロード'
is_search: Optional[bool] = False
ta_cd: Optional[str] = ''
inst_cd: Optional[str] = ''
emp_cd: Optional[str] = ''
apply_date_from: Optional[str] = ''
start_date_from: Optional[str] = ''
start_date_to: Optional[str] = ''
end_date_from: Optional[str] = ''
end_date_to: Optional[str] = ''
create_date_from: Optional[str] = ''
create_date_to: Optional[str] = ''
update_date_from: Optional[str] = ''
update_date_to: Optional[str] = ''
select_table: Optional[str] = ''
data_count: Optional[int] = 0
result_msg: Optional[str] = ''
download_file_url: Optional[str] = ''
file_name: Optional[str] = ''
def is_select_table_empty(self):
return not is_not_empty(self.select_table)
def is_download_file_url_empty(self):
return not is_not_empty(self.download_file_url)

View File

@ -1,5 +1,49 @@
from typing import Optional
from pydantic import BaseModel
from src.system_var import constants
class InstEmpCsvUploadViewModel(BaseModel):
subtitle: str = '施設担当者データCSVアップロード'
is_verified: Optional[bool]
is_insert: Optional[bool]
error_message_list: Optional[list[str]]
select_function: Optional[str]
select_table: Optional[str]
csv_file_name: Optional[str]
csv_upload_list: Optional[list[dict]]
json_upload_data: Optional[str]
result_message_list: Optional[list[str]]
select_function_message: Optional[str]
def select_table_message(self):
return self.__dummy_table() if self.select_table == 'dummy' else self.__real_table()
def upload_data_columns(self) -> list[str]:
return self.__inst_emp_columns()
def is_select_function_empty(self):
return self.select_function is None or len(self.select_function) == 0
def is_select_table_empty(self):
return self.select_table is None or len(self.select_table) == 0
def is_error_message_list_empty(self):
return self.error_message_list is None or len(self.error_message_list) == 0
def csv_data_count(self):
return 0 if self.csv_upload_list is None else len(self.csv_upload_list)
def __inst_emp_columns(self) -> list[str]:
if self.select_function == 'new':
return constants.NEW_INST_EMP_CSV_LOGICAL_NAMES
if self.select_function == 'change':
return constants.CHANGE_INST_CSV_LOGICAL_NAMES
return []
def __real_table(self):
return constants.CSV_REAL_TABLE_NAME
def __dummy_table(self):
return constants.CSV_CHANGE_TABLE_NAME

View File

@ -1,5 +1,8 @@
from pydantic import BaseModel
from typing import Optional
class TableOverrideViewModel(BaseModel):
subtitle: str = 'テーブル上書きコピー'
is_override: Optional[bool] = False

View File

@ -0,0 +1,32 @@
from src.repositories.base_repository import BaseRepository
from src.model.db.master_mente_count import MasterMenteCountModel
from src.logging.get_logger import get_logger
logger = get_logger('ビジネスユニットマスタ')
class BuMasterRepository(BaseRepository):
FETCH_COUNT_SQL = """\
SELECT
COUNT(*) AS count
FROM
src05.bu
WHERE
bu.bu_cd = :bu_cd
"""
def fetch_count(self, bu_cd) -> MasterMenteCountModel:
try:
self._database.connect()
query = self.FETCH_COUNT_SQL
result = self._database.execute_select(query, {'bu_cd': bu_cd})
models = [MasterMenteCountModel(**r) for r in result]
if len(models) == 0:
return 0
return models[0].count
except Exception as e:
logger.exception(f"DB Error : Exception={e.args}")
raise e
finally:
self._database.disconnect()

View File

@ -0,0 +1,300 @@
from src.repositories.base_repository import BaseRepository
from src.db.sql_condition import SQLCondition
from src.db import sql_condition as condition
from src.model.db.master_mente_count import MasterMenteCountModel
from src.model.request.master_mainte_csvdl import MasterMainteCsvDlModel
from src.util.string_util import is_not_empty
from src.logging.get_logger import get_logger
logger = get_logger('従業員担当施設マスタ')
class EmpChgInstRepository(BaseRepository):
def connect(self):
self._database.connect()
def begin(self):
self._database.begin()
def commit(self):
self._database.commit()
def rollback(self):
self._database.rollback()
def disconnect(self):
self._database.disconnect()
INSERT_SQL = """\
INSERT INTO {table_name}
(
inst_cd,
ta_cd,
emp_cd,
bu_cd,
start_date,
end_date,
main_chg_flg,
enabled_flg,
creater,
create_date,
updater,
update_date
)
VALUES (
:inst_cd,
:ta_cd,
:emp_cd,
:bu_cd,
:start_date,
:end_date,
'1',
'Y',
:create_user_name,
NOW(),
:update_user_name,
NOW()
)
"""
def insert_emp_chg_inst(self, inst_cd, ta_cd, emp_cd, bu_cd, start_date,
end_date, create_user_name, table_name):
try:
query = self.INSERT_SQL.format(table_name=table_name)
self._database.execute(query, {
'inst_cd': inst_cd,
'ta_cd': ta_cd,
'emp_cd': emp_cd,
'bu_cd': bu_cd,
'start_date': start_date,
'end_date': end_date,
'create_user_name': create_user_name,
'update_user_name': create_user_name
})
except Exception as e:
logger.exception(f'DB Error : Exception={e.args}')
raise e
UPDATE_END_DATE_SQL = """\
UPDATE
{table_name}
SET
end_date = :end_date,
updater = :update_user_name,
update_date = NOW()
WHERE
inst_cd = :inst_cd
and ta_cd = :ta_cd
and start_date = :start_date
"""
def end_emp_chg_inst(self, inst_cd, ta_cd, start_date,
end_date, update_user_name, table_name):
try:
query = self.UPDATE_END_DATE_SQL.format(table_name=table_name)
self._database.execute(query, {
'inst_cd': inst_cd,
'ta_cd': ta_cd,
'start_date': start_date,
'end_date': end_date,
'update_user_name': update_user_name
})
except Exception as e:
logger.exception(f'DB Error : Exception={e.args}')
raise e
UPDATE_EMP_CD_SQL = """\
UPDATE
{table_name}
SET
emp_cd = :emp_cd,
updater = :update_user_name,
update_date = now()
where
inst_cd = :inst_cd
and ta_cd = :ta_cd
and start_date = :start_date
"""
def modify_emp_chg_inst(self, inst_cd, ta_cd, start_date, emp_cd, update_user_name, table_name):
try:
query = self.UPDATE_EMP_CD_SQL.format(table_name=table_name)
self._database.execute(query, {
'inst_cd': inst_cd,
'ta_cd': ta_cd,
'start_date': start_date,
'emp_cd': emp_cd,
'update_user_name': update_user_name
})
except Exception as e:
logger.exception(f'DB Error : Exception={e.args}')
raise e
FETCH_COUNT_SQL = """\
SELECT
COUNT(*) AS count
FROM
{table_name}
WHERE
inst_cd = :inst_cd
AND ta_cd = :ta_cd
AND start_date = :start_date
"""
def fetch_count(self, inst_cd, ta_cd, start_date, table_name) -> MasterMenteCountModel:
try:
self._database.connect()
query = self.FETCH_COUNT_SQL.format(table_name=table_name)
result = self._database.execute_select(query, {'inst_cd': inst_cd, 'ta_cd': ta_cd,
'start_date': start_date})
models = [MasterMenteCountModel(**r) for r in result]
if len(models) == 0:
return 0
return models[0].count
except Exception as e:
logger.exception(f'DB Error : Exception={e.args}')
raise e
finally:
self._database.disconnect()
FETCH_SQL = """\
SELECT DISTINCT
eci.inst_cd AS inst_cd,
mi.inst_name AS inst_name,
eci.ta_cd AS ta_cd,
eci.emp_cd AS emp_cd,
CONCAT(emp.emp_name_family, " ", emp.emp_name_first) AS emp_name_full,
eci.bu_cd AS bu_cd,
bu.bu_name AS bu_name,
eci.start_date AS start_date,
eci.end_date AS end_date,
eci.creater AS creater,
eci.create_date AS create_date,
eci.updater AS updater,
eci.update_date AS update_date
FROM
{table_name} AS eci
LEFT JOIN mst_inst AS mi
ON eci.inst_cd = mi.inst_cd
LEFT JOIN emp
ON eci.emp_cd = emp.emp_cd
LEFT JOIN bu
ON eci.bu_cd = bu.bu_cd
WHERE
{where_clause}
"""
def fetch_as_data_frame(self, table_name: str, parameter: MasterMainteCsvDlModel):
try:
self._database.connect()
where_clause = self.__build_condition(parameter)
query = self.FETCH_SQL.format(table_name=table_name, where_clause=where_clause)
logger.debug(f'SQL: {query}')
df = self._to_data_frame(query, parameter)
logger.debug(f'count= {df.shape[0]}')
return df
except Exception as e:
logger.exception(f'DB Error : Exception={e.args}')
raise e
finally:
self._database.disconnect()
def __build_condition(self, parameter: MasterMainteCsvDlModel):
where_clauses: list[SQLCondition] = []
# 領域コードが入力されていた場合
if is_not_empty(parameter.ta_cd):
parameter.adapt_ta_cd = f'%{parameter.ta_cd}%'
where_clauses.append(SQLCondition('eci.ta_cd', condition.LIKE, 'adapt_ta_cd'))
# 施設コードが入力されていた場合
if is_not_empty(parameter.inst_cd):
parameter.adapt_inst_cd = f'%{parameter.inst_cd}%'
where_clauses.append(SQLCondition('eci.inst_cd', condition.LIKE, 'adapt_inst_cd'))
# MUIDが入力されていた場合
if is_not_empty(parameter.emp_cd):
parameter.adapt_emp_cd = f'%{parameter.emp_cd}%'
where_clauses.append(SQLCondition('eci.emp_cd', condition.LIKE, 'adapt_emp_cd'))
# 適用期間内が入力されていた場合
if is_not_empty(parameter.adapt_apply_date_from):
where_clauses.append(SQLCondition('eci.start_date',
condition.LE,
'adapt_apply_date_from'))
where_clauses.append(SQLCondition('eci.end_date',
condition.GE,
'adapt_apply_date_from'))
# 適用開始日FROMが入力されていた場合
if is_not_empty(parameter.adapt_start_date_from):
where_clauses.append(SQLCondition('eci.start_date',
condition.GE,
'adapt_start_date_from'))
# 適用開始日TOが入力されていた場合
if is_not_empty(parameter.adapt_start_date_to):
where_clauses.append(SQLCondition('eci.start_date',
condition.LE,
'adapt_start_date_to'))
# 適用終了日FROMが入力されていた場合
if is_not_empty(parameter.adapt_end_date_from):
where_clauses.append(SQLCondition('eci.end_date',
condition.GE,
'adapt_end_date_from'))
# 適用終了日TOが入力されていた場合
if is_not_empty(parameter.adapt_end_date_to):
where_clauses.append(SQLCondition('eci.end_date',
condition.LE,
'adapt_end_date_to'))
# データ作成日FROMが入力されていた場合
if is_not_empty(parameter.adapt_create_date_from):
where_clauses.append(SQLCondition('eci.create_date',
condition.GE,
'adapt_create_date_from'))
# データ作成日TOが入力されていた場合
if is_not_empty(parameter.adapt_create_date_to):
where_clauses.append(SQLCondition('eci.create_date',
condition.LE,
'adapt_create_date_to'))
# データ更新日FROMが入力されていた場合
if is_not_empty(parameter.adapt_update_date_from):
where_clauses.append(SQLCondition('eci.update_date',
condition.GE,
'adapt_update_date_from'))
# データ更新日TOが入力されていた場合
if is_not_empty(parameter.adapt_update_date_to):
where_clauses.append(SQLCondition('eci.update_date',
condition.LE,
'adapt_update_date_to'))
where_clauses_str = ' AND '.join([condition.apply() for condition in where_clauses])
logger.debug(f'条件設定終了:{where_clauses_str}')
return where_clauses_str
DELETE_SQL = "DELETE FROM emp_chg_inst_wrk"
def delete_dummy_table(self):
try:
query = self.DELETE_SQL
self._database.execute(query)
except Exception as e:
logger.exception(f'DB Error : Exception={e.args}')
raise e
COPY_TABLE_SQL = "INSERT INTO emp_chg_inst_wrk SELECT * FROM emp_chg_inst"
def copy_real_to_dummy(self):
try:
query = self.COPY_TABLE_SQL
self._database.execute(query)
except Exception as e:
logger.exception(f'DB Error : Exception={e.args}')
raise e

View File

@ -0,0 +1,34 @@
from src.repositories.base_repository import BaseRepository
from src.model.db.master_mente_count import MasterMenteCountModel
from src.logging.get_logger import get_logger
logger = get_logger('従業員マスタ')
class EmpMasterRepository(BaseRepository):
FETCH_COUNT_SQL = """\
SELECT
COUNT(*) AS count
FROM
src05.emp
WHERE
emp.emp_cd = :emp_cd
AND str_to_date(emp.start_date, '%Y%m%d') <= str_to_date(:start_work_date, '%Y%m%d')
AND str_to_date(:start_work_date, '%Y%m%d') <= str_to_date(emp.end_date ,'%Y%m%d')
"""
def fetch_count(self, emp_cd, start_work_date) -> MasterMenteCountModel:
try:
self._database.connect()
query = self.FETCH_COUNT_SQL
result = self._database.execute_select(query, {'emp_cd': emp_cd, 'start_work_date': start_work_date})
models = [MasterMenteCountModel(**r) for r in result]
if len(models) == 0:
return 0
return models[0].count
except Exception as e:
logger.exception(f"DB Error : Exception={e.args}")
raise e
finally:
self._database.disconnect()

View File

@ -0,0 +1,32 @@
from src.repositories.base_repository import BaseRepository
from src.model.db.master_mente_count import MasterMenteCountModel
from src.logging.get_logger import get_logger
logger = get_logger('メルク施設マスタ')
class MstInstRepository(BaseRepository):
FETCH_COUNT_SQL = """\
SELECT
COUNT(*) AS count
FROM
src05.mst_inst
WHERE
mst_inst.inst_cd = :inst_cd
"""
def fetch_count(self, inst_cd) -> MasterMenteCountModel:
try:
self._database.connect()
query = self.FETCH_COUNT_SQL
result = self._database.execute_select(query, {'inst_cd': inst_cd})
models = [MasterMenteCountModel(**r) for r in result]
if len(models) == 0:
return 0
return models[0].count
except Exception as e:
logger.exception(f"DB Error : Exception={e.args}")
raise e
finally:
self._database.disconnect()

View File

@ -0,0 +1,262 @@
import os
import json
import html
import csv
import pandas as pd
from fastapi import HTTPException
from io import TextIOWrapper
from src.aws.aws_api_client import AWSAPIClient
from src.aws.s3 import S3Client
from src.error.exceptions import DBException
from starlette import status
from datetime import datetime
from src.services.base_service import BaseService
from src.system_var import constants, environment
from src.repositories.base_repository import BaseRepository
from src.repositories.mst_inst_repository import MstInstRepository
from src.repositories.bu_master_cd_repository import BuMasterRepository
from src.repositories.emp_master_repository import EmpMasterRepository
from src.repositories.emp_chg_inst_repository import EmpChgInstRepository
from src.model.internal.master_mainte_csv import MasterMainteCSVItems
from src.model.internal.master_mainte_emp_chg_inst_function import NewEmpChgInstFunction
from src.model.internal.master_mainte_emp_chg_inst_function import ChangeEmpChgInstFunction
from src.model.view.inst_emp_csv_upload_view_model import InstEmpCsvUploadViewModel
from src.model.view.table_override_view_model import TableOverrideViewModel
from src.model.request.master_mainte_csvup import MasterMainteCsvUpModel
from src.model.request.master_mainte_csvdl import MasterMainteCsvDlModel
from src.logging.get_logger import get_logger
logger = get_logger('マスターメンテ')
class MasterMainteService(BaseService):
REPOSITORIES = {
'mst_inst_repository': MstInstRepository,
'emp_master_repository': EmpMasterRepository,
'bu_master_repository': BuMasterRepository,
'emp_chginst_repository': EmpChgInstRepository,
}
CLIENTS = {
's3_client': S3Client
}
mst_inst_repository: MstInstRepository
emp_master_repository: EmpMasterRepository
bu_master_repository: BuMasterRepository
emp_chginst_repository: EmpChgInstRepository
s3_client: S3Client
def __init__(self, repositories: dict[str, BaseRepository], clients: dict[str, AWSAPIClient]) -> None:
super().__init__(repositories, clients)
self.mst_inst_repository = repositories['mst_inst_repository']
self.emp_master_repository = repositories['emp_master_repository']
self.bu_master_repository = repositories['bu_master_repository']
self.emp_chginst_repository = repositories['emp_chginst_repository']
self.s3_client = clients['s3_client']
def prepare_mainte_csv_up_view(self,
file: TextIOWrapper,
csv_file_name: str,
csv_upload_form: MasterMainteCsvUpModel) -> InstEmpCsvUploadViewModel:
if csv_upload_form.select_function != 'new' and csv_upload_form.select_function != 'change':
raise Exception(f'機能の選択値が不正です: {csv_upload_form.select_function}')
if csv_upload_form.select_table != 'dummy' and csv_upload_form.select_table != 'real':
raise Exception(f'登録テーブルの選択値が不正です: {csv_upload_form.select_table}')
(table_name, selected_table_msg) = self.__choose_target_table(csv_upload_form.select_table)
csv_items = MasterMainteCSVItems(
file,
csv_upload_form.select_function,
table_name,
self.mst_inst_repository,
self.emp_master_repository,
self.bu_master_repository,
self.emp_chginst_repository
)
error_message_list = []
# CSVファイル0件(ヘッダ行のみ)チェック
if len(csv_items.lines) == 0:
error_message_list.append('選択されたCSVファイルの2行目以降に値が記入されておりません。')
else:
for row_item in csv_items:
error_message_list.extend([data for data in row_item.validate()])
csv_upload_list = []
json_upload_data = ''
if len(error_message_list) == 0:
csv_upload_list: list[dict] = csv_items.to_dict()
# json作成
json_upload_data = csv_items.to_json()
mainte_csv_up = InstEmpCsvUploadViewModel(
is_verified=True,
error_message_list=error_message_list,
select_function=csv_upload_form.select_function,
select_table=csv_upload_form.select_table,
csv_upload_list=csv_upload_list,
json_upload_data=json_upload_data,
csv_file_name=csv_file_name,
select_function_message=self.__make_dialog_confirm_message(
csv_upload_form.select_function,
selected_table_msg)
)
return mainte_csv_up
def prepare_mainte_new_inst_view(self,
user_name: str,
csv_upload_form: MasterMainteCsvUpModel) -> InstEmpCsvUploadViewModel:
(table_name, selected_table_msg) = self.__choose_target_table(csv_upload_form.select_table)
csv_data_list = json.loads(html.unescape(csv_upload_form.unescape().json_upload_data))
if csv_upload_form.select_function == 'new':
emp_chg_inst = NewEmpChgInstFunction(
csv_data_list,
table_name,
selected_table_msg,
user_name,
self.emp_chginst_repository)
elif csv_upload_form.select_function == 'change':
emp_chg_inst = ChangeEmpChgInstFunction(
csv_data_list,
table_name,
selected_table_msg,
user_name,
self.emp_chginst_repository)
else:
raise Exception(f'機能の選択値が不正です: {csv_upload_form.select_function}')
(result_message_list, raw_error_list) = emp_chg_inst.save()
error_message_list = []
error_message_list.extend(raw_error_list)
mainte_csv_up = InstEmpCsvUploadViewModel(
is_insert=True,
result_message_list=result_message_list,
error_message_list=error_message_list
)
return mainte_csv_up
def copy_data_real_to_dummy(self) -> TableOverrideViewModel:
try:
self.emp_chginst_repository.connect()
self.emp_chginst_repository.begin()
self.emp_chginst_repository.delete_dummy_table()
self.emp_chginst_repository.copy_real_to_dummy()
self.emp_chginst_repository.commit()
except Exception as e:
self.emp_chginst_repository.rollback()
raise e
finally:
self.emp_chginst_repository.disconnect()
# コピー完了をマークして画面に返却
table_override = TableOverrideViewModel(
is_override=True
)
return table_override
def search_emp_chg_inst_data(self, csv_download_form: MasterMainteCsvDlModel) -> pd.DataFrame:
try:
csv_download_form.unescape()
# 施設担当者データを検索
search_result_df = self.search_download_emp_chg_inst_data(csv_download_form)
except DBException as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail={'error': 'db_error', 'message': e.args}
)
return search_result_df
def search_download_emp_chg_inst_data(self, csv_download_form: MasterMainteCsvDlModel):
(table_name, _) = self.__choose_target_table(csv_download_form.select_table)
search_result_df = self.emp_chginst_repository.fetch_as_data_frame(table_name, csv_download_form)
return search_result_df
def write_csv_file(self, data_frame: pd.DataFrame, header: list[str], download_file_name: str):
# csvに書き込み
output_file_path = os.path.join(constants.MENTE_CSV_TEMPORARY_FILE_DIR_PATH, download_file_name)
# 横長のDataFrameとするため、ヘッダーの加工処理
header_data = {}
for df_column, header_column in zip(data_frame.columns, header):
header_data[df_column] = header_column
header_df = pd.DataFrame([header_data], index=None)
output_df = pd.concat([header_df, data_frame])
# ヘッダー行としてではなく、1レコードとして出力する
output_df.to_csv(output_file_path, encoding="utf-8_sig", quoting=csv.QUOTE_ALL, index=False, header=False)
return output_file_path
def upload_emp_chg_inst_data_file(self, df: pd.DataFrame, user_id: str, select_table: str) -> tuple[str, str]:
if df.shape[0] == 0:
return '該当データが存在しないためCSVファイルを出力しませんでした', ''
# ファイル名に使用するタイムスタンプを初期化しておく
current_timestamp = datetime.now()
download_file_name = f'Result_{user_id}_{current_timestamp:%Y%m%d%H%M%S%f}.csv'
# ファイルを書き出し(CSV)
local_file_path = self.__write_emp_chg_inst_data_to_file(df, download_file_name)
# ローカルファイルからS3にアップロードし、ダウンロード用URLを取得する
download_file_url = ''
try:
bucket_name = environment.MASTER_MAINTENANCE_BUCKET
file_key = f'data/{os.path.basename(local_file_path)}'
self.s3_client.upload_file(local_file_path, bucket_name, file_key)
# アップロード後、ローカルからは削除する
self.delete_local_file(local_file_path)
download_file_url = self.generate_download_file_url(local_file_path)
except Exception as e:
logger.exception(f'S3 アクセスエラー{e}')
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail={'error': 'aws_error', 'message': e.args}
)
if select_table == 'dummy':
result_msg = f'ダミーテーブルのデータ{df.shape[0]}件をCSVファイルに出力しました'
else:
result_msg = f'本番テーブルのデータ{df.shape[0]}件をCSVファイルに出力しました'
return result_msg, download_file_url
def generate_download_file_url(self, local_file_path: str) -> str:
bucket_name = environment.MASTER_MAINTENANCE_BUCKET
file_key = f'data/{os.path.basename(local_file_path)}'
return self.s3_client.generate_presigned_url(bucket_name, file_key, constants.MENTE_CSV_DOWNLOAD_FILE_NAME)
def __write_emp_chg_inst_data_to_file(self, df: pd.DataFrame, download_file_name: str) -> str:
logger.info('CSVファイルを出力する')
local_file_path = self.write_csv_file(
df, header=constants.MENTE_CSV_DOWNLOAD_HEADER, download_file_name=download_file_name)
return local_file_path
def __choose_target_table(self, select_table: str):
if select_table == 'dummy':
table_name = 'src05.emp_chg_inst_wrk'
selected_table_msg = constants.CSV_CHANGE_TABLE_NAME
elif select_table == 'real':
table_name = 'src05.emp_chg_inst'
selected_table_msg = constants.CSV_REAL_TABLE_NAME
else:
raise Exception(f'登録テーブルの選択値が不正です: {select_table}')
return (table_name, selected_table_msg)
def __make_dialog_confirm_message(self, select_function: str, selected_table_msg: str) -> str:
select_function_msg = '新規施設登録' if select_function == 'new' else '施設担当者変更'
return f'{selected_table_msg}{select_function_msg}を行いますか?'
def delete_local_file(self, local_file_path: str):
os.remove(local_file_path)

View File

@ -1,3 +1,9 @@
/* Bootstrap 5.10以降、box-sizingのデフォルト値によってテーブルがずれるため、このページ限定的にリセット */
/* @see https://bootstrap-guide.com/content/reboot#page-defaults */
table {
box-sizing: initial;
}
body{
background-color: LightCyan;
font-family : "ヒラギノ角ゴ Pro W3", "Hiragino Kaku Gothic Pro", "メイリオ", Meiryo, Osaka, " Pゴシック", "MS PGothic", sans-serif;
@ -5,6 +11,7 @@ body{
h1{
margin-left : 1%;
font-weight: 700;
}
@ -23,6 +30,10 @@ h1{
width: 20%;
}
.header_buttonSize{
width: 7rem;
font-size: initial;
}
.buttonSize{
width: 85px;
}
@ -45,6 +56,7 @@ h1{
padding-bottom: 1%;
border-bottom: solid 1px gray;
width: 94%;
border-collapse: initial;
}
.searchLabelTd{
@ -88,7 +100,7 @@ h1{
}
/*//////////////////////////*/
/*施設担当者データExcelアップロード*/
/*施設担当者データCSVアップロード*/
/*//////////////////////////*/
.inputTable{
margin-left: 3%;
@ -97,6 +109,7 @@ h1{
padding-bottom: 1%;
border-bottom: solid 1px gray;
width: 94%;
border-collapse: initial;
}
.inputLabelTd{
@ -160,5 +173,6 @@ table.inputData tbody td {
margin-bottom: 2%;
border-bottom: solid 1px gray;
width: 94%;
border-collapse: initial;
}

View File

@ -84,51 +84,54 @@ function selectDropDowList(id, selectedName){
function enableDatePicker() {
// カレンダーの表示を日曜日始まりに変更
flatpickr.l10ns.ja.firstDayOfWeek = 0;
$('.date_picker').flatpickr(
{
$(".date_picker").each(function(i, elem) {
const date_picker_name = elem.name;
flatpickr(elem, {
locale: 'ja', // 日本語カレンダー
allowInput: true, // 入力可能にする
dateFormat: 'Y/m/d' // 日付のフォーマットを修正
}
)
dateFormat: "YYYY/MM/DD", // 日付のフォーマット
onChange(_dates, currentDateString, _picker, _data) {
},
parseDate: function(strFormat, format) {
// yyyyMMddの場合→yyyy/MM/dd
const datePatternMatches = strFormat.match(/^(\d{4})(\d{2})(\d{2})$/);
if (datePatternMatches){
strFormat = `${datePatternMatches[1]}/${datePatternMatches[2]}/${datePatternMatches[3]}`;
}
// yyyy/00/00yyyy/00/00の場合→yyyy/01/01yyyy/12/31
// yyyy/MM/00yyyy/MM/01の場合→yyyy/MM/01yyyy/MM/末日
// 開始日の場合
if (date_picker_name.includes('from')){
strFormat = strFormat.replace("/00/00", "/01/01");
strFormat = strFormat.replace("/00", "/01");
}
// 終了日の場合
else if (date_picker_name.includes('to')){
strFormat = strFormat.replace("/00/00", "/12/31");
const date = new Date(strFormat.slice(0, 4), strFormat.slice(5, 7), 0).getDate();
strFormat = strFormat.replace("/00", "/"+date.toString());
}
return new Date(strFormat);
},
formatDate: (date, format) => {
// 日付の整合性チェック、不正の場合は空表示
if(isNaN(date.getDate())){
return;
}
// フォーマットを設定
const formatted = flatpickr.formatDate(date,'Y/m/d');
return formatted;
}
})
});
}
// 日付入力チェック
// 引数:チェックするテキストボックスNo
function autoModifyDate($this){
// 日付フォーマットチェック
if($this.value === "" ||
(!$this.value.match(/^\d{4}\/\d{2}\/\d{2}$/) && !$this.value.match(/^\d{4}\d{2}\d{2}$/)))
{
$this.value = "";
return;
}
/** @type { string }*/
let strFormat = $this.value;;
// yyyyMMddの場合→yyyy/MM/dd
const datePatternMatches = strFormat.match(/^(\d{4})(\d{2})(\d{2})$/);
if (datePatternMatches){
strFormat = `${datePatternMatches[1]}/${datePatternMatches[2]}/${datePatternMatches[3]}`;
}
// yyyy/00/00yyyy/00/00の場合→yyyy/01/01yyyy/12/31
// yyyy/MM/00yyyy/MM/01の場合→yyyy/MM/01yyyy/MM/末日
// 開始日の場合
if ($this.name.includes('from')){
strFormat = strFormat.replace("00/00", "01/01");
strFormat = strFormat.replace("00", "01");
}
// 終了日の場合
else if ($this.name.includes('to')){
strFormat = strFormat.replace("00/00", "12/31");
const date = new Date(strFormat.slice(0, 4), strFormat.slice(5, 7), 0).getDate();
strFormat = strFormat.replace("00", date.toString());
}
$this.value = strFormat;
}
// 前のスペースを許さない入力チェック
function checkSpaceForm($this)
{
@ -179,3 +182,66 @@ function allOff(){
$(".selected").prop("checked", false);
$(".send").prop('disabled',true);
}
// 検索結果のところのボタンをチェックが1個でも付いたら押せるようにして、チェックがなければ押せないようにする関数
// 条件:チェックボックスのクラス名に"selected"というのがついていること
// 条件:ボタンにクラス名 send がついていること
function resultBtDisablead(){
var cnt1 = $('.checkNum input:checkbox:checked').length;
console.log(cnt1);
if(cnt1 == 0) {
$(".send").prop('disabled',true);
}
else {
$(".send").prop('disabled',false);
}
}
// 数字-以外を許さない入力チェック
function checkNumberForm($this)
{
var str=$this.value;
while(str.match(/[^\d\-]/))
{
str=str.replace(/[^\d\-]/,"");
}
$this.value=str;
}
// 数字以外を許さない入力チェック
function checkNumberOnlyForm($this)
{
var str=$this.value;
while(str.match(/[^\d]/))
{
str=str.replace(/[^\d]/,"");
}
$this.value=str;
}
// メニューへボタンの関数
// 機能概要:マスターメンテメニュー画面に遷移する
function backToMainteMenu(){
sessionStorage.clear();
location.href = "/masterMainte/masterMainteMenu";
}
// 確認ダイアログ
function confirmDialog(strMesssage) {
var result = confirm(strMesssage);
return result;
}
function formInsertBtDisabled(){
var validFlg = false;
if(document.getElementById("csvFile").value === ""){
validFlg = true;
}
if (validFlg == true) {
document.getElementById("confirm").disabled = true;
}
else {
document.getElementById("confirm").disabled = false;
}
}

View File

@ -132,3 +132,123 @@ LOGOUT_REASON_MESSAGE_MAP = {
LOGOUT_REASON_DB_ERROR: 'DB接続に失敗しました。<br>再度Loginするか、<br>管理者にお問い合わせください。',
LOGOUT_REASON_UNEXPECTED: '予期しないエラーが発生しました。<br>再度Loginするか、<br>管理者に問い合わせてください。'
}
# 新規施設担当者登録CSV(マスターメンテ)
NEW_INST_EMP_CSV_LOGICAL_NAMES = [
'施設コード',
'施設名',
'領域コード',
'MUID',
'担当者名(姓)',
'担当者名(名)',
'ビジネスユニットコード',
'適用開始日',
'適用終了日'
]
# 施設コードの列No
CSV_NEW_INST_CD_COL_NO = 0
# 施設名の列No
CSV_NEW_INST_NAME_COL_NO = 1
# 領域コードの列No
CSV_NEW_TA_CD_COL_NO = 2
# MUIDの列No
CSV_NEW_EMP_CD_COL_NO = 3
# 担当者名の列No
CSV_NEW_EMP_NAME_FAMILY_COL_NO = 4
# 担当者名の列No
CSV_NEW_EMP_NAME_FIRST_COL_NO = 5
# ビジネスユニットコードの列No
CSV_NEW_BU_CD_COL_NO = 6
# 適用開始日の列No
CSV_NEW_START_DATE = 7
# 適用終了日の列No
CSV_NEW_END_DATE = 8
# 施設担当者変更登録CSV(マスターメンテ)
CHANGE_INST_CSV_LOGICAL_NAMES = [
'ビジネスユニットコード',
'ビジネスユニット名',
'組織コード',
'組織名略称',
'施設コード',
'施設名',
'領域コード',
'説明',
'MUID',
'担当者名',
'施設担当_開始日',
'施設担当_終了日',
'終了日の変更',
'コメント'
]
# ビジネスユニットコードの列No
CSV_CHANGE_BU_CD_COL_NO = 0
# ビジネスユニット名の列No
CSV_CHANGE_BU_NAME_COL_NO = 1
# 組織コードの列No
CSV_CHANGE_ORG_CD_COL_NO = 2
# 組織名略称の列No
CSV_CHANGE_ORG_SHORT_NAME_COL_NO = 3
# 施設コードの列No
CSV_CHANGE_INST_CD_COL_NO = 4
# 施設名の列No
CSV_CHANGE_INST_NAME_COL_NO = 5
# 領域コードの列No
CSV_CHANGE_TA_CD_COL_NO = 6
# 説明の列No
CSV_CHANGE_EXPLAIN_COL_NO = 7
# MUIDの列No
CSV_CHANGE_EMP_CD_COL_NO = 8
# 担当者名の列No
CSV_CHANGE_EMP_FULL_NAME_COL_NO = 9
# 施設担当_開始日の列No
CSV_CHANGE_INST_EMP_START_DATE_COL_NO = 10
# 施設担当_終了日の列No
CSV_CHANGE_INST_EMP_END_DATE_COL_NO = 11
# 終了日の変更の列No
CSV_CHANGE_CHANGE_END_DATE_COL_NO = 12
# コメントの列No
CSV_CHANGE_COMMENT = 13
# CSVアップロードテーブル名(マスターメンテ)
CSV_REAL_TABLE_NAME = '本番テーブル'
CSV_CHANGE_TABLE_NAME = 'ダミーテーブル'
MENTE_CSV_TEMPORARY_FILE_DIR_PATH = path.join(path.curdir, 'src', 'data')
MENTE_CSV_DOWNLOAD_EXTRACT_COLUMNS = [
'inst_cd',
'inst_name',
'ta_cd',
'emp_cd',
'emp_name_full',
'bu_cd',
'bu_name',
'start_date',
'end_date',
'creater',
'create_date',
'updater',
'update_date'
]
MENTE_CSV_DOWNLOAD_HEADER = [
'施設コード',
'施設名',
'領域コード',
'MUID',
'担当者名',
'ビジネスユニットコード',
'ビジネスユニット名',
'適用開始日',
'適用終了日',
'作成者',
'作成日',
'更新者',
'更新日'
]
MENTE_CSV_DOWNLOAD_FILE_NAME = 'instEmpData.csv'
# CSVアップロードの制限サイズ100MB
MENTE_CSV_UPLOAD_MAX_FILE_SIZE_BYTE = 104857600

View File

@ -11,6 +11,7 @@ COGNITO_CLIENT_SECRET = os.environ['COGNITO_CLIENT_SECRET']
AWS_REGION = os.environ['AWS_REGION']
SESSION_TABLE_NAME = os.environ['SESSION_TABLE_NAME']
BIO_ACCESS_LOG_BUCKET = os.environ['BIO_ACCESS_LOG_BUCKET']
MASTER_MAINTENANCE_BUCKET = os.environ['MASTER_MAINTENANCE_BUCKET']
DB_HOST = os.environ['DB_HOST']
DB_PORT = int(os.environ['DB_PORT'])

View File

@ -1,12 +1,187 @@
<!DOCTYPE html>
<html lang="ja">
<head>
{% with subtitle = view.subtitle %}
{% with subtitle = mainte_csv_dl.subtitle %}
{% include '_header.html' %}
{% endwith %}
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link href="/static/css/masterMainte.css" rel="stylesheet" />
<script type="text/javascript">
window.onload = function(){
// ボタン、テキストボックス初期化
formBtDisabled();
// DatePickerを有効化
enableDatePicker();
{% if mainte_csv_dl.is_search and mainte_csv_dl.data_count > 0 and mainte_csv_dl.is_download_file_url_empty() is false %}
// CSV自動ダウンロード処理
var link_tag = document.createElement("a");
link_tag.Target="_blank";
link_tag.id = "download_url_link";
link_tag.style.display = 'none';
link_tag.setAttribute("href", "{{mainte_csv_dl.download_file_url | safe}}");
link_tag.setAttribute("download", "{{mainte_csv_dl.file_name}}");
document.getElementById("notification").appendChild(link_tag);
document.getElementById("download_url_link").click();
document.getElementById("download_url_link").remove();
{% endif %}
};
function Form_Submit_Disp_Dialog(){
var msg = 'CSVファイルを出力しますか';
if (confirmDialog(msg)) {
document.getElementById("loading").style.display = "block";
document.getElementById("csvOutputMsg").style.display = "none";
} else {
return false;
}
}
</script>
</head>
<body>
<h1>施設担当者データCSVダウンロード</h1>
<!-- タイトルと上部ボタン -->
<h1>
<table class="headerTable">
<tr>
<td class="headerTdLeft"><h1>施設担当者データCSVダウンロード</h1></td>
<td class="headerTdRight"><input type="button" name="back" class="header_buttonSize" value="メニューへ" onclick="backToMainteMenu()"></td>
</tr>
</table>
</h1>
<!-- 検索フォーム -->
<form name="search" action="/masterMainte/download" method="POST" onsubmit="return Form_Submit_Disp_Dialog()">
<table class="searchTable">
<tbody>
<!-- 検索フォーム1行目 -->
<tr>
<!-- 領域コード -->
<td class="searchLabelTd">領域コード:</td>
<td class="searchInputTd">
<input class="searchTextbox" type="text" name="ctrl_ta_cd" value="{{mainte_csv_dl.ta_cd | safe}}" maxlength='3'
onchange="formBtDisabled()"
oninput="formBtDisabled()"
>
</td>
<!-- 施設コード -->
<td class="searchLabelTd">施設コード:</td>
<td class="searchInputTd">
<input class="searchTextbox" type="text" name="ctrl_inst_cd" value="{{mainte_csv_dl.inst_cd | safe}}" maxlength='18'
onchange="formBtDisabled()"
oninput="formBtDisabled()"
>
</td>
<!-- MUID -->
<td class="searchLabelTd">MUID</td>
<td class="searchInputTd">
<input class="searchTextbox" type="text" name="ctrl_emp_cd" value="{{mainte_csv_dl.emp_cd | safe}}" maxlength='10'
onchange="formBtDisabled()"
oninput="formBtDisabled()"
>
</td>
</tr>
<!-- 検索フォーム2行目 -->
<tr>
<!-- 適用期間内 -->
<td class="searchLabelTd">適用期間内:</td>
<td class="searchInputTd">
<input class="searchTextbox date_picker" type="text" name="ctrl_apply_date_from" value="{{mainte_csv_dl.apply_date_from | safe}}" maxlength='10'
onchange="formBtDisabled()"
oninput="formBtDisabled()"
>
</td>
<td class="searchLabelTd">適用開始日:</td>
<!-- 適用開始日 -->
<td class="searchInputTd">
<input class="searchDateTextbox date_picker" type="text" name="ctrl_start_date_from" value="{{mainte_csv_dl.start_date_from | safe}}" maxlength='10'
onchange="formBtDisabled()"
oninput="formBtDisabled()"
>
<input class="searchDateTextbox date_picker" type="text" name="ctrl_start_date_to" value="{{mainte_csv_dl.start_date_to | safe}}" maxlength='10'
onchange="formBtDisabled()"
oninput="formBtDisabled()"
>
</td>
<!-- 適用終了日 -->
<td class="searchLabelTd">適用終了日:</td>
<td class="searchInputTd">
<input class="searchDateTextbox date_picker" type="text" name="ctrl_end_date_from" value="{{mainte_csv_dl.end_date_from | safe}}" maxlength='10'
onchange="formBtDisabled()"
oninput="formBtDisabled()"
>
<input class="searchDateTextbox date_picker" type="text" name="ctrl_end_date_to" value="{{mainte_csv_dl.end_date_to | safe}}" maxlength='10'
onchange="formBtDisabled()"
oninput="formBtDisabled()"
>
</td>
</tr>
<!-- 検索フォーム3行目 -->
<tr>
<!-- 対象テーブル -->
<td class="searchLabelTd">対象テーブル:</td>
<td class="searchInputTd">
<label>
<input type="radio" name="radio_select_table" value="dummy"
{{ "checked " if mainte_csv_dl.select_table == 'dummy' or mainte_csv_dl.is_select_table_empty() }}
>ダミーテーブル
</label>
<label>
<input type="radio" name="radio_select_table" value="real"
{{ "checked " if mainte_csv_dl.select_table == 'real' }}
>本番テーブル
</label>
</td>
<!-- データ作成日 -->
<td class="searchLabelTd">データ作成日:</td>
<td class="search_tb">
<input class="searchDateTextbox date_picker" type="text" name="ctrl_create_date_from" value="{{mainte_csv_dl.create_date_from | safe}}" maxlength='10'
onchange="formBtDisabled()"
oninput="formBtDisabled()"
>
<input class="searchDateTextbox date_picker" type="text" name="ctrl_create_date_to" value="{{mainte_csv_dl.create_date_to | safe}}" maxlength='10'
onchange="formBtDisabled()"
oninput="formBtDisabled()"
>
</td>
<!-- データ更新日 -->
<td class="searchLabelTd">データ更新日:</td>
<td class="searchInputTd">
<input class="searchDateTextbox date_picker" type="text" name="ctrl_update_date_from" value="{{mainte_csv_dl.update_date_from | safe}}" maxlength='10'
onchange="formBtDisabled()"
oninput="formBtDisabled()"
>
<input class="searchDateTextbox date_picker" type="text" name="ctrl_update_date_to" value="{{mainte_csv_dl.update_date_to | safe}}" maxlength='10'
onchange="formBtDisabled()"
oninput="formBtDisabled()"
>
</td>
</tr>
<!-- 検索フォーム4行目 -->
<tr>
<!-- 検索、クリアボタン -->
<td class="searchButtonTd" colspan="6">
<input class="buttonSize" id="clear" type="button" name="clear_bt" value="クリア" onclick="clr();">
<input class="buttonSize" id="search_bt" name="search_bt" value="CSV出力" type="submit">
</td>
</tr>
</tbody>
</table>
</form>
<p id="notification">
{% if mainte_csv_dl.is_search %}
{% if mainte_csv_dl.data_count == 0 %}
<div id="csvOutputMsg" class="csvOutputMessage errorColor">{{mainte_csv_dl.result_msg}}</div>
{% else %}
<div id="csvOutputMsg" class="csvOutputMessage">{{mainte_csv_dl.result_msg}}</div>
{% endif %}
{% endif %}
<div id="loading" class="csvOutputMessage" style="display:none;">
<p>処理中...<br>しばらくお待ち下さい。</p>
</div>
</p>
</body>
</html>

View File

@ -1,13 +1,207 @@
<!DOCTYPE html>
<html lang="ja">
<head>
{% with subtitle = view.subtitle %}
{% with subtitle = mainte_csv_up.subtitle %}
{% include '_header.html' %}
{% endwith %}
<!-- TODO: CSS変える -->
<link href="/static/css/masterMainte.css" rel="stylesheet" />
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script type="text/javascript">
window.onload = function(){
{% if mainte_csv_up.is_insert %}
sessionStorage.clear();
{% else %}
if (sessionStorage["ctrl_select_function"]) {
var element = document.getElementById("upload_form");
if (sessionStorage["ctrl_select_function"] === "new") {
element.function_new.checked = true;
}
else if (sessionStorage["ctrl_select_function"] === "change") {
element.function_change.checked = true;
}
}
if (sessionStorage["ctrl_select_table"]) {
var element = document.getElementById("upload_form");
if (sessionStorage["ctrl_select_table"] === "dummy") {
element.dummy_table.checked = true;
}
else if (sessionStorage["ctrl_select_table"] === "real") {
element.real_table.checked = true;
}
}
{% endif %}
}
function Form_Submit(){
sessionStorage.clear();
var element = document.getElementById("upload_form")
sessionStorage.setItem("ctrl_select_function", element.ctrl_select_function.value);
sessionStorage.setItem("ctrl_select_table", element.ctrl_select_table.value);
document.getElementById("loading").style.display = "block";
if (document.getElementById("ulMsg") !== null) {
document.getElementById("ulMsg").style.display = "none";
}
}
function Form_Submit_Disp_Dialog(){
var msg = '{{ mainte_csv_up.select_function_message }}';
if (confirmDialog(msg)) {
document.getElementById("loading").style.display = "block";
if (document.getElementById("ulMsg") !== null) {
document.getElementById("ulMsg").style.display = "none";
}
} else {
return false;
}
}
</script>
</head>
<body>
<h1>施設担当者データCSVアップロード</h1>
<!-- タイトルと上部ボタン -->
<h1>
<table class="headerTable">
<tr>
<td class="headerTdLeft"><h1>施設担当者データCSVアップロード</h1></td>
<td class="headerTdRight">
{% if mainte_csv_up.is_verified and mainte_csv_up.is_error_message_list_empty() %}
<input type="button" class="header_buttonSize" onclick="location.href='/masterMainte/instEmpCsvUL' " value="戻る">
{% else %}
<input type="button" class="header_buttonSize" onclick="backToMainteMenu()" value="メニューへ" />
{% endif %}
</td>
</tr>
</table>
</h1>
<!-- 選択フォーム -->
<form name="input" action="{% if mainte_csv_up.is_verified and mainte_csv_up.is_error_message_list_empty() %}/masterMainte/newInst{% else %}/masterMainte/instEmpCsvUL{% endif %}"
method="POST" enctype="multipart/form-data"
{% if mainte_csv_up.is_verified and mainte_csv_up.is_error_message_list_empty() %}
onsubmit="return Form_Submit_Disp_Dialog();"
{% else %}
onsubmit="Form_Submit();"
{% endif %}
id="upload_form"
>
<table class="inputTable">
<tbody>
<!-- 選択フォーム1行目 -->
<tr>
<!-- 機能 -->
<td class="inputLabelTd">機能:</td>
<td class="inputTd">
<label>
<input type="radio" name="ctrl_select_function" value="new" id="function_new"
{{ "checked " if mainte_csv_up.select_function == 'new' or mainte_csv_up.is_select_function_empty() }}
{{ "disabled" if mainte_csv_up.is_verified and mainte_csv_up.is_error_message_list_empty() }}
>
新規施設登録
</label>
</td>
<td class="inputTd">
<label>
<input type="radio" name="ctrl_select_function" value="change" id="function_change"
{{ "checked " if mainte_csv_up.select_function == 'change' }}
{{ "disabled" if mainte_csv_up.is_verified and mainte_csv_up.is_error_message_list_empty() }}
>
施設担当者変更
</label>
</td>
</tr>
<!-- 選択フォーム2行目 -->
<tr>
<!-- 登録テーブル -->
<td class="inputLabelTd">登録テーブル:</td>
<td class="inputTd">
<label>
<input type="radio" name="ctrl_select_table" value="dummy" id="dummy_table"
{{ "checked " if mainte_csv_up.select_table == 'dummy' or mainte_csv_up.is_select_table_empty() }}
{{ "disabled" if mainte_csv_up.is_verified and mainte_csv_up.is_error_message_list_empty() }}
>
ダミーテーブル
</label>
</td>
<td class="inputTd">
<label>
<input type="radio" name="ctrl_select_table" value="real" id="real_table"
{{ "checked " if mainte_csv_up.select_table == 'real' }}
{{ "disabled" if mainte_csv_up.is_verified and mainte_csv_up.is_error_message_list_empty() }}
>
本番テーブル
</label>
</td>
</tr>
<!-- 選択フォーム3行目 -->
<tr>
<!-- 登録CSV -->
<td class="inputLabelTd">登録CSV</td>
<td class="input_tb" colspan="2">
{% if mainte_csv_up.is_verified and mainte_csv_up.is_error_message_list_empty() %}
{{mainte_csv_up.csv_file_name}}
{% else %}
<input type="file" id="csvFile" size="50" name="ctrl_csv_file" accept=".csv" onchange="formInsertBtDisabled()">
{% endif %}
</td>
<!-- ボタン -->
<td class="inputButtonTd">
{% if mainte_csv_up.is_verified and mainte_csv_up.is_error_message_list_empty() and mainte_csv_up.select_table == 'real' %}
<input name="btName" value="insert_bt" type="hidden">
<div class="errorColor">本番テーブルが選択されています<input class="buttonSize" id="insert" name="insert_bt" value="登録" type="submit" ></div>
{% elif mainte_csv_up.is_verified and mainte_csv_up.is_error_message_list_empty() and mainte_csv_up.select_table == 'dummy' %}
<input name="btName" value="insert_bt" type="hidden">
<input class="buttonSize" id="insert" name="insert_bt" value="登録" type="submit">
{% else %}
<input name="btName" value="input_bt" type="hidden">
<input class="buttonSize" id="confirm" name="input_bt" value="確認" type="submit" disabled>
{% endif %}
</td>
</tr>
</tbody>
</table>
{% if mainte_csv_up.is_verified and mainte_csv_up.is_error_message_list_empty() %}
<input name="ctrl_json_upload_data" value="{{mainte_csv_up.json_upload_data}}" type="hidden">
<input name="ctrl_select_function" value="{{mainte_csv_up.select_function}}" type="hidden">
<input name="ctrl_select_table" value="{{mainte_csv_up.select_table}}" type="hidden">
{% endif %}
</form>
<p>
<!-- 処理中メッセージ表示 -->
<div id="loading" class="csvOutputMessage" style="display:none;">
<p>処理中...<br>しばらくお待ち下さい。</p>
</div>
{% if not mainte_csv_up.is_error_message_list_empty() %}
<div id="ulMsg" class="footerMsg errorColor">
{% for error_message in mainte_csv_up.error_message_list %}
{{error_message}}<br>
{% endfor %}
</div>
{% elif mainte_csv_up.is_verified and mainte_csv_up.is_error_message_list_empty() %}
<div id="ulMsg">
<div class="dataCntDisp">件数:{{mainte_csv_up.csv_data_count()}}件</div>
<!-- 登録されるデータのリスト -->
<table class="inputData">
<tbody>
<tr>
{% for column_name in mainte_csv_up.upload_data_columns() %}
<th>{{column_name}}</th>
{% endfor %}
</tr>
{% for item in mainte_csv_up.csv_upload_list %}
<tr>
{% for key, value in item.items() %}
<td>{{value}}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% elif mainte_csv_up.is_insert %}
<div id="ulMsg" class="footerMsg">
{% for message in mainte_csv_up.result_message_list %}
{{ message }}<br>
{% endfor %}
</div>
{% endif %}
</p>
</body>
</html>

View File

@ -9,7 +9,7 @@
<div class="container-fluid text-center background">
<h1>MeDaCA<br/>マスターメンテメニュー</h1>
<br><br>
<!-- 施設担当者データExcelアップロード -->
<!-- 施設担当者データCSVアップロード -->
<a href="/masterMainte/instEmpCsvUL" class="btn btn-primary btn-lg btn_width">施設担当者データCSVアップロード</a><br><br>
<!-- 施設担当者データCSVダウンロード -->

View File

@ -1,12 +1,61 @@
<!DOCTYPE html>
<html lang="ja">
<head>
{% with subtitle = view.subtitle %}
{% with subtitle = table_override.subtitle %}
{% include '_header.html' %}
{% endwith %}
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link href="/static/css/masterMainte.css" rel="stylesheet" />
<script type="text/javascript">
function Form_Submit_Disp_Dialog(){
var msg = "ダミー従業員担当施設マスタのデータがすべて上書きされます。よろしいですか?"
if (confirmDialog(msg)) {
document.getElementById("loading").style.display = "block";
document.getElementById("overRided").style.display = "none";
} else {
return false;
}
}
</script>
</head>
<body>
<h1>テーブル上書きコピー</h1>
<!-- タイトルと上部ボタン -->
<h1>
<table class="headerTable">
<tr>
<td class="headerTdLeft"><h1>テーブル上書きコピー</h1></td>
<td class="headerTdRight"><input type="button" name="back" class="header_buttonSize" value="メニューへ" onclick="backToMainteMenu()"></td>
</tr>
</table>
</h1>
<!-- ダミーテーブルを本番テーブルで上書き機能 -->
<table class="tableOverRide">
<tr>
<td>
<label>
<input type="radio" name="selectTable" value="empChgInstRealToDummy" checked >
本番 従業員担当施設マスタ ⇒ ダミー 従業員担当施設マスタ
</label>
</td>
</tr>
<tr>
<td></td>
<td>
<form name="overRide" action="/masterMainte/tableOverride" method="POST" onsubmit="return Form_Submit_Disp_Dialog();">
<input type="submit" name="overRide_bt" class="header_buttonSize" value="データ上書" >
</form>
</td>
</tr>
</table>
{% if table_override.is_override %}
<p>
<div id="overRided" class="csvOutputMessage">ダミー従業員担当施設マスタのデータを本番従業員担当施設マスタのデータで上書きしました</div>
</p>
{% endif %}
<div id="loading" class="csvOutputMessage" style="display:none;">
<p>データ上書き中...<br>しばらくお待ち下さい。</p>
</div>
</body>
</html>