newdwh2021/ecs/jskult-batch/src/batch/trn_result_data_bio_lot.py

298 lines
14 KiB
Python

import json
from src.aws.s3 import JskTransferListBucket
from src.batch.environment.trn_result_data_bio_lot_environment import \
TrnResultDataBioLotEnvironment
from src.batch.jskult_batch_entrypoint import JskultBatchEntrypoint
from src.db.database import Database
from src.error.exceptions import (BatchOperationException,
EnvironmentVariableNotSetException,
MaxRunCountReachedException)
from src.logging.get_logger import get_logger
from src.manager.jskult_batch_run_manager import JskultBatchRunManager
from src.manager.jskult_batch_status_manager import JskultBatchStatusManager
from src.manager.jskult_hdke_tbl_manager import JskultHdkeTblManager
from src.system_var import constants
logger = get_logger('生物由来卸販売ロット分解')
class TrnResultDataBioLot(JskultBatchEntrypoint):
def __init__(self):
super().__init__()
self.environment = TrnResultDataBioLotEnvironment()
# 必須の環境変数が設定されていない場合、エラーにする
try:
self.environment.validate()
except EnvironmentVariableNotSetException as e:
logger.exception(e)
return
def execute(self):
"""生物由来卸販売ロット分解"""
logger.info('生物由来卸販売ロット分解処理開始')
jskult_hdke_tbl_manager = JskultHdkeTblManager()
jskult_batch_run_manager = JskultBatchRunManager(
self.environment.BATCH_MANAGE_DYNAMODB_TABLE_NAME,
self.environment.BATCH_EXECUTION_ID)
if not jskult_hdke_tbl_manager.can_run_process():
logger.error(
'日次バッチ処理中またはdump取得が正常終了していないため、生物由来卸販売ロット分解処理を終了します。')
# バッチ実行管理テーブルをfailedで登録
jskult_batch_run_manager.batch_failed()
return
# 業務日付を取得
_, _, process_date = jskult_hdke_tbl_manager.get_batch_statuses()
# 転送ファイル一覧を取得し、転送件数を取得
try:
transfer_list_bucket = JskTransferListBucket()
transfer_list_file_path = transfer_list_bucket.download_transfer_result_file(
process_date)
except Exception as e:
logger.exception(f'転送ファイル一覧の取得に失敗しました。 {e}')
# バッチ実行管理テーブルをfailedで登録
jskult_batch_run_manager.batch_failed()
with open(transfer_list_file_path) as f:
transfer_list = json.load(f)
# 実消化データ + アルトマークデータの転送件数を合算し、受信ファイル件数とする
receive_file_count = len(
transfer_list['jsk_transfer_list']) + len(transfer_list['ult_transfer_list'])
jskult_batch_status_manager = JskultBatchStatusManager(
self.environment.PROCESS_NAME,
constants.PROCESS_TYPE_POST_PROCESS,
self.environment.MAX_RUN_COUNT,
receive_file_count
)
try:
jskult_batch_status_manager.set_process_status(
constants.BATCH_ACTF_BATCH_START)
try:
if not jskult_batch_status_manager.can_run_post_process():
# 後続処理の起動条件を満たしていない場合
# 処理ステータスを「処理待」に設定
jskult_batch_status_manager.set_process_status(
constants.PROCESS_STATUS_WAITING)
# バッチ実行管理テーブルに「retry」で登録
jskult_batch_run_manager.batch_retry()
return
except MaxRunCountReachedException:
logger.info('最大起動回数に到達したため、生物由来卸販売ロット分解処理を実行します。')
jskult_batch_status_manager.set_process_status(
constants.PROCESS_STATUS_DOING)
db = Database.get_instance()
try:
db.connect()
db.begin()
# 生物由来ロット分解データの未確定データを削除する
self._delete_not_confirm_data_in_trn_result_data_bio_lot(db)
# 生物由来ロット分解データを作成する
self._insert_trn_result_data_bio_lot(db)
# 生物由来ロット分解データの不要レコードを削除する
self._delete_empty_lot_record(db)
# 製造ロット管理番号マスタから有効期限を生物由来ロット分解データにセットする
self._set_expr_dt_from_lot_num_mst(db)
# 施設情報を生物由来ロット分解データにセットする
self._set_inst_info_from_com_inst_or_com_pharm_or_mst_inst_merck(
db)
db.commit()
logger.info('生物由来卸販売ロット分解処理終了')
# 処理が全て正常終了した際に、バッチ実行管理テーブルに「success」で登録
logger.info("生物由来卸販売ロット分解処理を正常終了します。")
jskult_batch_run_manager.batch_success()
jskult_batch_status_manager.set_process_status(
constants.PROCESS_STATUS_DONE)
return
except Exception as e:
db.rollback()
raise BatchOperationException(e)
finally:
db.disconnect()
except Exception as e:
# 何らかのエラーが発生した際に、バッチ実行管理テーブルに「failed」で登録
logger.exception(f'予期せぬエラーが発生したため、生物由来卸販売ロット分解処理を終了します。{e}')
jskult_batch_run_manager.batch_failed()
jskult_batch_status_manager.set_process_status(
constants.PROCESS_STATUS_ERROR)
def _delete_not_confirm_data_in_trn_result_data_bio_lot(self, db: Database):
logger.info('生物由来ロット分解データの未確定データ削除開始')
try:
sql = """
DELETE lot FROM src07.trn_result_data_bio_lot AS lot
INNER JOIN src07.trn_result_data_bio AS bio
ON bio.account_ym = lot.account_ym
AND bio.seq_no = lot.seq_no
AND IFNULL(bio.upd_date, bio.ins_date) >= src07.get_syor_date()
"""
db.execute(sql)
except Exception as e:
logger.info('生物由来ロット分解データの未確定データ削除に失敗')
raise e
logger.info('生物由来ロット分解データの未確定データ削除に成功')
def _insert_trn_result_data_bio_lot(self, db: Database):
logger.info('生物由来ロット分解データの作成開始')
try:
sql = """
INSERT INTO src07.trn_result_data_bio_lot
SELECT
bio.account_ym AS account_ym,
bio.seq_no AS seq_no,
conv.conv_cd AS conv_cd,
bio.orig_whlslr_cd AS orig_whlslr_cd,
bio.orig_whlslr_sub_cd AS orig_whlslr_sub_cd,
bio.edit_whlslr_org_cd AS edit_whlslr_org_cd,
bio.orig_univ_product_cd AS orig_univ_product_cd,
bio.edit_deal_div_cd AS edit_deal_div_cd,
bio.cnvs_sales_dt AS cnvs_sales_dt,
bio.orig_slip_no AS orig_slip_no,
bio.orig_prod_nm AS orig_prod_nm,
bio.edit_endusr_cd AS edit_endusr_cd,
bio.orig_endusr_nm AS orig_endusr_nm,
bio.orig_jd45_addr_txt AS orig_jd45_addr_txt,
-- 3レコードに分解する
CASE conv.conv_cd
WHEN 1 THEN bio.cnvs_lot_no_1
WHEN 2 THEN bio.cnvs_lot_no_2
WHEN 3 THEN bio.cnvs_lot_no_3
END AS cnvs_lot_no,
bio.load_dt AS load_dt,
bio.cnvs_deal_div_cd AS cnvs_deal_div_cd,
bio.cls_deal_div_nm AS cls_deal_div_nm,
bio.cnvs_depo_cd AS cnvs_depo_cd,
bio.cls_depo_nm AS cls_depo_nm,
bio.cnvs_whlslr_cd AS cnvs_whlslr_cd,
bio.cls_whlslr_nm AS cls_whlslr_nm,
bio.cls_prod_nm AS cls_prod_nm,
bio.cnvs_prod_cd AS cnvs_prod_cd,
-- 3レコードに分解する
CASE conv.conv_cd
WHEN 1 THEN bio.cnvs_lot_sales_qty_1
WHEN 2 THEN bio.cnvs_lot_sales_qty_2
WHEN 3 THEN bio.cnvs_lot_sales_qty_3
END AS cnvs_lot_sales_qty,
bio.cnvs_inst_cd AS cnvs_inst_cd,
bio.cls_inst_nm AS cls_inst_nm,
-- COM_施設 or COM_薬局 or メルク独自施設マスタから後ほどセット
NULL AS inst_addr,
NULL AS inst_tel,
bio.result_cd AS result_cd,
bio.src_cd AS src_cd,
-- 判定結果CDより値を設定する
CASE bio.result_cd
WHEN '1' THEN '正常'
WHEN '2' THEN '卸間転送除外対象'
WHEN 'E' THEN 'エラー'
WHEN 'D' THEN 'エラー(重複)'
WHEN 'Z' THEN 'エラー(想定外)'
END AS data_kbn,
-- SRC_種類より値を設定する
CASE bio.result_cd
WHEN '1' THEN 'VAN'
WHEN '2' THEN '手入力'
WHEN '3' THEN 'VAN-Web'
WHEN 'S' THEN 'SCSK-VAN'
END AS if_kind,
-- 製品コード、ロット番号でロットマスタより後ほどセット
NULL AS ck_last_dt_txt
FROM
src07.trn_result_data_bio bio
-- 生物由来変換マスタ
CROSS JOIN src07.bio_conv conv
WHERE
IFNULL(bio.upd_date, bio.ins_date) >= src07.get_syor_date()
"""
db.execute(sql)
except Exception as e:
logger.info('生物由来ロット分解データの作成に失敗')
raise e
logger.info('生物由来ロット分解データの作成に成功')
def _delete_empty_lot_record(self, db: Database):
logger.info('生物由来ロット分解データのロット番号が空のレコードを削除開始')
try:
sql = """
DELETE FROM src07.trn_result_data_bio_lot lot
WHERE
-- 空白15桁のデータはロット情報が空とみなして削除する
lot.cnvs_lot_no = REPEAT(' ', 15) OR lot.cnvs_lot_no IS NULL
"""
db.execute(sql)
except Exception as e:
logger.info('生物由来ロット分解データのロット番号が空のレコードを削除に失敗')
raise e
logger.info('生物由来ロット分解データのロット番号が空のレコードを削除に成功')
def _set_inst_info_from_com_inst_or_com_pharm_or_mst_inst_merck(self, db: Database):
logger.info('COM_施設 or COM_薬局 or メルク独自施設マスタから施設情報を生物由来ロット分解データにセット開始')
try:
sql = """
UPDATE
src07.trn_result_data_bio_lot bio
-- COM_施設
LEFT OUTER JOIN src05.com_inst ci
ON bio.cnvs_inst_cd = ci.dcf_dsf_inst_cd
-- COM_薬局
LEFT OUTER JOIN src05.com_pharm cp
ON bio.cnvs_inst_cd = cp.dcf_dsf_inst_cd
-- 独自施設マスタ
LEFT OUTER JOIN src07.mst_inst_merck mim
ON bio.cnvs_inst_cd = mim.inst_cd
AND DATE_FORMAT(bio.cnvs_sales_dt, '%Y%m') BETWEEN mim.eff_start_ym
AND mim.eff_end_ym
-- 施設住所
SET bio.inst_addr = (
CASE LEFT(bio.cnvs_inst_cd, 2)
WHEN '00' THEN ci.inst_addr
WHEN '03' THEN cp.inst_addr
ELSE mim.addr2_nm_kj
END
),
-- 施設電話番号
bio.inst_tel = (
CASE LEFT(bio.cnvs_inst_cd, 2)
WHEN '00' THEN ci.inst_phone_number
WHEN '03' THEN cm.inst_phone_number
ELSE mim.tel_no
END
)
"""
db.execute(sql)
except Exception as e:
logger.info(
'COM_施設 or COM_薬局 or メルク独自施設マスタから施設情報を生物由来ロット分解データにセット失敗')
raise e
logger.info('COM_施設 or COM_薬局 or メルク独自施設マスタから施設情報を生物由来ロット分解データにセット成功')
def _set_ck_last_dt_txt_from_customer_lotno_all(self, db: Database):
# ロットマスタから有効期限をセット
logger.info('ロットマスタから有効期限をセット開始')
try:
sql = """
UPDATE
src07.trn_result_data_bio_lot bio
LEFT OUTER JOIN src07.customer_lotno_all cla
ON bio.cnvs_prod_cd = cla.material_cd
AND bio.cnvs_lot_no = cla.lot_no_txt
SET
bio.ck_last_dt_txt = cla.ck_last_dt_txt
"""
db.execute(sql)
except Exception as e:
logger.info('ロットマスタから有効期限をセット失敗')
raise e
logger.info('ロットマスタから有効期限をセット成功')