Merge pull request #93 feature-NEWDWH2021-670 into develop-8sap

This commit is contained in:
朝倉 明日香 2022-08-31 11:25:13 +09:00
commit 62910f83ac
7 changed files with 937 additions and 931 deletions

View File

@ -1,186 +1,187 @@
import os
import datetime
import boto3
import io
import re
import csv
import logging
from abc import *
from zoneinfo import ZoneInfo
import traceback
# 環境変数
CONFIG_BUCKET_NAME = os.environ["CONFIG_BUCKET_NAME"]
RECEIVE_MONTHLY_FILE_NAME_LIST_PATH = os.environ["RECEIVE_MONTHLY_FILE_NAME_LIST_PATH"]
NOTICE_MAIL_TITLE_TEMPLATE_PATH = os.environ["NOTICE_MAIL_TITLE_TEMPLATE_PATH"]
NOTICE_MAIL_BODY_TEMPLATE_PATH = os.environ["NOTICE_MAIL_BODY_TEMPLATE_PATH"]
MBJ_SAP_NOTICE_TOPIC = os.environ["MBJ_SAP_NOTICE_TOPIC"]
NDS_NOTICE_TOPIC = os.environ["NDS_NOTICE_TOPIC"]
NDS_NOTICE_TITLE = os.environ["NDS_NOTICE_TITLE"]
LOG_LEVEL = os.environ["LOG_LEVEL"]
# 定数
INDEX_REGEX = 0
INDEX_DATA_NAME = 1
# メール本文に出力する不足ファイル名一覧のインデント
MAIL_INDENT = '  '
# 変数
s3_client = boto3.client('s3')
s3_resource = boto3.resource('s3')
sns_client = boto3.client('sns')
# logger設定
logger = logging.getLogger()
def custome_time(*arg):
return datetime.datetime.now(ZoneInfo("Asia/Tokyo")).timetuple()
formatter = logging.Formatter(
'[%(levelname)s]\t%(asctime)s\t%(message)s\n',
'%Y-%m-%d %H:%M:%S'
)
formatter.converter = custome_time
for handler in logger.handlers:
handler.setFormatter(formatter)
level = logging.getLevelName(LOG_LEVEL)
if not isinstance(level, int):
level = logging.INFO
logger.setLevel(level)
def lambda_handler(event, context):
try:
# ① 処理開始ログを出力する
logger.info('I-01-01 処理開始 SAP_finデータ月次I/F受領通知処理')
execute_date = datetime.date.today().strftime('%Y/%m/%d')
logger.info(f'I-01-02 処理稼働日:{execute_date}')
mail_msg = ''
# ② 処理開始時に受け取ったイベント情報の以下内容をログに出力しメモリに保持する
logger.info('I-02-01 イベント情報出力処理')
s3_event = event["Records"][0]["s3"]
event_bucket_name = s3_event["bucket"]["name"]
event_file_path = s3_event["object"]["key"]
event_file_name = os.path.basename(event_file_path)
logger.info(f'I-02-02 バケット名:{event_bucket_name}')
logger.info(f'I-02-03 ファイルパス:{event_file_path}')
# ③ 設定ファイル[SAP_finI/Fファイルネーム設定ファイル月次]を読み込む
try:
logger.info(f'I-03-01 月次I/Fファイルネーム設定ファイル読込 読込元{CONFIG_BUCKET_NAME}/{RECEIVE_MONTHLY_FILE_NAME_LIST_PATH}')
receive_monthly_file_name_obj = s3_resource.Object(CONFIG_BUCKET_NAME, RECEIVE_MONTHLY_FILE_NAME_LIST_PATH)
receive_monthly_file_name_response = receive_monthly_file_name_obj.get()
logger.info('I-03-02 月次I/Fファイルネーム設定ファイルを読み込みました')
except Exception as e:
logger.error(f'E-03-01 月次I/Fファイルネーム設定ファイルの読み込みに失敗しました エラー内容{e}')
raise FileReadException('E-03-01', e)
# ④ 月次I/Fファイル受領通知処理を行う
logger.info('I-04-01 月次I/Fファイル受領通知処理開始')
logger.info(f'I-04-02 受領したファイル名:{event_file_name}')
logger.info('I-04-03 受領したファイル名と月次I/Fファイルネーム設定ファイルの突き合わせを開始します')
file_exists = False
receive_monthly_file_name_body = io.TextIOWrapper(io.BytesIO(receive_monthly_file_name_response["Body"].read()), encoding='utf-8')
for row in csv.reader(receive_monthly_file_name_body, delimiter='\t'):
match_result = re.fullmatch(row[INDEX_REGEX], event_file_name)
if match_result is not None:
file_exists = True
break
if file_exists == True:
logger.info(f'I-04-04 月次I/Fを受領しました ファイル名{row[INDEX_DATA_NAME]} {event_file_name}')
mail_msg += f'{MAIL_INDENT}{row[INDEX_DATA_NAME]} {event_file_name}\n'
else:
logger.info('I-04-05 受領したファイルは月次I/Fではありませんでした')
# ⑤ 「①」でメモリ保持しているメール挿入用文言に出力内容が存在するか確認する
logger.info('I-05-01 メール送信処理開始')
if len(mail_msg) > 0:
# 1.存在した場合
logger.info('I-05-02 月次I/Fファイルを受領したため、メール送信処理を開始します')
try:
logger.info(f'I-05-03 通知メール(タイトル)テンプレートファイル読込 読込元:{CONFIG_BUCKET_NAME}/{NOTICE_MAIL_TITLE_TEMPLATE_PATH}')
mail_title_obj = s3_client.get_object(Bucket=CONFIG_BUCKET_NAME, Key=NOTICE_MAIL_TITLE_TEMPLATE_PATH)
mail_title = mail_title_obj['Body'].read().decode('utf-8')
logger.info('I-05-04 通知メール(タイトル)テンプレートファイルを読み込みました')
except Exception as e:
logger.error(f'E-05-01 通知メール(タイトル)テンプレートファイルの読み込みに失敗しました エラー内容:{e}')
raise FileReadException('E-05-01', e)
try:
logger.info(f'I-05-05 通知メール(本文)テンプレートファイル読込 読込元:{CONFIG_BUCKET_NAME}/{NOTICE_MAIL_BODY_TEMPLATE_PATH}')
mail_body_obj = s3_client.get_object(Bucket=CONFIG_BUCKET_NAME, Key=NOTICE_MAIL_BODY_TEMPLATE_PATH)
mail_body_response = mail_body_obj['Body'].read().decode('utf-8')
# メール本文内のプレースホルダーを置き換える
mail_body = substitute_mail_body(mail_body_response, mail_msg)
logger.info('I-05-06 通知メール(本文)テンプレートファイルを読み込みました')
except Exception as e:
logger.error(f'E-05-02 通知メール(本文)テンプレートファイルの読み込みに失敗しました エラー内容:{e}')
raise FileReadException('E-05-02', e)
logger.info(f'I-05-07 メール送信指示をします 送信先トピック:{MBJ_SAP_NOTICE_TOPIC}')
params = {
'TopicArn': MBJ_SAP_NOTICE_TOPIC,
'Subject': mail_title.rstrip('\n'),
'Message': mail_body
}
sns_client.publish(**params)
logger.info('I-05-08 メール送信指示をしました')
else:
# 2.存在しない場合
logger.info('I-05-09 受領したファイルは月次I/Fファイルではないため、メール送信処理をスキップします')
# ⑥ 処理終了ログを出力する
logger.info('I-06-01 処理終了 SAP_finデータ月次I/F受領通知処理')
except CustomException as e:
traceback.print_exc()
error_notice(e.id, e.arg)
except Exception as e:
logger.error(f'E-99 想定外のエラーが発生しました エラー内容:{e}')
traceback.print_exc()
error_notice('E-99', e)
return
# 保守要員チーム通知
def error_notice(error_log_id, exception) -> None:
try:
error_msg = f'{error_log_id} のエラーが発生しました。ご確認ください\n詳細:{exception}'
params = {
'TopicArn': NDS_NOTICE_TOPIC,
'Subject': NDS_NOTICE_TITLE,
'Message': error_msg
}
sns_client.publish(**params)
logger.error(f'E-ERR-01 処理異常通知の送信指示をしました 通知先トピック:{NDS_NOTICE_TOPIC}')
except Exception as e:
logger.error(f'E-98 処理異常通知の送信指示に失敗しました エラー内容:{e}')
traceback.print_exc()
return
def substitute_mail_body(before_mail_body:str, mail_msg: str) -> str:
"""メール本文のプレースホルダーを置き換えます
Args:
before_mail_body (str): 置き換え前のメール本文
mail_msg (str): メール本文のプレースホルダーを置き換える文言
Returns:
str: 置き換え後のメール本文
"""
substitute_dict = {
"notice_file_names": mail_msg
}
mail_body = before_mail_body.format_map(substitute_dict)
return mail_body
# カスタムExceptionクラス
class CustomException(Exception, metaclass=ABCMeta):
def __init__(self, id, arg):
self.arg = arg
self.id = id
class FileReadException(CustomException):
pass
import os
import datetime
import boto3
import io
import re
import csv
import logging
from abc import *
from zoneinfo import ZoneInfo
import traceback
# 環境変数
CONFIG_BUCKET_NAME = os.environ["CONFIG_BUCKET_NAME"]
RECEIVE_MONTHLY_FILE_NAME_LIST_PATH = os.environ["RECEIVE_MONTHLY_FILE_NAME_LIST_PATH"]
NOTICE_MAIL_TITLE_TEMPLATE_PATH = os.environ["NOTICE_MAIL_TITLE_TEMPLATE_PATH"]
NOTICE_MAIL_BODY_TEMPLATE_PATH = os.environ["NOTICE_MAIL_BODY_TEMPLATE_PATH"]
MBJ_SAP_NOTICE_TOPIC = os.environ["MBJ_SAP_NOTICE_TOPIC"]
NDS_NOTICE_TOPIC = os.environ["NDS_NOTICE_TOPIC"]
NDS_NOTICE_TITLE = os.environ["NDS_NOTICE_TITLE"]
LOG_LEVEL = os.environ["LOG_LEVEL"]
# 定数
INDEX_REGEX = 0
INDEX_DATA_NAME = 1
# メール本文に出力する不足ファイル名一覧のインデント
MAIL_INDENT = '  '
# 変数
s3_client = boto3.client('s3')
s3_resource = boto3.resource('s3')
sns_client = boto3.client('sns')
# logger設定
logger = logging.getLogger()
def custome_time(*arg):
return datetime.datetime.now(ZoneInfo("Asia/Tokyo")).timetuple()
formatter = logging.Formatter(
'[%(levelname)s]\t%(asctime)s\t%(message)s\n',
'%Y-%m-%d %H:%M:%S'
)
formatter.converter = custome_time
for handler in logger.handlers:
handler.setFormatter(formatter)
level = logging.getLevelName(LOG_LEVEL)
if not isinstance(level, int):
level = logging.INFO
logger.setLevel(level)
def lambda_handler(event, context):
try:
# ① 処理開始ログを出力する
logger.info('I-01-01 処理開始 SAP_finデータ月次I/F受領通知処理')
execute_date = datetime.date.today().strftime('%Y/%m/%d')
logger.info(f'I-01-02 処理稼働日:{execute_date}')
mail_msg = ''
# ② 処理開始時に受け取ったイベント情報の以下内容をログに出力しメモリに保持する
logger.info('I-02-01 イベント情報出力処理')
s3_event = event["Records"][0]["s3"]
event_bucket_name = s3_event["bucket"]["name"]
event_file_path = s3_event["object"]["key"]
event_file_name = os.path.basename(event_file_path)
logger.info(f'I-02-02 バケット名:{event_bucket_name}')
logger.info(f'I-02-03 ファイルパス:{event_file_path}')
# ③ 設定ファイル[SAP_finI/Fファイルネーム設定ファイル月次]を読み込む
try:
logger.info(f'I-03-01 月次I/Fファイルネーム設定ファイル読込 読込元{CONFIG_BUCKET_NAME}/{RECEIVE_MONTHLY_FILE_NAME_LIST_PATH}')
receive_monthly_file_name_obj = s3_resource.Object(CONFIG_BUCKET_NAME, RECEIVE_MONTHLY_FILE_NAME_LIST_PATH)
receive_monthly_file_name_response = receive_monthly_file_name_obj.get()
logger.info('I-03-02 月次I/Fファイルネーム設定ファイルを読み込みました')
except Exception as e:
logger.error(f'E-03-01 月次I/Fファイルネーム設定ファイルの読み込みに失敗しました エラー内容{e}')
raise FileReadException('E-03-01', e)
# ④ 月次I/Fファイル受領通知処理を行う
logger.info('I-04-01 月次I/Fファイル受領通知処理開始')
logger.info(f'I-04-02 受領したファイル名:{event_file_name}')
logger.info('I-04-03 受領したファイル名と月次I/Fファイルネーム設定ファイルの突き合わせを開始します')
file_exists = False
receive_monthly_file_name_body = io.TextIOWrapper(io.BytesIO(receive_monthly_file_name_response["Body"].read()), encoding='utf-8')
for row in csv.reader(receive_monthly_file_name_body, delimiter='\t'):
match_result = re.fullmatch(row[INDEX_REGEX], event_file_name)
if match_result is not None:
file_exists = True
break
if file_exists == True:
logger.info(f'I-04-04 月次I/Fを受領しました ファイル名{row[INDEX_DATA_NAME]} {event_file_name}')
mail_msg += f'{MAIL_INDENT}{row[INDEX_DATA_NAME]} {event_file_name}\n'
else:
logger.info('I-04-05 受領したファイルは月次I/Fではありませんでした')
# ⑤ 「①」でメモリ保持しているメール挿入用文言に出力内容が存在するか確認する
logger.info('I-05-01 メール送信処理開始')
if len(mail_msg) > 0:
# 1.存在した場合
logger.info('I-05-02 月次I/Fファイルを受領したため、メール送信処理を開始します')
try:
logger.info(f'I-05-03 通知メール(タイトル)テンプレートファイル読込 読込元:{CONFIG_BUCKET_NAME}/{NOTICE_MAIL_TITLE_TEMPLATE_PATH}')
mail_title_obj = s3_client.get_object(Bucket=CONFIG_BUCKET_NAME, Key=NOTICE_MAIL_TITLE_TEMPLATE_PATH)
mail_title = mail_title_obj['Body'].read().decode('utf-8')
logger.info('I-05-04 通知メール(タイトル)テンプレートファイルを読み込みました')
except Exception as e:
logger.error(f'E-05-01 通知メール(タイトル)テンプレートファイルの読み込みに失敗しました エラー内容:{e}')
raise FileReadException('E-05-01', e)
try:
logger.info(f'I-05-05 通知メール(本文)テンプレートファイル読込 読込元:{CONFIG_BUCKET_NAME}/{NOTICE_MAIL_BODY_TEMPLATE_PATH}')
mail_body_obj = s3_client.get_object(Bucket=CONFIG_BUCKET_NAME, Key=NOTICE_MAIL_BODY_TEMPLATE_PATH)
mail_body_response = mail_body_obj['Body'].read().decode('utf-8')
# メール本文内のプレースホルダーを置き換える
mail_body = substitute_mail_body(mail_body_response, mail_msg)
logger.info('I-05-06 通知メール(本文)テンプレートファイルを読み込みました')
except Exception as e:
logger.error(f'E-05-02 通知メール(本文)テンプレートファイルの読み込みに失敗しました エラー内容:{e}')
raise FileReadException('E-05-02', e)
logger.info(f'I-05-07 メール送信指示をします 送信先トピック:{MBJ_SAP_NOTICE_TOPIC}')
mail_title_without_line_break = mail_title.splitlines()[0]
params = {
'TopicArn': MBJ_SAP_NOTICE_TOPIC,
'Subject': mail_title_without_line_break,
'Message': mail_body
}
sns_client.publish(**params)
logger.info('I-05-08 メール送信指示をしました')
else:
# 2.存在しない場合
logger.info('I-05-09 受領したファイルは月次I/Fファイルではないため、メール送信処理をスキップします')
# ⑥ 処理終了ログを出力する
logger.info('I-06-01 処理終了 SAP_finデータ月次I/F受領通知処理')
except CustomException as e:
traceback.print_exc()
error_notice(e.id, e.arg)
except Exception as e:
logger.error(f'E-99 想定外のエラーが発生しました エラー内容:{e}')
traceback.print_exc()
error_notice('E-99', e)
return
# 保守要員チーム通知
def error_notice(error_log_id, exception) -> None:
try:
error_msg = f'{error_log_id} のエラーが発生しました。ご確認ください\n詳細:{exception}'
params = {
'TopicArn': NDS_NOTICE_TOPIC,
'Subject': NDS_NOTICE_TITLE,
'Message': error_msg
}
sns_client.publish(**params)
logger.error(f'E-ERR-01 処理異常通知の送信指示をしました 通知先トピック:{NDS_NOTICE_TOPIC}')
except Exception as e:
logger.error(f'E-98 処理異常通知の送信指示に失敗しました エラー内容:{e}')
traceback.print_exc()
return
def substitute_mail_body(before_mail_body:str, mail_msg: str) -> str:
"""メール本文のプレースホルダーを置き換えます
Args:
before_mail_body (str): 置き換え前のメール本文
mail_msg (str): メール本文のプレースホルダーを置き換える文言
Returns:
str: 置き換え後のメール本文
"""
substitute_dict = {
"notice_file_names": mail_msg
}
mail_body = before_mail_body.format_map(substitute_dict)
return mail_body
# カスタムExceptionクラス
class CustomException(Exception, metaclass=ABCMeta):
def __init__(self, id, arg):
self.arg = arg
self.id = id
class FileReadException(CustomException):
pass

