feat: 休日判定諸々

This commit is contained in:
shimoda.m@nds-tyo.co.jp 2023-04-14 17:42:02 +09:00
parent e36285c6f2
commit d3d385c214
15 changed files with 218 additions and 66 deletions

View File

@ -8,3 +8,6 @@ ULTMARC_DATA_BUCKET=****************
ULTMARC_DATA_FOLDER=recv
ULTMARC_BACKUP_BUCKET=****************
ULTMARC_BACKUP_FOLDER=ultmarc
JSKULT_CONFIG_BUCKET=**********************
JSKULT_CONFIG_CALENDAR_FOLDER=jskult/calendar
JSKULT_CONFIG_HOLIDAY_LIST_FILE_NAME=jskult_holiday_list.txt

View File

@ -76,6 +76,20 @@ class UltmarcBucket(S3Bucket):
self._s3_client.delete_file(self._bucket_name, dat_file_key)
class ConfigBucket(S3Bucket):
_bucket_name = environment.JSKULT_CONFIG_BUCKET
def download_holiday_list(self):
# 一時ファイルとして保存する
temporary_dir = tempfile.mkdtemp()
temporary_file_path = path.join(temporary_dir, environment.JSKULT_CONFIG_HOLIDAY_LIST_FILE_NAME)
holiday_list_key = f'{environment.JSKULT_CONFIG_CALENDAR_FOLDER}/{environment.JSKULT_CONFIG_HOLIDAY_LIST_FILE_NAME}'
with open(temporary_file_path, mode='wb') as f:
self._s3_client.download_file(self._bucket_name, holiday_list_key, f)
f.seek(0)
return temporary_file_path
class JskUltBackupBucket(S3Bucket):
_bucket_name = environment.ULTMARC_BACKUP_BUCKET

View File

@ -1,10 +0,0 @@
class BatchConfig:
# 処理日(yyyy/mm/dd形式)
syor_date: str
__instance = None
@classmethod
def get_instance(cls):
if cls.__instance is None:
cls.__instance = cls()
return cls.__instance

View File

@ -0,0 +1,39 @@
class BatchContext:
__instance = None
__syor_date: str # 処理日(yyyy/mm/dd形式)
__is_not_business_day: bool # 日次バッチ起動日フラグ
__is_ultmarc_imported: bool # アルトマーク取込実施済フラグ
def __init__(self) -> None:
self.__is_not_business_day = False
self.__is_ultmarc_imported = False
@classmethod
def get_instance(cls):
if cls.__instance is None:
cls.__instance = cls()
return cls.__instance
@property
def syor_date(self):
return self.__syor_date
@syor_date.setter
def syor_date(self, syor_date_str: str):
self.__syor_date = syor_date_str
@property
def is_not_business_day(self):
return self.__is_not_business_day
@is_not_business_day.setter
def is_not_business_day(self, flag: bool):
self.__is_not_business_day = flag
@property
def is_ultmarc_imported(self):
return self.__is_ultmarc_imported
@is_ultmarc_imported.setter
def is_ultmarc_imported(self, flag: bool):
self.__is_ultmarc_imported = flag

View File

@ -0,0 +1,32 @@
from src.system_var import constants
class CalendarFile:
"""カレンダーファイル"""
__calendar_file_lines: list[str]
def __init__(self, calendar_file_path):
with open(calendar_file_path) as f:
self.__calendar_file_lines: list[str] = f.readlines()
def compare_date(self, date_str: str) -> bool:
"""与えられた日付がカレンダーファイル内に含まれているかどうか
カレンダーファイル内の日付はyyyy/mm/ddで書かれている前提
コメント#)が含まれている行は無視される
Args:
date_str (str): yyyy/mm/dd文字列
Returns:
bool: 含まれていればTrue
"""
for calendar_date in self.__calendar_file_lines:
# コメント行が含まれている場合はスキップ
if constants.CALENDAR_COMMENT_SYMBOL in calendar_date:
continue
if date_str in calendar_date:
return True
return False

View File

