From add64b3bc8b9bfa46a1f6ff6adb92383f4d13082 Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Tue, 13 Feb 2024 12:49:11 +0900 Subject: [PATCH 01/14] =?UTF-8?q?feat:=20Encise=E8=87=AA=E5=8B=95=E9=80=A3?= =?UTF-8?q?=E6=90=BA=20=E3=83=87=E3=83=BC=E3=82=BF=E6=9C=AA=E5=8F=97?= =?UTF-8?q?=E4=BF=A1=E3=83=81=E3=82=A7=E3=83=83=E3=82=AF=E5=87=A6=E7=90=86?= =?UTF-8?q?=E5=AE=9F=E8=A3=85=E3=80=82=E7=B4=B0=E3=81=8B=E3=81=84=E3=83=AD?= =?UTF-8?q?=E3=82=B8=E3=83=83=E3=82=AF=E3=81=AE=E5=AE=9F=E8=A3=85=E3=81=8C?= =?UTF-8?q?=E3=81=BE=E3=81=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../encise-data-unreceive-check.py | 293 ++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 lambda/encise-data-unreceive-check/encise-data-unreceive-check.py diff --git a/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py b/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py new file mode 100644 index 00000000..6dc2e89c --- /dev/null +++ b/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py @@ -0,0 +1,293 @@ +import csv +import datetime +import io +import json +import logging +import os +import re +from zoneinfo import ZoneInfo + +import boto3 + +# 環境変数 +CHECK_BUCKET_NAME = os.environ["CHECK_BUCKET_NAME"] +CHECK_TARGET_FILE_NAME_LIST_FOLDER_PATH = os.environ["CHECK_TARGET_FILE_NAME_LIST_FOLDER_PATH"] +CONFIG_BUCKET_NAME = os.environ["CONFIG_BUCKET_NAME"] +LOG_LEVEL = os.environ["LOG_LEVEL"] +MAIL_TEMPLATE_FOLDER_PATH = os.environ["MAIL_TEMPLATE_FOLDER_PATH"] +MBJ_NOTICE_TOPIC = os.environ["MBJ_NOTICE_TOPIC"] +NDS_NOTICE_TITLE = os.environ["NDS_NOTICE_TITLE"] +NDS_NOTICE_TOPIC = os.environ["NDS_NOTICE_TOPIC"] +PROCESSED_MESSAGE_DYNAMODB_TABLE_NAME = os.environ["PROCESSED_MESSAGE_DYNAMODB_TABLE_NAME"] +PROCESSED_MESSAGE_EXPIRES_PERIOD = os.environ["PROCESSED_MESSAGE_EXPIRES_PERIOD"] +TZ = os.environ["TZ"] + +# 定数 +ROW_COMMENT_SYMBOL = '#' +INDEX_REGEX = 0 +INDEX_DATA_NAME = 1 +INDEX_ROW_COMMENT_SYMBOL = 0 +INDEX_SPLIT_NUM = 1 +INDEX_LAST = -1 + +# メール本文に出力する不足ファイル名一覧のインデント +MAIL_INDENT = '  ' + +# AWS操作クライアント +s3_client = boto3.client('s3') +sns_client = boto3.client('sns') +dynamodb_client = boto3.client('dynamodb') + + +# logger設定 + + +def log_datetime_convert_tz(*arg): + """ログに出力するタイムスタンプのロケールを変更する(JST指定)""" + return datetime.datetime.now(ZoneInfo(TZ)).timetuple() + + +logger = logging.getLogger() +formatter = logging.Formatter( + '[%(levelname)s]\t%(asctime)s\t%(message)s\n', + '%Y-%m-%d %H:%M:%S' +) +formatter.converter = log_datetime_convert_tz +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 is_duplicate_message(message_id: str) -> bool: + """DynamoDBテーブルに処理済みのSQSメッセージIdが存在するかどうかを調査する + + Args: + message_id (str): SQSメッセージId + + Returns: + bool: 存在する場合はTrue + """ + return dynamodb_client.query( + TableName=PROCESSED_MESSAGE_DYNAMODB_TABLE_NAME, + Select='COUNT', + KeyConditionExpression='message_id = :message_id', + ExpressionAttributeValues={ + ':message_id': {'S': message_id} + } + )["Count"] != 0 + + +# Put the message to the DynamoDB Table. +# @input string batch_item_success +# +# @param batch_item_success of the message to put. +# @return Boolean +def push_success_messages_to_dynamo_db(batch_item_success: list[str]) -> bool: + """処理済みのSQSメッセージIdをDynamoDBにPushする + + Args: + batch_item_success (list[str]): SQSメッセージIdのリスト + + Returns: + bool: 登録成功の場合、True + """ + for message_id in batch_item_success: + dynamodb_client.put_item( + TableName=PROCESSED_MESSAGE_DYNAMODB_TABLE_NAME, + Item={'message_id': {'S': message_id}} + ) + return True + + +def substitute_mail_template(mail_template: str, receive_timing: str, mail_msg: str) -> str: + """メールテンプレートのプレースホルダーを置き換えます + + Args: + mail_template (str): 置き換え前のメールテンプレート + receive_timing (str): メールテンプレートのプレースホルダーを置き換える文言(受信タイミング) + mail_msg (str): メールテンプレートのプレースホルダーを置き換える文言(ファイル一覧) + + Returns: + str: 置き換え後のメール本文 + """ + substitute_dict = { + "receive_timing": receive_timing, + "notice_file_names": mail_msg + } + mail_str = mail_template.format_map(substitute_dict) + return mail_str + + +def unreceive_check(records: list, execute_month: str) -> tuple[list[dict[str, str]], list[str]]: + + batch_item_failures = [] + batch_item_success = [] + + for record in records: + # メール挿入用文言を格納するためのメモリを保持する + mail_message = '' + + try: + # 1.SQSメッセージIDを取得する + message_id = record["messageId"] + # 2.DynamoDBテーブルからレコードを取得し、処理済みメッセージかどうかを判別する + if is_duplicate_message(message_id): + logger.info(f'受信したメッセージは既に処理済みのため、処理をスキップします。メッセージID: {message_id}') + continue + except Exception as e: + # TODO: エラー処理実装 + raise e + + # SQSパラメータをJSONシリアライズし、Pythonの辞書オブジェクト(イベントパラメータ)を取得する。 + + event_parameter = json.loads(record['body']) + + # ③ 設定ファイル[受領チェック対象ファイルリスト]を読み込む + try: + logger.info( + 'I-03-01 ' + + f'受領チェック対象ファイルリスト読込 読込元:{CONFIG_BUCKET_NAME}/{CHECK_TARGET_FILE_NAME_LIST_FOLDER_PATH}/{event_parameter["check_target_file_list"]}' + ) + check_target_file_list_response = s3_client.get_object( + Bucket=CONFIG_BUCKET_NAME, + Key=f'{CHECK_TARGET_FILE_NAME_LIST_FOLDER_PATH}/{event_parameter["check_target_file_list"]}' + ) + logger.info('I-03-02 受領チェック対象ファイルリストを読み込みました') + except Exception as e: + # TODO: エラー処理実装 + raise e + + # ④ 受領チェック処理を行う + receive_timing = event_parameter['receive_timing'] + logger.info(f'I-04-01 Enciseデータ受領チェック ({receive_timing}) 処理開始') + object_prefix = f'{event_parameter["check_folder_prefix"]}{execute_month}/' + # 1.Enciseデータバックアップ保管バケットの処理稼働月に該当するサブフォルダにあるファイル一覧を取得する + logger.info( + f'I-04-02 オブジェクトリストの取得 取得先:{CHECK_BUCKET_NAME}/{object_prefix}' + ) + check_target_file_list_response = s3_client.list_objects_v2(CHECK_BUCKET_NAME, Prefix=object_prefix) + check_target_file_list = [] + for content in check_target_file_list_response[['Contents']]: + # オブジェクトのキーからファイル名を切り出してリストに追加 + obj_key = content['Key'].rsplit('/', INDEX_SPLIT_NUM) + check_target_file_list.append(obj_key[INDEX_LAST]) + + # 2.I/Fファイルチェック処理 + logger.info(f'I-04-03 Enciseデータ({receive_timing}) ファイルチェック処理開始') + receive_monthly_file_name_body = io.TextIOWrapper(io.BytesIO(check_target_file_list_response["Body"].read()), encoding='utf-8') + match_count = 0 + row_count = 0 + for tsv_row in csv.reader(receive_monthly_file_name_body, delimiter='\t'): + # 「④1.」で取得したリストが「③」で読み込んだファイル内に存在するか確認する + is_file_not_exists = True + for file_name in check_target_file_list: + match_result = re.fullmatch(tsv_row[INDEX_REGEX], file_name) + # 「③」で読み込んだファイルに記載されている全てが「④1.」で取得したリストに存在した場合 + if match_result is not None: + # 存在したファイルの年月部分を抜き出し、チェック対象年月(処理稼働月-1)である場合 + if True: # TODO + logger.info(f'I-04-04 I/Fファイルの受領を確認しました ファイル名:{file_name}') + is_file_not_exists = False + match_count += 1 + else: + logger.info(f'I-04-07 I/Fファイルの年月がチェック対象年月と一致しません ファイル名:{file_name}') + mail_message += f'{MAIL_INDENT}{tsv_row[INDEX_DATA_NAME]}(受領年月が不正:{file_name})\n' + break + if is_file_not_exists: + logger.info(f'E-04-06 月次I/Fファイルに不足があります ファイル名:{tsv_row[INDEX_DATA_NAME]}') + mail_message += f'{MAIL_INDENT}{tsv_row[INDEX_DATA_NAME]}\n' + + row_count += 1 + + if row_count == match_count: + logger.info('I-04-05 I/Fファイルは全て受領していることを確認しました') + + # ⑤ 「①」でメモリ保持しているメール挿入用文言に出力内容が存在するか確認する + logger.info('I-05-01 メール送信処理開始') + + if len(mail_message) == 0: + logger.info(f'I-05-09 {execute_month} {receive_timing}データI/Fファイルに不足が無いため、メール送信処理をスキップします') + batch_item_success.append(message_id) + continue + + # 1.存在した場合 + logger.info(f'I-05-02 {execute_month} {receive_timing}データI/Fファイルに不足があるため、メール送信処理を開始します') + + try: + logger.info( + 'I-05-03 ' + + f'通知メール(タイトル)テンプレートファイル読込 読込元:{CONFIG_BUCKET_NAME}/{MAIL_TEMPLATE_FOLDER_PATH}/{event_parameter["notice_mail_title_template"]}' + ) + mail_title_response = s3_client.get_object( + Bucket=CONFIG_BUCKET_NAME, + Key=f'{MAIL_TEMPLATE_FOLDER_PATH}/{event_parameter["notice_mail_title_template"]}' + ) + mail_title_template = mail_title_response['Body'].read().decode('utf-8') + # 改行を取り除く + mail_title = substitute_mail_template(mail_title_template, receive_timing, mail_message) + mail_title_without_line_break = mail_title.splitlines()[0] + logger.info('I-05-04 通知メール(タイトル)テンプレートファイルを読み込みました') + except Exception as e: + logger.error(f'E-05-01 通知メール(タイトル)テンプレートファイルの読み込みに失敗しました エラー内容:{e}') + raise e + + try: + logger.info( + 'I-05-05 ' + + f'通知メール(本文)テンプレートファイル読込 読込元:{CONFIG_BUCKET_NAME}/{MAIL_TEMPLATE_FOLDER_PATH}/{event_parameter["notice_mail_body_template"]}' + ) + mail_body_template_response = s3_client.get_object( + Bucket=CONFIG_BUCKET_NAME, + Key=f'{MAIL_TEMPLATE_FOLDER_PATH}/{event_parameter["notice_mail_body_template"]}' + ) + mail_body_template = mail_body_template_response['Body'].read().decode('utf-8') + # メール本文内のプレースホルダーを置き換える + mail_body = substitute_mail_template(mail_body_template, receive_timing, mail_message) + logger.info('I-05-06 通知メール(本文)テンプレートファイルを読み込みました') + except Exception as e: + logger.error(f'E-05-02 通知メール(本文)テンプレートファイルの読み込みに失敗しました エラー内容:{e}') + raise e + + logger.info(f'I-05-07 メール送信指示をします 送信先トピック:{MBJ_NOTICE_TOPIC}') + params = { + 'TopicArn': MBJ_NOTICE_TOPIC, + 'Subject': mail_title_without_line_break, + 'Message': mail_body + } + sns_client.publish(**params) + logger.info('I-05-08 メール送信指示をしました') + + batch_item_success.append(message_id) + + return batch_item_failures, batch_item_success + + +def lambda_handler(event, context): + try: + # ① 処理開始ログを出力する + logger.info('I-01-01 処理開始 Enciseデータ受領チェック処理') + # 処理稼働年月を取得しメモリに保持する + execute_date_today = datetime.date.today() + execute_month = execute_date_today.strftime('%Y/%m') + logger.info(f'I-01-02 処理稼働月:{execute_month}') + # 処理失敗メッセージIDリストをメモリに保持する(初期値=空のリスト) + batch_item_failures = [] + # 処理成功メッセージIDリストをメモリに保持する(初期値=空のリスト) + batch_item_success = [] + # ② SQSメッセージ重複排除処理を行う + logger.info('I-02-01 メッセージ処理開始') + batch_item_failures, batch_item_success = unreceive_check(event["Records"], execute_month) + logger.info('I-06-01 すべてのメッセージの処理完了') + + # ⑦ メッセージを処理済として、以下のDynamoDBテーブルに記録する + push_success_messages_to_dynamo_db(batch_item_success) + logger.info('I-07-01 処理済みメッセージIDの記録完了') + logger.info('I-07-02 処理終了 Enciseデータ受領チェック処理') + except Exception as e: + logger.exception(f'E-99 想定外のエラーが発生しました エラー内容:{e}') + + return batch_item_failures From 43d959f6698b980770a0208a80afab74640e8b07 Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Tue, 13 Feb 2024 13:04:36 +0900 Subject: [PATCH 02/14] =?UTF-8?q?feat:=20=E3=82=A8=E3=83=A9=E3=83=BC?= =?UTF-8?q?=E5=87=A6=E7=90=86=E3=82=92=E5=AE=9F=E8=A3=85=EF=BC=88=E3=81=BE?= =?UTF-8?q?=E3=81=A0=E9=80=94=E4=B8=AD=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../encise-data-unreceive-check.py | 69 +++++++++++-------- 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py b/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py index 6dc2e89c..6448adcd 100644 --- a/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py +++ b/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py @@ -122,6 +122,18 @@ def substitute_mail_template(mail_template: str, receive_timing: str, mail_msg: return mail_str +def make_failure_item_on_error(message_id: str) -> dict[str, str]: + """Report batch item failuresによる処理に失敗したメッセージの判別のためのレスポンスを作成する + @see + Args: + message_id (str): SQSメッセージId + + Returns: + dict[str, str]: Report batch item failuresで失敗したSQSメッセージを判別するための辞書オブジェクト + """ + return {"itemIdentifier": message_id} + + def unreceive_check(records: list, execute_month: str) -> tuple[list[dict[str, str]], list[str]]: batch_item_failures = [] @@ -139,11 +151,11 @@ def unreceive_check(records: list, execute_month: str) -> tuple[list[dict[str, s logger.info(f'受信したメッセージは既に処理済みのため、処理をスキップします。メッセージID: {message_id}') continue except Exception as e: - # TODO: エラー処理実装 - raise e + logger.error(f"E-02-01 メッセージ重複チェック処理に失敗しました エラー内容:{e}") + batch_item_failures.append(make_failure_item_on_error(message_id)) + continue # SQSパラメータをJSONシリアライズし、Pythonの辞書オブジェクト(イベントパラメータ)を取得する。 - event_parameter = json.loads(record['body']) # ③ 設定ファイル[受領チェック対象ファイルリスト]を読み込む @@ -158,8 +170,9 @@ def unreceive_check(records: list, execute_month: str) -> tuple[list[dict[str, s ) logger.info('I-03-02 受領チェック対象ファイルリストを読み込みました') except Exception as e: - # TODO: エラー処理実装 - raise e + logger.error(f"E-03-01 受領チェック対象ファイルリストの読み込みに失敗しました エラー内容:{e}") + batch_item_failures.append(make_failure_item_on_error(message_id)) + continue # ④ 受領チェック処理を行う receive_timing = event_parameter['receive_timing'] @@ -232,8 +245,10 @@ def unreceive_check(records: list, execute_month: str) -> tuple[list[dict[str, s mail_title_without_line_break = mail_title.splitlines()[0] logger.info('I-05-04 通知メール(タイトル)テンプレートファイルを読み込みました') except Exception as e: + # TODO: エラー処理実装 logger.error(f'E-05-01 通知メール(タイトル)テンプレートファイルの読み込みに失敗しました エラー内容:{e}') - raise e + batch_item_failures.append(make_failure_item_on_error(message_id)) + continue try: logger.info( @@ -250,7 +265,8 @@ def unreceive_check(records: list, execute_month: str) -> tuple[list[dict[str, s logger.info('I-05-06 通知メール(本文)テンプレートファイルを読み込みました') except Exception as e: logger.error(f'E-05-02 通知メール(本文)テンプレートファイルの読み込みに失敗しました エラー内容:{e}') - raise e + batch_item_failures.append(make_failure_item_on_error(message_id)) + continue logger.info(f'I-05-07 メール送信指示をします 送信先トピック:{MBJ_NOTICE_TOPIC}') params = { @@ -267,27 +283,24 @@ def unreceive_check(records: list, execute_month: str) -> tuple[list[dict[str, s def lambda_handler(event, context): - try: - # ① 処理開始ログを出力する - logger.info('I-01-01 処理開始 Enciseデータ受領チェック処理') - # 処理稼働年月を取得しメモリに保持する - execute_date_today = datetime.date.today() - execute_month = execute_date_today.strftime('%Y/%m') - logger.info(f'I-01-02 処理稼働月:{execute_month}') - # 処理失敗メッセージIDリストをメモリに保持する(初期値=空のリスト) - batch_item_failures = [] - # 処理成功メッセージIDリストをメモリに保持する(初期値=空のリスト) - batch_item_success = [] - # ② SQSメッセージ重複排除処理を行う - logger.info('I-02-01 メッセージ処理開始') - batch_item_failures, batch_item_success = unreceive_check(event["Records"], execute_month) - logger.info('I-06-01 すべてのメッセージの処理完了') + # ① 処理開始ログを出力する + logger.info('I-01-01 処理開始 Enciseデータ受領チェック処理') + # 処理稼働年月を取得しメモリに保持する + execute_date_today = datetime.date.today() + execute_month = execute_date_today.strftime('%Y/%m') + logger.info(f'I-01-02 処理稼働月:{execute_month}') + # 処理失敗メッセージIDリストをメモリに保持する(初期値=空のリスト) + batch_item_failures = [] + # 処理成功メッセージIDリストをメモリに保持する(初期値=空のリスト) + batch_item_success = [] + # ② SQSメッセージ重複排除処理を行う + logger.info('I-02-01 メッセージ処理開始') + batch_item_failures, batch_item_success = unreceive_check(event["Records"], execute_month) + logger.info('I-06-01 すべてのメッセージの処理完了') - # ⑦ メッセージを処理済として、以下のDynamoDBテーブルに記録する - push_success_messages_to_dynamo_db(batch_item_success) - logger.info('I-07-01 処理済みメッセージIDの記録完了') - logger.info('I-07-02 処理終了 Enciseデータ受領チェック処理') - except Exception as e: - logger.exception(f'E-99 想定外のエラーが発生しました エラー内容:{e}') + # ⑦ メッセージを処理済として、以下のDynamoDBテーブルに記録する + push_success_messages_to_dynamo_db(batch_item_success) + logger.info('I-07-01 処理済みメッセージIDの記録完了') + logger.info('I-07-02 処理終了 Enciseデータ受領チェック処理') return batch_item_failures From 29dccb84fff52ef7d9ef2445aad14a9d8e5739ee Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Tue, 13 Feb 2024 13:23:03 +0900 Subject: [PATCH 03/14] =?UTF-8?q?style:=20=E3=82=A8=E3=83=A9=E3=83=BC?= =?UTF-8?q?=E5=87=A6=E7=90=86=E5=AE=9F=E8=A3=85TODO=E3=82=B3=E3=83=A1?= =?UTF-8?q?=E3=83=B3=E3=83=88=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../encise-data-unreceive-check/encise-data-unreceive-check.py | 1 - 1 file changed, 1 deletion(-) diff --git a/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py b/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py index 6448adcd..e1e9761b 100644 --- a/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py +++ b/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py @@ -245,7 +245,6 @@ def unreceive_check(records: list, execute_month: str) -> tuple[list[dict[str, s mail_title_without_line_break = mail_title.splitlines()[0] logger.info('I-05-04 通知メール(タイトル)テンプレートファイルを読み込みました') except Exception as e: - # TODO: エラー処理実装 logger.error(f'E-05-01 通知メール(タイトル)テンプレートファイルの読み込みに失敗しました エラー内容:{e}') batch_item_failures.append(make_failure_item_on_error(message_id)) continue From 58e3a182bc62edd32a69c043796dcd1c47ae5e4e Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Tue, 13 Feb 2024 13:33:45 +0900 Subject: [PATCH 04/14] =?UTF-8?q?feat:=20=E6=83=B3=E5=AE=9A=E5=A4=96?= =?UTF-8?q?=E3=81=AE=E3=82=A8=E3=83=A9=E3=83=BC=E7=99=BA=E7=94=9F=E6=99=82?= =?UTF-8?q?=E3=81=AE=E3=82=A8=E3=83=A9=E3=83=BC=E5=87=A6=E7=90=86=E5=AE=9F?= =?UTF-8?q?=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../encise-data-unreceive-check.py | 243 +++++++++--------- 1 file changed, 124 insertions(+), 119 deletions(-) diff --git a/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py b/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py index e1e9761b..ca77d714 100644 --- a/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py +++ b/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py @@ -142,142 +142,147 @@ def unreceive_check(records: list, execute_month: str) -> tuple[list[dict[str, s for record in records: # メール挿入用文言を格納するためのメモリを保持する mail_message = '' - try: - # 1.SQSメッセージIDを取得する - message_id = record["messageId"] - # 2.DynamoDBテーブルからレコードを取得し、処理済みメッセージかどうかを判別する - if is_duplicate_message(message_id): - logger.info(f'受信したメッセージは既に処理済みのため、処理をスキップします。メッセージID: {message_id}') + try: + # 1.SQSメッセージIDを取得する + message_id = record["messageId"] + # 2.DynamoDBテーブルからレコードを取得し、処理済みメッセージかどうかを判別する + if is_duplicate_message(message_id): + logger.info(f'受信したメッセージは既に処理済みのため、処理をスキップします。メッセージID: {message_id}') + continue + except Exception as e: + logger.error(f"E-02-01 メッセージ重複チェック処理に失敗しました エラー内容:{e}") + batch_item_failures.append(make_failure_item_on_error(message_id)) continue - except Exception as e: - logger.error(f"E-02-01 メッセージ重複チェック処理に失敗しました エラー内容:{e}") - batch_item_failures.append(make_failure_item_on_error(message_id)) - continue - # SQSパラメータをJSONシリアライズし、Pythonの辞書オブジェクト(イベントパラメータ)を取得する。 - event_parameter = json.loads(record['body']) + # SQSパラメータをJSONシリアライズし、Pythonの辞書オブジェクト(イベントパラメータ)を取得する。 + event_parameter = json.loads(record['body']) - # ③ 設定ファイル[受領チェック対象ファイルリスト]を読み込む - try: + # ③ 設定ファイル[受領チェック対象ファイルリスト]を読み込む + try: + logger.info( + 'I-03-01 ' + + '受領チェック対象ファイルリスト読込 読込元:' + + f'{CONFIG_BUCKET_NAME}/{CHECK_TARGET_FILE_NAME_LIST_FOLDER_PATH}/{event_parameter["check_target_file_list"]}' + ) + check_target_file_list_response = s3_client.get_object( + Bucket=CONFIG_BUCKET_NAME, + Key=f'{CHECK_TARGET_FILE_NAME_LIST_FOLDER_PATH}/{event_parameter["check_target_file_list"]}' + ) + logger.info('I-03-02 受領チェック対象ファイルリストを読み込みました') + except Exception as e: + logger.error(f"E-03-01 受領チェック対象ファイルリストの読み込みに失敗しました エラー内容:{e}") + batch_item_failures.append(make_failure_item_on_error(message_id)) + continue + + # ④ 受領チェック処理を行う + receive_timing = event_parameter['receive_timing'] + logger.info(f'I-04-01 Enciseデータ受領チェック ({receive_timing}) 処理開始') + object_prefix = f'{event_parameter["check_folder_prefix"]}{execute_month}/' + # 1.Enciseデータバックアップ保管バケットの処理稼働月に該当するサブフォルダにあるファイル一覧を取得する logger.info( - 'I-03-01 ' + - f'受領チェック対象ファイルリスト読込 読込元:{CONFIG_BUCKET_NAME}/{CHECK_TARGET_FILE_NAME_LIST_FOLDER_PATH}/{event_parameter["check_target_file_list"]}' + f'I-04-02 オブジェクトリストの取得 取得先:{CHECK_BUCKET_NAME}/{object_prefix}' ) - check_target_file_list_response = s3_client.get_object( - Bucket=CONFIG_BUCKET_NAME, - Key=f'{CHECK_TARGET_FILE_NAME_LIST_FOLDER_PATH}/{event_parameter["check_target_file_list"]}' - ) - logger.info('I-03-02 受領チェック対象ファイルリストを読み込みました') - except Exception as e: - logger.error(f"E-03-01 受領チェック対象ファイルリストの読み込みに失敗しました エラー内容:{e}") - batch_item_failures.append(make_failure_item_on_error(message_id)) - continue + check_target_file_list_response = s3_client.list_objects_v2(CHECK_BUCKET_NAME, Prefix=object_prefix) + check_target_file_list = [] + for content in check_target_file_list_response[['Contents']]: + # オブジェクトのキーからファイル名を切り出してリストに追加 + obj_key = content['Key'].rsplit('/', INDEX_SPLIT_NUM) + check_target_file_list.append(obj_key[INDEX_LAST]) - # ④ 受領チェック処理を行う - receive_timing = event_parameter['receive_timing'] - logger.info(f'I-04-01 Enciseデータ受領チェック ({receive_timing}) 処理開始') - object_prefix = f'{event_parameter["check_folder_prefix"]}{execute_month}/' - # 1.Enciseデータバックアップ保管バケットの処理稼働月に該当するサブフォルダにあるファイル一覧を取得する - logger.info( - f'I-04-02 オブジェクトリストの取得 取得先:{CHECK_BUCKET_NAME}/{object_prefix}' - ) - check_target_file_list_response = s3_client.list_objects_v2(CHECK_BUCKET_NAME, Prefix=object_prefix) - check_target_file_list = [] - for content in check_target_file_list_response[['Contents']]: - # オブジェクトのキーからファイル名を切り出してリストに追加 - obj_key = content['Key'].rsplit('/', INDEX_SPLIT_NUM) - check_target_file_list.append(obj_key[INDEX_LAST]) + # 2.I/Fファイルチェック処理 + logger.info(f'I-04-03 Enciseデータ({receive_timing}) ファイルチェック処理開始') + receive_monthly_file_name_body = io.TextIOWrapper(io.BytesIO(check_target_file_list_response["Body"].read()), encoding='utf-8') + match_count = 0 + row_count = 0 + for tsv_row in csv.reader(receive_monthly_file_name_body, delimiter='\t'): + # 「④1.」で取得したリストが「③」で読み込んだファイル内に存在するか確認する + is_file_not_exists = True + for file_name in check_target_file_list: + match_result = re.fullmatch(tsv_row[INDEX_REGEX], file_name) + # 「③」で読み込んだファイルに記載されている全てが「④1.」で取得したリストに存在した場合 + if match_result is not None: + # 存在したファイルの年月部分を抜き出し、チェック対象年月(処理稼働月-1)である場合 + if True: # TODO + logger.info(f'I-04-04 I/Fファイルの受領を確認しました ファイル名:{file_name}') + is_file_not_exists = False + match_count += 1 + else: + logger.info(f'I-04-07 I/Fファイルの年月がチェック対象年月と一致しません ファイル名:{file_name}') + mail_message += f'{MAIL_INDENT}{tsv_row[INDEX_DATA_NAME]}(受領年月が不正:{file_name})\n' + break + if is_file_not_exists: + logger.info(f'E-04-06 月次I/Fファイルに不足があります ファイル名:{tsv_row[INDEX_DATA_NAME]}') + mail_message += f'{MAIL_INDENT}{tsv_row[INDEX_DATA_NAME]}\n' - # 2.I/Fファイルチェック処理 - logger.info(f'I-04-03 Enciseデータ({receive_timing}) ファイルチェック処理開始') - receive_monthly_file_name_body = io.TextIOWrapper(io.BytesIO(check_target_file_list_response["Body"].read()), encoding='utf-8') - match_count = 0 - row_count = 0 - for tsv_row in csv.reader(receive_monthly_file_name_body, delimiter='\t'): - # 「④1.」で取得したリストが「③」で読み込んだファイル内に存在するか確認する - is_file_not_exists = True - for file_name in check_target_file_list: - match_result = re.fullmatch(tsv_row[INDEX_REGEX], file_name) - # 「③」で読み込んだファイルに記載されている全てが「④1.」で取得したリストに存在した場合 - if match_result is not None: - # 存在したファイルの年月部分を抜き出し、チェック対象年月(処理稼働月-1)である場合 - if True: # TODO - logger.info(f'I-04-04 I/Fファイルの受領を確認しました ファイル名:{file_name}') - is_file_not_exists = False - match_count += 1 - else: - logger.info(f'I-04-07 I/Fファイルの年月がチェック対象年月と一致しません ファイル名:{file_name}') - mail_message += f'{MAIL_INDENT}{tsv_row[INDEX_DATA_NAME]}(受領年月が不正:{file_name})\n' - break - if is_file_not_exists: - logger.info(f'E-04-06 月次I/Fファイルに不足があります ファイル名:{tsv_row[INDEX_DATA_NAME]}') - mail_message += f'{MAIL_INDENT}{tsv_row[INDEX_DATA_NAME]}\n' + row_count += 1 - row_count += 1 + if row_count == match_count: + logger.info('I-04-05 I/Fファイルは全て受領していることを確認しました') - if row_count == match_count: - logger.info('I-04-05 I/Fファイルは全て受領していることを確認しました') + # ⑤ 「①」でメモリ保持しているメール挿入用文言に出力内容が存在するか確認する + logger.info('I-05-01 メール送信処理開始') - # ⑤ 「①」でメモリ保持しているメール挿入用文言に出力内容が存在するか確認する - logger.info('I-05-01 メール送信処理開始') + if len(mail_message) == 0: + logger.info(f'I-05-09 {execute_month} {receive_timing}データI/Fファイルに不足が無いため、メール送信処理をスキップします') + batch_item_success.append(message_id) + continue + + # 1.存在した場合 + logger.info(f'I-05-02 {execute_month} {receive_timing}データI/Fファイルに不足があるため、メール送信処理を開始します') + + try: + logger.info( + 'I-05-03 ' + + f'通知メール(タイトル)テンプレートファイル読込 読込元:{CONFIG_BUCKET_NAME}/{MAIL_TEMPLATE_FOLDER_PATH}/{event_parameter["notice_mail_title_template"]}' + ) + mail_title_response = s3_client.get_object( + Bucket=CONFIG_BUCKET_NAME, + Key=f'{MAIL_TEMPLATE_FOLDER_PATH}/{event_parameter["notice_mail_title_template"]}' + ) + mail_title_template = mail_title_response['Body'].read().decode('utf-8') + # 改行を取り除く + mail_title = substitute_mail_template(mail_title_template, receive_timing, mail_message) + mail_title_without_line_break = mail_title.splitlines()[0] + logger.info('I-05-04 通知メール(タイトル)テンプレートファイルを読み込みました') + except Exception as e: + logger.error(f'E-05-01 通知メール(タイトル)テンプレートファイルの読み込みに失敗しました エラー内容:{e}') + batch_item_failures.append(make_failure_item_on_error(message_id)) + continue + + try: + logger.info( + 'I-05-05 ' + + f'通知メール(本文)テンプレートファイル読込 読込元:{CONFIG_BUCKET_NAME}/{MAIL_TEMPLATE_FOLDER_PATH}/{event_parameter["notice_mail_body_template"]}' + ) + mail_body_template_response = s3_client.get_object( + Bucket=CONFIG_BUCKET_NAME, + Key=f'{MAIL_TEMPLATE_FOLDER_PATH}/{event_parameter["notice_mail_body_template"]}' + ) + mail_body_template = mail_body_template_response['Body'].read().decode('utf-8') + # メール本文内のプレースホルダーを置き換える + mail_body = substitute_mail_template(mail_body_template, receive_timing, mail_message) + logger.info('I-05-06 通知メール(本文)テンプレートファイルを読み込みました') + except Exception as e: + logger.error(f'E-05-02 通知メール(本文)テンプレートファイルの読み込みに失敗しました エラー内容:{e}') + batch_item_failures.append(make_failure_item_on_error(message_id)) + continue + + logger.info(f'I-05-07 メール送信指示をします 送信先トピック:{MBJ_NOTICE_TOPIC}') + params = { + 'TopicArn': MBJ_NOTICE_TOPIC, + 'Subject': mail_title_without_line_break, + 'Message': mail_body + } + sns_client.publish(**params) + logger.info('I-05-08 メール送信指示をしました') - if len(mail_message) == 0: - logger.info(f'I-05-09 {execute_month} {receive_timing}データI/Fファイルに不足が無いため、メール送信処理をスキップします') batch_item_success.append(message_id) - continue - - # 1.存在した場合 - logger.info(f'I-05-02 {execute_month} {receive_timing}データI/Fファイルに不足があるため、メール送信処理を開始します') - - try: - logger.info( - 'I-05-03 ' + - f'通知メール(タイトル)テンプレートファイル読込 読込元:{CONFIG_BUCKET_NAME}/{MAIL_TEMPLATE_FOLDER_PATH}/{event_parameter["notice_mail_title_template"]}' - ) - mail_title_response = s3_client.get_object( - Bucket=CONFIG_BUCKET_NAME, - Key=f'{MAIL_TEMPLATE_FOLDER_PATH}/{event_parameter["notice_mail_title_template"]}' - ) - mail_title_template = mail_title_response['Body'].read().decode('utf-8') - # 改行を取り除く - mail_title = substitute_mail_template(mail_title_template, receive_timing, mail_message) - mail_title_without_line_break = mail_title.splitlines()[0] - logger.info('I-05-04 通知メール(タイトル)テンプレートファイルを読み込みました') except Exception as e: - logger.error(f'E-05-01 通知メール(タイトル)テンプレートファイルの読み込みに失敗しました エラー内容:{e}') + logger.error(f'E-99 想定外のエラーが発生しました エラー内容:{e}') batch_item_failures.append(make_failure_item_on_error(message_id)) continue - try: - logger.info( - 'I-05-05 ' + - f'通知メール(本文)テンプレートファイル読込 読込元:{CONFIG_BUCKET_NAME}/{MAIL_TEMPLATE_FOLDER_PATH}/{event_parameter["notice_mail_body_template"]}' - ) - mail_body_template_response = s3_client.get_object( - Bucket=CONFIG_BUCKET_NAME, - Key=f'{MAIL_TEMPLATE_FOLDER_PATH}/{event_parameter["notice_mail_body_template"]}' - ) - mail_body_template = mail_body_template_response['Body'].read().decode('utf-8') - # メール本文内のプレースホルダーを置き換える - mail_body = substitute_mail_template(mail_body_template, receive_timing, mail_message) - logger.info('I-05-06 通知メール(本文)テンプレートファイルを読み込みました') - except Exception as e: - logger.error(f'E-05-02 通知メール(本文)テンプレートファイルの読み込みに失敗しました エラー内容:{e}') - batch_item_failures.append(make_failure_item_on_error(message_id)) - continue - - logger.info(f'I-05-07 メール送信指示をします 送信先トピック:{MBJ_NOTICE_TOPIC}') - params = { - 'TopicArn': MBJ_NOTICE_TOPIC, - 'Subject': mail_title_without_line_break, - 'Message': mail_body - } - sns_client.publish(**params) - logger.info('I-05-08 メール送信指示をしました') - - batch_item_success.append(message_id) - return batch_item_failures, batch_item_success From 8ca83fcc74a1741a48ded89ffb4c6a1497ca6d64 Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Tue, 13 Feb 2024 13:34:46 +0900 Subject: [PATCH 05/14] =?UTF-8?q?style:=20=E4=B8=8D=E8=A6=81=E3=81=AA?= =?UTF-8?q?=E3=82=B3=E3=83=A1=E3=83=B3=E3=83=88=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../encise-data-unreceive-check.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py b/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py index ca77d714..4e782b03 100644 --- a/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py +++ b/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py @@ -81,11 +81,6 @@ def is_duplicate_message(message_id: str) -> bool: )["Count"] != 0 -# Put the message to the DynamoDB Table. -# @input string batch_item_success -# -# @param batch_item_success of the message to put. -# @return Boolean def push_success_messages_to_dynamo_db(batch_item_success: list[str]) -> bool: """処理済みのSQSメッセージIdをDynamoDBにPushする @@ -104,7 +99,7 @@ def push_success_messages_to_dynamo_db(batch_item_success: list[str]) -> bool: def substitute_mail_template(mail_template: str, receive_timing: str, mail_msg: str) -> str: - """メールテンプレートのプレースホルダーを置き換えます + """メールテンプレートのプレースホルダーを置き換える Args: mail_template (str): 置き換え前のメールテンプレート From 41542bbd9d535e1936aac13e2ae9223f27aca66f Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Tue, 13 Feb 2024 13:38:43 +0900 Subject: [PATCH 06/14] =?UTF-8?q?feat:=20lambda=5Fhandler=E3=81=AB?= =?UTF-8?q?=E4=BE=8B=E5=A4=96=E5=87=A6=E7=90=86=E8=BF=BD=E5=8A=A0=E3=80=81?= =?UTF-8?q?=E3=82=B3=E3=83=A1=E3=83=B3=E3=83=88=E8=BF=BD=E5=8A=A0=E3=80=81?= =?UTF-8?q?=E6=9C=AA=E5=8F=97=E9=A0=98=E3=83=81=E3=82=A7=E3=83=83=E3=82=AF?= =?UTF-8?q?=E9=96=A2=E6=95=B0=E5=90=8D=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../encise-data-unreceive-check.py | 61 +++++++++++-------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py b/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py index 4e782b03..dc6085cf 100644 --- a/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py +++ b/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py @@ -129,8 +129,16 @@ def make_failure_item_on_error(message_id: str) -> dict[str, str]: return {"itemIdentifier": message_id} -def unreceive_check(records: list, execute_month: str) -> tuple[list[dict[str, str]], list[str]]: +def encise_data_unreceive_check(records: list, execute_month: str) -> tuple[list[dict[str, str]], list[str]]: + """Enciseデータ未受領チェック + Args: + records (list): SQS Eventのレコードリスト + execute_month (str): 処理起動年月 + + Returns: + tuple[list[dict[str, str]], list[str]]: 失敗メッセージIdのリスト, 成功メッセージIdのリスト + """ batch_item_failures = [] batch_item_success = [] @@ -146,7 +154,7 @@ def unreceive_check(records: list, execute_month: str) -> tuple[list[dict[str, s logger.info(f'受信したメッセージは既に処理済みのため、処理をスキップします。メッセージID: {message_id}') continue except Exception as e: - logger.error(f"E-02-01 メッセージ重複チェック処理に失敗しました エラー内容:{e}") + logger.exception(f"E-02-01 メッセージ重複チェック処理に失敗しました エラー内容:{e}") batch_item_failures.append(make_failure_item_on_error(message_id)) continue @@ -166,7 +174,7 @@ def unreceive_check(records: list, execute_month: str) -> tuple[list[dict[str, s ) logger.info('I-03-02 受領チェック対象ファイルリストを読み込みました') except Exception as e: - logger.error(f"E-03-01 受領チェック対象ファイルリストの読み込みに失敗しました エラー内容:{e}") + logger.exception(f"E-03-01 受領チェック対象ファイルリストの読み込みに失敗しました エラー内容:{e}") batch_item_failures.append(make_failure_item_on_error(message_id)) continue @@ -241,7 +249,7 @@ def unreceive_check(records: list, execute_month: str) -> tuple[list[dict[str, s mail_title_without_line_break = mail_title.splitlines()[0] logger.info('I-05-04 通知メール(タイトル)テンプレートファイルを読み込みました') except Exception as e: - logger.error(f'E-05-01 通知メール(タイトル)テンプレートファイルの読み込みに失敗しました エラー内容:{e}') + logger.exception(f'E-05-01 通知メール(タイトル)テンプレートファイルの読み込みに失敗しました エラー内容:{e}') batch_item_failures.append(make_failure_item_on_error(message_id)) continue @@ -259,7 +267,7 @@ def unreceive_check(records: list, execute_month: str) -> tuple[list[dict[str, s mail_body = substitute_mail_template(mail_body_template, receive_timing, mail_message) logger.info('I-05-06 通知メール(本文)テンプレートファイルを読み込みました') except Exception as e: - logger.error(f'E-05-02 通知メール(本文)テンプレートファイルの読み込みに失敗しました エラー内容:{e}') + logger.exception(f'E-05-02 通知メール(本文)テンプレートファイルの読み込みに失敗しました エラー内容:{e}') batch_item_failures.append(make_failure_item_on_error(message_id)) continue @@ -274,7 +282,7 @@ def unreceive_check(records: list, execute_month: str) -> tuple[list[dict[str, s batch_item_success.append(message_id) except Exception as e: - logger.error(f'E-99 想定外のエラーが発生しました エラー内容:{e}') + logger.exception(f'E-99 想定外のエラーが発生しました エラー内容:{e}') batch_item_failures.append(make_failure_item_on_error(message_id)) continue @@ -282,24 +290,29 @@ def unreceive_check(records: list, execute_month: str) -> tuple[list[dict[str, s def lambda_handler(event, context): - # ① 処理開始ログを出力する - logger.info('I-01-01 処理開始 Enciseデータ受領チェック処理') - # 処理稼働年月を取得しメモリに保持する - execute_date_today = datetime.date.today() - execute_month = execute_date_today.strftime('%Y/%m') - logger.info(f'I-01-02 処理稼働月:{execute_month}') - # 処理失敗メッセージIDリストをメモリに保持する(初期値=空のリスト) - batch_item_failures = [] - # 処理成功メッセージIDリストをメモリに保持する(初期値=空のリスト) - batch_item_success = [] - # ② SQSメッセージ重複排除処理を行う - logger.info('I-02-01 メッセージ処理開始') - batch_item_failures, batch_item_success = unreceive_check(event["Records"], execute_month) - logger.info('I-06-01 すべてのメッセージの処理完了') + try: + # ① 処理開始ログを出力する + logger.info('I-01-01 処理開始 Enciseデータ受領チェック処理') + # 処理稼働年月を取得しメモリに保持する + execute_date_today = datetime.date.today() + execute_month = execute_date_today.strftime('%Y/%m') + logger.info(f'I-01-02 処理稼働月:{execute_month}') + # 処理失敗メッセージIDリストをメモリに保持する(初期値=空のリスト) + batch_item_failures = [] + # 処理成功メッセージIDリストをメモリに保持する(初期値=空のリスト) + batch_item_success = [] + # ② SQSメッセージ重複排除処理を行う + logger.info('I-02-01 メッセージ処理開始') + batch_item_failures, batch_item_success = encise_data_unreceive_check(event["Records"], execute_month) + logger.info('I-06-01 すべてのメッセージの処理完了') - # ⑦ メッセージを処理済として、以下のDynamoDBテーブルに記録する - push_success_messages_to_dynamo_db(batch_item_success) - logger.info('I-07-01 処理済みメッセージIDの記録完了') - logger.info('I-07-02 処理終了 Enciseデータ受領チェック処理') + # ⑦ メッセージを処理済として、以下のDynamoDBテーブルに記録する + push_success_messages_to_dynamo_db(batch_item_success) + logger.info('I-07-01 処理済みメッセージIDの記録完了') + logger.info('I-07-02 処理終了 Enciseデータ受領チェック処理') + + except Exception as e: + logger.exception(f'E-99 想定外のエラーが発生しました エラー内容:{e}') + raise e return batch_item_failures From d3615e38c4e8daf62b792421901db30a0cdfff47 Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Tue, 13 Feb 2024 13:46:50 +0900 Subject: [PATCH 07/14] =?UTF-8?q?feat:=20NDS=E9=80=9A=E7=9F=A5SNS=E3=81=AF?= =?UTF-8?q?=E4=B8=8D=E8=A6=81=E3=81=AA=E3=81=AE=E3=81=A7=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../encise-data-unreceive-check/encise-data-unreceive-check.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py b/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py index dc6085cf..130e0a9a 100644 --- a/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py +++ b/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py @@ -16,8 +16,6 @@ CONFIG_BUCKET_NAME = os.environ["CONFIG_BUCKET_NAME"] LOG_LEVEL = os.environ["LOG_LEVEL"] MAIL_TEMPLATE_FOLDER_PATH = os.environ["MAIL_TEMPLATE_FOLDER_PATH"] MBJ_NOTICE_TOPIC = os.environ["MBJ_NOTICE_TOPIC"] -NDS_NOTICE_TITLE = os.environ["NDS_NOTICE_TITLE"] -NDS_NOTICE_TOPIC = os.environ["NDS_NOTICE_TOPIC"] PROCESSED_MESSAGE_DYNAMODB_TABLE_NAME = os.environ["PROCESSED_MESSAGE_DYNAMODB_TABLE_NAME"] PROCESSED_MESSAGE_EXPIRES_PERIOD = os.environ["PROCESSED_MESSAGE_EXPIRES_PERIOD"] TZ = os.environ["TZ"] From 5cadb1a466be0371aa80f71c9c09635b742e3818 Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Tue, 13 Feb 2024 14:02:08 +0900 Subject: [PATCH 08/14] =?UTF-8?q?feat:=20DynamoDB=E3=83=86=E3=83=BC?= =?UTF-8?q?=E3=83=96=E3=83=AB=E3=81=AE=E3=83=AC=E3=82=B3=E3=83=BC=E3=83=89?= =?UTF-8?q?=E6=9C=89=E5=8A=B9=E6=9C=9F=E9=99=90=E7=94=A8=E3=81=AE=E9=A0=85?= =?UTF-8?q?=E7=9B=AE=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../encise-data-unreceive-check.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py b/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py index 130e0a9a..e4e26de8 100644 --- a/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py +++ b/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py @@ -17,7 +17,7 @@ LOG_LEVEL = os.environ["LOG_LEVEL"] MAIL_TEMPLATE_FOLDER_PATH = os.environ["MAIL_TEMPLATE_FOLDER_PATH"] MBJ_NOTICE_TOPIC = os.environ["MBJ_NOTICE_TOPIC"] PROCESSED_MESSAGE_DYNAMODB_TABLE_NAME = os.environ["PROCESSED_MESSAGE_DYNAMODB_TABLE_NAME"] -PROCESSED_MESSAGE_EXPIRES_PERIOD = os.environ["PROCESSED_MESSAGE_EXPIRES_PERIOD"] +PROCESSED_MESSAGE_EXPIRES_PERIOD = int(os.environ["PROCESSED_MESSAGE_EXPIRES_PERIOD"]) TZ = os.environ["TZ"] # 定数 @@ -79,7 +79,7 @@ def is_duplicate_message(message_id: str) -> bool: )["Count"] != 0 -def push_success_messages_to_dynamo_db(batch_item_success: list[str]) -> bool: +def put_success_messages_to_dynamo_db(batch_item_success: list[str]) -> bool: """処理済みのSQSメッセージIdをDynamoDBにPushする Args: @@ -88,10 +88,19 @@ def push_success_messages_to_dynamo_db(batch_item_success: list[str]) -> bool: Returns: bool: 登録成功の場合、True """ + + # レコードの有効期限を算出 + now = datetime.datetime.now(ZoneInfo(TZ)) + record_expiration_datetime = now + datetime.timedelta(minutes=PROCESSED_MESSAGE_EXPIRES_PERIOD) + record_expiration_time = record_expiration_datetime.timestamp() + for message_id in batch_item_success: dynamodb_client.put_item( TableName=PROCESSED_MESSAGE_DYNAMODB_TABLE_NAME, - Item={'message_id': {'S': message_id}} + Item={ + 'message_id': {'S': message_id}, + 'record_expiration_time': {'N': f'{record_expiration_time}'} + } ) return True @@ -305,7 +314,7 @@ def lambda_handler(event, context): logger.info('I-06-01 すべてのメッセージの処理完了') # ⑦ メッセージを処理済として、以下のDynamoDBテーブルに記録する - push_success_messages_to_dynamo_db(batch_item_success) + put_success_messages_to_dynamo_db(batch_item_success) logger.info('I-07-01 処理済みメッセージIDの記録完了') logger.info('I-07-02 処理終了 Enciseデータ受領チェック処理') From d2485a4afec4cd42fbe78c8ac793b6491a319ecf Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Tue, 13 Feb 2024 14:45:58 +0900 Subject: [PATCH 09/14] =?UTF-8?q?feat:=20=E6=9C=AA=E5=8F=97=E9=A0=98?= =?UTF-8?q?=E3=83=81=E3=82=A7=E3=83=83=E3=82=AF=E5=AF=BE=E8=B1=A1=E3=83=95?= =?UTF-8?q?=E3=82=A1=E3=82=A4=E3=83=AB=E3=83=AA=E3=82=B9=E3=83=88=E3=82=92?= =?UTF-8?q?=E4=BD=9C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../en_cluster_direct_file_list.config | 3 +++ .../en_cluster_file_list.config | 6 ++++++ .../unreceive_check_target/en_fixed_file_list.config | 11 +++++++++++ .../en_nation_direct_fixed_file_list.config | 1 + .../unreceive_check_target/en_quick_file_list.config | 10 ++++++++++ 5 files changed, 31 insertions(+) create mode 100644 s3/config/encise/unreceive_check_target/en_cluster_direct_file_list.config create mode 100644 s3/config/encise/unreceive_check_target/en_cluster_file_list.config create mode 100644 s3/config/encise/unreceive_check_target/en_fixed_file_list.config create mode 100644 s3/config/encise/unreceive_check_target/en_nation_direct_fixed_file_list.config create mode 100644 s3/config/encise/unreceive_check_target/en_quick_file_list.config diff --git a/s3/config/encise/unreceive_check_target/en_cluster_direct_file_list.config b/s3/config/encise/unreceive_check_target/en_cluster_direct_file_list.config new file mode 100644 index 00000000..44631a3a --- /dev/null +++ b/s3/config/encise/unreceive_check_target/en_cluster_direct_file_list.config @@ -0,0 +1,3 @@ +CLUFD_Merck02_496_([0-9]{6})D\.(CSV|csv) 直販分 En-Clusterデータ Merck02 +CLUFD_Merck03_496_([0-9]{6})D\.(CSV|csv) 直販分 En-Clusterデータ Merck03 +CLUFD_Merck04_496_([0-9]{6})D\.(CSV|csv) 直販分 En-Clusterデータ Merck04 diff --git a/s3/config/encise/unreceive_check_target/en_cluster_file_list.config b/s3/config/encise/unreceive_check_target/en_cluster_file_list.config new file mode 100644 index 00000000..33c31f6f --- /dev/null +++ b/s3/config/encise/unreceive_check_target/en_cluster_file_list.config @@ -0,0 +1,6 @@ +CLUFD_Merck02_496_([0-9]{6})\.(CSV|csv) En-Cluster データ Merck02 +CLUFD_Merck03_496_([0-9]{6})\.(CSV|csv) En-Cluster データ Merck03 +CLUFD_Merck04_496_([0-9]{6})\.(CSV|csv) En-Cluster データ Merck04 +CLUFM_CLUMST_496_01_([0-9]{6})\.(CSV|csv) En-Cluster クラスタマスタ +CLUFM_PROADD_496_([0-9]{6})\.(CSV|csv) En-Cluster 製品定義ファイル +CLUFM_PROLST_496_([0-9]{6})\.(CSV|csv) En-Cluster 製品マスタ diff --git a/s3/config/encise/unreceive_check_target/en_fixed_file_list.config b/s3/config/encise/unreceive_check_target/en_fixed_file_list.config new file mode 100644 index 00000000..edd0126b --- /dev/null +++ b/s3/config/encise/unreceive_check_target/en_fixed_file_list.config @@ -0,0 +1,11 @@ +NATFD_496_([0-9]{6})\.(CSV|csv) 確定版 En-Nation データ +NATFM_PROADD_496_([0-9]{6})\.(CSV|csv) 確定版 En-Nation 製品定義ファイル +NATFM_SEGMNT_496_([0-9]{6})\.(CSV|csv) 確定版 En-Nation セグメントマスタ +MST_BRAND([0-9]{6})\.(CSV|csv) 確定版 En-Nation ブランドマスタ +CITFD_Merck01_496_([0-9]{6})\.(CSV|csv) 確定版 En-City データ Merck01 +CITFD_Merck06_496_([0-9]{6})\.(CSV|csv) 確定版 En-City データ Merck06 +CITFD_Merck07_496_([0-9]{6})\.(CSV|csv) 確定版 En-City データ Merck07 +CITFM_PROADD_496_([0-9]{6})\.(CSV|csv) 確定版 En-City 製品定義ファイル +CITFM_PROLST_496_([0-9]{6})\.(CSV|csv) 確定版 En-City 製品マスタ +CITFM_REGION_496_([0-9]{6})\.(CSV|csv) 確定版 En-City 地域マスタ +CITFM_SEGMNT_496_([0-9]{6})\.(CSV|csv) 確定版 En-City セグメントマスタ diff --git a/s3/config/encise/unreceive_check_target/en_nation_direct_fixed_file_list.config b/s3/config/encise/unreceive_check_target/en_nation_direct_fixed_file_list.config new file mode 100644 index 00000000..dfb557e8 --- /dev/null +++ b/s3/config/encise/unreceive_check_target/en_nation_direct_fixed_file_list.config @@ -0,0 +1 @@ +NATFD_496_([0-9]{6})D\.(CSV|csv) 確定版 En-Nation データ 直販分 \ No newline at end of file diff --git a/s3/config/encise/unreceive_check_target/en_quick_file_list.config b/s3/config/encise/unreceive_check_target/en_quick_file_list.config new file mode 100644 index 00000000..ae8a4761 --- /dev/null +++ b/s3/config/encise/unreceive_check_target/en_quick_file_list.config @@ -0,0 +1,10 @@ +NATQD_496_([0-9]{6}\).(CSV|csv) 速報版 En-Nation データ +NATQM_PROADD_496_([0-9]{6})\.(CSV|csv) 速報版 En-Nation 製品定義ファイル +NATQM_SEGMNT_496_([0-9]{6})\.(CSV|csv) 速報版 En-Nation セグメントマスタ +CITQD_Merck01_496_([0-9]{6})\.(CSV|csv) 速報版 En-City データ Merck01 +CITQD_Merck06_496_([0-9]{6})\.(CSV|csv) 速報版 En-City データ Merck06 +CITQD_Merck07_496_([0-9]{6})\.(CSV|csv) 速報版 En-City データ Merck07 +CITQM_PROADD_496_([0-9]{6})\.(CSV|csv) 速報版 En-City 製品定義ファイル +CITQM_PROLST_496_([0-9]{6})\.(CSV|csv) 速報版 En-City 製品マスタ +CITQM_REGION_496_([0-9]{6})\.(CSV|csv) 速報版 En-City 地域マスタ +CITQM_SEGMNT_496_([0-9]{6})\.(CSV|csv) 速報版 En-City セグメントマスタ From 2b7031f685ef1f768f52a4ca7433fa4c9e1344c4 Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Tue, 13 Feb 2024 14:48:44 +0900 Subject: [PATCH 10/14] =?UTF-8?q?feat:=20=E3=80=81=E9=80=9A=E7=9F=A5?= =?UTF-8?q?=E3=83=A1=E3=83=BC=E3=83=AB=E3=83=86=E3=83=B3=E3=83=97=E3=83=AC?= =?UTF-8?q?=E3=83=BC=E3=83=88=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB=E3=82=92?= =?UTF-8?q?=E4=BD=9C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../en_direct_unreceive_notice_mail_body.config | 9 +++++++++ .../en_direct_unreceive_notice_mail_title.config | 1 + .../en_unreceive_notice_mail_body.config | 9 +++++++++ .../en_unreceive_notice_mail_title.config | 1 + 4 files changed, 20 insertions(+) create mode 100644 s3/config/encise/notice_mail_template/en_direct_unreceive_notice_mail_body.config create mode 100644 s3/config/encise/notice_mail_template/en_direct_unreceive_notice_mail_title.config create mode 100644 s3/config/encise/notice_mail_template/en_unreceive_notice_mail_body.config create mode 100644 s3/config/encise/notice_mail_template/en_unreceive_notice_mail_title.config diff --git a/s3/config/encise/notice_mail_template/en_direct_unreceive_notice_mail_body.config b/s3/config/encise/notice_mail_template/en_direct_unreceive_notice_mail_body.config new file mode 100644 index 00000000..9cf79023 --- /dev/null +++ b/s3/config/encise/notice_mail_template/en_direct_unreceive_notice_mail_body.config @@ -0,0 +1,9 @@ +宛先各位 + Encise {receive_timing}である以下のファイルを受領できておりません。 +{notice_file_names} + + + QlikSenseサーバー側の送信状況のご確認をお願いいたします。 + + 尚、本メールはシステム自動送信のため、返信は出来ません。 + 本件に関する問い合わせは、MeDaCA Enciseデータ担当者にお願いいたします。 diff --git a/s3/config/encise/notice_mail_template/en_direct_unreceive_notice_mail_title.config b/s3/config/encise/notice_mail_template/en_direct_unreceive_notice_mail_title.config new file mode 100644 index 00000000..d40c304d --- /dev/null +++ b/s3/config/encise/notice_mail_template/en_direct_unreceive_notice_mail_title.config @@ -0,0 +1 @@ +【MeDaCa連携エラー通知】Encise {receive_timing}ファイル未受領 \ No newline at end of file diff --git a/s3/config/encise/notice_mail_template/en_unreceive_notice_mail_body.config b/s3/config/encise/notice_mail_template/en_unreceive_notice_mail_body.config new file mode 100644 index 00000000..591d85cb --- /dev/null +++ b/s3/config/encise/notice_mail_template/en_unreceive_notice_mail_body.config @@ -0,0 +1,9 @@ +宛先各位 + Encise {receive_timing}である以下のファイルを受領できておりません。 +{notice_file_names} + + + Encise社へ送信状況のご確認をお願いいたします。 + + 尚、本メールはシステム自動送信のため、返信は出来ません。 + 本件に関する問い合わせは、MeDaCA Enciseデータ担当者にお願いいたします。 diff --git a/s3/config/encise/notice_mail_template/en_unreceive_notice_mail_title.config b/s3/config/encise/notice_mail_template/en_unreceive_notice_mail_title.config new file mode 100644 index 00000000..d40c304d --- /dev/null +++ b/s3/config/encise/notice_mail_template/en_unreceive_notice_mail_title.config @@ -0,0 +1 @@ +【MeDaCa連携エラー通知】Encise {receive_timing}ファイル未受領 \ No newline at end of file From 1153cfa8b52263ef55c7e3f011b2b8a0ca813909 Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Tue, 13 Feb 2024 16:21:44 +0900 Subject: [PATCH 11/14] =?UTF-8?q?fix:=20=E3=83=95=E3=82=A1=E3=82=A4?= =?UTF-8?q?=E3=83=AB=E3=81=AE=E6=AD=A3=E8=A6=8F=E8=A1=A8=E7=8F=BE=E3=81=AE?= =?UTF-8?q?=E3=83=9F=E3=82=B9=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../encise/unreceive_check_target/en_quick_file_list.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s3/config/encise/unreceive_check_target/en_quick_file_list.config b/s3/config/encise/unreceive_check_target/en_quick_file_list.config index ae8a4761..e3f3ebcd 100644 --- a/s3/config/encise/unreceive_check_target/en_quick_file_list.config +++ b/s3/config/encise/unreceive_check_target/en_quick_file_list.config @@ -1,4 +1,4 @@ -NATQD_496_([0-9]{6}\).(CSV|csv) 速報版 En-Nation データ +NATQD_496_([0-9]{6})\.(CSV|csv) 速報版 En-Nation データ NATQM_PROADD_496_([0-9]{6})\.(CSV|csv) 速報版 En-Nation 製品定義ファイル NATQM_SEGMNT_496_([0-9]{6})\.(CSV|csv) 速報版 En-Nation セグメントマスタ CITQD_Merck01_496_([0-9]{6})\.(CSV|csv) 速報版 En-City データ Merck01 From f1ce484d1dda6e911fb9080997312e8e67221699 Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Tue, 13 Feb 2024 16:24:16 +0900 Subject: [PATCH 12/14] =?UTF-8?q?feat:=20=E3=83=81=E3=82=A7=E3=83=83?= =?UTF-8?q?=E3=82=AF=E5=AF=BE=E8=B1=A1=E5=B9=B4=E6=9C=88=E3=81=AE=E3=83=AD?= =?UTF-8?q?=E3=82=B8=E3=83=83=E3=82=AF=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../encise-data-unreceive-check.py | 91 ++++++++++++------- 1 file changed, 59 insertions(+), 32 deletions(-) diff --git a/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py b/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py index e4e26de8..1667f9e2 100644 --- a/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py +++ b/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py @@ -8,6 +8,7 @@ import re from zoneinfo import ZoneInfo import boto3 +from dateutil.relativedelta import relativedelta # 環境変数 CHECK_BUCKET_NAME = os.environ["CHECK_BUCKET_NAME"] @@ -17,7 +18,8 @@ LOG_LEVEL = os.environ["LOG_LEVEL"] MAIL_TEMPLATE_FOLDER_PATH = os.environ["MAIL_TEMPLATE_FOLDER_PATH"] MBJ_NOTICE_TOPIC = os.environ["MBJ_NOTICE_TOPIC"] PROCESSED_MESSAGE_DYNAMODB_TABLE_NAME = os.environ["PROCESSED_MESSAGE_DYNAMODB_TABLE_NAME"] -PROCESSED_MESSAGE_EXPIRES_PERIOD = int(os.environ["PROCESSED_MESSAGE_EXPIRES_PERIOD"]) +PROCESSED_MESSAGE_EXPIRES_PERIOD = int( + os.environ["PROCESSED_MESSAGE_EXPIRES_PERIOD"]) TZ = os.environ["TZ"] # 定数 @@ -91,7 +93,8 @@ def put_success_messages_to_dynamo_db(batch_item_success: list[str]) -> bool: # レコードの有効期限を算出 now = datetime.datetime.now(ZoneInfo(TZ)) - record_expiration_datetime = now + datetime.timedelta(minutes=PROCESSED_MESSAGE_EXPIRES_PERIOD) + record_expiration_datetime = now + \ + datetime.timedelta(minutes=PROCESSED_MESSAGE_EXPIRES_PERIOD) record_expiration_time = record_expiration_datetime.timestamp() for message_id in batch_item_success: @@ -158,11 +161,13 @@ def encise_data_unreceive_check(records: list, execute_month: str) -> tuple[list message_id = record["messageId"] # 2.DynamoDBテーブルからレコードを取得し、処理済みメッセージかどうかを判別する if is_duplicate_message(message_id): - logger.info(f'受信したメッセージは既に処理済みのため、処理をスキップします。メッセージID: {message_id}') + logger.info( + f'受信したメッセージは既に処理済みのため、処理をスキップします。メッセージID: {message_id}') continue except Exception as e: logger.exception(f"E-02-01 メッセージ重複チェック処理に失敗しました エラー内容:{e}") - batch_item_failures.append(make_failure_item_on_error(message_id)) + batch_item_failures.append( + make_failure_item_on_error(message_id)) continue # SQSパラメータをJSONシリアライズし、Pythonの辞書オブジェクト(イベントパラメータ)を取得する。 @@ -181,49 +186,60 @@ def encise_data_unreceive_check(records: list, execute_month: str) -> tuple[list ) logger.info('I-03-02 受領チェック対象ファイルリストを読み込みました') except Exception as e: - logger.exception(f"E-03-01 受領チェック対象ファイルリストの読み込みに失敗しました エラー内容:{e}") - batch_item_failures.append(make_failure_item_on_error(message_id)) + logger.exception( + f"E-03-01 受領チェック対象ファイルリストの読み込みに失敗しました エラー内容:{e}") + batch_item_failures.append( + make_failure_item_on_error(message_id)) continue # ④ 受領チェック処理を行う receive_timing = event_parameter['receive_timing'] logger.info(f'I-04-01 Enciseデータ受領チェック ({receive_timing}) 処理開始') - object_prefix = f'{event_parameter["check_folder_prefix"]}{execute_month}/' + object_prefix = f'{event_parameter["check_folder_prefix"]}/{execute_month}/' # 1.Enciseデータバックアップ保管バケットの処理稼働月に該当するサブフォルダにあるファイル一覧を取得する logger.info( f'I-04-02 オブジェクトリストの取得 取得先:{CHECK_BUCKET_NAME}/{object_prefix}' ) - check_target_file_list_response = s3_client.list_objects_v2(CHECK_BUCKET_NAME, Prefix=object_prefix) - check_target_file_list = [] - for content in check_target_file_list_response[['Contents']]: + receive_file_list_response = s3_client.list_objects_v2( + Bucket=CHECK_BUCKET_NAME, Prefix=object_prefix) + receive_file_list = [] + for content in receive_file_list_response.get('Contents', []): # オブジェクトのキーからファイル名を切り出してリストに追加 obj_key = content['Key'].rsplit('/', INDEX_SPLIT_NUM) - check_target_file_list.append(obj_key[INDEX_LAST]) + receive_file_list.append(obj_key[INDEX_LAST]) # 2.I/Fファイルチェック処理 logger.info(f'I-04-03 Enciseデータ({receive_timing}) ファイルチェック処理開始') - receive_monthly_file_name_body = io.TextIOWrapper(io.BytesIO(check_target_file_list_response["Body"].read()), encoding='utf-8') + check_target_file_name_body = io.TextIOWrapper(io.BytesIO( + check_target_file_list_response["Body"].read()), encoding='utf-8') match_count = 0 row_count = 0 - for tsv_row in csv.reader(receive_monthly_file_name_body, delimiter='\t'): + for tsv_row in csv.reader(check_target_file_name_body, delimiter='\t'): # 「④1.」で取得したリストが「③」で読み込んだファイル内に存在するか確認する is_file_not_exists = True - for file_name in check_target_file_list: - match_result = re.fullmatch(tsv_row[INDEX_REGEX], file_name) + for file_name in receive_file_list: + match_result = re.fullmatch( + tsv_row[INDEX_REGEX], file_name) # 「③」で読み込んだファイルに記載されている全てが「④1.」で取得したリストに存在した場合 if match_result is not None: # 存在したファイルの年月部分を抜き出し、チェック対象年月(処理稼働月-1)である場合 - if True: # TODO - logger.info(f'I-04-04 I/Fファイルの受領を確認しました ファイル名:{file_name}') + match_group_yyyymm = match_result.group(1) + check_target_yyyymm = (datetime.datetime.now( + ZoneInfo(TZ)) - relativedelta(month=1)).strftime('%Y%m') + if match_group_yyyymm == check_target_yyyymm: + logger.info( + f'I-04-04 I/Fファイルの受領を確認しました ファイル名:{file_name}') is_file_not_exists = False match_count += 1 else: - logger.info(f'I-04-07 I/Fファイルの年月がチェック対象年月と一致しません ファイル名:{file_name}') + logger.info( + f'I-04-07 I/Fファイルの年月がチェック対象年月と一致しません ファイル名:{file_name}') mail_message += f'{MAIL_INDENT}{tsv_row[INDEX_DATA_NAME]}(受領年月が不正:{file_name})\n' break - if is_file_not_exists: - logger.info(f'E-04-06 月次I/Fファイルに不足があります ファイル名:{tsv_row[INDEX_DATA_NAME]}') - mail_message += f'{MAIL_INDENT}{tsv_row[INDEX_DATA_NAME]}\n' + if is_file_not_exists: + logger.info( + f'E-04-06 月次I/Fファイルに不足があります ファイル名:{tsv_row[INDEX_DATA_NAME]}') + mail_message += f'{MAIL_INDENT}{tsv_row[INDEX_DATA_NAME]}\n' row_count += 1 @@ -234,12 +250,14 @@ def encise_data_unreceive_check(records: list, execute_month: str) -> tuple[list logger.info('I-05-01 メール送信処理開始') if len(mail_message) == 0: - logger.info(f'I-05-09 {execute_month} {receive_timing}データI/Fファイルに不足が無いため、メール送信処理をスキップします') + logger.info( + f'I-05-09 {execute_month} {receive_timing}データI/Fファイルに不足が無いため、メール送信処理をスキップします') batch_item_success.append(message_id) continue # 1.存在した場合 - logger.info(f'I-05-02 {execute_month} {receive_timing}データI/Fファイルに不足があるため、メール送信処理を開始します') + logger.info( + f'I-05-02 {execute_month} {receive_timing}データI/Fファイルに不足があるため、メール送信処理を開始します') try: logger.info( @@ -250,14 +268,18 @@ def encise_data_unreceive_check(records: list, execute_month: str) -> tuple[list Bucket=CONFIG_BUCKET_NAME, Key=f'{MAIL_TEMPLATE_FOLDER_PATH}/{event_parameter["notice_mail_title_template"]}' ) - mail_title_template = mail_title_response['Body'].read().decode('utf-8') + mail_title_template = ( + mail_title_response['Body'].read().decode('utf-8')) # 改行を取り除く - mail_title = substitute_mail_template(mail_title_template, receive_timing, mail_message) + mail_title = substitute_mail_template( + mail_title_template, receive_timing, mail_message) mail_title_without_line_break = mail_title.splitlines()[0] logger.info('I-05-04 通知メール(タイトル)テンプレートファイルを読み込みました') except Exception as e: - logger.exception(f'E-05-01 通知メール(タイトル)テンプレートファイルの読み込みに失敗しました エラー内容:{e}') - batch_item_failures.append(make_failure_item_on_error(message_id)) + logger.exception( + f'E-05-01 通知メール(タイトル)テンプレートファイルの読み込みに失敗しました エラー内容:{e}') + batch_item_failures.append( + make_failure_item_on_error(message_id)) continue try: @@ -269,13 +291,17 @@ def encise_data_unreceive_check(records: list, execute_month: str) -> tuple[list Bucket=CONFIG_BUCKET_NAME, Key=f'{MAIL_TEMPLATE_FOLDER_PATH}/{event_parameter["notice_mail_body_template"]}' ) - mail_body_template = mail_body_template_response['Body'].read().decode('utf-8') + mail_body_template = mail_body_template_response['Body'].read().decode( + 'utf-8') # メール本文内のプレースホルダーを置き換える - mail_body = substitute_mail_template(mail_body_template, receive_timing, mail_message) + mail_body = substitute_mail_template( + mail_body_template, receive_timing, mail_message) logger.info('I-05-06 通知メール(本文)テンプレートファイルを読み込みました') except Exception as e: - logger.exception(f'E-05-02 通知メール(本文)テンプレートファイルの読み込みに失敗しました エラー内容:{e}') - batch_item_failures.append(make_failure_item_on_error(message_id)) + logger.exception( + f'E-05-02 通知メール(本文)テンプレートファイルの読み込みに失敗しました エラー内容:{e}') + batch_item_failures.append( + make_failure_item_on_error(message_id)) continue logger.info(f'I-05-07 メール送信指示をします 送信先トピック:{MBJ_NOTICE_TOPIC}') @@ -310,7 +336,8 @@ def lambda_handler(event, context): batch_item_success = [] # ② SQSメッセージ重複排除処理を行う logger.info('I-02-01 メッセージ処理開始') - batch_item_failures, batch_item_success = encise_data_unreceive_check(event["Records"], execute_month) + batch_item_failures, batch_item_success = encise_data_unreceive_check( + event["Records"], execute_month) logger.info('I-06-01 すべてのメッセージの処理完了') # ⑦ メッセージを処理済として、以下のDynamoDBテーブルに記録する From d5d5b719f7ad3127df5cc25280aa4a233f7f1afa Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Tue, 13 Feb 2024 16:26:20 +0900 Subject: [PATCH 13/14] =?UTF-8?q?feat:=20=E3=83=AD=E3=83=BC=E3=82=AB?= =?UTF-8?q?=E3=83=AB=E5=8B=95=E4=BD=9C=E7=A2=BA=E8=AA=8D=E7=94=A8=E3=81=AE?= =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=89=E3=82=92=E3=82=B3=E3=83=A1=E3=83=B3?= =?UTF-8?q?=E3=83=88=E3=81=A7=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../encise-data-unreceive-check.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py b/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py index 1667f9e2..9499d2b2 100644 --- a/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py +++ b/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py @@ -350,3 +350,27 @@ def lambda_handler(event, context): raise e return batch_item_failures + + +# 動作確認用のコード +# if __name__ == '__main__': +# lambda_handler({ +# "Records": [ +# { +# "messageId": "19dd0b57-b21e-4ac1-bd88-01bbb068cb78", +# "receiptHandle": "MessageReceiptHandle", +# "body": "{\"receive_timing\": \"速報\",\"check_folder_prefix\": \"encise\",\"check_target_file_list\": \"en_quick_file_list.config\",\"notice_mail_title_template\": \"en_unreceive_notice_mail_title.config\",\"notice_mail_body_template\": \"en_unreceive_notice_mail_body.config\"\r\n}", +# "attributes": { +# "ApproximateReceiveCount": "1", +# "SentTimestamp": "1523232000000", +# "SenderId": "123456789012", +# "ApproximateFirstReceiveTimestamp": "1523232000001" +# }, +# "messageAttributes": {}, +# "md5OfBody": "{{{md5_of_body}}}", +# "eventSource": "aws:sqs", +# "eventSourceARN": "arn:aws:sqs:us-east-1:123456789012:MyQueue", +# "awsRegion": "us-east-1" +# } +# ] +# }, {}) From b0f39ea79d8430d0bf5049f5b0df78cb8b084035 Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Tue, 13 Feb 2024 17:12:31 +0900 Subject: [PATCH 14/14] =?UTF-8?q?style:=20=E3=83=95=E3=82=A9=E3=83=BC?= =?UTF-8?q?=E3=83=9E=E3=83=83=E3=83=88=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../encise-data-unreceive-check.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py b/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py index 9499d2b2..d762c275 100644 --- a/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py +++ b/lambda/encise-data-unreceive-check/encise-data-unreceive-check.py @@ -14,12 +14,12 @@ from dateutil.relativedelta import relativedelta CHECK_BUCKET_NAME = os.environ["CHECK_BUCKET_NAME"] CHECK_TARGET_FILE_NAME_LIST_FOLDER_PATH = os.environ["CHECK_TARGET_FILE_NAME_LIST_FOLDER_PATH"] CONFIG_BUCKET_NAME = os.environ["CONFIG_BUCKET_NAME"] -LOG_LEVEL = os.environ["LOG_LEVEL"] MAIL_TEMPLATE_FOLDER_PATH = os.environ["MAIL_TEMPLATE_FOLDER_PATH"] MBJ_NOTICE_TOPIC = os.environ["MBJ_NOTICE_TOPIC"] PROCESSED_MESSAGE_DYNAMODB_TABLE_NAME = os.environ["PROCESSED_MESSAGE_DYNAMODB_TABLE_NAME"] PROCESSED_MESSAGE_EXPIRES_PERIOD = int( os.environ["PROCESSED_MESSAGE_EXPIRES_PERIOD"]) +LOG_LEVEL = os.environ["LOG_LEVEL"] TZ = os.environ["TZ"] # 定数 @@ -40,8 +40,6 @@ dynamodb_client = boto3.client('dynamodb') # logger設定 - - def log_datetime_convert_tz(*arg): """ログに出力するタイムスタンプのロケールを変更する(JST指定)""" return datetime.datetime.now(ZoneInfo(TZ)).timetuple() @@ -222,6 +220,7 @@ def encise_data_unreceive_check(records: list, execute_month: str) -> tuple[list tsv_row[INDEX_REGEX], file_name) # 「③」で読み込んだファイルに記載されている全てが「④1.」で取得したリストに存在した場合 if match_result is not None: + is_file_not_exists = False # 存在したファイルの年月部分を抜き出し、チェック対象年月(処理稼働月-1)である場合 match_group_yyyymm = match_result.group(1) check_target_yyyymm = (datetime.datetime.now( @@ -229,7 +228,6 @@ def encise_data_unreceive_check(records: list, execute_month: str) -> tuple[list if match_group_yyyymm == check_target_yyyymm: logger.info( f'I-04-04 I/Fファイルの受領を確認しました ファイル名:{file_name}') - is_file_not_exists = False match_count += 1 else: logger.info( @@ -291,8 +289,8 @@ def encise_data_unreceive_check(records: list, execute_month: str) -> tuple[list Bucket=CONFIG_BUCKET_NAME, Key=f'{MAIL_TEMPLATE_FOLDER_PATH}/{event_parameter["notice_mail_body_template"]}' ) - mail_body_template = mail_body_template_response['Body'].read().decode( - 'utf-8') + mail_body_template = ( + mail_body_template_response['Body'].read().decode('utf-8')) # メール本文内のプレースホルダーを置き換える mail_body = substitute_mail_template( mail_body_template, receive_timing, mail_message)