View File

@ -1,242 +1,243 @@
import os
import datetime
import boto3
import io
import re
import csv
import logging
from abc import *
from zoneinfo import ZoneInfo
import traceback
# 環境変数
CHECK_BUCKET_NAME = os.environ["CHECK_BUCKET_NAME"]
CONFIG_BUCKET_NAME = os.environ["CONFIG_BUCKET_NAME"]
RECEIVE_DAILY_FILE_NAME_LIST_PATH = os.environ["RECEIVE_DAILY_FILE_NAME_LIST_PATH"]
NON_BUSINESS_DAY_LIST_PATH = os.environ["NON_BUSINESS_DAY_LIST_PATH"]
NOTICE_MAIL_TITLE_TEMPLATE_PATH = os.environ["NOTICE_MAIL_TITLE_TEMPLATE_PATH"]
NOTICE_MAIL_BODY_TEMPLATE_PATH = os.environ["NOTICE_MAIL_BODY_TEMPLATE_PATH"]
MBJ_SAP_NOTICE_TOPIC = os.environ["MBJ_SAP_NOTICE_TOPIC"]
NDS_NOTICE_TOPIC = os.environ["NDS_NOTICE_TOPIC"]
NDS_NOTICE_TITLE = os.environ["NDS_NOTICE_TITLE"]
LOG_LEVEL = os.environ["LOG_LEVEL"]
# 定数
ROW_COMMENT_SYMBOL = '#'
INDEX_REGEX = 0
INDEX_DATA_NAME = 1
INDEX_ROW_COMMENT_SYMBOL = 0
INDEX_SPLIT_NUM = 1
INDEX_LAST = -1
# メール本文に出力する不足ファイル名一覧のインデント
MAIL_INDENT = '  '
# 変数
s3_client = boto3.client('s3')
s3_resource = boto3.resource('s3')
sns_client = boto3.client('sns')
# logger設定
logger = logging.getLogger()
def custome_time(*arg):
return datetime.datetime.now(ZoneInfo("Asia/Tokyo")).timetuple()
formatter = logging.Formatter(
'[%(levelname)s]\t%(asctime)s\t%(message)s\n',
'%Y-%m-%d %H:%M:%S'
)
formatter.converter = custome_time
for handler in logger.handlers:
handler.setFormatter(formatter)
level = logging.getLevelName(LOG_LEVEL)
if not isinstance(level, int):
level = logging.INFO
logger.setLevel(level)
def lambda_handler(event, context):
try:
# ① 処理開始ログを出力する
logger.info('I-01-01 処理開始 SAP_finデータ受領チェック処理日次')
execute_date = datetime.date.today().strftime('%Y/%m/%d')
logger.info(f'I-01-02 処理稼働日:{execute_date}')
mail_msg = ''
# ② 営業日チェック処理を行う
logger.info('I-02-01 営業日チェック処理開始')
# 1.設定ファイル[メルク社非営業日設定ファイル]を読み込む
try:
logger.info(f'I-02-02 非営業日設定ファイル読込 読込元:{CONFIG_BUCKET_NAME}/{NON_BUSINESS_DAY_LIST_PATH}')
non_business_day_obj = s3_resource.Object(CONFIG_BUCKET_NAME, NON_BUSINESS_DAY_LIST_PATH)
non_business_day_response = non_business_day_obj.get()
logger.info('I-02-03 非営業日設定ファイルを読み込みました')
except Exception as e:
logger.error(f'E-02-01 非営業日設定ファイルの読み込みに失敗しました エラー内容:{e}')
raise FileReadException('E-02-01', e)
# 2.処理稼働日が「②1.」で読み込んだ「メルク社非営業日設定ファイル」に存在するか確認する
try:
logger.info(f'I-02-04 本日が非営業日かチェックします チェック日:{execute_date}')
none_business_day_list = []
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
else:
logger.info('I-02-06 本日は営業日のため、チェック処理を実施します')
except Exception as e:
logger.error(f'E-02-02 メルク社非営業日設定ファイルに不備があります エラー内容:{e}')
raise NoneBusinessDayException('E-02-02', e)
# ③ 設定ファイル[SAP_finI/Fファイルネーム設定ファイル日次]を読み込む
try:
logger.info(f'I-03-01 日次I/Fファイルネーム設定ファイル読込 読込元{CONFIG_BUCKET_NAME}/{RECEIVE_DAILY_FILE_NAME_LIST_PATH}')
receive_daily_file_name_obj = s3_resource.Object(CONFIG_BUCKET_NAME, RECEIVE_DAILY_FILE_NAME_LIST_PATH)
receive_daily_file_name_response = receive_daily_file_name_obj.get()
logger.info('I-03-02 日次I/Fファイルネーム設定ファイルを読み込みました')
except Exception as e:
logger.error(f'E-03-01 日次I/Fファイルネーム設定ファイルの読み込みに失敗しました エラー内容{e}')
raise FileReadException('E-03-01', e)
# ④ 日次チェック処理を行う
logger.info('I-04-01 日次チェック処理開始')
# 1.SAP保管用バケットの処理稼働日に該当するサブフォルダにあるファイル一覧を取得する
logger.info(f'I-04-02 オブジェクトリストの取得 取得先:{CHECK_BUCKET_NAME}/{execute_date}/')
object_prefix = f'{execute_date}/'
object_list = s3_resource.Bucket(CHECK_BUCKET_NAME).objects.filter(Prefix=object_prefix)
file_list = []
for obj in object_list:
obj_key = obj.key.rsplit('/', INDEX_SPLIT_NUM)
file_list.append(obj_key[INDEX_LAST])
# 2.日次I/Fファイルチェック処理
logger.info('I-04-03 日次I/Fファイルチェック処理開始')
logger.info('I-04-04 取得したオブジェクトリストと日次I/Fファイルネーム設定ファイルの突き合わせを開始します')
receive_daily_file_name_body = io.TextIOWrapper(io.BytesIO(receive_daily_file_name_response["Body"].read()), encoding='utf-8')
match_count = 0
row_count = sum(1 for line in io.BytesIO(receive_daily_file_name_obj.get()["Body"].read()))
for row in csv.reader(receive_daily_file_name_body, delimiter='\t'):
file_exists = False
for file_name in file_list:
match_result = re.fullmatch(row[INDEX_REGEX], file_name)
if match_result is not None:
file_exists = True
break
if file_exists == True:
match_count += 1
logger.info(f'I-04-05 日次I/Fファイルの受領を確認しました ファイル名{file_name}')
else:
logger.error(f'E-04-01 日次I/Fファイルに不足があります ファイル名{row[INDEX_DATA_NAME]}')
mail_msg += f'{MAIL_INDENT}{row[INDEX_DATA_NAME]}\n'
if row_count == match_count:
logger.info('I-04-06 日次I/Fファイルは全て受領していることを確認しました')
# ⑤ 「①」でメモリ保持しているメール挿入用文言に出力内容が存在するか確認する
logger.info('I-05-01 メール送信処理開始')
if len(mail_msg) > 0:
# 1.存在した場合
logger.info(f'I-05-02 {execute_date} 日次I/Fファイルに不足があるため、メール送信処理を開始します')
try:
logger.info(f'I-05-03 通知メール(タイトル)テンプレートファイル読込 読込元:{CONFIG_BUCKET_NAME}/{NOTICE_MAIL_TITLE_TEMPLATE_PATH}')
mail_title_obj = s3_client.get_object(Bucket=CONFIG_BUCKET_NAME, Key=NOTICE_MAIL_TITLE_TEMPLATE_PATH)
mail_title = mail_title_obj['Body'].read().decode('utf-8')
logger.info('I-05-04 通知メール(タイトル)テンプレートファイルを読み込みました')
except Exception as e:
logger.error(f'E-05-01 通知メール(タイトル)テンプレートファイルの読み込みに失敗しました エラー内容:{e}')
raise FileReadException('E-05-01', e)
try:
logger.info(f'I-05-05 通知メール(本文)テンプレートファイル読込 読込元:{CONFIG_BUCKET_NAME}/{NOTICE_MAIL_BODY_TEMPLATE_PATH}')
mail_body_obj = s3_client.get_object(Bucket=CONFIG_BUCKET_NAME, Key=NOTICE_MAIL_BODY_TEMPLATE_PATH)
mail_body_response = mail_body_obj['Body'].read().decode('utf-8')
# メール本文内のプレースホルダーを置き換える
mail_body = substitute_mail_body(mail_body_response, mail_msg)
logger.info('I-05-06 通知メール(本文)テンプレートファイルを読み込みました')
except Exception as e:
logger.error(f'E-05-02 通知メール(本文)テンプレートファイルの読み込みに失敗しました エラー内容:{e}')
raise FileReadException('E-05-02', e)
logger.info(f'I-05-07 メール送信指示をします 送信先トピック:{MBJ_SAP_NOTICE_TOPIC}')
params = {
'TopicArn': MBJ_SAP_NOTICE_TOPIC,
'Subject': mail_title.rstrip('\n'),
'Message': mail_body
}
sns_client.publish(**params)
logger.info('I-05-08 メール送信指示をしました')
else:
# 2.存在しない場合
logger.info(f'I-05-09 {execute_date} 日次I/Fファイルに不足がなかったため、メール送信処理をスキップします')
# ⑥ 処理終了ログを出力する
logger.info('I-06-01 処理終了 SAP_finデータ受領チェック処理日次')
except CustomException as e:
traceback.print_exc()
error_notice(e.id, e.arg)
except Exception as e:
logger.error(f'E-99 想定外のエラーが発生しました エラー内容:{e}')
traceback.print_exc()
error_notice('E-99', e)
return
# 保守要員チーム通知
def error_notice(error_log_id, exception) -> None:
try:
error_msg = f'{error_log_id} のエラーが発生しました。ご確認ください\n詳細:{exception}'
params = {
'TopicArn': NDS_NOTICE_TOPIC,
'Subject': NDS_NOTICE_TITLE,
'Message': error_msg
}
sns_client.publish(**params)
logger.error(f'E-ERR-01 処理異常通知の送信指示をしました 通知先トピック:{NDS_NOTICE_TOPIC}')
except Exception as e:
logger.error(f'E-98 処理異常通知の送信指示に失敗しました エラー内容:{e}')
traceback.print_exc()
return
def substitute_mail_body(before_mail_body:str, mail_msg: str) -> str:
"""メール本文のプレースホルダーを置き換えます
Args:
before_mail_body (str): 置き換え前のメール本文
mail_msg (str): メール本文のプレースホルダーを置き換える文言
Returns:
str: 置き換え後のメール本文
"""
substitute_dict = {
"notice_file_names": mail_msg
}
mail_body = before_mail_body.format_map(substitute_dict)
return mail_body
# カスタムExceptionクラス
class CustomException(Exception, metaclass=ABCMeta):
def __init__(self, id, arg):
self.arg = arg
self.id = id
class FileReadException(CustomException):
pass
class NoneBusinessDayException(CustomException):
pass
import os
import datetime
import boto3
import io
import re
import csv
import logging
from abc import *
from zoneinfo import ZoneInfo
import traceback
# 環境変数
CHECK_BUCKET_NAME = os.environ["CHECK_BUCKET_NAME"]
CONFIG_BUCKET_NAME = os.environ["CONFIG_BUCKET_NAME"]
RECEIVE_DAILY_FILE_NAME_LIST_PATH = os.environ["RECEIVE_DAILY_FILE_NAME_LIST_PATH"]
NON_BUSINESS_DAY_LIST_PATH = os.environ["NON_BUSINESS_DAY_LIST_PATH"]
NOTICE_MAIL_TITLE_TEMPLATE_PATH = os.environ["NOTICE_MAIL_TITLE_TEMPLATE_PATH"]
NOTICE_MAIL_BODY_TEMPLATE_PATH = os.environ["NOTICE_MAIL_BODY_TEMPLATE_PATH"]
MBJ_SAP_NOTICE_TOPIC = os.environ["MBJ_SAP_NOTICE_TOPIC"]
NDS_NOTICE_TOPIC = os.environ["NDS_NOTICE_TOPIC"]
NDS_NOTICE_TITLE = os.environ["NDS_NOTICE_TITLE"]
LOG_LEVEL = os.environ["LOG_LEVEL"]
# 定数
ROW_COMMENT_SYMBOL = '#'
INDEX_REGEX = 0
INDEX_DATA_NAME = 1
INDEX_ROW_COMMENT_SYMBOL = 0
INDEX_SPLIT_NUM = 1
INDEX_LAST = -1
# メール本文に出力する不足ファイル名一覧のインデント
MAIL_INDENT = '  '
# 変数
s3_client = boto3.client('s3')
s3_resource = boto3.resource('s3')
sns_client = boto3.client('sns')
# logger設定
logger = logging.getLogger()
def custome_time(*arg):
return datetime.datetime.now(ZoneInfo("Asia/Tokyo")).timetuple()
formatter = logging.Formatter(
'[%(levelname)s]\t%(asctime)s\t%(message)s\n',
'%Y-%m-%d %H:%M:%S'
)
formatter.converter = custome_time
for handler in logger.handlers:
handler.setFormatter(formatter)
level = logging.getLevelName(LOG_LEVEL)
if not isinstance(level, int):
level = logging.INFO
logger.setLevel(level)
def lambda_handler(event, context):
try:
# ① 処理開始ログを出力する
logger.info('I-01-01 処理開始 SAP_finデータ受領チェック処理日次')
execute_date = datetime.date.today().strftime('%Y/%m/%d')
logger.info(f'I-01-02 処理稼働日:{execute_date}')
mail_msg = ''
# ② 営業日チェック処理を行う
logger.info('I-02-01 営業日チェック処理開始')
# 1.設定ファイル[メルク社非営業日設定ファイル]を読み込む
try:
logger.info(f'I-02-02 非営業日設定ファイル読込 読込元:{CONFIG_BUCKET_NAME}/{NON_BUSINESS_DAY_LIST_PATH}')
non_business_day_obj = s3_resource.Object(CONFIG_BUCKET_NAME, NON_BUSINESS_DAY_LIST_PATH)
non_business_day_response = non_business_day_obj.get()
logger.info('I-02-03 非営業日設定ファイルを読み込みました')
except Exception as e:
logger.error(f'E-02-01 非営業日設定ファイルの読み込みに失敗しました エラー内容:{e}')
raise FileReadException('E-02-01', e)
# 2.処理稼働日が「②1.」で読み込んだ「メルク社非営業日設定ファイル」に存在するか確認する
try:
logger.info(f'I-02-04 本日が非営業日かチェックします チェック日:{execute_date}')
none_business_day_list = []
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
else:
logger.info('I-02-06 本日は営業日のため、チェック処理を実施します')
except Exception as e:
logger.error(f'E-02-02 メルク社非営業日設定ファイルに不備があります エラー内容:{e}')
raise NoneBusinessDayException('E-02-02', e)
# ③ 設定ファイル[SAP_finI/Fファイルネーム設定ファイル日次]を読み込む
try:
logger.info(f'I-03-01 日次I/Fファイルネーム設定ファイル読込 読込元{CONFIG_BUCKET_NAME}/{RECEIVE_DAILY_FILE_NAME_LIST_PATH}')
receive_daily_file_name_obj = s3_resource.Object(CONFIG_BUCKET_NAME, RECEIVE_DAILY_FILE_NAME_LIST_PATH)
receive_daily_file_name_response = receive_daily_file_name_obj.get()
logger.info('I-03-02 日次I/Fファイルネーム設定ファイルを読み込みました')
except Exception as e:
logger.error(f'E-03-01 日次I/Fファイルネーム設定ファイルの読み込みに失敗しました エラー内容{e}')
raise FileReadException('E-03-01', e)
# ④ 日次チェック処理を行う
logger.info('I-04-01 日次チェック処理開始')
# 1.SAP保管用バケットの処理稼働日に該当するサブフォルダにあるファイル一覧を取得する
logger.info(f'I-04-02 オブジェクトリストの取得 取得先:{CHECK_BUCKET_NAME}/{execute_date}/')
object_prefix = f'{execute_date}/'
object_list = s3_resource.Bucket(CHECK_BUCKET_NAME).objects.filter(Prefix=object_prefix)
file_list = []
for obj in object_list:
obj_key = obj.key.rsplit('/', INDEX_SPLIT_NUM)
file_list.append(obj_key[INDEX_LAST])
# 2.日次I/Fファイルチェック処理
logger.info('I-04-03 日次I/Fファイルチェック処理開始')
logger.info('I-04-04 取得したオブジェクトリストと日次I/Fファイルネーム設定ファイルの突き合わせを開始します')
receive_daily_file_name_body = io.TextIOWrapper(io.BytesIO(receive_daily_file_name_response["Body"].read()), encoding='utf-8')
match_count = 0
row_count = sum(1 for line in io.BytesIO(receive_daily_file_name_obj.get()["Body"].read()))
for row in csv.reader(receive_daily_file_name_body, delimiter='\t'):
file_exists = False
for file_name in file_list:
match_result = re.fullmatch(row[INDEX_REGEX], file_name)
if match_result is not None:
file_exists = True
break
if file_exists == True:
match_count += 1
logger.info(f'I-04-05 日次I/Fファイルの受領を確認しました ファイル名{file_name}')
else:
logger.error(f'E-04-01 日次I/Fファイルに不足があります ファイル名{row[INDEX_DATA_NAME]}')
mail_msg += f'{MAIL_INDENT}{row[INDEX_DATA_NAME]}\n'
if row_count == match_count:
logger.info('I-04-06 日次I/Fファイルは全て受領していることを確認しました')
# ⑤ 「①」でメモリ保持しているメール挿入用文言に出力内容が存在するか確認する
logger.info('I-05-01 メール送信処理開始')
if len(mail_msg) > 0:
# 1.存在した場合
logger.info(f'I-05-02 {execute_date} 日次I/Fファイルに不足があるため、メール送信処理を開始します')
try:
logger.info(f'I-05-03 通知メール(タイトル)テンプレートファイル読込 読込元:{CONFIG_BUCKET_NAME}/{NOTICE_MAIL_TITLE_TEMPLATE_PATH}')
mail_title_obj = s3_client.get_object(Bucket=CONFIG_BUCKET_NAME, Key=NOTICE_MAIL_TITLE_TEMPLATE_PATH)
mail_title = mail_title_obj['Body'].read().decode('utf-8')
logger.info('I-05-04 通知メール(タイトル)テンプレートファイルを読み込みました')
except Exception as e:
logger.error(f'E-05-01 通知メール(タイトル)テンプレートファイルの読み込みに失敗しました エラー内容:{e}')
raise FileReadException('E-05-01', e)
try:
logger.info(f'I-05-05 通知メール(本文)テンプレートファイル読込 読込元:{CONFIG_BUCKET_NAME}/{NOTICE_MAIL_BODY_TEMPLATE_PATH}')
mail_body_obj = s3_client.get_object(Bucket=CONFIG_BUCKET_NAME, Key=NOTICE_MAIL_BODY_TEMPLATE_PATH)
mail_body_response = mail_body_obj['Body'].read().decode('utf-8')
# メール本文内のプレースホルダーを置き換える
mail_body = substitute_mail_body(mail_body_response, mail_msg)
logger.info('I-05-06 通知メール(本文)テンプレートファイルを読み込みました')
except Exception as e:
logger.error(f'E-05-02 通知メール(本文)テンプレートファイルの読み込みに失敗しました エラー内容:{e}')
raise FileReadException('E-05-02', e)
logger.info(f'I-05-07 メール送信指示をします 送信先トピック:{MBJ_SAP_NOTICE_TOPIC}')
mail_title_without_line_break = mail_title.splitlines()[0]
params = {
'TopicArn': MBJ_SAP_NOTICE_TOPIC,
'Subject': mail_title_without_line_break,
'Message': mail_body
}
sns_client.publish(**params)
logger.info('I-05-08 メール送信指示をしました')
else:
# 2.存在しない場合
logger.info(f'I-05-09 {execute_date} 日次I/Fファイルに不足がなかったため、メール送信処理をスキップします')
# ⑥ 処理終了ログを出力する
logger.info('I-06-01 処理終了 SAP_finデータ受領チェック処理日次')
except CustomException as e:
traceback.print_exc()
error_notice(e.id, e.arg)
except Exception as e:
logger.error(f'E-99 想定外のエラーが発生しました エラー内容:{e}')
traceback.print_exc()
error_notice('E-99', e)
return
# 保守要員チーム通知
def error_notice(error_log_id, exception) -> None:
try:
error_msg = f'{error_log_id} のエラーが発生しました。ご確認ください\n詳細:{exception}'
params = {
'TopicArn': NDS_NOTICE_TOPIC,
'Subject': NDS_NOTICE_TITLE,
'Message': error_msg
}
sns_client.publish(**params)
logger.error(f'E-ERR-01 処理異常通知の送信指示をしました 通知先トピック:{NDS_NOTICE_TOPIC}')
except Exception as e:
logger.error(f'E-98 処理異常通知の送信指示に失敗しました エラー内容:{e}')
traceback.print_exc()
return
def substitute_mail_body(before_mail_body:str, mail_msg: str) -> str:
"""メール本文のプレースホルダーを置き換えます
Args:
before_mail_body (str): 置き換え前のメール本文
mail_msg (str): メール本文のプレースホルダーを置き換える文言
Returns:
str: 置き換え後のメール本文
"""
substitute_dict = {
"notice_file_names": mail_msg
}
mail_body = before_mail_body.format_map(substitute_dict)
return mail_body
# カスタムExceptionクラス
class CustomException(Exception, metaclass=ABCMeta):
def __init__(self, id, arg):
self.arg = arg
self.id = id
class FileReadException(CustomException):
pass
class NoneBusinessDayException(CustomException):
pass