@ -1,12 +1,12 @@
from src.batch.batch_functions import logging_sql
from src.batch.common.batch_config import BatchConfig
from src.batch.common.batch_context import BatchContext
from src.db.database import Database
from src.error.exceptions import BatchOperationException
from src.logging.get_logger import get_logger
from src.time.elapsed_time import ElapsedTime
logger = get_logger('48-施設担当者マスタ洗替')
batch_config = BatchConfig.get_instance()
batch_context = BatchContext.get_instance()
def exec():
@ -15,7 +15,7 @@ def exec():
logger.info('##########################')
logger.info('START Changing Employee in charge of institution PGM.')
# 業務日付を取得
syor_date = batch_config.syor_date
syor_date = batch_context.syor_date
# `emp_chg_inst_lau`をTruncate
truncate_emp_chg_inst_lau(db)
# emp_chg_inst から、`emp_chg_inst_lau`へInsert

View File

@ -0,0 +1,3 @@
def exec():
"""メルク施設マスタ作成"""
pass

View File

@ -1,17 +1,20 @@
"""アルトマークデータ保管"""
"""アルトマークデータ処理"""
from datetime import datetime
from src.aws.s3 import UltmarcBucket
from src.batch.common.batch_config import BatchConfig
from src.batch.common.batch_context import BatchContext
from src.batch.ultmarc.datfile import DatFile
from src.batch.ultmarc.utmp_tables.ultmarc_table_mapper_factory import \
UltmarcTableMapperFactory
from src.db.database import Database
from src.error.exceptions import BatchOperationException
from src.logging.get_logger import get_logger
from src.system_var import constants
logger = get_logger('アルトマークデータ保管')
logger = get_logger('アルトマークデータ処理')
ultmarc_bucket = UltmarcBucket()
batch_config = BatchConfig.get_instance()
batch_context = BatchContext.get_instance()
def exec_import():
@ -23,13 +26,16 @@ def exec_import():
# ファイルがない場合は処理せず、正常終了とする
if len(dat_file_list) == 0:
logger.info('ファイルがないため、アルトマーク取込処理をスキップします')
logger.info('取込ファイルがないため、アルトマーク取込処理をスキップします')
# アルトマークデータ受信予定曜日である月曜日は、保守ユーザーに通知する
if datetime.strptime(batch_context.syor_date, '%Y/%m/%d').weekday() == constants.WEEKDAY_MONDAY:
logger.info('[NOTICE]アルトマークデータの受信がありませんでした')
return
# ファイルが複数ある場合はエラーとする
if len(dat_file_list) > 1:
logger.error(f'複数の取込ファイルがあるため、異常終了 ファイル一覧:{dat_file_list}')
return
raise BatchOperationException()
# ファイルの件数は必ず1件になる
dat_file_info = dat_file_list[0]
@ -42,7 +48,7 @@ def exec_import():
logger.info(f"{dat_file_name}を取り込みます")
# ファイルをバックアップ
# 現行は、jobctrl_dailyの先頭でやっている
ultmarc_bucket.backup_dat_file(dat_file_name, batch_config.syor_date)
ultmarc_bucket.backup_dat_file(dat_file_name, batch_context.syor_date)
# datファイルをダウンロード
local_file_path = ultmarc_bucket.download_dat_file(dat_file_name)
dat_file = DatFile.from_path(local_file_path)
@ -51,11 +57,18 @@ def exec_import():
# 処理後、ファイルをS3から削除する
logger.info(f'取り込み処理が完了したため、datファイルを削除。ファイル名={dat_file_name}')
ultmarc_bucket.delete_dat_file(dat_file_name)
# アルトマーク取込済をマーク
batch_context.is_ultmarc_imported = True
logger.info('アルトマーク取込処理: 終了')
except Exception as e:
logger.exception(e)
raise BatchOperationException(e)
finally:
logger.info('アルトマーク取込処理: 終了')
def exec_export():
# 取り込み日に限らず、毎日実行する
"""V実消化用施設・薬局薬店データ作成処理"""
pass
def _import_to_ultmarc_table(dat_file: DatFile):

View File

