ファイル存在チェックまで実装

This commit is contained in:
x.azuma.m@nds-tyo.co.jp 2023-04-25 12:37:08 +09:00
parent bd8e396e0a
commit 9ba4eda8a3
8 changed files with 384 additions and 1 deletions

View File

@ -11,3 +11,6 @@ ULTMARC_BACKUP_FOLDER=ultmarc
JSKULT_CONFIG_BUCKET=**********************
JSKULT_CONFIG_CALENDAR_FOLDER=jskult/calendar
JSKULT_CONFIG_CALENDAR_HOLIDAY_LIST_FILE_NAME=jskult_holiday_list.txt
JSKULT_CONFIG_CALENDAR_WHOLESALER_STOCK_FILE_NAME=jskult_wholesaler_stock_input_day_list.txt
JSKULT_DATA_BUCKET=**********************
JSKULT_DATA_FOLDER_RECV=**********************

View File

@ -1,3 +1,4 @@
import io
import os.path as path
import tempfile
@ -16,7 +17,8 @@ class S3Client:
return []
contents = response['Contents']
# 末尾がスラッシュで終わるものはフォルダとみなしてスキップする
objects = [{'filename': content['Key'], 'size': content['Size']} for content in contents if not content['Key'].endswith('/')]
objects = [{'filename': content['Key'], 'size': content['Size']}
for content in contents if not content['Key'].endswith('/')]
return objects
def copy(self, src_bucket: str, src_key: str, dest_bucket: str, dest_key: str) -> None:
@ -89,6 +91,16 @@ class ConfigBucket(S3Bucket):
f.seek(0)
return temporary_file_path
def download_wholesaler_stock_list(self):
# 一時ファイルとして保存する
temporary_dir = tempfile.mkdtemp()
temporary_file_path = path.join(temporary_dir, environment.JSKULT_CONFIG_CALENDAR_WHOLESALER_STOCK_FILE_NAME)
holiday_list_key = f'{environment.JSKULT_CONFIG_CALENDAR_FOLDER}/{environment.JSKULT_CONFIG_CALENDAR_WHOLESALER_STOCK_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.JSKULT_BACKUP_BUCKET
@ -96,3 +108,16 @@ class JskUltBackupBucket(S3Bucket):
class UltmarcBackupBucket(JskUltBackupBucket):
_folder = environment.ULTMARC_BACKUP_FOLDER
class VjskBucket(S3Bucket):
# TODO:V実消化バケットから見たり取ってきたりする実装をやる
_bucket_name = environment.JSKULT_DATA_BUCKET
_recv_folder = environment.JSKULT_DATA_FOLDER_RECV
def get_file_list(self):
return self._s3_client.list_objects(self._bucket_name, self._recv_folder)
# def download_data_file(self, data_filename: str):
# temporary_dir = tempfile.mkdtemp()
# temporary_file_path = path.join(temporary_dir, f'{data_filename.replace(f"{self._folder}/", "")}')

View File

@ -3,6 +3,7 @@ class BatchContext:
__syor_date: str # 処理日(yyyy/mm/dd形式)
__is_not_business_day: bool # 日次バッチ起動日フラグ
__is_ultmarc_imported: bool # アルトマーク取込実施済フラグ
__is_import_target_vjsk_stockslipdata: bool # 卸在庫データ取込対象フラグ
def __init__(self) -> None:
self.__is_not_business_day = False
@ -37,3 +38,11 @@ class BatchContext:
@is_ultmarc_imported.setter
def is_ultmarc_imported(self, flag: bool):
self.__is_ultmarc_imported = flag
@property
def is_import_target_vjsk_stockslipdata(self):
return self.__is_import_target_vjsk_stockslipdata
@is_import_target_vjsk_stockslipdata.setter
def is_import_target_vjsk_stockslipdata(self, flag: bool):
self.__is_import_target_vjsk_stockslipdata = flag

View File