View File

@ -173,9 +173,10 @@ def lambda_handler(event, context):
raise FileReadException('E-05-02', e)
logger.info(f'I-05-07 メール送信指示をします 送信先トピック:{MBJ_SAP_NOTICE_TOPIC}')
mail_title_without_line_break = mail_title.splitlines()[0]
params = {
'TopicArn': MBJ_SAP_NOTICE_TOPIC,
'Subject': mail_title.rstrip('\n'),
'Subject': mail_title_without_line_break,
'Message': mail_body
}
sns_client.publish(**params)

View File

@ -1,186 +1,187 @@
import os
import datetime
import boto3
import io
import re
import csv
import logging
from abc import *
from zoneinfo import ZoneInfo
import traceback
# 環境変数
CONFIG_BUCKET_NAME = os.environ["CONFIG_BUCKET_NAME"]
RECEIVE_MONTHLY_FILE_NAME_LIST_PATH = os.environ["RECEIVE_MONTHLY_FILE_NAME_LIST_PATH"]
NOTICE_MAIL_TITLE_TEMPLATE_PATH = os.environ["NOTICE_MAIL_TITLE_TEMPLATE_PATH"]
NOTICE_MAIL_BODY_TEMPLATE_PATH = os.environ["NOTICE_MAIL_BODY_TEMPLATE_PATH"]
MBJ_SAP_NOTICE_TOPIC = os.environ["MBJ_SAP_NOTICE_TOPIC"]
NDS_NOTICE_TOPIC = os.environ["NDS_NOTICE_TOPIC"]
NDS_NOTICE_TITLE = os.environ["NDS_NOTICE_TITLE"]
LOG_LEVEL = os.environ["LOG_LEVEL"]
# 定数
INDEX_REGEX = 0
INDEX_DATA_NAME = 1
# メール本文に出力する不足ファイル名一覧のインデント
MAIL_INDENT = '  '
# 変数
s3_client = boto3.client('s3')
s3_resource = boto3.resource('s3')
sns_client = boto3.client('sns')
# logger設定
logger = logging.getLogger()
def custome_time(*arg):
return datetime.datetime.now(ZoneInfo("Asia/Tokyo")).timetuple()
formatter = logging.Formatter(
'[%(levelname)s]\t%(asctime)s\t%(message)s\n',
'%Y-%m-%d %H:%M:%S'
)
formatter.converter = custome_time
for handler in logger.handlers:
handler.setFormatter(formatter)
level = logging.getLevelName(LOG_LEVEL)
if not isinstance(level, int):
level = logging.INFO
logger.setLevel(level)
def lambda_handler(event, context):
try:
# ① 処理開始ログを出力する
logger.info('I-01-01 処理開始 SAP_supデータ月次I/F受領通知処理')
execute_date = datetime.date.today().strftime('%Y/%m/%d')
logger.info(f'I-01-02 処理稼働日:{execute_date}')
mail_msg = ''
# ② 処理開始時に受け取ったイベント情報の以下内容をログに出力しメモリに保持する
logger.info('I-02-01 イベント情報出力処理')
s3_event = event["Records"][0]["s3"]
event_bucket_name = s3_event["bucket"]["name"]
event_file_path = s3_event["object"]["key"]
event_file_name = os.path.basename(event_file_path)
logger.info(f'I-02-02 バケット名:{event_bucket_name}')
logger.info(f'I-02-03 ファイルパス:{event_file_path}')
# ③ 設定ファイル[SAP_supI/Fファイルネーム設定ファイル月次]を読み込む
try:
logger.info(f'I-03-01 月次I/Fファイルネーム設定ファイル読込 読込元{CONFIG_BUCKET_NAME}/{RECEIVE_MONTHLY_FILE_NAME_LIST_PATH}')
receive_monthly_file_name_obj = s3_resource.Object(CONFIG_BUCKET_NAME, RECEIVE_MONTHLY_FILE_NAME_LIST_PATH)
receive_monthly_file_name_response = receive_monthly_file_name_obj.get()
logger.info('I-03-02 月次I/Fファイルネーム設定ファイルを読み込みました')
except Exception as e:
logger.error(f'E-03-01 月次I/Fファイルネーム設定ファイルの読み込みに失敗しました エラー内容{e}')
raise FileReadException('E-03-01', e)
# ④ 月次I/Fファイル受領通知処理を行う
logger.info('I-04-01 月次I/Fファイル受領通知処理開始')
logger.info(f'I-04-02 受領したファイル名:{event_file_name}')
logger.info('I-04-03 受領したファイル名と月次I/Fファイルネーム設定ファイルの突き合わせを開始します')
file_exists = False
receive_monthly_file_name_body = io.TextIOWrapper(io.BytesIO(receive_monthly_file_name_response["Body"].read()), encoding='utf-8')
for row in csv.reader(receive_monthly_file_name_body, delimiter='\t'):
match_result = re.fullmatch(row[INDEX_REGEX], event_file_name)
if match_result is not None:
file_exists = True
break
if file_exists == True:
logger.info(f'I-04-04 月次I/Fを受領しました ファイル名{row[INDEX_DATA_NAME]} {event_file_name}')
mail_msg += f'{MAIL_INDENT}{row[INDEX_DATA_NAME]} {event_file_name}\n'
else:
logger.info('I-04-05 受領したファイルは月次I/Fではありませんでした')
# ⑤ 「①」でメモリ保持しているメール挿入用文言に出力内容が存在するか確認する
logger.info('I-05-01 メール送信処理開始')
if len(mail_msg) > 0:
# 1.存在した場合
logger.info('I-05-02 月次I/Fファイルを受領したため、メール送信処理を開始します')
try:
logger.info(f'I-05-03 通知メール(タイトル)テンプレートファイル読込 読込元:{CONFIG_BUCKET_NAME}/{NOTICE_MAIL_TITLE_TEMPLATE_PATH}')
mail_title_obj = s3_client.get_object(Bucket=CONFIG_BUCKET_NAME, Key=NOTICE_MAIL_TITLE_TEMPLATE_PATH)
mail_title = mail_title_obj['Body'].read().decode('utf-8')
logger.info('I-05-04 通知メール(タイトル)テンプレートファイルを読み込みました')
except Exception as e:
logger.error(f'E-05-01 通知メール(タイトル)テンプレートファイルの読み込みに失敗しました エラー内容:{e}')
raise FileReadException('E-05-01', e)
try:
logger.info(f'I-05-05 通知メール(本文)テンプレートファイル読込 読込元:{CONFIG_BUCKET_NAME}/{NOTICE_MAIL_BODY_TEMPLATE_PATH}')
mail_body_obj = s3_client.get_object(Bucket=CONFIG_BUCKET_NAME, Key=NOTICE_MAIL_BODY_TEMPLATE_PATH)
mail_body_response = mail_body_obj['Body'].read().decode('utf-8')
# メール本文内のプレースホルダーを置き換える
mail_body = substitute_mail_body(mail_body_response, mail_msg)
logger.info('I-05-06 通知メール(本文)テンプレートファイルを読み込みました')
except Exception as e:
logger.error(f'E-05-02 通知メール(本文)テンプレートファイルの読み込みに失敗しました エラー内容:{e}')
raise FileReadException('E-05-02', e)
logger.info(f'I-05-07 メール送信指示をします 送信先トピック:{MBJ_SAP_NOTICE_TOPIC}')
params = {
'TopicArn': MBJ_SAP_NOTICE_TOPIC,
'Subject': mail_title.rstrip('\n'),
'Message': mail_body
}
sns_client.publish(**params)
logger.info('I-05-08 メール送信指示をしました')
else:
# 2.存在しない場合
logger.info('I-05-09 受領したファイルは月次I/Fファイルではないため、メール送信処理をスキップします')
# ⑥ 処理終了ログを出力する
logger.info('I-06-01 処理終了 SAP_supデータ月次I/F受領通知処理')
except CustomException as e:
traceback.print_exc()
error_notice(e.id, e.arg)
except Exception as e:
logger.error(f'E-99 想定外のエラーが発生しました エラー内容:{e}')
traceback.print_exc()
error_notice('E-99', e)
return
# 保守要員チーム通知
def error_notice(error_log_id, exception) -> None:
try:
error_msg = f'{error_log_id} のエラーが発生しました。ご確認ください\n詳細:{exception}'
params = {
'TopicArn': NDS_NOTICE_TOPIC,
'Subject': NDS_NOTICE_TITLE,
'Message': error_msg
}
sns_client.publish(**params)
logger.error(f'E-ERR-01 処理異常通知の送信指示をしました 通知先トピック:{NDS_NOTICE_TOPIC}')
except Exception as e:
logger.error(f'E-98 処理異常通知の送信指示に失敗しました エラー内容:{e}')
traceback.print_exc()
return
def substitute_mail_body(before_mail_body:str, mail_msg: str) -> str:
"""メール本文のプレースホルダーを置き換えます
Args:
before_mail_body (str): 置き換え前のメール本文
mail_msg (str): メール本文のプレースホルダーを置き換える文言
Returns:
str: 置き換え後のメール本文
"""
substitute_dict = {
"notice_file_names": mail_msg
}
mail_body = before_mail_body.format_map(substitute_dict)
return mail_body
# カスタムExceptionクラス
class CustomException(Exception, metaclass=ABCMeta):
def __init__(self, id, arg):
self.arg = arg
self.id = id
class FileReadException(CustomException):
pass
import os
import datetime
import boto3
import io
import re
import csv
import logging
from abc import *
from zoneinfo import ZoneInfo
import traceback
# 環境変数
CONFIG_BUCKET_NAME = os.environ["CONFIG_BUCKET_NAME"]
RECEIVE_MONTHLY_FILE_NAME_LIST_PATH = os.environ["RECEIVE_MONTHLY_FILE_NAME_LIST_PATH"]
NOTICE_MAIL_TITLE_TEMPLATE_PATH = os.environ["NOTICE_MAIL_TITLE_TEMPLATE_PATH"]
NOTICE_MAIL_BODY_TEMPLATE_PATH = os.environ["NOTICE_MAIL_BODY_TEMPLATE_PATH"]
MBJ_SAP_NOTICE_TOPIC = os.environ["MBJ_SAP_NOTICE_TOPIC"]
NDS_NOTICE_TOPIC = os.environ["NDS_NOTICE_TOPIC"]
NDS_NOTICE_TITLE = os.environ["NDS_NOTICE_TITLE"]
LOG_LEVEL = os.environ["LOG_LEVEL"]
# 定数
INDEX_REGEX = 0
INDEX_DATA_NAME = 1
# メール本文に出力する不足ファイル名一覧のインデント
MAIL_INDENT = '  '
# 変数
s3_client = boto3.client('s3')
s3_resource = boto3.resource('s3')
sns_client = boto3.client('sns')
# logger設定
logger = logging.getLogger()
def custome_time(*arg):
return datetime.datetime.now(ZoneInfo("Asia/Tokyo")).timetuple()
formatter = logging.Formatter(
'[%(levelname)s]\t%(asctime)s\t%(message)s\n',
'%Y-%m-%d %H:%M:%S'
)
formatter.converter = custome_time
for handler in logger.handlers:
handler.setFormatter(formatter)
level = logging.getLevelName(LOG_LEVEL)
if not isinstance(level, int):
level = logging.INFO
logger.setLevel(level)
def lambda_handler(event, context):
try:
# ① 処理開始ログを出力する
logger.info('I-01-01 処理開始 SAP_supデータ月次I/F受領通知処理')
execute_date = datetime.date.today().strftime('%Y/%m/%d')
logger.info(f'I-01-02 処理稼働日:{execute_date}')
mail_msg = ''
# ② 処理開始時に受け取ったイベント情報の以下内容をログに出力しメモリに保持する
logger.info('I-02-01 イベント情報出力処理')
s3_event = event["Records"][0]["s3"]
event_bucket_name = s3_event["bucket"]["name"]
event_file_path = s3_event["object"]["key"]
event_file_name = os.path.basename(event_file_path)
logger.info(f'I-02-02 バケット名:{event_bucket_name}')
logger.info(f'I-02-03 ファイルパス:{event_file_path}')
# ③ 設定ファイル[SAP_supI/Fファイルネーム設定ファイル月次]を読み込む
try:
logger.info(f'I-03-01 月次I/Fファイルネーム設定ファイル読込 読込元{CONFIG_BUCKET_NAME}/{RECEIVE_MONTHLY_FILE_NAME_LIST_PATH}')
receive_monthly_file_name_obj = s3_resource.Object(CONFIG_BUCKET_NAME, RECEIVE_MONTHLY_FILE_NAME_LIST_PATH)
receive_monthly_file_name_response = receive_monthly_file_name_obj.get()
logger.info('I-03-02 月次I/Fファイルネーム設定ファイルを読み込みました')
except Exception as e:
logger.error(f'E-03-01 月次I/Fファイルネーム設定ファイルの読み込みに失敗しました エラー内容{e}')
raise FileReadException('E-03-01', e)
# ④ 月次I/Fファイル受領通知処理を行う
logger.info('I-04-01 月次I/Fファイル受領通知処理開始')
logger.info(f'I-04-02 受領したファイル名:{event_file_name}')
logger.info('I-04-03 受領したファイル名と月次I/Fファイルネーム設定ファイルの突き合わせを開始します')
file_exists = False
receive_monthly_file_name_body = io.TextIOWrapper(io.BytesIO(receive_monthly_file_name_response["Body"].read()), encoding='utf-8')
for row in csv.reader(receive_monthly_file_name_body, delimiter='\t'):
match_result = re.fullmatch(row[INDEX_REGEX], event_file_name)
if match_result is not None:
file_exists = True
break
if file_exists == True:
logger.info(f'I-04-04 月次I/Fを受領しました ファイル名{row[INDEX_DATA_NAME]} {event_file_name}')
mail_msg += f'{MAIL_INDENT}{row[INDEX_DATA_NAME]} {event_file_name}\n'
else:
logger.info('I-04-05 受領したファイルは月次I/Fではありませんでした')
# ⑤ 「①」でメモリ保持しているメール挿入用文言に出力内容が存在するか確認する
logger.info('I-05-01 メール送信処理開始')
if len(mail_msg) > 0:
# 1.存在した場合
logger.info('I-05-02 月次I/Fファイルを受領したため、メール送信処理を開始します')
try:
logger.info(f'I-05-03 通知メール(タイトル)テンプレートファイル読込 読込元:{CONFIG_BUCKET_NAME}/{NOTICE_MAIL_TITLE_TEMPLATE_PATH}')
mail_title_obj = s3_client.get_object(Bucket=CONFIG_BUCKET_NAME, Key=NOTICE_MAIL_TITLE_TEMPLATE_PATH)
mail_title = mail_title_obj['Body'].read().decode('utf-8')
logger.info('I-05-04 通知メール(タイトル)テンプレートファイルを読み込みました')
except Exception as e:
logger.error(f'E-05-01 通知メール(タイトル)テンプレートファイルの読み込みに失敗しました エラー内容:{e}')
raise FileReadException('E-05-01', e)
try:
logger.info(f'I-05-05 通知メール(本文)テンプレートファイル読込 読込元:{CONFIG_BUCKET_NAME}/{NOTICE_MAIL_BODY_TEMPLATE_PATH}')
mail_body_obj = s3_client.get_object(Bucket=CONFIG_BUCKET_NAME, Key=NOTICE_MAIL_BODY_TEMPLATE_PATH)
mail_body_response = mail_body_obj['Body'].read().decode('utf-8')
# メール本文内のプレースホルダーを置き換える
mail_body = substitute_mail_body(mail_body_response, mail_msg)
logger.info('I-05-06 通知メール(本文)テンプレートファイルを読み込みました')
except Exception as e:
logger.error(f'E-05-02 通知メール(本文)テンプレートファイルの読み込みに失敗しました エラー内容:{e}')
raise FileReadException('E-05-02', e)
logger.info(f'I-05-07 メール送信指示をします 送信先トピック:{MBJ_SAP_NOTICE_TOPIC}')
mail_title_without_line_break = mail_title.splitlines()[0]
params = {
'TopicArn': MBJ_SAP_NOTICE_TOPIC,
'Subject': mail_title_without_line_break,
'Message': mail_body
}
sns_client.publish(**params)
logger.info('I-05-08 メール送信指示をしました')
else:
# 2.存在しない場合
logger.info('I-05-09 受領したファイルは月次I/Fファイルではないため、メール送信処理をスキップします')
# ⑥ 処理終了ログを出力する
logger.info('I-06-01 処理終了 SAP_supデータ月次I/F受領通知処理')
except CustomException as e:
traceback.print_exc()
error_notice(e.id, e.arg)
except Exception as e:
logger.error(f'E-99 想定外のエラーが発生しました エラー内容:{e}')
traceback.print_exc()
error_notice('E-99', e)
return
# 保守要員チーム通知
def error_notice(error_log_id, exception) -> None:
try:
error_msg = f'{error_log_id} のエラーが発生しました。ご確認ください\n詳細:{exception}'
params = {
'TopicArn': NDS_NOTICE_TOPIC,
'Subject': NDS_NOTICE_TITLE,
'Message': error_msg
}
sns_client.publish(**params)
logger.error(f'E-ERR-01 処理異常通知の送信指示をしました 通知先トピック:{NDS_NOTICE_TOPIC}')
except Exception as e:
logger.error(f'E-98 処理異常通知の送信指示に失敗しました エラー内容:{e}')
traceback.print_exc()
return
def substitute_mail_body(before_mail_body:str, mail_msg: str) -> str:
"""メール本文のプレースホルダーを置き換えます
Args:
before_mail_body (str): 置き換え前のメール本文
mail_msg (str): メール本文のプレースホルダーを置き換える文言
Returns:
str: 置き換え後のメール本文
"""
substitute_dict = {
"notice_file_names": mail_msg
}
mail_body = before_mail_body.format_map(substitute_dict)
return mail_body
# カスタムExceptionクラス
class CustomException(Exception, metaclass=ABCMeta):
def __init__(self, id, arg):
self.arg = arg
self.id = id
class FileReadException(CustomException):
pass