@ -1,12 +1,12 @@
from abc import ABCMeta, abstractmethod
from datetime import datetime
from src.batch.common.batch_config import BatchConfig
from src.batch.common.batch_context import BatchContext
from src.batch.ultmarc.utmp_tables.tables.ultmarc_table import UltmarcTable
from src.db.database import Database
# 処理日を使用するために、configを使用
batch_config = BatchConfig.get_instance()
batch_context = BatchContext.get_instance()
class UltmarcTableMapper(metaclass=ABCMeta):
@ -32,7 +32,7 @@ class UltmarcTableMapper(metaclass=ABCMeta):
'execute_date_str_ymd': execute_date_str_ymd,
'execute_datetime': execute_datetime,
# バッチ共通設定から処理日を取得
'syor_date': batch_config.syor_date
'syor_date': batch_context.syor_date
}
@abstractmethod

View File

@ -1,9 +1,11 @@
"""実消化&アルトマーク 日次バッチ処理"""
from src.aws.s3 import ConfigBucket
from src.batch.batch_functions import (
get_batch_statuses, update_batch_process_complete,
update_batch_processing_flag_in_processing)
from src.batch.common.batch_config import BatchConfig
from src.batch.common.batch_context import BatchContext
from src.batch.common.calendar_file import CalendarFile
from src.batch.laundering import sales_laundering
from src.batch.ultmarc import ultmarc_process
from src.error.exceptions import BatchOperationException
@ -13,7 +15,7 @@ from src.system_var import constants
logger = get_logger('日次処理コントロール')
# バッチ共通設定を取得
batch_config = BatchConfig.get_instance()
batch_context = BatchContext.get_instance()
def exec():
@ -32,13 +34,34 @@ def exec():
return constants.BATCH_EXIT_CODE_SUCCESS
# dump取得が正常終了していない場合、後続の処理は行わない
if dump_status_kbn != constants.DUMP_STATUS_KBN_COMPLETE:
if dump_status_kbn != constants.DUMP_STATUS_KBN_COMPLETE and dump_status_kbn != constants.DUMP_STATUS_KBN_DUMP_SKIP:
logger.error('dump取得が正常終了していないため、日次バッチ処理を終了します。')
return constants.BATCH_EXIT_CODE_SUCCESS # TODO: エラーで返せば、StepFunctionsでリトライしてくれるので、どう返すかは要検討
logger.info(f'処理日={syor_date}')
# バッチ共通設定に処理日を追加
batch_config.syor_date = syor_date
batch_context.syor_date = syor_date
# 稼働日かかどうかを設定
# 非営業日ファイルをダウンロードして判定
holiday_list_file_path = ConfigBucket().download_holiday_list()
holiday_calendar = CalendarFile(holiday_list_file_path)
# 非稼働日かどうかを設定
batch_context.is_not_business_day = not holiday_calendar.compare_date(syor_date)
# for row in io.TextIOWrapper(io.BytesIO(non_business_day_response["Body"].read()), encoding='utf-8'):
# if row[INDEX_ROW_COMMENT_SYMBOL] == ROW_COMMENT_SYMBOL:
# continue
# non_date = row.rstrip('\n')
# # 日付妥当性判定
# try:
# datetime.datetime.strptime(non_date, "%Y/%m/%d")
# except Exception as e:
# raise e
# none_business_day_list.append(non_date)
# if execute_date in none_business_day_list:
# logger.info('I-02-05 本日は非営業日のため、チェック処理をスキップします')
# return
# バッチ処理中に更新
try:
@ -84,29 +107,42 @@ def exec():
# except BatchOperationException as e:
# logger.error(f'卸在庫データ取込処理エラー(異常終了){e}')
logger.info('日次処理(アルトマーク)')
if True: # アルトマーク取り込み処理内で実装
logger.info('日次処理(アルトマーク)実行対象日でない為未実行')
# if True: # アルトマーク取り込み処理内で実装
# logger.info('日次処理(アルトマーク)実行対象日でない為未実行')
try:
logger.info('アルトマーク取込:起動')
ultmarc_process.exec_import()
logger.info('アルトマーク取込:終了')
except BatchOperationException as e:
logger.error(f'アルトマーク取込処理エラー(異常終了){e}')
logger.exception(f'アルトマーク取込処理エラー(異常終了){e}')
return constants.BATCH_EXIT_CODE_SUCCESS
if True: # 休日判定、メルク施設マスタ作成内で行いたい
try:
logger.info('メルク施設マスタ作成')
logger.info('メルク施設マスタ作成終了')
except BatchOperationException as e:
logger.error(f'メルク施設マスタ作成エラー(異常終了){e}')
return constants.BATCH_EXIT_CODE_SUCCESS
try:
logger.info('DCF施設統合マスタ作成')
logger.info('DCF施設統合マスタ作成終了')
except BatchOperationException as e:
logger.error(f'DCF施設統合マスタ作成エラー異常終了{e}')
return constants.BATCH_EXIT_CODE_SUCCESS
# if False: # ($holiday === FALSE) # DCF施設統合マスタを作成する日は必ず休日なので、V実消化の取り込みは行わない。
try:
logger.info('V実消化用施設・薬局薬店データ作成処理起動')
ultmarc_process.exec_export()
logger.info('V実消化用施設・薬局薬店データ作成処理終了')
except BatchOperationException as e:
logger.exception(f'V実消化用施設・薬局薬店データ作成処理エラー異常終了{e}')
return constants.BATCH_EXIT_CODE_SUCCESS
# TODO: 現行では休日も、メルク施設マスタと施設統合マスタの作成を行っている。
# 実績洗い替えの中でもメルク施設マスタと施設統合マスタの作成は行っているが、他の処理は動かしたくない。
# つまり、休日だったら、メルク施設マスタと施設統合マスタ以外の作成は行わない、とすれば、シンプルになる?
# if True: # 休日判定、メルク施設マスタ作成内で行いたい
# try:
# logger.info('メルク施設マスタ作成')
# logger.info('メルク施設マスタ作成終了')
# except BatchOperationException as e:
# logger.error(f'メルク施設マスタ作成エラー(異常終了){e}')
# return constants.BATCH_EXIT_CODE_SUCCESS
# try:
# logger.info('DCF施設統合マスタ作成')
# logger.info('DCF施設統合マスタ作成終了')
# except BatchOperationException as e:
# logger.error(f'DCF施設統合マスタ作成エラー異常終了{e}')
# return constants.BATCH_EXIT_CODE_SUCCESS
# if False: # ($holiday === FALSE) # V実消化非稼働日は、V実消化の取り込みは行わない。
# TODO: データ存在確認は実消化取り込み内で行う
# logger.info('V実消化連携データ存在確認')
# if True:
@ -120,8 +156,18 @@ def exec():
logger.exception(f'V実消化取込処理エラー異常終了{e}')
return constants.BATCH_EXIT_CODE_SUCCESS
# 非稼働日や、月火水に限らず、必ず実施
logger.info('メルク施設マスタ作成')
try:
logger.info('メルク施設マスタ作成:起動')
logger.info('メルク施設マスタ作成:終了')
except BatchOperationException as e:
logger.exception(f'メルク施設マスタ作成 エラー(異常終了){e}')
return constants.BATCH_EXIT_CODE_SUCCESS
logger.info('日次処理(実績更新)')
# ここも、休日判定を内側で行う
# ここも、休日判定を実績更新内で行う
# 休日であっても、施設統合マスタの作成だけは行う。
try:
# ここで、生物由来ロット分解と並行処理
logger.info('実績更新:起動')
@ -140,7 +186,8 @@ def exec():
logger.exception(f'日次バッチ完了処理 エラー(異常終了){e}')
return constants.BATCH_EXIT_CODE_SUCCESS
logger.info('日次ジョブ:終了(正常終了)')
# 正常終了を保守ユーザーに通知
logger.info('[NOTICE]日次ジョブ:終了(正常終了)')
return constants.BATCH_EXIT_CODE_SUCCESS
except Exception as e:
logger.exception(f'日次バッチ処理中に想定外のエラーが発生しました {e}')