@ -0,0 +1,32 @@
from src.system_var import constants
class CalendarWholwSalerStockFile:
"""V実消化卸在庫データ連携日ファイル"""
__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:
"""与えられた日付がV実消化卸在庫データ連携日ファイル内に含まれているかどうか
V実消化卸在庫データ連携日ファイル内の日付は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

@ -0,0 +1,143 @@
from src.aws.s3 import ConfigBucket, VjskBucket
from src.batch.common.batch_context import BatchContext
from src.batch.common.calendar_wholestocksaler_file import \
CalendarWholwSalerStockFile
from src.batch.vjsk.vjsk_recv_file_mapper import VjskRecvFileMapper
from src.error.exceptions import BatchOperationException
from src.logging.get_logger import get_logger
# from src.batch.datachange import emp_chg_inst_lau
logger = get_logger('V実消化データ取込')
batch_context = BatchContext.get_instance()
vjsk_recv_bucket = VjskBucket()
vjsk_mapper = VjskRecvFileMapper()
def _check_if_file_exists(src_list: list, key: str) -> bool:
pref = vjsk_mapper.get_file_prefix(key)
suff = vjsk_mapper.get_file_suffix(key)
for idx, elem in enumerate(src_list):
buf = elem.get("filename")
filename = buf[buf.rfind("/") + 1:]
if filename.startswith(pref) and filename.endswith(suff):
return True
return False
def _check_received_files():
"""V実消化連携データ存在確認処理"""
logger.debug('V実消化連携データ存在確認処理開始')
# 実消化&アルトマーク V実消化データ受領バケットにあるファイル一覧を取得
received_files = vjsk_recv_bucket.get_file_list()
logger.debug(f'ファイル一覧{received_files}')
# ファイル存在確認 卸在庫データファイル(卸在庫データ処理対象日のみ実施)
if batch_context.is_import_target_vjsk_stockslipdata:
if not _check_if_file_exists(received_files, vjsk_mapper.CONDKEY_STOCK_SLIP_DATA):
raise BatchOperationException(f'卸在庫データファイルがありません ファイル一覧:{received_files}')
# ファイル存在確認 卸販売データ
if not _check_if_file_exists(received_files, vjsk_mapper.CONDKEY_SLIP_DATA):
raise BatchOperationException(f'卸販売データファイルがありません ファイル一覧:{received_files}')
# ファイル存在確認 卸組織変換マスタ
if not _check_if_file_exists(received_files, vjsk_mapper.CONDKEY_ORG_CNV_MST):
raise BatchOperationException(f'卸組織変換マスタファイルがありません ファイル一覧:{received_files}')
# ファイル存在確認 施設統合マスタ
if not _check_if_file_exists(received_files, vjsk_mapper.CONDKEY_VOP_HCO_MERGE):
raise BatchOperationException(f'施設統合マスタファイルがありません ファイル一覧:{received_files}')
# ファイル存在確認 卸マスタ
if not _check_if_file_exists(received_files, vjsk_mapper.CONDKEY_WHS_MST):
raise BatchOperationException(f'卸マスタファイルがありません ファイル一覧:{received_files}')
# ファイル存在確認 卸ホールディングスマスタ
if not _check_if_file_exists(received_files, vjsk_mapper.CONDKEY_HLD_MST):
raise BatchOperationException(f'卸ホールディングスマスタファイルがありません ファイル一覧:{received_files}')
# ファイル存在確認 施設マスタ
if not _check_if_file_exists(received_files, vjsk_mapper.CONDKEY_FCL_MST):
raise BatchOperationException(f'施設マスタファイルがありません ファイル一覧:{received_files}')
# ファイル存在確認 メーカー卸組織展開表
if not _check_if_file_exists(received_files, vjsk_mapper.CONDKEY_MKR_ORG_HORIZON):
raise BatchOperationException(f'メーカー卸組織展開表ファイルがありません ファイル一覧:{received_files}')
# ファイル存在確認 取引区分マスタ
if not _check_if_file_exists(received_files, vjsk_mapper.CONDKEY_TRAN_KBN_MST):
raise BatchOperationException(f'取引区分マスタファイルがありません ファイル一覧:{received_files}')
# ファイル存在確認 製品マスタ
if not _check_if_file_exists(received_files, vjsk_mapper.CONDKEY_PHM_PRD_MST):
raise BatchOperationException(f'製品マスタファイルがありません ファイル一覧:{received_files}')
# ファイル存在確認 製品価格マスタ
if not _check_if_file_exists(received_files, vjsk_mapper.CONDKEY_PHM_PRICE_MST):
raise BatchOperationException(f'製品価格マスタファイルがありません ファイル一覧:{received_files}')
# ファイル存在確認 卸得意先情報マスタ
if not _check_if_file_exists(received_files, vjsk_mapper.CONDKEY_WHS_CUSTOMER_MST):
raise BatchOperationException(f'卸得意先情報マスタファイルがありません ファイル一覧:{received_files}')
# ファイル存在確認 MDBコード変換マスタ
if not _check_if_file_exists(received_files, vjsk_mapper.CONDKEY_MDB_CONV_MST):
raise BatchOperationException(f'MDBコード変換マスタファイルがありません ファイル一覧:{received_files}')
logger.debug('V実消化連携データ存在確認処理終了')
return True
def _import_file_to_db():
logger.debug('V実消化取込処理開始')
# diff_upsertに変わるやつを呼び出す
# emp_chg_inst_lau.batch_process() みたいに
logger.debug('V実消化取込処理終了')
def _determine_today_is_stockslipdata_target():
try:
# 設定ファイル「V実消化卸在庫データ連携日ファイル」の内容を取得して、処理日が該当していればTrueを返却する
today = batch_context.syor_date
holiday_list_file_path = ConfigBucket().download_wholesaler_stock_list()
targetdays = CalendarWholwSalerStockFile(holiday_list_file_path)
ret = targetdays.compare_date(today)
except Exception as e:
logger.error(f'{e}')
raise e
return ret
def exec():
"""V実消化データ取込"""
logger.info('Start Jitsusyouka Torikomi PGM.')
# 卸在庫データ取込対象日であれば、卸在庫データ処理対象フラグを立てる
logger.debug('卸在庫データ取込対象日であるかを判定')
batch_context.is_import_target_vjsk_stockslipdata = _determine_today_is_stockslipdata_target()
logger.debug(f'判定結果 : {batch_context.is_import_target_vjsk_stockslipdata}')
if batch_context.is_import_target_vjsk_stockslipdata:
logger.info('卸在庫データ取込対象日です')
# V実消化データファイル受領チェック
logger.debug('V実消化データファイル受領チェック開始')
try:
_check_received_files()
except BatchOperationException as e:
logger.error('受領したV実消化データファイルに欠落があります')
raise e
logger.debug('V実消化データファイル受領チェック終了')
# データベース取込
logger.debug('V実消化データ取込開始')
try:
_import_file_to_db()
except Exception as e:
logger.error(f'データベース登録失敗 {e}')
logger.debug('V実消化データ取込終了')

View File

@ -0,0 +1,166 @@
class VjskRecvFileMapper:
CONDKEY_SLIP_DATA = "SLIP_DATA" # 販売実績データ
CONDKEY_HLD_MST = "HLD_MST" # V卸ホールディングスマスタ
CONDKEY_WHS_MST = "WHS_MST" # V卸マスタ
CONDKEY_MKR_ORG_HORIZON = "MKR_ORG_HORIZON" # Vメーカー卸組織展開表
CONDKEY_ORG_CNV_MST = "ORG_CNV_MST" # V卸組織変換マスタ
CONDKEY_TRAN_KBN_MST = "TRAN_KBN_MST" # V取引区分マスタ
CONDKEY_FCL_MST = "FCL_MST" # V施設マスタ
CONDKEY_PHM_PRD_MST = "PHM_PRD_MST" # V製品マスタ
CONDKEY_PHM_PRICE_MST = "PHM_PRICE_MST" # V製品価格マスタ
CONDKEY_VOP_HCO_MERGE = "VOP_HCO_MERGE" # V施設統合マスタ
CONDKEY_WHS_CUSTOMER_MST = "WHS_CUSTOMER_MST" # V卸得意先情報マスタ
CONDKEY_MDB_CONV_MST = "MDB_CONV_MST" # MDBコード変換表
CONDKEY_STOCK_SLIP_DATA = "STOCK_SLIP_DATA" # 卸在庫データ
CONDKEY_BIO_SLIP_DATA = "BIO_SLIP_DATA" # 生物由来データ
CONDKEY_LOT_NUM_MS = "LOT_NUM_MS" # ロットマスタデータ
_KEY_FILE_PREFIX = "file_prefix"
_KEY_FILE_SUFFIX = "file_suffix"
_KEY_ORG_TABLE = "org_table"
_KEY_SRC_TABLE = "src_table"
_VJSK_INTERFACE_MAPPING = {
# 販売実績データ
CONDKEY_SLIP_DATA: {
_KEY_FILE_PREFIX: "slip_data_",
_KEY_FILE_SUFFIX: ".tsv",
_KEY_ORG_TABLE: "org05.sales",
_KEY_SRC_TABLE: "src05.sales"
},
# V卸ホールディングスマスタ
CONDKEY_HLD_MST: {
_KEY_FILE_PREFIX: "hld_mst_",
_KEY_FILE_SUFFIX: ".tsv",
_KEY_ORG_TABLE: "org05.hld_mst_v",
_KEY_SRC_TABLE: "src05.hld_mst_v"
},
# V卸マスタ
CONDKEY_WHS_MST: {
_KEY_FILE_PREFIX: "whs_mst_",
_KEY_FILE_SUFFIX: ".tsv",
_KEY_ORG_TABLE: "org05.whs_mst_v",
_KEY_SRC_TABLE: "src05.whs_mst_v"
},
# Vメーカー卸組織展開表
CONDKEY_MKR_ORG_HORIZON: {
_KEY_FILE_PREFIX: "mkr_org_horizon_",
_KEY_FILE_SUFFIX: ".tsv",
_KEY_ORG_TABLE: "org05.mkr_org_horizon_v",
_KEY_SRC_TABLE: "src05.mkr_org_horizon_v"
},
# V卸組織変換マスタ
CONDKEY_ORG_CNV_MST: {
_KEY_FILE_PREFIX: "org_cnv_mst_",
_KEY_FILE_SUFFIX: ".tsv",
_KEY_ORG_TABLE: "org05.org_cnv_mst_v",
_KEY_SRC_TABLE: "src05.org_cnv_mst_v"
},
# V取引区分マスタ
CONDKEY_TRAN_KBN_MST: {
_KEY_FILE_PREFIX: "tran_kbn_mst_",
_KEY_FILE_SUFFIX: ".tsv",
_KEY_ORG_TABLE: "org05.tran_kbn_mst_v",
_KEY_SRC_TABLE: "src05.tran_kbn_mst_v"
},
# V施設マスタ
CONDKEY_FCL_MST: {
_KEY_FILE_PREFIX: "fcl_mst_",
_KEY_FILE_SUFFIX: ".tsv",
_KEY_ORG_TABLE: "org05.fcl_mst_v",
_KEY_SRC_TABLE: "src05.fcl_mst_v"
},
# V製品マスタ
CONDKEY_PHM_PRD_MST: {
_KEY_FILE_PREFIX: "phm_prd_mst_",
_KEY_FILE_SUFFIX: ".tsv",
_KEY_ORG_TABLE: "org05.phm_prd_mst_v",
_KEY_SRC_TABLE: "src05.phm_prd_mst_v"
},
# V製品価格マスタ
CONDKEY_PHM_PRICE_MST: {
_KEY_FILE_PREFIX: "phm_price_mst_",
_KEY_FILE_SUFFIX: ".tsv",
_KEY_ORG_TABLE: "org05.phm_price_mst_v",
_KEY_SRC_TABLE: "src05.phm_price_mst_v"
},
# V施設統合マスタ
CONDKEY_VOP_HCO_MERGE: {
_KEY_FILE_PREFIX: "vop_hco_merge_",
_KEY_FILE_SUFFIX: ".tsv",
_KEY_ORG_TABLE: "org05.vop_hco_merge_v",
_KEY_SRC_TABLE: "src05.vop_hco_merge_v"
},
# V卸得意先情報マスタ
CONDKEY_WHS_CUSTOMER_MST: {
_KEY_FILE_PREFIX: "whs_customer_mst_",
_KEY_FILE_SUFFIX: ".tsv",
_KEY_ORG_TABLE: "org05.whs_customer_mst_v",
_KEY_SRC_TABLE: "src05.whs_customer_mst_v"
},
# MDBコード変換表
CONDKEY_MDB_CONV_MST: {
_KEY_FILE_PREFIX: "mdb_conv_mst_",
_KEY_FILE_SUFFIX: ".tsv",
_KEY_ORG_TABLE: "org05.mdb_conv_mst_v",
_KEY_SRC_TABLE: "src05.mdb_conv_mst_v"
},
# 卸在庫データ
CONDKEY_STOCK_SLIP_DATA: {
_KEY_FILE_PREFIX: "stock_slip_data_",
_KEY_FILE_SUFFIX: ".tsv",
_KEY_ORG_TABLE: "org05.whole_stock",
_KEY_SRC_TABLE: "src05.whole_stock"
},
# 生物由来データ
CONDKEY_BIO_SLIP_DATA: {
_KEY_FILE_PREFIX: "bio_slip_data_",
_KEY_FILE_SUFFIX: ".tsv",
_KEY_ORG_TABLE: "org05.bio_sales",
_KEY_SRC_TABLE: "src05.bio_sales"
},
# ロットマスタデータ
CONDKEY_LOT_NUM_MS: {
_KEY_FILE_PREFIX: "lot_num_ms_",
_KEY_FILE_SUFFIX: ".tsv",
_KEY_ORG_TABLE: "org05.lot_num_mst",
_KEY_SRC_TABLE: "src05.lot_num_mst"
},
}
def get_file_prefix(self, condkey: str) -> str:
ret = None
if condkey in self._VJSK_INTERFACE_MAPPING:
ret = self._VJSK_INTERFACE_MAPPING.get(condkey).get(self._KEY_FILE_PREFIX)
return ret
def get_file_suffix(self, condkey: str) -> str:
ret = None
if condkey in self._VJSK_INTERFACE_MAPPING:
ret = self._VJSK_INTERFACE_MAPPING.get(condkey).get(self._KEY_FILE_SUFFIX)
return ret
def get_org_table(self, condkey: str) -> str:
ret = None
if condkey in self._VJSK_INTERFACE_MAPPING:
ret = self._VJSK_INTERFACE_MAPPING.get(condkey).get(self._KEY_ORG_TABLE)
return ret
def get_src_table(self, condkey: str) -> str:
ret = None
if condkey in self._VJSK_INTERFACE_MAPPING:
ret = self._VJSK_INTERFACE_MAPPING.get(condkey).get(self._KEY_SRC_TABLE)
return ret

View File

@ -9,6 +9,7 @@ from src.batch.common.batch_context import BatchContext
from src.batch.common.calendar_file import CalendarFile
from src.batch.laundering import create_dcf_inst_merge, create_mst_inst
from src.batch.ultmarc import ultmarc_process
from src.batch.vjsk import vjsk_importer
from src.error.exceptions import BatchOperationException
from src.logging.get_logger import get_logger
from src.system_var import constants
@ -84,6 +85,7 @@ def exec():
logger.info('日次処理V実消化')
try:
logger.info('V実消化取込起動')
vjsk_importer.exec()
logger.info('V実消化取込終了')
except BatchOperationException as e:
logger.exception(f'V実消化取込処理エラー異常終了{e}')

View File

@ -15,6 +15,9 @@ 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_CALENDAR_HOLIDAY_LIST_FILE_NAME = os.environ['JSKULT_CONFIG_CALENDAR_HOLIDAY_LIST_FILE_NAME']
JSKULT_CONFIG_CALENDAR_WHOLESALER_STOCK_FILE_NAME = os.environ['JSKULT_CONFIG_CALENDAR_WHOLESALER_STOCK_FILE_NAME']
JSKULT_DATA_BUCKET = os.environ['JSKULT_DATA_BUCKET']
JSKULT_DATA_FOLDER_RECV = os.environ['JSKULT_DATA_FOLDER_RECV']
# 初期値がある環境変数
LOG_LEVEL = os.environ.get('LOG_LEVEL', 'INFO')