View File

@ -1,242 +1,243 @@
import os
import datetime
import boto3
import io
import re
import csv
import logging
from abc import *
from zoneinfo import ZoneInfo
import traceback
# 環境変数
CHECK_BUCKET_NAME = os.environ["CHECK_BUCKET_NAME"]
CONFIG_BUCKET_NAME = os.environ["CONFIG_BUCKET_NAME"]
RECEIVE_DAILY_FILE_NAME_LIST_PATH = os.environ["RECEIVE_DAILY_FILE_NAME_LIST_PATH"]
NON_BUSINESS_DAY_LIST_PATH = os.environ["NON_BUSINESS_DAY_LIST_PATH"]
NOTICE_MAIL_TITLE_TEMPLATE_PATH = os.environ["NOTICE_MAIL_TITLE_TEMPLATE_PATH"]
NOTICE_MAIL_BODY_TEMPLATE_PATH = os.environ["NOTICE_MAIL_BODY_TEMPLATE_PATH"]
MBJ_SAP_NOTICE_TOPIC = os.environ["MBJ_SAP_NOTICE_TOPIC"]
NDS_NOTICE_TOPIC = os.environ["NDS_NOTICE_TOPIC"]
NDS_NOTICE_TITLE = os.environ["NDS_NOTICE_TITLE"]
LOG_LEVEL = os.environ["LOG_LEVEL"]
# 定数
ROW_COMMENT_SYMBOL = '#'
INDEX_REGEX = 0
INDEX_DATA_NAME = 1
INDEX_ROW_COMMENT_SYMBOL = 0
INDEX_SPLIT_NUM = 1
INDEX_LAST = -1
# メール本文に出力する不足ファイル名一覧のインデント
MAIL_INDENT = '  '
# 変数
s3_client = boto3.client('s3')
s3_resource = boto3.resource('s3')
sns_client = boto3.client('sns')
# logger設定
logger = logging.getLogger()
def custome_time(*arg):
return datetime.datetime.now(ZoneInfo("Asia/Tokyo")).timetuple()
formatter = logging.Formatter(
'[%(levelname)s]\t%(asctime)s\t%(message)s\n',
'%Y-%m-%d %H:%M:%S'
)
formatter.converter = custome_time
for handler in logger.handlers:
handler.setFormatter(formatter)
level = logging.getLevelName(LOG_LEVEL)
if not isinstance(level, int):
level = logging.INFO
logger.setLevel(level)
def lambda_handler(event, context):
try:
# ① 処理開始ログを出力する
logger.info('I-01-01 処理開始 SAP_supデータ受領チェック処理日次')
execute_date = datetime.date.today().strftime('%Y/%m/%d')
logger.info(f'I-01-02 処理稼働日:{execute_date}')
mail_msg = ''
# ② 営業日チェック処理を行う
logger.info('I-02-01 営業日チェック処理開始')
# 1.設定ファイル[メルク社非営業日設定ファイル]を読み込む
try:
logger.info(f'I-02-02 非営業日設定ファイル読込 読込元:{CONFIG_BUCKET_NAME}/{NON_BUSINESS_DAY_LIST_PATH}')
non_business_day_obj = s3_resource.Object(CONFIG_BUCKET_NAME, NON_BUSINESS_DAY_LIST_PATH)
non_business_day_response = non_business_day_obj.get()
logger.info('I-02-03 非営業日設定ファイルを読み込みました')
except Exception as e:
logger.error(f'E-02-01 非営業日設定ファイルの読み込みに失敗しました エラー内容:{e}')
raise FileReadException('E-02-01', e)
# 2.処理稼働日が「②1.」で読み込んだ「メルク社非営業日設定ファイル」に存在するか確認する
try:
logger.info(f'I-02-04 本日が非営業日かチェックします チェック日:{execute_date}')
none_business_day_list = []
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
else:
logger.info('I-02-06 本日は営業日のため、チェック処理を実施します')
except Exception as e:
logger.error(f'E-02-02 メルク社非営業日設定ファイルに不備があります エラー内容:{e}')
raise NoneBusinessDayException('E-02-02', e)
# ③ 設定ファイル[SAP_supI/Fファイルネーム設定ファイル日次]を読み込む
try:
logger.info(f'I-03-01 日次I/Fファイルネーム設定ファイル読込 読込元{CONFIG_BUCKET_NAME}/{RECEIVE_DAILY_FILE_NAME_LIST_PATH}')
receive_daily_file_name_obj = s3_resource.Object(CONFIG_BUCKET_NAME, RECEIVE_DAILY_FILE_NAME_LIST_PATH)
receive_daily_file_name_response = receive_daily_file_name_obj.get()
logger.info('I-03-02 日次I/Fファイルネーム設定ファイルを読み込みました')
except Exception as e:
logger.error(f'E-03-01 日次I/Fファイルネーム設定ファイルの読み込みに失敗しました エラー内容{e}')
raise FileReadException('E-03-01', e)
# ④ 日次チェック処理を行う
logger.info('I-04-01 日次チェック処理開始')
# 1.SAP保管用バケットの処理稼働日に該当するサブフォルダにあるファイル一覧を取得する
logger.info(f'I-04-02 オブジェクトリストの取得 取得先:{CHECK_BUCKET_NAME}/{execute_date}/')
object_prefix = f'{execute_date}/'
object_list = s3_resource.Bucket(CHECK_BUCKET_NAME).objects.filter(Prefix=object_prefix)
file_list = []
for obj in object_list:
obj_key = obj.key.rsplit('/', INDEX_SPLIT_NUM)
file_list.append(obj_key[INDEX_LAST])
# 2.日次I/Fファイルチェック処理
logger.info('I-04-03 日次I/Fファイルチェック処理開始')
logger.info('I-04-04 取得したオブジェクトリストと日次I/Fファイルネーム設定ファイルの突き合わせを開始します')
receive_daily_file_name_body = io.TextIOWrapper(io.BytesIO(receive_daily_file_name_response["Body"].read()), encoding='utf-8')
match_count = 0
row_count = sum(1 for line in io.BytesIO(receive_daily_file_name_obj.get()["Body"].read()))
for row in csv.reader(receive_daily_file_name_body, delimiter='\t'):
file_exists = False
for file_name in file_list:
match_result = re.fullmatch(row[INDEX_REGEX], file_name)
if match_result is not None:
file_exists = True
break
if file_exists == True:
match_count += 1
logger.info(f'I-04-05 日次I/Fファイルの受領を確認しました ファイル名{file_name}')
else:
logger.error(f'E-04-01 日次I/Fファイルに不足があります ファイル名{row[INDEX_DATA_NAME]}')
mail_msg += f'{MAIL_INDENT}{row[INDEX_DATA_NAME]}\n'
if row_count == match_count:
logger.info('I-04-06 日次I/Fファイルは全て受領していることを確認しました')
# ⑤ 「①」でメモリ保持しているメール挿入用文言に出力内容が存在するか確認する
logger.info('I-05-01 メール送信処理開始')
if len(mail_msg) > 0:
# 1.存在した場合
logger.info(f'I-05-02 {execute_date} 日次I/Fファイルに不足があるため、メール送信処理を開始します')
try:
logger.info(f'I-05-03 通知メール(タイトル)テンプレートファイル読込 読込元:{CONFIG_BUCKET_NAME}/{NOTICE_MAIL_TITLE_TEMPLATE_PATH}')
mail_title_obj = s3_client.get_object(Bucket=CONFIG_BUCKET_NAME, Key=NOTICE_MAIL_TITLE_TEMPLATE_PATH)
mail_title = mail_title_obj['Body'].read().decode('utf-8')
logger.info('I-05-04 通知メール(タイトル)テンプレートファイルを読み込みました')
except Exception as e:
logger.error(f'E-05-01 通知メール(タイトル)テンプレートファイルの読み込みに失敗しました エラー内容:{e}')
raise FileReadException('E-05-01', e)
try:
logger.info(f'I-05-05 通知メール(本文)テンプレートファイル読込 読込元:{CONFIG_BUCKET_NAME}/{NOTICE_MAIL_BODY_TEMPLATE_PATH}')
mail_body_obj = s3_client.get_object(Bucket=CONFIG_BUCKET_NAME, Key=NOTICE_MAIL_BODY_TEMPLATE_PATH)
mail_body_response = mail_body_obj['Body'].read().decode('utf-8')
# メール本文内のプレースホルダーを置き換える
mail_body = substitute_mail_body(mail_body_response, mail_msg)
logger.info('I-05-06 通知メール(本文)テンプレートファイルを読み込みました')
except Exception as e:
logger.error(f'E-05-02 通知メール(本文)テンプレートファイルの読み込みに失敗しました エラー内容:{e}')
raise FileReadException('E-05-02', e)
logger.info(f'I-05-07 メール送信指示をします 送信先トピック:{MBJ_SAP_NOTICE_TOPIC}')
params = {
'TopicArn': MBJ_SAP_NOTICE_TOPIC,
'Subject': mail_title.rstrip('\n'),
'Message': mail_body
}
sns_client.publish(**params)
logger.info('I-05-08 メール送信指示をしました')
else:
# 2.存在しない場合
logger.info(f'I-05-09 {execute_date} 日次I/Fファイルに不足がなかったため、メール送信処理をスキップします')
# ⑥ 処理終了ログを出力する
logger.info('I-06-01 処理終了 SAP_supデータ受領チェック処理日次')
except CustomException as e:
traceback.print_exc()
error_notice(e.id, e.arg)
except Exception as e:
logger.error(f'E-99 想定外のエラーが発生しました エラー内容:{e}')
traceback.print_exc()
error_notice('E-99', e)
return
# 保守要員チーム通知
def error_notice(error_log_id, exception) -> None:
try:
error_msg = f'{error_log_id} のエラーが発生しました。ご確認ください\n詳細:{exception}'
params = {
'TopicArn': NDS_NOTICE_TOPIC,
'Subject': NDS_NOTICE_TITLE,
'Message': error_msg
}
sns_client.publish(**params)
logger.error(f'E-ERR-01 処理異常通知の送信指示をしました 通知先トピック:{NDS_NOTICE_TOPIC}')
except Exception as e:
logger.error(f'E-98 処理異常通知の送信指示に失敗しました エラー内容:{e}')
traceback.print_exc()
return
def substitute_mail_body(before_mail_body:str, mail_msg: str) -> str:
"""メール本文のプレースホルダーを置き換えます
Args:
before_mail_body (str): 置き換え前のメール本文
mail_msg (str): メール本文のプレースホルダーを置き換える文言
Returns:
str: 置き換え後のメール本文
"""
substitute_dict = {
"notice_file_names": mail_msg
}
mail_body = before_mail_body.format_map(substitute_dict)
return mail_body
# カスタムExceptionクラス
class CustomException(Exception, metaclass=ABCMeta):
def __init__(self, id, arg):
self.arg = arg
self.id = id
class FileReadException(CustomException):
pass
class NoneBusinessDayException(CustomException):
pass
import os
import datetime
import boto3
import io
import re
import csv
import logging
from abc import *
from zoneinfo import ZoneInfo
import traceback
# 環境変数
CHECK_BUCKET_NAME = os.environ["CHECK_BUCKET_NAME"]
CONFIG_BUCKET_NAME = os.environ["CONFIG_BUCKET_NAME"]
RECEIVE_DAILY_FILE_NAME_LIST_PATH = os.environ["RECEIVE_DAILY_FILE_NAME_LIST_PATH"]
NON_BUSINESS_DAY_LIST_PATH = os.environ["NON_BUSINESS_DAY_LIST_PATH"]
NOTICE_MAIL_TITLE_TEMPLATE_PATH = os.environ["NOTICE_MAIL_TITLE_TEMPLATE_PATH"]
NOTICE_MAIL_BODY_TEMPLATE_PATH = os.environ["NOTICE_MAIL_BODY_TEMPLATE_PATH"]
MBJ_SAP_NOTICE_TOPIC = os.environ["MBJ_SAP_NOTICE_TOPIC"]
NDS_NOTICE_TOPIC = os.environ["NDS_NOTICE_TOPIC"]
NDS_NOTICE_TITLE = os.environ["NDS_NOTICE_TITLE"]
LOG_LEVEL = os.environ["LOG_LEVEL"]
# 定数
ROW_COMMENT_SYMBOL = '#'
INDEX_REGEX = 0
INDEX_DATA_NAME = 1
INDEX_ROW_COMMENT_SYMBOL = 0
INDEX_SPLIT_NUM = 1
INDEX_LAST = -1
# メール本文に出力する不足ファイル名一覧のインデント
MAIL_INDENT = '  '
# 変数
s3_client = boto3.client('s3')
s3_resource = boto3.resource('s3')
sns_client = boto3.client('sns')
# logger設定
logger = logging.getLogger()
def custome_time(*arg):
return datetime.datetime.now(ZoneInfo("Asia/Tokyo")).timetuple()
formatter = logging.Formatter(
'[%(levelname)s]\t%(asctime)s\t%(message)s\n',
'%Y-%m-%d %H:%M:%S'
)
formatter.converter = custome_time
for handler in logger.handlers:
handler.setFormatter(formatter)
level = logging.getLevelName(LOG_LEVEL)
if not isinstance(level, int):
level = logging.INFO
logger.setLevel(level)
def lambda_handler(event, context):
try:
# ① 処理開始ログを出力する
logger.info('I-01-01 処理開始 SAP_supデータ受領チェック処理日次')
execute_date = datetime.date.today().strftime('%Y/%m/%d')
logger.info(f'I-01-02 処理稼働日:{execute_date}')
mail_msg = ''
# ② 営業日チェック処理を行う
logger.info('I-02-01 営業日チェック処理開始')
# 1.設定ファイル[メルク社非営業日設定ファイル]を読み込む
try:
logger.info(f'I-02-02 非営業日設定ファイル読込 読込元:{CONFIG_BUCKET_NAME}/{NON_BUSINESS_DAY_LIST_PATH}')
non_business_day_obj = s3_resource.Object(CONFIG_BUCKET_NAME, NON_BUSINESS_DAY_LIST_PATH)
non_business_day_response = non_business_day_obj.get()
logger.info('I-02-03 非営業日設定ファイルを読み込みました')
except Exception as e:
logger.error(f'E-02-01 非営業日設定ファイルの読み込みに失敗しました エラー内容:{e}')
raise FileReadException('E-02-01', e)
# 2.処理稼働日が「②1.」で読み込んだ「メルク社非営業日設定ファイル」に存在するか確認する
try:
logger.info(f'I-02-04 本日が非営業日かチェックします チェック日:{execute_date}')
none_business_day_list = []
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
else:
logger.info('I-02-06 本日は営業日のため、チェック処理を実施します')
except Exception as e:
logger.error(f'E-02-02 メルク社非営業日設定ファイルに不備があります エラー内容:{e}')
raise NoneBusinessDayException('E-02-02', e)
# ③ 設定ファイル[SAP_supI/Fファイルネーム設定ファイル日次]を読み込む
try:
logger.info(f'I-03-01 日次I/Fファイルネーム設定ファイル読込 読込元{CONFIG_BUCKET_NAME}/{RECEIVE_DAILY_FILE_NAME_LIST_PATH}')
receive_daily_file_name_obj = s3_resource.Object(CONFIG_BUCKET_NAME, RECEIVE_DAILY_FILE_NAME_LIST_PATH)
receive_daily_file_name_response = receive_daily_file_name_obj.get()
logger.info('I-03-02 日次I/Fファイルネーム設定ファイルを読み込みました')
except Exception as e:
logger.error(f'E-03-01 日次I/Fファイルネーム設定ファイルの読み込みに失敗しました エラー内容{e}')
raise FileReadException('E-03-01', e)
# ④ 日次チェック処理を行う
logger.info('I-04-01 日次チェック処理開始')
# 1.SAP保管用バケットの処理稼働日に該当するサブフォルダにあるファイル一覧を取得する
logger.info(f'I-04-02 オブジェクトリストの取得 取得先:{CHECK_BUCKET_NAME}/{execute_date}/')
object_prefix = f'{execute_date}/'
object_list = s3_resource.Bucket(CHECK_BUCKET_NAME).objects.filter(Prefix=object_prefix)
file_list = []
for obj in object_list:
obj_key = obj.key.rsplit('/', INDEX_SPLIT_NUM)
file_list.append(obj_key[INDEX_LAST])
# 2.日次I/Fファイルチェック処理
logger.info('I-04-03 日次I/Fファイルチェック処理開始')
logger.info('I-04-04 取得したオブジェクトリストと日次I/Fファイルネーム設定ファイルの突き合わせを開始します')
receive_daily_file_name_body = io.TextIOWrapper(io.BytesIO(receive_daily_file_name_response["Body"].read()), encoding='utf-8')
match_count = 0
row_count = sum(1 for line in io.BytesIO(receive_daily_file_name_obj.get()["Body"].read()))
for row in csv.reader(receive_daily_file_name_body, delimiter='\t'):
file_exists = False
for file_name in file_list:
match_result = re.fullmatch(row[INDEX_REGEX], file_name)
if match_result is not None:
file_exists = True
break
if file_exists == True:
match_count += 1
logger.info(f'I-04-05 日次I/Fファイルの受領を確認しました ファイル名{file_name}')
else:
logger.error(f'E-04-01 日次I/Fファイルに不足があります ファイル名{row[INDEX_DATA_NAME]}')
mail_msg += f'{MAIL_INDENT}{row[INDEX_DATA_NAME]}\n'
if row_count == match_count:
logger.info('I-04-06 日次I/Fファイルは全て受領していることを確認しました')
# ⑤ 「①」でメモリ保持しているメール挿入用文言に出力内容が存在するか確認する
logger.info('I-05-01 メール送信処理開始')
if len(mail_msg) > 0:
# 1.存在した場合
logger.info(f'I-05-02 {execute_date} 日次I/Fファイルに不足があるため、メール送信処理を開始します')
try:
logger.info(f'I-05-03 通知メール(タイトル)テンプレートファイル読込 読込元:{CONFIG_BUCKET_NAME}/{NOTICE_MAIL_TITLE_TEMPLATE_PATH}')
mail_title_obj = s3_client.get_object(Bucket=CONFIG_BUCKET_NAME, Key=NOTICE_MAIL_TITLE_TEMPLATE_PATH)
mail_title = mail_title_obj['Body'].read().decode('utf-8')
logger.info('I-05-04 通知メール(タイトル)テンプレートファイルを読み込みました')
except Exception as e:
logger.error(f'E-05-01 通知メール(タイトル)テンプレートファイルの読み込みに失敗しました エラー内容:{e}')
raise FileReadException('E-05-01', e)
try:
logger.info(f'I-05-05 通知メール(本文)テンプレートファイル読込 読込元:{CONFIG_BUCKET_NAME}/{NOTICE_MAIL_BODY_TEMPLATE_PATH}')
mail_body_obj = s3_client.get_object(Bucket=CONFIG_BUCKET_NAME, Key=NOTICE_MAIL_BODY_TEMPLATE_PATH)
mail_body_response = mail_body_obj['Body'].read().decode('utf-8')
# メール本文内のプレースホルダーを置き換える
mail_body = substitute_mail_body(mail_body_response, mail_msg)
logger.info('I-05-06 通知メール(本文)テンプレートファイルを読み込みました')
except Exception as e:
logger.error(f'E-05-02 通知メール(本文)テンプレートファイルの読み込みに失敗しました エラー内容:{e}')
raise FileReadException('E-05-02', e)
logger.info(f'I-05-07 メール送信指示をします 送信先トピック:{MBJ_SAP_NOTICE_TOPIC}')
mail_title_without_line_break = mail_title.splitlines()[0]
params = {
'TopicArn': MBJ_SAP_NOTICE_TOPIC,
'Subject': mail_title_without_line_break,
'Message': mail_body
}
sns_client.publish(**params)
logger.info('I-05-08 メール送信指示をしました')
else:
# 2.存在しない場合
logger.info(f'I-05-09 {execute_date} 日次I/Fファイルに不足がなかったため、メール送信処理をスキップします')
# ⑥ 処理終了ログを出力する
logger.info('I-06-01 処理終了 SAP_supデータ受領チェック処理日次')
except CustomException as e:
traceback.print_exc()
error_notice(e.id, e.arg)
except Exception as e:
logger.error(f'E-99 想定外のエラーが発生しました エラー内容:{e}')
traceback.print_exc()
error_notice('E-99', e)
return
# 保守要員チーム通知
def error_notice(error_log_id, exception) -> None:
try:
error_msg = f'{error_log_id} のエラーが発生しました。ご確認ください\n詳細:{exception}'
params = {
'TopicArn': NDS_NOTICE_TOPIC,
'Subject': NDS_NOTICE_TITLE,
'Message': error_msg
}
sns_client.publish(**params)
logger.error(f'E-ERR-01 処理異常通知の送信指示をしました 通知先トピック:{NDS_NOTICE_TOPIC}')
except Exception as e:
logger.error(f'E-98 処理異常通知の送信指示に失敗しました エラー内容:{e}')
traceback.print_exc()
return
def substitute_mail_body(before_mail_body:str, mail_msg: str) -> str:
"""メール本文のプレースホルダーを置き換えます
Args:
before_mail_body (str): 置き換え前のメール本文
mail_msg (str): メール本文のプレースホルダーを置き換える文言
Returns:
str: 置き換え後のメール本文
"""
substitute_dict = {
"notice_file_names": mail_msg
}
mail_body = before_mail_body.format_map(substitute_dict)
return mail_body
# カスタムExceptionクラス
class CustomException(Exception, metaclass=ABCMeta):
def __init__(self, id, arg):
self.arg = arg
self.id = id
class FileReadException(CustomException):
pass
class NoneBusinessDayException(CustomException):
pass