View File

@ -9,3 +9,11 @@ BATCH_ACTF_BATCH_IN_PROCESSING = '1'
DUMP_STATUS_KBN_UNPROCESSED = '0'
# dump取得状態区分dump取得正常終了
DUMP_STATUS_KBN_COMPLETE = '2'
# dump取得状態区分dump取得スキップ
DUMP_STATUS_KBN_DUMP_SKIP = '3'
# カレンダーファイルのコメントシンボル
CALENDAR_COMMENT_SYMBOL = '#'
# 月曜日(datetime.weekday()で月曜日を表す数字)
WEEKDAY_MONDAY = 0

View File

@ -12,6 +12,9 @@ ULTMARC_DATA_BUCKET = os.environ['ULTMARC_DATA_BUCKET']
ULTMARC_DATA_FOLDER = os.environ['ULTMARC_DATA_FOLDER']
ULTMARC_BACKUP_BUCKET = os.environ['ULTMARC_BACKUP_BUCKET']
ULTMARC_BACKUP_FOLDER = os.environ['ULTMARC_BACKUP_FOLDER']
JSKULT_CONFIG_BUCKET = os.environ['JSKULT_CONFIG_BUCKET']
JSKULT_CONFIG_CALENDAR_FOLDER = os.environ['JSKULT_CONFIG_CALENDAR_FOLDER']
JSKULT_CONFIG_HOLIDAY_LIST_FILE_NAME = os.environ['JSKULT_CONFIG_HOLIDAY_LIST_FILE_NAME']
# 初期値がある環境変数
LOG_LEVEL = os.environ.get('LOG_LEVEL', 'INFO')