View File

@ -173,9 +173,10 @@ def lambda_handler(event, context):
raise FileReadException('E-05-02', e)
logger.info(f'I-05-07 メール送信指示をします 送信先トピック:{MBJ_SAP_NOTICE_TOPIC}')
mail_title_without_line_break = mail_title.splitlines()[0]
params = {
'TopicArn': MBJ_SAP_NOTICE_TOPIC,
'Subject': mail_title.rstrip('\n'),
'Subject': mail_title_without_line_break,
'Message': mail_body
}
sns_client.publish(**params)

View File

@ -1,73 +1,73 @@
2022/06/04
2022/06/05
2022/06/11
2022/06/12
2022/06/18
2022/06/19
2022/06/25
2022/06/26
2022/07/02
2022/07/03
2022/07/09
2022/07/10
2022/07/16
2022/07/17
2022/07/18
2022/07/23
2022/07/24
2022/07/30
2022/07/31
2022/08/06
2022/08/07
2022/08/11
2022/08/12
2022/08/13
2022/08/14
2022/08/15
2022/08/16
2022/08/20
2022/08/21
2022/08/27
2022/08/28
2022/09/03
2022/09/04
2022/09/10
2022/09/11
2022/09/17
2022/09/18
2022/09/19
2022/09/23
2022/09/24
2022/09/25
2022/10/01
2022/10/02
2022/10/08
2022/10/09
2022/10/10
2022/10/15
2022/10/16
2022/10/22
2022/10/23
2022/10/29
2022/10/30
2022/11/03
2022/11/05
2022/11/06
2022/11/12
2022/11/13
2022/11/19
2022/11/20
2022/11/23
2022/11/26
2022/11/27
2022/12/03
2022/12/04
2022/12/10
2022/12/11
2022/12/17
2022/12/18
2022/12/24
2022/12/25
2022/12/29
2022/12/30
2022/12/31
2022/06/04
2022/06/05
2022/06/11
2022/06/12
2022/06/18
2022/06/19
2022/06/25
2022/06/26
2022/07/02
2022/07/03
2022/07/09
2022/07/10
2022/07/16
2022/07/17
2022/07/18
2022/07/23
2022/07/24
2022/07/30
2022/07/31
2022/08/06
2022/08/07
2022/08/11
2022/08/12
2022/08/13
2022/08/14
2022/08/15
2022/08/16
2022/08/20
2022/08/21
2022/08/27
2022/08/28
2022/09/03
2022/09/04
2022/09/10
2022/09/11
2022/09/17
2022/09/18
2022/09/19
2022/09/23
2022/09/24
2022/09/25
2022/10/01
2022/10/02
2022/10/08
2022/10/09
2022/10/10
2022/10/15
2022/10/16
2022/10/22
2022/10/23
2022/10/29
2022/10/30
2022/11/03
2022/11/05
2022/11/06
2022/11/12
2022/11/13
2022/11/19
2022/11/20
2022/11/23
2022/11/26
2022/11/27
2022/12/03
2022/12/04
2022/12/10
2022/12/11
2022/12/17
2022/12/18
2022/12/24
2022/12/25
2022/12/29
2022/12/30
2022/12/31