View File

@ -3,7 +3,7 @@ from datetime import datetime
import pytest
from src.batch.common.batch_config import BatchConfig
from src.batch.common.batch_context import BatchContext
from src.batch.ultmarc.utmp_tables.table_mapper.concrete import com_alma_mapper
from src.db.database import Database
from tests.testing_utility import (assert_table_results,
@ -18,13 +18,13 @@ class TestComAlmaMapper:
"""レイアウト区分004: COM_出身校"""
db: Database
batch_config: BatchConfig
batch_context: BatchContext
test_file_path: str = path.dirname(__file__)
@pytest.fixture(autouse=True, scope='function')
def pre_test(self, database: Database):
"""テスト実行前後処理"""
self.batch_config = BatchConfig.get_instance()
self.batch_context = BatchContext.get_instance()
# setup
self.db = database
self.db.connect()
@ -50,7 +50,7 @@ class TestComAlmaMapper:
# Arrange
# 処理日設定
self.batch_config.syor_date = datetime.strftime(datetime.now(), '%Y/%m/%d')
self.batch_context.syor_date = datetime.strftime(datetime.now(), '%Y/%m/%d')
# テスト用のCSVを読み込む
test_dat_file = create_ultmarc_test_data_from_csv(path.join(self.test_file_path, 'com_alma_insert.csv'))
# 一旦全データをDBから削除
@ -95,7 +95,7 @@ class TestComAlmaMapper:
# Arrange
# 処理日設定
self.batch_config.syor_date = datetime.strftime(datetime.now(), '%Y/%m/%d')
self.batch_context.syor_date = datetime.strftime(datetime.now(), '%Y/%m/%d')
# テスト用のCSVを読み込む
test_dat_file = create_ultmarc_test_data_from_csv(path.join(self.test_file_path, 'com_alma_update.csv'))
# 一旦全データをDBから削除
@ -152,7 +152,7 @@ class TestComAlmaMapper:
# Arrange
# 処理日設定
self.batch_config.syor_date = datetime.strftime(datetime.now(), '%Y/%m/%d')
self.batch_context.syor_date = datetime.strftime(datetime.now(), '%Y/%m/%d')
# テスト用のCSVを読み込む
test_dat_file = create_ultmarc_test_data_from_csv(path.join(self.test_file_path, 'com_alma_delete.csv'))
# 一旦全データをDBから削除

View File

@ -2,7 +2,7 @@ import os.path as path
import pytest
from src.batch.common.batch_config import BatchConfig
from src.batch.common.batch_context import BatchContext
from src.batch.ultmarc.utmp_tables.table_mapper.concrete import \
com_dr_wrkplace_mapper
from src.db.database import Database
@ -18,13 +18,13 @@ class TestComDrWrkplaceMapper:
"""COM_DCF医師勤務先"""
db: Database
batch_config: BatchConfig
batch_context: BatchContext
test_file_path: str = path.dirname(__file__)
@ pytest.fixture(autouse=True, scope='function')
def pre_test(self, database: Database):
"""テスト実行前後処理"""
self.batch_config = BatchConfig.get_instance()
self.batch_context = BatchContext.get_instance()
# setup
self.db = database
@ -53,7 +53,7 @@ class TestComDrWrkplaceMapper:
# Arrange
# 処理日設定
# 適用開始日と同値になる
self.batch_config.syor_date = '2020/02/22'
self.batch_context.syor_date = '2020/02/22'
# テスト用のCSVを読み込む
test_dat_file = create_ultmarc_test_data_from_csv(path.join(self.test_file_path, 'com_dr_wrkplace_insert.csv'))
# 一旦全データをDBから削除
@ -147,7 +147,7 @@ class TestComDrWrkplaceMapper:
# Arrange
# 処理日設定
# 適用開始日と同値、適用終了日の+1日になる
self.batch_config.syor_date = '2020/02/23'
self.batch_context.syor_date = '2020/02/23'
# テスト用のCSVを読み込む
test_dat_file = create_ultmarc_test_data_from_csv(path.join(self.test_file_path, 'com_dr_wrkplace_update.csv'))
# 一旦全データをDBから削除
@ -264,7 +264,7 @@ class TestComDrWrkplaceMapper:
# Arrange
# 処理日設定
self.batch_config.syor_date = '2020/02/24'
self.batch_context.syor_date = '2020/02/24'
# テスト用のCSVを読み込む
test_dat_file = create_ultmarc_test_data_from_csv(path.join(self.test_file_path, 'com_dr_wrkplace_delete.csv'))
# 一旦全データをDBから削除

View File

@ -3,7 +3,7 @@ from datetime import datetime
import pytest
from src.batch.common.batch_config import BatchConfig
from src.batch.common.batch_context import BatchContext
from src.batch.ultmarc.utmp_tables.table_mapper.concrete import \
com_hamtec_mapper
from src.db.database import Database
@ -19,13 +19,13 @@ class TestComHamtecMapper:
"""レイアウト区分021: COM_高度先進医療"""
db: Database
batch_config: BatchConfig
batch_context: BatchContext
test_file_path: str = path.dirname(__file__)
@pytest.fixture(autouse=True, scope='function')
def pre_test(self, database: Database):
"""テスト実行前後処理"""
self.batch_config = BatchConfig.get_instance()
self.batch_context = BatchContext.get_instance()
# setup
self.db = database
self.db.connect()
@ -51,7 +51,7 @@ class TestComHamtecMapper:
# Arrange
# 処理日設定
self.batch_config.syor_date = datetime.strftime(datetime.now(), '%Y/%m/%d')
self.batch_context.syor_date = datetime.strftime(datetime.now(), '%Y/%m/%d')
# テスト用のCSVを読み込む
test_dat_file = create_ultmarc_test_data_from_csv(path.join(self.test_file_path, 'com_hamtec_insert.csv'))
# 一旦全データをDBから削除
@ -96,7 +96,7 @@ class TestComHamtecMapper:
# Arrange
# 処理日設定
self.batch_config.syor_date = datetime.strftime(datetime.now(), '%Y/%m/%d')
self.batch_context.syor_date = datetime.strftime(datetime.now(), '%Y/%m/%d')
# テスト用のCSVを読み込む
test_dat_file = create_ultmarc_test_data_from_csv(path.join(self.test_file_path, 'com_hamtec_update.csv'))
# 一旦全データをDBから削除
@ -153,7 +153,7 @@ class TestComHamtecMapper:
# Arrange
# 処理日設定
self.batch_config.syor_date = datetime.strftime(datetime.now(), '%Y/%m/%d')
self.batch_context.syor_date = datetime.strftime(datetime.now(), '%Y/%m/%d')
# テスト用のCSVを読み込む
test_dat_file = create_ultmarc_test_data_from_csv(path.join(self.test_file_path, 'com_hamtec_delete.csv'))
# 一旦全データをDBから削除