diff --git a/.gitignore b/.gitignore index e4f6d9fb..4342f002 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ -lambda/mbj-newdwh2021-staging-NoticeToSlack/package-lock.json -lambda/mbj-newdwh2021-staging-NoticeToSlack/node_modules/* -lambda/mbj-newdwh2021-staging-PublishFromLog/package-lock.json -lambda/mbj-newdwh2021-staging-PublishFromLog/node_modules/* \ No newline at end of file +# Node.jsで実装されたLambdaの管理対象外ファイル群 +package-lock.json +node_modules/ +# ローカル確認用環境変数ファイル +.env +# pythonのキャッシュファイル +__pycache__/ \ No newline at end of file diff --git a/ecs/Dockerfile/Dockerfile b/ecs/Dockerfile/Dockerfile deleted file mode 100644 index ec5fb0e0..00000000 --- a/ecs/Dockerfile/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM python:3.9 - -ENV TZ="Asia/Tokyo" - -WORKDIR /usr/src/app -COPY requirements.txt ./ -RUN pip install --no-cache-dir -r requirements.txt -COPY dataimport ./ - -CMD [ "python", "./controller.py" ] diff --git a/ecs/dataimport/Dockerfile b/ecs/dataimport/Dockerfile new file mode 100644 index 00000000..dfe25cb3 --- /dev/null +++ b/ecs/dataimport/Dockerfile @@ -0,0 +1,15 @@ +FROM python:3.9 + +ENV TZ="Asia/Tokyo" + +WORKDIR /usr/src/app +COPY requirements.txt ./ +RUN \ + apt update -y && \ + # パッケージのセキュリティアップデートのみを適用するコマンド + apt install -y unattended-upgrades && \ + unattended-upgrades && \ + pip install --no-cache-dir -r requirements.txt +COPY dataimport ./ + +CMD [ "python", "./controller.py" ] diff --git a/ecs/Dockerfile/dataimport/chk.py b/ecs/dataimport/dataimport/chk.py similarity index 100% rename from ecs/Dockerfile/dataimport/chk.py rename to ecs/dataimport/dataimport/chk.py diff --git a/ecs/Dockerfile/dataimport/common.py b/ecs/dataimport/dataimport/common.py similarity index 100% rename from ecs/Dockerfile/dataimport/common.py rename to ecs/dataimport/dataimport/common.py diff --git a/ecs/Dockerfile/dataimport/controller.py b/ecs/dataimport/dataimport/controller.py similarity index 100% rename from ecs/Dockerfile/dataimport/controller.py rename to ecs/dataimport/dataimport/controller.py diff --git a/ecs/Dockerfile/dataimport/end.py b/ecs/dataimport/dataimport/end.py similarity index 100% rename from ecs/Dockerfile/dataimport/end.py rename to ecs/dataimport/dataimport/end.py diff --git a/ecs/Dockerfile/dataimport/error.py b/ecs/dataimport/dataimport/error.py similarity index 100% rename from ecs/Dockerfile/dataimport/error.py rename to ecs/dataimport/dataimport/error.py diff --git a/ecs/Dockerfile/dataimport/ini.py b/ecs/dataimport/dataimport/ini.py similarity index 100% rename from ecs/Dockerfile/dataimport/ini.py rename to ecs/dataimport/dataimport/ini.py diff --git a/ecs/Dockerfile/dataimport/main.py b/ecs/dataimport/dataimport/main.py similarity index 100% rename from ecs/Dockerfile/dataimport/main.py rename to ecs/dataimport/dataimport/main.py diff --git a/ecs/Dockerfile/requirements.txt b/ecs/dataimport/requirements.txt similarity index 100% rename from ecs/Dockerfile/requirements.txt rename to ecs/dataimport/requirements.txt diff --git a/lambda/mbj-newdwh2021-staging-NoticeToSlack/index.js b/lambda/NoticeToSlack/index.js similarity index 96% rename from lambda/mbj-newdwh2021-staging-NoticeToSlack/index.js rename to lambda/NoticeToSlack/index.js index 5c0a7226..630c769d 100644 --- a/lambda/mbj-newdwh2021-staging-NoticeToSlack/index.js +++ b/lambda/NoticeToSlack/index.js @@ -1,37 +1,37 @@ -"use-strict"; - -const request = require("request-promise"); -exports.handler = (event, context, callback) => { - const attaches = event.Records.map(evt => { - return { - "fallback":`Notification from mbj-newdwh2021 AWS: ${evt.EventSubscriptionArn}`, - "pretext":`Notification from mbj-newdwh2021 AWS: ${evt.EventSubscriptionArn}`, - "color":"#0000D0", - "fields":[ - { - "title": `${evt.Sns.Subject}`, - "value": `${evt.Sns.Timestamp}: ${evt.Sns.Message} (MessageId: ${evt.Sns.MessageId})`, - "short": false - } - ] - }; - }); - request({ - method: "POST", - url: process.env.webhookurl, - body: { - attachments: attaches - - }, - json: true - }).then((body => { - callback(null, `Request succeed. ${body}`); - })).catch((err) => { - callback("failed to request to slack.", { - result: "ERROR", - event: event, - cause: `request failed. ${err}.` - }); - }) - -}; +"use-strict"; + +const request = require("request-promise"); +exports.handler = (event, context, callback) => { + const attaches = event.Records.map(evt => { + return { + "fallback":`Notification from mbj-newdwh2021 AWS: ${evt.EventSubscriptionArn}`, + "pretext":`Notification from mbj-newdwh2021 AWS: ${evt.EventSubscriptionArn}`, + "color":"#0000D0", + "fields":[ + { + "title": `${evt.Sns.Subject}`, + "value": `${evt.Sns.Timestamp}: ${evt.Sns.Message} (MessageId: ${evt.Sns.MessageId})`, + "short": false + } + ] + }; + }); + request({ + method: "POST", + url: process.env.webhookurl, + body: { + attachments: attaches + + }, + json: true + }).then((body => { + callback(null, `Request succeed. ${body}`); + })).catch((err) => { + callback("failed to request to slack.", { + result: "ERROR", + event: event, + cause: `request failed. ${err}.` + }); + }) + +}; diff --git a/lambda/mbj-newdwh2021-staging-NoticeToSlack/mbj-newdwh2021-staging-NoticeToSlack.zip b/lambda/NoticeToSlack/mbj-newdwh2021-staging-NoticeToSlack.zip similarity index 100% rename from lambda/mbj-newdwh2021-staging-NoticeToSlack/mbj-newdwh2021-staging-NoticeToSlack.zip rename to lambda/NoticeToSlack/mbj-newdwh2021-staging-NoticeToSlack.zip diff --git a/lambda/mbj-newdwh2021-staging-NoticeToSlack/package.json b/lambda/NoticeToSlack/package.json similarity index 95% rename from lambda/mbj-newdwh2021-staging-NoticeToSlack/package.json rename to lambda/NoticeToSlack/package.json index 1495f188..30e2c8fe 100644 --- a/lambda/mbj-newdwh2021-staging-NoticeToSlack/package.json +++ b/lambda/NoticeToSlack/package.json @@ -1,15 +1,15 @@ -{ - "name": "mbj-newdwh2021-staging-noticetoslack", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "ISC", - "dependencies": { - "request": "^2.88.2", - "request-promise": "^4.2.6" - } -} +{ + "name": "mbj-newdwh2021-staging-noticetoslack", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "request": "^2.88.2", + "request-promise": "^4.2.6" + } +} diff --git a/lambda/mbj-newdwh2021-staging-PublishFromLog/index.js b/lambda/PublishFromLog/index.js similarity index 97% rename from lambda/mbj-newdwh2021-staging-PublishFromLog/index.js rename to lambda/PublishFromLog/index.js index f0b608f8..196905d1 100644 --- a/lambda/mbj-newdwh2021-staging-PublishFromLog/index.js +++ b/lambda/PublishFromLog/index.js @@ -1,30 +1,30 @@ -const zlib = require("zlib"); -const aws = require("aws-sdk"); -const sns = new aws.SNS({ - apiVersion: "2010-03-31", - region: 'ap-northeast-1' -}); - -exports.handler = function(input, context) { - var payload = new Buffer.from(input.awslogs.data, 'base64'); - zlib.gunzip(payload, function(e, result) { - if (e) { - context.fail(e); - } else { - result = JSON.parse(result.toString('UTF-8')); - const publishMessage = { - Subject: `Detect Error(or Warning) in ${result.logGroup}`, - Message: result.logEvents.map((l) => l.message).join('\n'), - TopicArn: process.env.topicArn - }; - console.log(publishMessage); - - sns.publish(publishMessage, (err, data) => { - console.log(err, data); - if(err){ - context.fail(err); - } - }); - } - }); +const zlib = require("zlib"); +const aws = require("aws-sdk"); +const sns = new aws.SNS({ + apiVersion: "2010-03-31", + region: 'ap-northeast-1' +}); + +exports.handler = function(input, context) { + var payload = new Buffer.from(input.awslogs.data, 'base64'); + zlib.gunzip(payload, function(e, result) { + if (e) { + context.fail(e); + } else { + result = JSON.parse(result.toString('UTF-8')); + const publishMessage = { + Subject: `Detect Error(or Warning) in ${result.logGroup}`, + Message: result.logEvents.map((l) => l.message).join('\n'), + TopicArn: process.env.topicArn + }; + console.log(publishMessage); + + sns.publish(publishMessage, (err, data) => { + console.log(err, data); + if(err){ + context.fail(err); + } + }); + } + }); }; \ No newline at end of file diff --git a/lambda/mbj-newdwh2021-staging-PublishFromLog/mbj-newdwh2021-staging-PublishFromLog.zip b/lambda/PublishFromLog/mbj-newdwh2021-staging-PublishFromLog.zip similarity index 100% rename from lambda/mbj-newdwh2021-staging-PublishFromLog/mbj-newdwh2021-staging-PublishFromLog.zip rename to lambda/PublishFromLog/mbj-newdwh2021-staging-PublishFromLog.zip diff --git a/lambda/mbj-newdwh2021-staging-PublishFromLog/package.json b/lambda/PublishFromLog/package.json similarity index 95% rename from lambda/mbj-newdwh2021-staging-PublishFromLog/package.json rename to lambda/PublishFromLog/package.json index 1e0d12e7..c1156fde 100644 --- a/lambda/mbj-newdwh2021-staging-PublishFromLog/package.json +++ b/lambda/PublishFromLog/package.json @@ -1,15 +1,15 @@ -{ - "name": "mbj-newdwh2021-staging-publishfromlog", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "ISC", - "dependencies": { - "aws-sdk": "^2.1011.0", - "zlib": "^1.0.5" - } -} +{ + "name": "mbj-newdwh2021-staging-publishfromlog", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "aws-sdk": "^2.1011.0", + "zlib": "^1.0.5" + } +} diff --git a/lambda/mbj-newdwh2021-staging-lambda-dataimport.py b/lambda/dataimport/dataimport.py similarity index 83% rename from lambda/mbj-newdwh2021-staging-lambda-dataimport.py rename to lambda/dataimport/dataimport.py index fb79ede5..00fe2f86 100644 --- a/lambda/mbj-newdwh2021-staging-lambda-dataimport.py +++ b/lambda/dataimport/dataimport.py @@ -8,10 +8,8 @@ TASK_NAME = os.environ["TASK_NAME"] CONTAINER_NAME = os.environ["CONTAINER_NAME"] SUBNET_ID_AP_NORTHEAST_1A = os.environ["SUBNET_ID_AP_NORTHEAST_1A"] SUBNET_ID_AP_NORTHEAST_1D = os.environ["SUBNET_ID_AP_NORTHEAST_1D"] -SECURITY_GROUP_ID_ECRAPI = os.environ["SECURITY_GROUP_ID_ECRAPI"] -SECURITY_GROUP_ID_ECRDKR = os.environ["SECURITY_GROUP_ID_ECRDKR"] -SECURITY_GROUP_ID_LOGS = os.environ["SECURITY_GROUP_ID_LOGS"] -SECURITY_GROUP_ID_RDS = os.environ["SECURITY_GROUP_ID_RDS"] +SECURITY_GROUP_ID_ECSALL = os.environ["SECURITY_GROUP_ID_ECSALL"] +SECURITY_GROUP_ID_ECSDATAIMPORT = os.environ["SECURITY_GROUP_ID_ECSDATAIMPORT"] MODE = os.environ["MODE"] # クラス変数 @@ -43,12 +41,9 @@ def lambda_handler(event, context): SUBNET_ID_AP_NORTHEAST_1D, ], "securityGroups": [ - SECURITY_GROUP_ID_ECRAPI, - SECURITY_GROUP_ID_ECRDKR, - SECURITY_GROUP_ID_LOGS, - SECURITY_GROUP_ID_RDS, + SECURITY_GROUP_ID_ECSALL, + SECURITY_GROUP_ID_ECSDATAIMPORT, ], - "assignPublicIp": 'ENABLED', } }, overrides={ diff --git a/lambda/sap-data-decrypt/Dockerfile b/lambda/sap-data-decrypt/Dockerfile new file mode 100644 index 00000000..a850e222 --- /dev/null +++ b/lambda/sap-data-decrypt/Dockerfile @@ -0,0 +1,16 @@ +FROM python:3.9 + +ENV TZ="Asia/Tokyo" + +WORKDIR /function +COPY requirements.txt ./ +RUN \ + apt update -y && \ + # パッケージのセキュリティアップデートのみを適用するコマンド + apt install -y unattended-upgrades && \ + unattended-upgrades && \ + pip install --no-cache-dir -r requirements.txt +COPY datadecrypt ./ + +ENTRYPOINT [ "/usr/local/bin/python", "-m", "awslambdaric" ] +CMD [ "main.handler" ] \ No newline at end of file diff --git a/lambda/sap-data-decrypt/datadecrypt/main.py b/lambda/sap-data-decrypt/datadecrypt/main.py new file mode 100644 index 00000000..ec4d24ae --- /dev/null +++ b/lambda/sap-data-decrypt/datadecrypt/main.py @@ -0,0 +1,268 @@ +import logging +import os +import boto3 +import gnupg +import datetime +import logging +from abc import * +from zoneinfo import ZoneInfo +import traceback + +# 環境変数 +SECRET_KEY_FILE_BUCKET_NAME = os.environ["SECRET_KEY_FILE_BUCKET_NAME"] +SECRET_KEY_FILE_PATH = os.environ["SECRET_KEY_FILE_PATH"] +SAP_SUP_BUCKET_NAME = os.environ["SAP_SUP_BUCKET_NAME"] +SAP_FIN_BUCKET_NAME = os.environ["SAP_FIN_BUCKET_NAME"] +SAP_DATA_BACKUP_BUCKET_NAME = os.environ["SAP_DATA_BACKUP_BUCKET_NAME"] +DATA_SOURCE_SAP_SUP = os.environ["DATA_SOURCE_SAP_SUP"] +DATA_SOURCE_SAP_FIN = os.environ["DATA_SOURCE_SAP_FIN"] +NDS_NOTICE_TOPIC = os.environ["NDS_NOTICE_TOPIC"] +NDS_NOTICE_TITLE = os.environ["NDS_NOTICE_TITLE"] +LOG_LEVEL = os.environ["LOG_LEVEL"] + +# 定数 +DIRECTORY_RECV = '/recv/' +DIRECTORY_RECV_ERROR = '/recv_error/' +EXTENSION_ERROR = '.error' +EXTENSION_DECRYPT_ERROR = '.decrypt_error' +INDEX_EXTENSION_DELETE_NUM = -4 +PATH_TEMP = '/tmp' +PATH_TEMP_PRIVATE_KEY = '/tmp/private.key' +PATH_TEMP_ENCRYPT_FILE = '/tmp/encrypt_file' +PATH_TEMP_DECRYPT_FILE = '/tmp/decrypt_file' +TARGET_BUCKET_BY_DATA_SOURCE = { + DATA_SOURCE_SAP_SUP: SAP_SUP_BUCKET_NAME, + DATA_SOURCE_SAP_FIN: SAP_FIN_BUCKET_NAME +} + +# 変数 +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 handler(event, context): + try: + # ① 処理開始ログを出力する + logger.info('I-01-01 処理開始 SAPデータ復号処理') + execute_date = datetime.date.today().strftime('%Y/%m/%d') + logger.info(f'I-01-02 処理稼働日:{execute_date}') + + # ② 処理開始時に受け取ったイベント情報の以下内容をログに出力しメモリに保持する + logger.info('I-02-01 イベント情報出力処理') + s3_event = S3EventInfo(event["Records"][0]["s3"]) + logger.info(f'I-02-02 バケット名:{s3_event.bucket_name}') + logger.info(f'I-02-03 ファイルパス:{s3_event.file_path}') + logger.info(f'I-02-04 データソース名:{s3_event.data_source_name}') + + # ③ S3からPGP暗号化ファイルを読み込む + try: + logger.info(f'I-03-01 PGP暗号化ファイル読込 読込元:{s3_event.bucket_name}/{s3_event.file_path}') + s3_client.download_file(s3_event.bucket_name, s3_event.file_path, PATH_TEMP_ENCRYPT_FILE) + logger.info('I-03-02 PGP暗号化ファイルを読み込みました') + except Exception as e: + logger.error(f'E-03-01 PGP暗号化ファイルの読み込みに失敗しました エラー内容:{e}') + raise EncryptFileReadException('E-03-01', EXTENSION_ERROR, e) + + # ④ S3から秘密鍵ファイルを読み込む + try: + logger.info(f'I-04-01 秘密鍵ファイル読込 読込元:{SECRET_KEY_FILE_BUCKET_NAME}/{SECRET_KEY_FILE_PATH}') + s3_client.download_file(SECRET_KEY_FILE_BUCKET_NAME, SECRET_KEY_FILE_PATH, PATH_TEMP_PRIVATE_KEY) + logger.info('I-04-02 秘密鍵ファイルを読み込みました') + except Exception as e: + logger.error(f'E-04-01 秘密鍵ファイルの読み込みに失敗しました エラー内容:{e}') + raise FileReadException('E-04-01', EXTENSION_ERROR, e) + + # ⑤ 「③」で読み込んだ秘密鍵ファイルをPGPライブラリにインポートを行う + try: + logger.info('I-05-01 秘密鍵ファイルインポート') + gpg = gnupg.GPG(gnupghome=PATH_TEMP) + with open(PATH_TEMP_PRIVATE_KEY) as key_file: + gpg.import_keys(key_file.read()) + logger.info('I-05-02 秘密鍵ファイルをインポートしました') + except Exception as e: + logger.error(f'E-05-01 秘密鍵ファイルのインポートに失敗しました エラー内容:{e}') + raise PrivateKeyImportException('E-05-01', EXTENSION_ERROR, e) + + # ⑥ 「④」で読み込んだPGP暗号化ファイルを「⑤」でインポートした秘密鍵ファイルで復号する + try: + logger.info('I-06-01 PGP暗号化ファイルの復号化') + with open(PATH_TEMP_ENCRYPT_FILE, 'rb') as temp_encrypr_file: + gpg.decrypt_file(temp_encrypr_file, output=PATH_TEMP_DECRYPT_FILE) + decrypt_file = open(PATH_TEMP_DECRYPT_FILE, 'rb') + logger.info('I-06-02 PGP暗号化ファイルを復号しました') + except Exception as e: + logger.error(f'E-06-01 PGP暗号化ファイルの復号化に失敗しました エラー内容:{e}') + raise DecryptException('E-06-01', EXTENSION_DECRYPT_ERROR, e) + + # ⑦ 各ファイルをS3に出力する + try: + logger.info('I-07-01 各ファイルをS3に出力する') + + # 「⑥」で復号化したファイルをSAPデータ保管用バケットに出力する + decrypt_file_name = s3_event.file_name[:INDEX_EXTENSION_DELETE_NUM] + decrypt_file_key = f'{execute_date}/{decrypt_file_name}' + decrypt_bucket_name = TARGET_BUCKET_BY_DATA_SOURCE[s3_event.data_source_name] + logger.info(f'I-07-02 復号化ファイル出力 ファイル名:{decrypt_file_name} 出力先:{decrypt_bucket_name}/{decrypt_file_key}') + decrypt_file_obj = s3_resource.Object(decrypt_bucket_name, decrypt_file_key) + decrypt_file_obj.put(Body=decrypt_file) + decrypt_file.close + logger.info('I-07-03 復号化ファイルをS3に出力しました') + except Exception as e: + logger.error(f'E-07-01 復号化ファイルのS3出力に失敗しました エラー内容:{e}') + raise FileOutputException('E-07-01', EXTENSION_ERROR, e) + + # 「④」で読み込んだPGP暗号化ファイルを以下に移動(コピー削除)する + try: + copy_source = { + 'Bucket': s3_event.bucket_name, + 'Key': s3_event.file_path + } + backup_file_key = f'{s3_event.data_source_name}/{execute_date}/{s3_event.file_name}' + logger.info(f'I-07-04 PGP暗号化ファイル移動 移動元:{s3_event.bucket_name}/{s3_event.file_path} 移動先:{SAP_DATA_BACKUP_BUCKET_NAME}/{backup_file_key}') + backup_file_obj = s3_resource.Object(SAP_DATA_BACKUP_BUCKET_NAME, backup_file_key) + backup_file_obj.copy(copy_source) + s3_client.delete_object(Bucket=s3_event.bucket_name, Key=s3_event.file_path) + logger.info('I-07-05 PGP暗号化ファイルをバックアップ用バケットに移動しました') + except Exception as e: + logger.error(f'E-07-02 PGP暗号化ファイルのS3出力に失敗しました エラー内容:{e}') + raise FileOutputException('E-07-02', EXTENSION_ERROR, e) + + # ⑧ 処理終了ログを出力する + logger.info('I-08-01 処理終了 SAPデータ復号処理') + except EncryptFileReadException as e: + traceback.print_exc() + create_status_file(s3_event, e.extension) + error_notice(e.id, e.arg) + except CustomException as e: + traceback.print_exc() + create_status_file(s3_event, e.extension) + move_encrypt_file(s3_event) + error_notice(e.id, e.arg) + except Exception as e: + logger.error(f'E-99 想定外のエラーが発生しました エラー内容:{e}') + traceback.print_exc() + create_status_file(s3_event, EXTENSION_ERROR) + move_encrypt_file(s3_event) + error_notice('E-99', e) + return + + +# エラーステータスファイル作成 +def create_status_file(s3_event, extension) -> None: + try: + result_error_file_name = s3_event.file_name + extension + result_error_key = s3_event.data_source_name + DIRECTORY_RECV + result_error_file_name + result_error_obj = s3_resource.Object(s3_event.bucket_name, result_error_key) + result_error_obj.put(Body='') + logger.error(f'E-ERR-01 recvディレクトリにエラーファイルを作成しました ファイル名:{result_error_file_name} 出力先:{s3_event.bucket_name}/{result_error_key}') + except Exception as e: + logger.error(f'E-96 エラーステータスファイルの作成に失敗しました エラー内容:{e}') + traceback.print_exc() + return + + +# PGP暗号化ファイル移動 +def move_encrypt_file(s3_event) -> None: + try: + copy_source = { + 'Bucket': s3_event.bucket_name, + 'Key': s3_event.file_path + } + error_file_name = f'{datetime.datetime.now():%Y%m%d%H%M%S}_{s3_event.file_name}' + error_key = s3_event.data_source_name + DIRECTORY_RECV_ERROR + error_file_name + error_obj = s3_resource.Object(s3_event.bucket_name, error_key) + error_obj.copy(copy_source) + s3_client.delete_object(Bucket=s3_event.bucket_name, Key=s3_event.file_path) + logger.error(f'E-ERR-02 recv_errorディレクトリにファイルを移動しました 移動元:{s3_event.bucket_name}/{s3_event.file_path} 移動先:{s3_event.bucket_name}/{error_key}') + except Exception as e: + logger.error(f'E-97 PGP暗号化ファイルの移動に失敗しました エラー内容:{e}') + traceback.print_exc() + 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-03 処理異常通知の送信指示をしました 通知先トピック:{NDS_NOTICE_TOPIC}') + except Exception as e: + logger.error(f'E-98 処理異常通知の送信指示に失敗しました エラー内容:{e}') + traceback.print_exc() + return + + +# S3イベント情報を保持するクラス +class S3EventInfo: + def __init__(self, s3_event) -> None: + self._bucket_name = s3_event["bucket"]["name"] + self._file_path = s3_event["object"]["key"] + self._file_name = os.path.basename(s3_event["object"]["key"]) + self._data_source_name = os.path.dirname(s3_event["object"]["key"]).split('/')[0] + + @property + def bucket_name(self): + return self._bucket_name + + @property + def file_path(self): + return self._file_path + + @property + def file_name(self): + return self._file_name + + @property + def data_source_name(self): + return self._data_source_name + + +# カスタムExceptionクラス +class CustomException(Exception, metaclass=ABCMeta): + def __init__(self, id, extension, arg): + self.id = id + self.extension = extension + self.arg = arg + + +class FileReadException(CustomException): + pass + + +class EncryptFileReadException(CustomException): + pass + + +class FileOutputException(CustomException): + pass + + +class PrivateKeyImportException(CustomException): + pass + + +class DecryptException(CustomException): + pass diff --git a/lambda/sap-data-decrypt/requirements.txt b/lambda/sap-data-decrypt/requirements.txt new file mode 100644 index 00000000..ae60d971 --- /dev/null +++ b/lambda/sap-data-decrypt/requirements.txt @@ -0,0 +1,3 @@ +awslambdaric +boto3 +python-gnupg \ No newline at end of file diff --git a/lambda/sap-fin-monthly-data-notice-daily/sap-fin-monthly-data-notice-daily.py b/lambda/sap-fin-monthly-data-notice-daily/sap-fin-monthly-data-notice-daily.py new file mode 100644 index 00000000..f5b59d26 --- /dev/null +++ b/lambda/sap-fin-monthly-data-notice-daily/sap-fin-monthly-data-notice-daily.py @@ -0,0 +1,186 @@ +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 diff --git a/lambda/sap-fin-receive-check-daily/sap-fin-receive-check-daily.py b/lambda/sap-fin-receive-check-daily/sap-fin-receive-check-daily.py new file mode 100644 index 00000000..35fc666e --- /dev/null +++ b/lambda/sap-fin-receive-check-daily/sap-fin-receive-check-daily.py @@ -0,0 +1,242 @@ +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 diff --git a/lambda/sap-fin-receive-check-monthly/sap-fin-receive-check-monthly.py b/lambda/sap-fin-receive-check-monthly/sap-fin-receive-check-monthly.py new file mode 100644 index 00000000..57688ebb --- /dev/null +++ b/lambda/sap-fin-receive-check-monthly/sap-fin-receive-check-monthly.py @@ -0,0 +1,245 @@ +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_MONTHLY_FILE_NAME_LIST_PATH = os.environ["RECEIVE_MONTHLY_FILE_NAME_LIST_PATH"] +MONTHLY_CEHCK_DAY_LIST_PATH = os.environ["MONTHLY_CEHCK_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_datetoday = datetime.date.today() + execute_date = execute_datetoday.strftime('%Y/%m/%d') + execute_month = f'{execute_datetoday.strftime("%Y")}/{execute_datetoday.strftime("%m")}' + 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}/{MONTHLY_CEHCK_DAY_LIST_PATH}') + monthly_day_obj = s3_resource.Object(CONFIG_BUCKET_NAME, MONTHLY_CEHCK_DAY_LIST_PATH) + monthly_day_response = monthly_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}') + check_date_list = [] + for row in io.TextIOWrapper(io.BytesIO(monthly_day_response["Body"].read()), encoding='utf-8'): + if row[INDEX_ROW_COMMENT_SYMBOL] == ROW_COMMENT_SYMBOL: + continue + check_date = row.rstrip('\n') + # 日付妥当性判定 + try: + datetime.datetime.strptime(check_date, "%Y/%m/%d") + except Exception as e: + raise e + check_date_list.append(check_date) + if execute_date in check_date_list: + logger.info('I-02-05 本日はチェック処理実施指定日のため、チェック処理を実施します') + else: + logger.info('I-02-06 本日はチェック処理実施指定日ではないため、チェック処理をスキップします') + return + except Exception as e: + logger.error(f'E-02-02 チェック処理実施指定日設定ファイルに不備があります エラー内容:{e}') + raise CheckDayException('E-02-02', e) + + # ③ 設定ファイル[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) + + # ④ 月次チェック処理を行う + logger.info('I-04-01 月次チェック処理開始') + + # 1.SAP保管用バケットの処理稼働月に該当するサブフォルダにあるファイル一覧を取得する + logger.info(f'I-04-02 オブジェクトリストの取得 取得先:{CHECK_BUCKET_NAME}/{execute_month}/') + object_prefix = f'{execute_month}/' + 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_monthly_file_name_body = io.TextIOWrapper(io.BytesIO(receive_monthly_file_name_response["Body"].read()), encoding='utf-8') + match_count = 0 + row_count = sum(1 for line in io.BytesIO(receive_monthly_file_name_obj.get()["Body"].read())) + for row in csv.reader(receive_monthly_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_month} 月次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_month} 月次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 CheckDayException(CustomException): + pass diff --git a/lambda/sap-sup-monthly-data-notice-daily/sap-sup-monthly-data-notice-daily.py b/lambda/sap-sup-monthly-data-notice-daily/sap-sup-monthly-data-notice-daily.py new file mode 100644 index 00000000..a160cf94 --- /dev/null +++ b/lambda/sap-sup-monthly-data-notice-daily/sap-sup-monthly-data-notice-daily.py @@ -0,0 +1,186 @@ +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 diff --git a/lambda/sap-sup-receive-check-daily/sap-sup-receive-check-daily.py b/lambda/sap-sup-receive-check-daily/sap-sup-receive-check-daily.py new file mode 100644 index 00000000..addb19b3 --- /dev/null +++ b/lambda/sap-sup-receive-check-daily/sap-sup-receive-check-daily.py @@ -0,0 +1,242 @@ +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 diff --git a/lambda/sap-sup-receive-check-monthly/sap-sup-receive-check-monthly.py b/lambda/sap-sup-receive-check-monthly/sap-sup-receive-check-monthly.py new file mode 100644 index 00000000..7d91326a --- /dev/null +++ b/lambda/sap-sup-receive-check-monthly/sap-sup-receive-check-monthly.py @@ -0,0 +1,245 @@ +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_MONTHLY_FILE_NAME_LIST_PATH = os.environ["RECEIVE_MONTHLY_FILE_NAME_LIST_PATH"] +MONTHLY_CEHCK_DAY_LIST_PATH = os.environ["MONTHLY_CEHCK_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_datetoday = datetime.date.today() + execute_date = execute_datetoday.strftime('%Y/%m/%d') + execute_month = f'{execute_datetoday.strftime("%Y")}/{execute_datetoday.strftime("%m")}' + 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}/{MONTHLY_CEHCK_DAY_LIST_PATH}') + monthly_day_obj = s3_resource.Object(CONFIG_BUCKET_NAME, MONTHLY_CEHCK_DAY_LIST_PATH) + monthly_day_response = monthly_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}') + check_date_list = [] + for row in io.TextIOWrapper(io.BytesIO(monthly_day_response["Body"].read()), encoding='utf-8'): + if row[INDEX_ROW_COMMENT_SYMBOL] == ROW_COMMENT_SYMBOL: + continue + check_date = row.rstrip('\n') + # 日付妥当性判定 + try: + datetime.datetime.strptime(check_date, "%Y/%m/%d") + except Exception as e: + raise e + check_date_list.append(check_date) + if execute_date in check_date_list: + logger.info('I-02-05 本日はチェック処理実施指定日のため、チェック処理を実施します') + else: + logger.info('I-02-06 本日はチェック処理実施指定日ではないため、チェック処理をスキップします') + return + except Exception as e: + logger.error(f'E-02-02 チェック処理実施指定日設定ファイルに不備があります エラー内容:{e}') + raise CheckDayException('E-02-02', e) + + # ③ 設定ファイル[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) + + # ④ 月次チェック処理を行う + logger.info('I-04-01 月次チェック処理開始') + + # 1.SAP保管用バケットの処理稼働月に該当するサブフォルダにあるファイル一覧を取得する + logger.info(f'I-04-02 オブジェクトリストの取得 取得先:{CHECK_BUCKET_NAME}/{execute_month}/') + object_prefix = f'{execute_month}/' + 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_monthly_file_name_body = io.TextIOWrapper(io.BytesIO(receive_monthly_file_name_response["Body"].read()), encoding='utf-8') + match_count = 0 + row_count = sum(1 for line in io.BytesIO(receive_monthly_file_name_obj.get()["Body"].read())) + for row in csv.reader(receive_monthly_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_month} 月次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_month} 月次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 CheckDayException(CustomException): + pass diff --git a/s3/config/SAP/monthly_check_day_list.config b/s3/config/SAP/monthly_check_day_list.config new file mode 100644 index 00000000..900bcc9a --- /dev/null +++ b/s3/config/SAP/monthly_check_day_list.config @@ -0,0 +1,7 @@ +2022/06/15 +2022/07/15 +2022/08/15 +2022/09/15 +2022/10/15 +2022/11/15 +2022/12/15 diff --git a/s3/config/SAP/sap_fin_daily_receive_file_name_list.config b/s3/config/SAP/sap_fin_daily_receive_file_name_list.config new file mode 100644 index 00000000..10ee861a --- /dev/null +++ b/s3/config/SAP/sap_fin_daily_receive_file_name_list.config @@ -0,0 +1,4 @@ +CostReport_[0-9]{8}_[0-9]{6}\.tsv Cost Report +IOReport_[0-9]{8}_[0-9]{6}\.tsv Internal Order Report +WBSReport_[0-9]{8}_[0-9]{6}\.tsv WBS Report +Invoice_[0-9]{8}_[0-9]{6}\.tsv Invoice Data diff --git a/s3/config/SAP/sap_fin_monthly_data_notice_mail_body_monthly.config b/s3/config/SAP/sap_fin_monthly_data_notice_mail_body_monthly.config new file mode 100644 index 00000000..f5ee0569 --- /dev/null +++ b/s3/config/SAP/sap_fin_monthly_data_notice_mail_body_monthly.config @@ -0,0 +1,6 @@ +宛先各位 + SAP月次I/Fである以下のファイルを受領しましたので、通知いたします。 +{notice_file_names} + + 尚、本メールはシステム自動送信のため、返信は出来ません。 + 本件に関する問い合わせは、IT部門 ゴザリ様にお願いいたします。 diff --git a/s3/config/SAP/sap_fin_monthly_data_notice_mail_title_monthly.config b/s3/config/SAP/sap_fin_monthly_data_notice_mail_title_monthly.config new file mode 100644 index 00000000..a9dbb42f --- /dev/null +++ b/s3/config/SAP/sap_fin_monthly_data_notice_mail_title_monthly.config @@ -0,0 +1 @@ +【MeDaCa連携通知】SAP Finance 月次I/Fファイルを受領しました diff --git a/s3/config/SAP/sap_fin_monthly_receive_file_name_list.config b/s3/config/SAP/sap_fin_monthly_receive_file_name_list.config new file mode 100644 index 00000000..ecc258fe --- /dev/null +++ b/s3/config/SAP/sap_fin_monthly_receive_file_name_list.config @@ -0,0 +1 @@ +WBSList_[0-9]{8}_[0-9]{6}\.tsv WBS List diff --git a/s3/config/SAP/sap_fin_receive_check_mail_body_daily.config b/s3/config/SAP/sap_fin_receive_check_mail_body_daily.config new file mode 100644 index 00000000..f1b7410f --- /dev/null +++ b/s3/config/SAP/sap_fin_receive_check_mail_body_daily.config @@ -0,0 +1,8 @@ +宛先各位 + SAP日次I/Fである以下のファイルを受領できておりません。 +{notice_file_names} + + SAPシステム側のSFTP送信状況のご確認をお願いいたします。 + + 尚、本メールはシステム自動送信のため、返信は出来ません。 + 本件に関する問い合わせは、IT部門 ゴザリ様にお願いいたします。 diff --git a/s3/config/SAP/sap_fin_receive_check_mail_body_monthly.config b/s3/config/SAP/sap_fin_receive_check_mail_body_monthly.config new file mode 100644 index 00000000..17fd53d7 --- /dev/null +++ b/s3/config/SAP/sap_fin_receive_check_mail_body_monthly.config @@ -0,0 +1,8 @@ +宛先各位 + SAP月次I/Fである以下のファイルを受領できておりません。 +{notice_file_names} + + SAPシステム側のSFTP送信状況のご確認をお願いいたします。 + + 尚、本メールはシステム自動送信のため、返信は出来ません。 + 本件に関する問い合わせは、IT部門 ゴザリ様にお願いいたします。 diff --git a/s3/config/SAP/sap_fin_receive_check_mail_title_daily.config b/s3/config/SAP/sap_fin_receive_check_mail_title_daily.config new file mode 100644 index 00000000..f45971a0 --- /dev/null +++ b/s3/config/SAP/sap_fin_receive_check_mail_title_daily.config @@ -0,0 +1 @@ +【MeDaCa連携エラー通知】SAP Finance 日次I/Fファイル未受領 diff --git a/s3/config/SAP/sap_fin_receive_check_mail_title_monthly.config b/s3/config/SAP/sap_fin_receive_check_mail_title_monthly.config new file mode 100644 index 00000000..a6ba208a --- /dev/null +++ b/s3/config/SAP/sap_fin_receive_check_mail_title_monthly.config @@ -0,0 +1 @@ +【MeDaCa連携エラー通知】SAP Finance 月次I/Fファイル未受領 diff --git a/s3/config/SAP/sap_sup_daily_receive_file_name_list.config b/s3/config/SAP/sap_sup_daily_receive_file_name_list.config new file mode 100644 index 00000000..202d503f --- /dev/null +++ b/s3/config/SAP/sap_sup_daily_receive_file_name_list.config @@ -0,0 +1 @@ +StockList_[0-9]{8}_[0-9]{6}\.tsv Stock List diff --git a/s3/config/SAP/sap_sup_monthly_data_notice_mail_body_monthly.config b/s3/config/SAP/sap_sup_monthly_data_notice_mail_body_monthly.config new file mode 100644 index 00000000..f5ee0569 --- /dev/null +++ b/s3/config/SAP/sap_sup_monthly_data_notice_mail_body_monthly.config @@ -0,0 +1,6 @@ +宛先各位 + SAP月次I/Fである以下のファイルを受領しましたので、通知いたします。 +{notice_file_names} + + 尚、本メールはシステム自動送信のため、返信は出来ません。 + 本件に関する問い合わせは、IT部門 ゴザリ様にお願いいたします。 diff --git a/s3/config/SAP/sap_sup_monthly_data_notice_mail_title_monthly.config b/s3/config/SAP/sap_sup_monthly_data_notice_mail_title_monthly.config new file mode 100644 index 00000000..adafc514 --- /dev/null +++ b/s3/config/SAP/sap_sup_monthly_data_notice_mail_title_monthly.config @@ -0,0 +1 @@ +【MeDaCa連携通知】SAP SupplyChain 月次I/Fファイルを受領しました diff --git a/s3/config/SAP/sap_sup_monthly_receive_file_name_list.config b/s3/config/SAP/sap_sup_monthly_receive_file_name_list.config new file mode 100644 index 00000000..cbc5ee68 --- /dev/null +++ b/s3/config/SAP/sap_sup_monthly_receive_file_name_list.config @@ -0,0 +1,6 @@ +GRReport_[0-9]{8}_[0-9]{6}\.tsv Goods Receipt data +QAReport_[0-9]{8}_[0-9]{6}\.tsv QA release data +MLCReport_[0-9]{8}_[0-9]{6}\.tsv MLC transfer data +POReport_[0-9]{8}_[0-9]{6}\.tsv Purchase Order data +ConfReport_[0-9]{8}_[0-9]{6}\.tsv Process Order Confirmation data +GMReport_[0-9]{8}_[0-9]{6}\.tsv Process Order Goods movement data diff --git a/s3/config/SAP/sap_sup_receive_check_mail_body_daily.config b/s3/config/SAP/sap_sup_receive_check_mail_body_daily.config new file mode 100644 index 00000000..f1b7410f --- /dev/null +++ b/s3/config/SAP/sap_sup_receive_check_mail_body_daily.config @@ -0,0 +1,8 @@ +宛先各位 + SAP日次I/Fである以下のファイルを受領できておりません。 +{notice_file_names} + + SAPシステム側のSFTP送信状況のご確認をお願いいたします。 + + 尚、本メールはシステム自動送信のため、返信は出来ません。 + 本件に関する問い合わせは、IT部門 ゴザリ様にお願いいたします。 diff --git a/s3/config/SAP/sap_sup_receive_check_mail_body_monthly.config b/s3/config/SAP/sap_sup_receive_check_mail_body_monthly.config new file mode 100644 index 00000000..17fd53d7 --- /dev/null +++ b/s3/config/SAP/sap_sup_receive_check_mail_body_monthly.config @@ -0,0 +1,8 @@ +宛先各位 + SAP月次I/Fである以下のファイルを受領できておりません。 +{notice_file_names} + + SAPシステム側のSFTP送信状況のご確認をお願いいたします。 + + 尚、本メールはシステム自動送信のため、返信は出来ません。 + 本件に関する問い合わせは、IT部門 ゴザリ様にお願いいたします。 diff --git a/s3/config/SAP/sap_sup_receive_check_mail_title_daily.config b/s3/config/SAP/sap_sup_receive_check_mail_title_daily.config new file mode 100644 index 00000000..10015ee3 --- /dev/null +++ b/s3/config/SAP/sap_sup_receive_check_mail_title_daily.config @@ -0,0 +1 @@ +【MeDaCa連携エラー通知】SAP SupplyChain 日次I/Fファイル未受領 diff --git a/s3/config/SAP/sap_sup_receive_check_mail_title_monthly.config b/s3/config/SAP/sap_sup_receive_check_mail_title_monthly.config new file mode 100644 index 00000000..a85319bb --- /dev/null +++ b/s3/config/SAP/sap_sup_receive_check_mail_title_monthly.config @@ -0,0 +1 @@ +【MeDaCa連携エラー通知】SAP SupplyChain 月次I/Fファイル未受領 diff --git a/s3/config/non_business_day_list.config b/s3/config/non_business_day_list.config new file mode 100644 index 00000000..b816fa34 --- /dev/null +++ b/s3/config/non_business_day_list.config @@ -0,0 +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 diff --git a/config/data_import/encise/CITFD_Merck01.txt b/s3/data/encise/settings/CITFD_Merck01.txt similarity index 96% rename from config/data_import/encise/CITFD_Merck01.txt rename to s3/data/encise/settings/CITFD_Merck01.txt index 229d1550..e6f0a4f9 100644 --- a/config/data_import/encise/CITFD_Merck01.txt +++ b/s3/data/encise/settings/CITFD_Merck01.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -13 -地域コード,地域名,セグメントコード,セグメント名,施設コード,施設名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 -region_code,region_name,segment_code,segment_name,HCO_code,HCO_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month -src01.en_citfd -org01.en_citfd_01 - +ensice +, +cp932 +" +CRLF +1 +13 +地域コード,地域名,セグメントコード,セグメント名,施設コード,施設名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 +region_code,region_name,segment_code,segment_name,HCO_code,HCO_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month +src01.en_citfd +org01.en_citfd_01 + diff --git a/config/data_import/encise/CITFD_Merck06.txt b/s3/data/encise/settings/CITFD_Merck06.txt similarity index 96% rename from config/data_import/encise/CITFD_Merck06.txt rename to s3/data/encise/settings/CITFD_Merck06.txt index e6c8955f..2d2983c1 100644 --- a/config/data_import/encise/CITFD_Merck06.txt +++ b/s3/data/encise/settings/CITFD_Merck06.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -13 -地域コード,地域名,セグメントコード,セグメント名,施設コード,施設名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 -region_code,region_name,segment_code,segment_name,HCO_code,HCO_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month -src01.en_citfd -org01.en_citfd_06 - +ensice +, +cp932 +" +CRLF +1 +13 +地域コード,地域名,セグメントコード,セグメント名,施設コード,施設名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 +region_code,region_name,segment_code,segment_name,HCO_code,HCO_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month +src01.en_citfd +org01.en_citfd_06 + diff --git a/config/data_import/encise/CITFD_Merck07.txt b/s3/data/encise/settings/CITFD_Merck07.txt similarity index 96% rename from config/data_import/encise/CITFD_Merck07.txt rename to s3/data/encise/settings/CITFD_Merck07.txt index 03dd1512..cc8f6376 100644 --- a/config/data_import/encise/CITFD_Merck07.txt +++ b/s3/data/encise/settings/CITFD_Merck07.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -13 -地域コード,地域名,セグメントコード,セグメント名,施設コード,施設名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 -region_code,region_name,segment_code,segment_name,HCO_code,HCO_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month -src01.en_citfd -org01.en_citfd_07 - +ensice +, +cp932 +" +CRLF +1 +13 +地域コード,地域名,セグメントコード,セグメント名,施設コード,施設名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 +region_code,region_name,segment_code,segment_name,HCO_code,HCO_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month +src01.en_citfd +org01.en_citfd_07 + diff --git a/config/data_import/encise/CITFD_Merck10.txt b/s3/data/encise/settings/CITFD_Merck10.txt similarity index 96% rename from config/data_import/encise/CITFD_Merck10.txt rename to s3/data/encise/settings/CITFD_Merck10.txt index 1a6d9b28..4c350bb7 100644 --- a/config/data_import/encise/CITFD_Merck10.txt +++ b/s3/data/encise/settings/CITFD_Merck10.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -13 -地域コード,地域名,セグメントコード,セグメント名,施設コード,施設名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 -region_code,region_name,segment_code,segment_name,HCO_code,HCO_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month -src01.en_citfd -org01.en_citfd_10 - +ensice +, +cp932 +" +CRLF +1 +13 +地域コード,地域名,セグメントコード,セグメント名,施設コード,施設名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 +region_code,region_name,segment_code,segment_name,HCO_code,HCO_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month +src01.en_citfd +org01.en_citfd_10 + diff --git a/config/data_import/encise/CITFM_PROADD.txt b/s3/data/encise/settings/CITFM_PROADD.txt similarity index 99% rename from config/data_import/encise/CITFM_PROADD.txt rename to s3/data/encise/settings/CITFM_PROADD.txt index 4858d296..a885b1ef 100644 --- a/config/data_import/encise/CITFM_PROADD.txt +++ b/s3/data/encise/settings/CITFM_PROADD.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -49 -統一商品コード,販売元コード,販売元名称,製造販売元コード,製造販売元名称,製品分類コード(大),製品分類名称(大),製品分類コード(中),製品分類名称(中),製品分類コード(小),製品分類名称(小),Encise ATC分類コード(第1レベル),Encise ATC分類名称(第1レベル),Encise ATC分類コード(第2レベル),Encise ATC分類名称(第2レベル),Encise ATC分類コード(第3レベル),Encise ATC分類名称(第3レベル),Encise ATC分類コード(第4レベル),Encise ATC分類名称(第4レベル),WHO ATC分類コード(第1レベル),WHO ATC分類名称(第1レベル),WHO ATC分類コード(第2レベル),WHO ATC分類名称(第2レベル),WHO ATC分類コード(第3レベル),WHO ATC分類名称(第3レベル),WHO ATC分類コード(第4レベル),WHO ATC分類名称(第4レベル),日本標準商品分類番号薬効分類コード(大),日本標準商品分類番号薬効分類名称(大),日本標準商品分類番号薬効分類コード(中),日本標準商品分類番号薬効分類名称(中),日本標準商品分類番号薬効分類コード(小),日本標準商品分類番号薬効分類名称(小),日本標準商品分類番号薬効分類コード(細),日本標準商品分類番号薬効分類名称(細),使用区分コード,使用区分名称,剤型区分コード,剤型区分名称,長期収載品区分コード,長期収載品区分名,薬価基準収載区分コード,薬価基準収載区分名,後発医薬品区分コード,後発医薬品区分名,有効成分一般名コード,有効成分一般名,新薬創出加算区分,更新日(西暦) -universal_product_code,seller_code,seller_name,manufacturer_code,manufacturer_name,product_brand_code,product_brand_name,product_item_code,product_item_name,product_SKU_code,product_SKU_name,Encise_ATC_1_code,Encise_ATC_1_name,Encise_ATC_2_code,Encise_ATC_2_name,Encise_ATC_3_code,Encise_ATC_3_name,Encise_ATC_4_code,Encise_ATC_4_name,WHO_ATC_1_code,WHO_ATC_1_name,WHO_ATC_2_code,WHO_ATC_2_name,WHO_ATC_3_code,WHO_ATC_3_name,WHO_ATC_4_code,WHO_ATC_4_name,JPN_pharma_category_1_code,JPN_pharma_category_1_name,JPN_pharma_category_2_code,JPN_pharma_category_2_name,JPN_pharma_category_3_code,JPN_pharma_category_3_name,JPN_pharma_category_4_code,JPN_pharma_category_4_name,drug_usage_code,drug_usage_name,drug_form_code,drug_form_name,long_listed_code,long_listed_flag,NHI_pricing_code,NHI_pricing_flag,generic_code,generic_flag,active_ingredient_code,active_ingredient_name,new_drug_premium_code,update_date -src01.en_citfm_proadd -org01.en_citfm_proadd - +ensice +, +cp932 +" +CRLF +1 +49 +統一商品コード,販売元コード,販売元名称,製造販売元コード,製造販売元名称,製品分類コード(大),製品分類名称(大),製品分類コード(中),製品分類名称(中),製品分類コード(小),製品分類名称(小),Encise ATC分類コード(第1レベル),Encise ATC分類名称(第1レベル),Encise ATC分類コード(第2レベル),Encise ATC分類名称(第2レベル),Encise ATC分類コード(第3レベル),Encise ATC分類名称(第3レベル),Encise ATC分類コード(第4レベル),Encise ATC分類名称(第4レベル),WHO ATC分類コード(第1レベル),WHO ATC分類名称(第1レベル),WHO ATC分類コード(第2レベル),WHO ATC分類名称(第2レベル),WHO ATC分類コード(第3レベル),WHO ATC分類名称(第3レベル),WHO ATC分類コード(第4レベル),WHO ATC分類名称(第4レベル),日本標準商品分類番号薬効分類コード(大),日本標準商品分類番号薬効分類名称(大),日本標準商品分類番号薬効分類コード(中),日本標準商品分類番号薬効分類名称(中),日本標準商品分類番号薬効分類コード(小),日本標準商品分類番号薬効分類名称(小),日本標準商品分類番号薬効分類コード(細),日本標準商品分類番号薬効分類名称(細),使用区分コード,使用区分名称,剤型区分コード,剤型区分名称,長期収載品区分コード,長期収載品区分名,薬価基準収載区分コード,薬価基準収載区分名,後発医薬品区分コード,後発医薬品区分名,有効成分一般名コード,有効成分一般名,新薬創出加算区分,更新日(西暦) +universal_product_code,seller_code,seller_name,manufacturer_code,manufacturer_name,product_brand_code,product_brand_name,product_item_code,product_item_name,product_SKU_code,product_SKU_name,Encise_ATC_1_code,Encise_ATC_1_name,Encise_ATC_2_code,Encise_ATC_2_name,Encise_ATC_3_code,Encise_ATC_3_name,Encise_ATC_4_code,Encise_ATC_4_name,WHO_ATC_1_code,WHO_ATC_1_name,WHO_ATC_2_code,WHO_ATC_2_name,WHO_ATC_3_code,WHO_ATC_3_name,WHO_ATC_4_code,WHO_ATC_4_name,JPN_pharma_category_1_code,JPN_pharma_category_1_name,JPN_pharma_category_2_code,JPN_pharma_category_2_name,JPN_pharma_category_3_code,JPN_pharma_category_3_name,JPN_pharma_category_4_code,JPN_pharma_category_4_name,drug_usage_code,drug_usage_name,drug_form_code,drug_form_name,long_listed_code,long_listed_flag,NHI_pricing_code,NHI_pricing_flag,generic_code,generic_flag,active_ingredient_code,active_ingredient_name,new_drug_premium_code,update_date +src01.en_citfm_proadd +org01.en_citfm_proadd + diff --git a/config/data_import/encise/CITFM_PROLST.txt b/s3/data/encise/settings/CITFM_PROLST.txt similarity index 96% rename from config/data_import/encise/CITFM_PROLST.txt rename to s3/data/encise/settings/CITFM_PROLST.txt index dac87a8b..f428a804 100644 --- a/config/data_import/encise/CITFM_PROLST.txt +++ b/s3/data/encise/settings/CITFM_PROLST.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -7 -統一商品コード,製品名,包装単位,販売元名,更新日(西暦),薬効分類コード,薬効分類名 -universal_product_code,product_SKU_name,package,seller_name,update_date,data_file_code,data_file_name -src01.en_citfm_prolst -org01.en_citfm_prolst - +ensice +, +cp932 +" +CRLF +1 +7 +統一商品コード,製品名,包装単位,販売元名,更新日(西暦),薬効分類コード,薬効分類名 +universal_product_code,product_SKU_name,package,seller_name,update_date,data_file_code,data_file_name +src01.en_citfm_prolst +org01.en_citfm_prolst + diff --git a/config/data_import/encise/CITFM_REGION.txt b/s3/data/encise/settings/CITFM_REGION.txt similarity index 92% rename from config/data_import/encise/CITFM_REGION.txt rename to s3/data/encise/settings/CITFM_REGION.txt index 75d4ae36..5cee5d25 100644 --- a/config/data_import/encise/CITFM_REGION.txt +++ b/s3/data/encise/settings/CITFM_REGION.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -3 -地域コード,地域名,更新日(西暦) -region_code,region_name,update_date -src01.en_citfm_region -org01.en_citfm_region - +ensice +, +cp932 +" +CRLF +1 +3 +地域コード,地域名,更新日(西暦) +region_code,region_name,update_date +src01.en_citfm_region +org01.en_citfm_region + diff --git a/config/data_import/encise/CITFM_SEGMNT.txt b/s3/data/encise/settings/CITFM_SEGMNT.txt similarity index 93% rename from config/data_import/encise/CITFM_SEGMNT.txt rename to s3/data/encise/settings/CITFM_SEGMNT.txt index 2a936099..dbc75ce1 100644 --- a/config/data_import/encise/CITFM_SEGMNT.txt +++ b/s3/data/encise/settings/CITFM_SEGMNT.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -3 -セグメントコード,セグメント名,更新日(西暦) -segment_code,segment_name,update_date -src01.en_citfm_segmnt -org01.en_citfm_segmnt - +ensice +, +cp932 +" +CRLF +1 +3 +セグメントコード,セグメント名,更新日(西暦) +segment_code,segment_name,update_date +src01.en_citfm_segmnt +org01.en_citfm_segmnt + diff --git a/config/data_import/encise/CITQD_Merck01.txt b/s3/data/encise/settings/CITQD_Merck01.txt similarity index 96% rename from config/data_import/encise/CITQD_Merck01.txt rename to s3/data/encise/settings/CITQD_Merck01.txt index 891d5c2c..49bc0b90 100644 --- a/config/data_import/encise/CITQD_Merck01.txt +++ b/s3/data/encise/settings/CITQD_Merck01.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -13 -地域コード,地域名,セグメントコード,セグメント名,施設コード,施設名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 -region_code,region_name,segment_code,segment_name,HCO_code,HCO_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month -src01.en_citqd -org01.en_citqd_01 - +ensice +, +cp932 +" +CRLF +1 +13 +地域コード,地域名,セグメントコード,セグメント名,施設コード,施設名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 +region_code,region_name,segment_code,segment_name,HCO_code,HCO_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month +src01.en_citqd +org01.en_citqd_01 + diff --git a/config/data_import/encise/CITQD_Merck06.txt b/s3/data/encise/settings/CITQD_Merck06.txt similarity index 96% rename from config/data_import/encise/CITQD_Merck06.txt rename to s3/data/encise/settings/CITQD_Merck06.txt index 09423f1f..30412a25 100644 --- a/config/data_import/encise/CITQD_Merck06.txt +++ b/s3/data/encise/settings/CITQD_Merck06.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -13 -地域コード,地域名,セグメントコード,セグメント名,施設コード,施設名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 -region_code,region_name,segment_code,segment_name,HCO_code,HCO_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month -src01.en_citqd -org01.en_citqd_06 - +ensice +, +cp932 +" +CRLF +1 +13 +地域コード,地域名,セグメントコード,セグメント名,施設コード,施設名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 +region_code,region_name,segment_code,segment_name,HCO_code,HCO_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month +src01.en_citqd +org01.en_citqd_06 + diff --git a/config/data_import/encise/CITQD_Merck07.txt b/s3/data/encise/settings/CITQD_Merck07.txt similarity index 96% rename from config/data_import/encise/CITQD_Merck07.txt rename to s3/data/encise/settings/CITQD_Merck07.txt index 71443d89..ba1fede1 100644 --- a/config/data_import/encise/CITQD_Merck07.txt +++ b/s3/data/encise/settings/CITQD_Merck07.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -13 -地域コード,地域名,セグメントコード,セグメント名,施設コード,施設名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 -region_code,region_name,segment_code,segment_name,HCO_code,HCO_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month -src01.en_citqd -org01.en_citqd_07 - +ensice +, +cp932 +" +CRLF +1 +13 +地域コード,地域名,セグメントコード,セグメント名,施設コード,施設名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 +region_code,region_name,segment_code,segment_name,HCO_code,HCO_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month +src01.en_citqd +org01.en_citqd_07 + diff --git a/config/data_import/encise/CITQD_Merck10.txt b/s3/data/encise/settings/CITQD_Merck10.txt similarity index 96% rename from config/data_import/encise/CITQD_Merck10.txt rename to s3/data/encise/settings/CITQD_Merck10.txt index 087164c2..51aab6d0 100644 --- a/config/data_import/encise/CITQD_Merck10.txt +++ b/s3/data/encise/settings/CITQD_Merck10.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -13 -地域コード,地域名,セグメントコード,セグメント名,施設コード,施設名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 -region_code,region_name,segment_code,segment_name,HCO_code,HCO_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month -src01.en_citqd -org01.en_citqd_10 - +ensice +, +cp932 +" +CRLF +1 +13 +地域コード,地域名,セグメントコード,セグメント名,施設コード,施設名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 +region_code,region_name,segment_code,segment_name,HCO_code,HCO_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month +src01.en_citqd +org01.en_citqd_10 + diff --git a/config/data_import/encise/CITQM_PROADD.txt b/s3/data/encise/settings/CITQM_PROADD.txt similarity index 99% rename from config/data_import/encise/CITQM_PROADD.txt rename to s3/data/encise/settings/CITQM_PROADD.txt index d62e0f00..e5347211 100644 --- a/config/data_import/encise/CITQM_PROADD.txt +++ b/s3/data/encise/settings/CITQM_PROADD.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -49 -統一商品コード,販売元コード,販売元名称,製造販売元コード,製造販売元名称,製品分類コード(大),製品分類名称(大),製品分類コード(中),製品分類名称(中),製品分類コード(小),製品分類名称(小),Encise ATC分類コード(第1レベル),Encise ATC分類名称(第1レベル),Encise ATC分類コード(第2レベル),Encise ATC分類名称(第2レベル),Encise ATC分類コード(第3レベル),Encise ATC分類名称(第3レベル),Encise ATC分類コード(第4レベル),Encise ATC分類名称(第4レベル),WHO ATC分類コード(第1レベル),WHO ATC分類名称(第1レベル),WHO ATC分類コード(第2レベル),WHO ATC分類名称(第2レベル),WHO ATC分類コード(第3レベル),WHO ATC分類名称(第3レベル),WHO ATC分類コード(第4レベル),WHO ATC分類名称(第4レベル),日本標準商品分類番号薬効分類コード(大),日本標準商品分類番号薬効分類名称(大),日本標準商品分類番号薬効分類コード(中),日本標準商品分類番号薬効分類名称(中),日本標準商品分類番号薬効分類コード(小),日本標準商品分類番号薬効分類名称(小),日本標準商品分類番号薬効分類コード(細),日本標準商品分類番号薬効分類名称(細),使用区分コード,使用区分名称,剤型区分コード,剤型区分名称,長期収載品区分コード,長期収載品区分名,薬価基準収載区分コード,薬価基準収載区分名,後発医薬品区分コード,後発医薬品区分名,有効成分一般名コード,有効成分一般名,新薬創出加算区分,更新日(西暦) -universal_product_code,seller_code,seller_name,manufacturer_code,manufacturer_name,product_brand_code,product_brand_name,product_item_code,product_item_name,product_SKU_code,product_SKU_name,Encise_ATC_1_code,Encise_ATC_1_name,Encise_ATC_2_code,Encise_ATC_2_name,Encise_ATC_3_code,Encise_ATC_3_name,Encise_ATC_4_code,Encise_ATC_4_name,WHO_ATC_1_code,WHO_ATC_1_name,WHO_ATC_2_code,WHO_ATC_2_name,WHO_ATC_3_code,WHO_ATC_3_name,WHO_ATC_4_code,WHO_ATC_4_name,JPN_pharma_category_1_code,JPN_pharma_category_1_name,JPN_pharma_category_2_code,JPN_pharma_category_2_name,JPN_pharma_category_3_code,JPN_pharma_category_3_name,JPN_pharma_category_4_code,JPN_pharma_category_4_name,drug_usage_code,drug_usage_name,drug_form_code,drug_form_name,long_listed_code,long_listed_flag,NHI_pricing_code,NHI_pricing_flag,generic_code,generic_flag,active_ingredient_code,active_ingredient_name,new_drug_premium_code,update_date -src01.en_citqm_proadd -org01.en_citqm_proadd - +ensice +, +cp932 +" +CRLF +1 +49 +統一商品コード,販売元コード,販売元名称,製造販売元コード,製造販売元名称,製品分類コード(大),製品分類名称(大),製品分類コード(中),製品分類名称(中),製品分類コード(小),製品分類名称(小),Encise ATC分類コード(第1レベル),Encise ATC分類名称(第1レベル),Encise ATC分類コード(第2レベル),Encise ATC分類名称(第2レベル),Encise ATC分類コード(第3レベル),Encise ATC分類名称(第3レベル),Encise ATC分類コード(第4レベル),Encise ATC分類名称(第4レベル),WHO ATC分類コード(第1レベル),WHO ATC分類名称(第1レベル),WHO ATC分類コード(第2レベル),WHO ATC分類名称(第2レベル),WHO ATC分類コード(第3レベル),WHO ATC分類名称(第3レベル),WHO ATC分類コード(第4レベル),WHO ATC分類名称(第4レベル),日本標準商品分類番号薬効分類コード(大),日本標準商品分類番号薬効分類名称(大),日本標準商品分類番号薬効分類コード(中),日本標準商品分類番号薬効分類名称(中),日本標準商品分類番号薬効分類コード(小),日本標準商品分類番号薬効分類名称(小),日本標準商品分類番号薬効分類コード(細),日本標準商品分類番号薬効分類名称(細),使用区分コード,使用区分名称,剤型区分コード,剤型区分名称,長期収載品区分コード,長期収載品区分名,薬価基準収載区分コード,薬価基準収載区分名,後発医薬品区分コード,後発医薬品区分名,有効成分一般名コード,有効成分一般名,新薬創出加算区分,更新日(西暦) +universal_product_code,seller_code,seller_name,manufacturer_code,manufacturer_name,product_brand_code,product_brand_name,product_item_code,product_item_name,product_SKU_code,product_SKU_name,Encise_ATC_1_code,Encise_ATC_1_name,Encise_ATC_2_code,Encise_ATC_2_name,Encise_ATC_3_code,Encise_ATC_3_name,Encise_ATC_4_code,Encise_ATC_4_name,WHO_ATC_1_code,WHO_ATC_1_name,WHO_ATC_2_code,WHO_ATC_2_name,WHO_ATC_3_code,WHO_ATC_3_name,WHO_ATC_4_code,WHO_ATC_4_name,JPN_pharma_category_1_code,JPN_pharma_category_1_name,JPN_pharma_category_2_code,JPN_pharma_category_2_name,JPN_pharma_category_3_code,JPN_pharma_category_3_name,JPN_pharma_category_4_code,JPN_pharma_category_4_name,drug_usage_code,drug_usage_name,drug_form_code,drug_form_name,long_listed_code,long_listed_flag,NHI_pricing_code,NHI_pricing_flag,generic_code,generic_flag,active_ingredient_code,active_ingredient_name,new_drug_premium_code,update_date +src01.en_citqm_proadd +org01.en_citqm_proadd + diff --git a/config/data_import/encise/CITQM_PROLST.txt b/s3/data/encise/settings/CITQM_PROLST.txt similarity index 96% rename from config/data_import/encise/CITQM_PROLST.txt rename to s3/data/encise/settings/CITQM_PROLST.txt index a12c8d9e..028149c2 100644 --- a/config/data_import/encise/CITQM_PROLST.txt +++ b/s3/data/encise/settings/CITQM_PROLST.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -7 -統一商品コード,製品名,包装単位,販売元名,更新日(西暦),薬効分類コード,薬効分類名 -universal_product_code,product_SKU_name,package,seller_name,update_date,data_file_code,data_file_name -src01.en_citqm_prolst -org01.en_citqm_prolst - +ensice +, +cp932 +" +CRLF +1 +7 +統一商品コード,製品名,包装単位,販売元名,更新日(西暦),薬効分類コード,薬効分類名 +universal_product_code,product_SKU_name,package,seller_name,update_date,data_file_code,data_file_name +src01.en_citqm_prolst +org01.en_citqm_prolst + diff --git a/config/data_import/encise/CITQM_REGION.txt b/s3/data/encise/settings/CITQM_REGION.txt similarity index 92% rename from config/data_import/encise/CITQM_REGION.txt rename to s3/data/encise/settings/CITQM_REGION.txt index e618e526..b8272963 100644 --- a/config/data_import/encise/CITQM_REGION.txt +++ b/s3/data/encise/settings/CITQM_REGION.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -3 -地域コード,地域名,更新日(西暦) -region_code,region_name,update_date -src01.en_citqm_region -org01.en_citqm_region - +ensice +, +cp932 +" +CRLF +1 +3 +地域コード,地域名,更新日(西暦) +region_code,region_name,update_date +src01.en_citqm_region +org01.en_citqm_region + diff --git a/config/data_import/encise/CITQM_SEGMNT.txt b/s3/data/encise/settings/CITQM_SEGMNT.txt similarity index 93% rename from config/data_import/encise/CITQM_SEGMNT.txt rename to s3/data/encise/settings/CITQM_SEGMNT.txt index 0ccc7faf..abffa6da 100644 --- a/config/data_import/encise/CITQM_SEGMNT.txt +++ b/s3/data/encise/settings/CITQM_SEGMNT.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -3 -セグメントコード,セグメント名,更新日(西暦) -segment_code,segment_name,update_date -src01.en_citqm_segmnt -org01.en_citqm_segmnt - +ensice +, +cp932 +" +CRLF +1 +3 +セグメントコード,セグメント名,更新日(西暦) +segment_code,segment_name,update_date +src01.en_citqm_segmnt +org01.en_citqm_segmnt + diff --git a/config/data_import/encise/CLUFD_Merck02.txt b/s3/data/encise/settings/CLUFD_Merck02.txt similarity index 96% rename from config/data_import/encise/CLUFD_Merck02.txt rename to s3/data/encise/settings/CLUFD_Merck02.txt index ec73fad8..e7b98408 100644 --- a/config/data_import/encise/CLUFD_Merck02.txt +++ b/s3/data/encise/settings/CLUFD_Merck02.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -11 -クラスターコード,クラスター名,セグメントコード,セグメント名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 -cluster_code,cluster_name,segment_code,segment_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month -src01.en_clufd -org01.en_clufd_02 - +ensice +, +cp932 +" +CRLF +1 +11 +クラスターコード,クラスター名,セグメントコード,セグメント名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 +cluster_code,cluster_name,segment_code,segment_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month +src01.en_clufd +org01.en_clufd_02 + diff --git a/config/data_import/encise/CLUFD_Merck02_D.txt b/s3/data/encise/settings/CLUFD_Merck02_D.txt similarity index 96% rename from config/data_import/encise/CLUFD_Merck02_D.txt rename to s3/data/encise/settings/CLUFD_Merck02_D.txt index 992b88c7..f6f35e6b 100644 --- a/config/data_import/encise/CLUFD_Merck02_D.txt +++ b/s3/data/encise/settings/CLUFD_Merck02_D.txt @@ -1,12 +1,12 @@ -ensice -, -utf-8-sig - -CRLF -1 -12 -クラスターコード,クラスター名,セグメントコード,セグメント名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月,direct_flg -cluster_code,cluster_name,segment_code,segment_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month,direct_flg -src01.en_clufd -org01.en_clufd_d_02 - +ensice +, +utf-8-sig + +CRLF +1 +12 +クラスターコード,クラスター名,セグメントコード,セグメント名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月,direct_flg +cluster_code,cluster_name,segment_code,segment_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month,direct_flg +src01.en_clufd +org01.en_clufd_d_02 + diff --git a/config/data_import/encise/CLUFD_Merck03.txt b/s3/data/encise/settings/CLUFD_Merck03.txt similarity index 96% rename from config/data_import/encise/CLUFD_Merck03.txt rename to s3/data/encise/settings/CLUFD_Merck03.txt index c456b163..46622eb0 100644 --- a/config/data_import/encise/CLUFD_Merck03.txt +++ b/s3/data/encise/settings/CLUFD_Merck03.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -11 -クラスターコード,クラスター名,セグメントコード,セグメント名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 -cluster_code,cluster_name,segment_code,segment_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month -src01.en_clufd -org01.en_clufd_03 - +ensice +, +cp932 +" +CRLF +1 +11 +クラスターコード,クラスター名,セグメントコード,セグメント名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 +cluster_code,cluster_name,segment_code,segment_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month +src01.en_clufd +org01.en_clufd_03 + diff --git a/config/data_import/encise/CLUFD_Merck03_D.txt b/s3/data/encise/settings/CLUFD_Merck03_D.txt similarity index 96% rename from config/data_import/encise/CLUFD_Merck03_D.txt rename to s3/data/encise/settings/CLUFD_Merck03_D.txt index ad37c208..4121304b 100644 --- a/config/data_import/encise/CLUFD_Merck03_D.txt +++ b/s3/data/encise/settings/CLUFD_Merck03_D.txt @@ -1,12 +1,12 @@ -ensice -, -utf-8-sig - -CRLF -1 -12 -クラスターコード,クラスター名,セグメントコード,セグメント名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月,direct_flg -cluster_code,cluster_name,segment_code,segment_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month,direct_flg -src01.en_clufd -org01.en_clufd_d_03 - +ensice +, +utf-8-sig + +CRLF +1 +12 +クラスターコード,クラスター名,セグメントコード,セグメント名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月,direct_flg +cluster_code,cluster_name,segment_code,segment_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month,direct_flg +src01.en_clufd +org01.en_clufd_d_03 + diff --git a/config/data_import/encise/CLUFD_Merck04.txt b/s3/data/encise/settings/CLUFD_Merck04.txt similarity index 96% rename from config/data_import/encise/CLUFD_Merck04.txt rename to s3/data/encise/settings/CLUFD_Merck04.txt index 7727273e..ad207cad 100644 --- a/config/data_import/encise/CLUFD_Merck04.txt +++ b/s3/data/encise/settings/CLUFD_Merck04.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -11 -クラスターコード,クラスター名,セグメントコード,セグメント名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 -cluster_code,cluster_name,segment_code,segment_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month -src01.en_clufd -org01.en_clufd_04 - +ensice +, +cp932 +" +CRLF +1 +11 +クラスターコード,クラスター名,セグメントコード,セグメント名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 +cluster_code,cluster_name,segment_code,segment_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month +src01.en_clufd +org01.en_clufd_04 + diff --git a/config/data_import/encise/CLUFD_Merck04_D.txt b/s3/data/encise/settings/CLUFD_Merck04_D.txt similarity index 96% rename from config/data_import/encise/CLUFD_Merck04_D.txt rename to s3/data/encise/settings/CLUFD_Merck04_D.txt index 765bd4a5..187b65aa 100644 --- a/config/data_import/encise/CLUFD_Merck04_D.txt +++ b/s3/data/encise/settings/CLUFD_Merck04_D.txt @@ -1,12 +1,12 @@ -ensice -, -utf-8-sig - -CRLF -1 -12 -クラスターコード,クラスター名,セグメントコード,セグメント名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月,direct_flg -cluster_code,cluster_name,segment_code,segment_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month,direct_flg -src01.en_clufd -org01.en_clufd_d_04 - +ensice +, +utf-8-sig + +CRLF +1 +12 +クラスターコード,クラスター名,セグメントコード,セグメント名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月,direct_flg +cluster_code,cluster_name,segment_code,segment_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month,direct_flg +src01.en_clufd +org01.en_clufd_d_04 + diff --git a/config/data_import/encise/CLUFM_CLUMST.txt b/s3/data/encise/settings/CLUFM_CLUMST.txt similarity index 97% rename from config/data_import/encise/CLUFM_CLUMST.txt rename to s3/data/encise/settings/CLUFM_CLUMST.txt index c3b2598a..c2693b08 100644 --- a/config/data_import/encise/CLUFM_CLUMST.txt +++ b/s3/data/encise/settings/CLUFM_CLUMST.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -12 -対象期間,クラスターコード,クラスター名,都道府県コード,都道府県名,施設コード,施設名,更新日,更新事由,適用年月,セグメントコード,セグメント名 -data_period,cluster_code,cluster_name,pref_code,pref_name,HCO_coce,HCO_name,update_date,update_remarks,master_YM,segment_code,segment_name -src01.en_clufm_clumst -org01.en_clufm_clumst -CLUFM_CLUMST_ex.sql +ensice +, +cp932 +" +CRLF +1 +12 +対象期間,クラスターコード,クラスター名,都道府県コード,都道府県名,施設コード,施設名,更新日,更新事由,適用年月,セグメントコード,セグメント名 +data_period,cluster_code,cluster_name,pref_code,pref_name,HCO_coce,HCO_name,update_date,update_remarks,master_YM,segment_code,segment_name +src01.en_clufm_clumst +org01.en_clufm_clumst +CLUFM_CLUMST_ex.sql diff --git a/config/data_import/encise/CLUFM_CLUMST_ex.sql b/s3/data/encise/settings/CLUFM_CLUMST_ex.sql similarity index 97% rename from config/data_import/encise/CLUFM_CLUMST_ex.sql rename to s3/data/encise/settings/CLUFM_CLUMST_ex.sql index 2b6f8b5d..20bebf79 100644 --- a/config/data_import/encise/CLUFM_CLUMST_ex.sql +++ b/s3/data/encise/settings/CLUFM_CLUMST_ex.sql @@ -1,7 +1,7 @@ -/* クラスターマスタのTO年月をセットする */ -update src01.en_clufm_clumst set -to_ym = case when substr(data_period,9,7) is null then '0000/00' - else substr(data_period,9,7) - end -where to_ym is null; - +/* クラスターマスタのTO年月をセットする */ +update src01.en_clufm_clumst set +to_ym = case when substr(data_period,9,7) is null then '0000/00' + else substr(data_period,9,7) + end +where to_ym is null; + diff --git a/config/data_import/encise/CLUFM_PROADD.txt b/s3/data/encise/settings/CLUFM_PROADD.txt similarity index 99% rename from config/data_import/encise/CLUFM_PROADD.txt rename to s3/data/encise/settings/CLUFM_PROADD.txt index 8cb378b4..488bd73e 100644 --- a/config/data_import/encise/CLUFM_PROADD.txt +++ b/s3/data/encise/settings/CLUFM_PROADD.txt @@ -1,12 +1,12 @@ -encise -, -cp932 -" -CRLF -1 -49 -統一商品コード,販売元コード,販売元名称,製造販売元コード,製造販売元名称,製品分類コード(大),製品分類名称(大),製品分類コード(中),製品分類名称(中),製品分類コード(小),製品分類名称(小),Encise ATC分類コード(第1レベル),Encise ATC分類名称(第1レベル),Encise ATC分類コード(第2レベル),Encise ATC分類名称(第2レベル),Encise ATC分類コード(第3レベル),Encise ATC分類名称(第3レベル),Encise ATC分類コード(第4レベル),Encise ATC分類名称(第4レベル),WHO ATC分類コード(第1レベル),WHO ATC分類名称(第1レベル),WHO ATC分類コード(第2レベル),WHO ATC分類名称(第2レベル),WHO ATC分類コード(第3レベル),WHO ATC分類名称(第3レベル),WHO ATC分類コード(第4レベル),WHO ATC分類名称(第4レベル),日本標準商品分類番号薬効分類コード(大),日本標準商品分類番号薬効分類名称(大),日本標準商品分類番号薬効分類コード(中),日本標準商品分類番号薬効分類名称(中),日本標準商品分類番号薬効分類コード(小),日本標準商品分類番号薬効分類名称(小),日本標準商品分類番号薬効分類コード(細),日本標準商品分類番号薬効分類名称(細),使用区分コード,使用区分名称,剤型区分コード,剤型区分名称,長期収載品区分コード,長期収載品区分名,薬価基準収載区分コード,薬価基準収載区分名,後発医薬品区分コード,後発医薬品区分名,有効成分一般名コード,有効成分一般名,新薬創出加算区分,更新日(西暦) -universal_product_code,seller_code,seller_name,manufacturer_code,manufacturer_name,product_brand_code,product_brand_name,product_item_code,product_item_name,product_SKU_code,product_SKU_name,Encise_ATC_1_code,Encise_ATC_1_name,Encise_ATC_2_code,Encise_ATC_2_name,Encise_ATC_3_code,Encise_ATC_3_name,Encise_ATC_4_code,Encise_ATC_4_name,WHO_ATC_1_code,WHO_ATC_1_name,WHO_ATC_2_code,WHO_ATC_2_name,WHO_ATC_3_code,WHO_ATC_3_name,WHO_ATC_4_code,WHO_ATC_4_name,JPN_pharma_category_1_code,JPN_pharma_category_1_name,JPN_pharma_category_2_code,JPN_pharma_category_2_name,JPN_pharma_category_3_code,JPN_pharma_category_3_name,JPN_pharma_category_4_code,JPN_pharma_category_4_name,drug_usage_code,drug_usage_name,drug_form_code,drug_form_name,long_listed_code,long_listed_flag,NHI_pricing_code,NHI_pricing_flag,generic_code,generic_flag,active_ingredient_code,active_ingredient_name,new_drug_premium_code,update_date -src01.en_clufm_proadd -org01.en_clufm_proadd - +encise +, +cp932 +" +CRLF +1 +49 +統一商品コード,販売元コード,販売元名称,製造販売元コード,製造販売元名称,製品分類コード(大),製品分類名称(大),製品分類コード(中),製品分類名称(中),製品分類コード(小),製品分類名称(小),Encise ATC分類コード(第1レベル),Encise ATC分類名称(第1レベル),Encise ATC分類コード(第2レベル),Encise ATC分類名称(第2レベル),Encise ATC分類コード(第3レベル),Encise ATC分類名称(第3レベル),Encise ATC分類コード(第4レベル),Encise ATC分類名称(第4レベル),WHO ATC分類コード(第1レベル),WHO ATC分類名称(第1レベル),WHO ATC分類コード(第2レベル),WHO ATC分類名称(第2レベル),WHO ATC分類コード(第3レベル),WHO ATC分類名称(第3レベル),WHO ATC分類コード(第4レベル),WHO ATC分類名称(第4レベル),日本標準商品分類番号薬効分類コード(大),日本標準商品分類番号薬効分類名称(大),日本標準商品分類番号薬効分類コード(中),日本標準商品分類番号薬効分類名称(中),日本標準商品分類番号薬効分類コード(小),日本標準商品分類番号薬効分類名称(小),日本標準商品分類番号薬効分類コード(細),日本標準商品分類番号薬効分類名称(細),使用区分コード,使用区分名称,剤型区分コード,剤型区分名称,長期収載品区分コード,長期収載品区分名,薬価基準収載区分コード,薬価基準収載区分名,後発医薬品区分コード,後発医薬品区分名,有効成分一般名コード,有効成分一般名,新薬創出加算区分,更新日(西暦) +universal_product_code,seller_code,seller_name,manufacturer_code,manufacturer_name,product_brand_code,product_brand_name,product_item_code,product_item_name,product_SKU_code,product_SKU_name,Encise_ATC_1_code,Encise_ATC_1_name,Encise_ATC_2_code,Encise_ATC_2_name,Encise_ATC_3_code,Encise_ATC_3_name,Encise_ATC_4_code,Encise_ATC_4_name,WHO_ATC_1_code,WHO_ATC_1_name,WHO_ATC_2_code,WHO_ATC_2_name,WHO_ATC_3_code,WHO_ATC_3_name,WHO_ATC_4_code,WHO_ATC_4_name,JPN_pharma_category_1_code,JPN_pharma_category_1_name,JPN_pharma_category_2_code,JPN_pharma_category_2_name,JPN_pharma_category_3_code,JPN_pharma_category_3_name,JPN_pharma_category_4_code,JPN_pharma_category_4_name,drug_usage_code,drug_usage_name,drug_form_code,drug_form_name,long_listed_code,long_listed_flag,NHI_pricing_code,NHI_pricing_flag,generic_code,generic_flag,active_ingredient_code,active_ingredient_name,new_drug_premium_code,update_date +src01.en_clufm_proadd +org01.en_clufm_proadd + diff --git a/config/data_import/encise/CLUFM_PROLST.txt b/s3/data/encise/settings/CLUFM_PROLST.txt similarity index 96% rename from config/data_import/encise/CLUFM_PROLST.txt rename to s3/data/encise/settings/CLUFM_PROLST.txt index ce4c4dcb..f8a827b4 100644 --- a/config/data_import/encise/CLUFM_PROLST.txt +++ b/s3/data/encise/settings/CLUFM_PROLST.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -7 -統一商品コード,製品名,包装単位,販売元名,更新日(西暦),薬効分類コード,薬効分類名 -universal_product_code,product_SKU_name,package,seller_name,update_date,data_file_code,data_file_name -src01.en_clufm_prolst -org01.en_clufm_prolst - +ensice +, +cp932 +" +CRLF +1 +7 +統一商品コード,製品名,包装単位,販売元名,更新日(西暦),薬効分類コード,薬効分類名 +universal_product_code,product_SKU_name,package,seller_name,update_date,data_file_code,data_file_name +src01.en_clufm_prolst +org01.en_clufm_prolst + diff --git a/config/data_import/encise/MST_BRAND.txt b/s3/data/encise/settings/MST_BRAND.txt similarity index 98% rename from config/data_import/encise/MST_BRAND.txt rename to s3/data/encise/settings/MST_BRAND.txt index 032c6a87..42fc7fde 100644 --- a/config/data_import/encise/MST_BRAND.txt +++ b/s3/data/encise/settings/MST_BRAND.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -30 -JANコード,統一商品コード,YJコード,使用区分名,剤型コード,剤型名,商品名,一般名,規格容量,規格単位名,販売元コード,販売元名,製造元コード,製造元名,Route of Administration,Form,Brand_Name,Molecule_Name,Strength,SalesCompany,Manufacturer,薬効分類コード,薬効分類名,日本標準薬効2,日本標準薬効名2,薬価基準収載医薬品コード,処方せん医薬品,薬価基準収載区分,ENCODE,名称 -jan_code,universal_product_code,yj_code,drug_usage_name,drug_form_code,drug_form_name,product_SKU_name,active_ingredient_name,package,SKU_name,seller_code,seller_name,manufacturer_code,manufacturer_name,eng_route_of_administration,eng_form,eng_brand_name,eng_molecule_name,eng_strength,eng_seller_name,eng_manufacturer_name,JPN_pharma_category_4_code,JPN_pharma_category_4_name,JPN_pharma_category_2_code,JPN_pharma_category_2_name,NHI_pricing_code,ethical_drug_flag,NHI_pricing_flag,encode,encise_active_ingredient_name -src01.en_mst_brand -org01.en_mst_brand - +ensice +, +cp932 +" +CRLF +1 +30 +JANコード,統一商品コード,YJコード,使用区分名,剤型コード,剤型名,商品名,一般名,規格容量,規格単位名,販売元コード,販売元名,製造元コード,製造元名,Route of Administration,Form,Brand_Name,Molecule_Name,Strength,SalesCompany,Manufacturer,薬効分類コード,薬効分類名,日本標準薬効2,日本標準薬効名2,薬価基準収載医薬品コード,処方せん医薬品,薬価基準収載区分,ENCODE,名称 +jan_code,universal_product_code,yj_code,drug_usage_name,drug_form_code,drug_form_name,product_SKU_name,active_ingredient_name,package,SKU_name,seller_code,seller_name,manufacturer_code,manufacturer_name,eng_route_of_administration,eng_form,eng_brand_name,eng_molecule_name,eng_strength,eng_seller_name,eng_manufacturer_name,JPN_pharma_category_4_code,JPN_pharma_category_4_name,JPN_pharma_category_2_code,JPN_pharma_category_2_name,NHI_pricing_code,ethical_drug_flag,NHI_pricing_flag,encode,encise_active_ingredient_name +src01.en_mst_brand +org01.en_mst_brand + diff --git a/config/data_import/encise/NATFD.txt b/s3/data/encise/settings/NATFD.txt similarity index 96% rename from config/data_import/encise/NATFD.txt rename to s3/data/encise/settings/NATFD.txt index 7529f0c9..a0e8da1b 100644 --- a/config/data_import/encise/NATFD.txt +++ b/s3/data/encise/settings/NATFD.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -13 -地域コード,地域名,セグメントコード,セグメント名,施設コード,施設名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 -region_code,region_name,segment_code,segment_name,HCO_code,HCO_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month -src01.en_natfd -org01.en_natfd - +ensice +, +cp932 +" +CRLF +1 +13 +地域コード,地域名,セグメントコード,セグメント名,施設コード,施設名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 +region_code,region_name,segment_code,segment_name,HCO_code,HCO_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month +src01.en_natfd +org01.en_natfd + diff --git a/config/data_import/encise/NATFD_D.txt b/s3/data/encise/settings/NATFD_D.txt similarity index 97% rename from config/data_import/encise/NATFD_D.txt rename to s3/data/encise/settings/NATFD_D.txt index 080cceab..5694a989 100644 --- a/config/data_import/encise/NATFD_D.txt +++ b/s3/data/encise/settings/NATFD_D.txt @@ -1,12 +1,12 @@ -ensice -, -utf-8-sig - -CRLF -1 -14 -地域コード,地域名,セグメントコード,セグメント名,施設コード,施設名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月,direct_flg -region_code,region_name,segment_code,segment_name,HCO_code,HCO_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month,direct_flg -src01.en_natfd -org01.en_natfd_d - +ensice +, +utf-8-sig + +CRLF +1 +14 +地域コード,地域名,セグメントコード,セグメント名,施設コード,施設名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月,direct_flg +region_code,region_name,segment_code,segment_name,HCO_code,HCO_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month,direct_flg +src01.en_natfd +org01.en_natfd_d + diff --git a/config/data_import/encise/NATFM_PROADD.txt b/s3/data/encise/settings/NATFM_PROADD.txt similarity index 99% rename from config/data_import/encise/NATFM_PROADD.txt rename to s3/data/encise/settings/NATFM_PROADD.txt index 43bfe5f9..41a7e5b6 100644 --- a/config/data_import/encise/NATFM_PROADD.txt +++ b/s3/data/encise/settings/NATFM_PROADD.txt @@ -1,12 +1,12 @@ -encise -, -cp932 -" -CRLF -1 -49 -統一商品コード,販売元コード,販売元名称,製造販売元コード,製造販売元名称,製品分類コード(大),製品分類名称(大),製品分類コード(中),製品分類名称(中),製品分類コード(小),製品分類名称(小),Encise ATC分類コード(第1レベル),Encise ATC分類名称(第1レベル),Encise ATC分類コード(第2レベル),Encise ATC分類名称(第2レベル),Encise ATC分類コード(第3レベル),Encise ATC分類名称(第3レベル),Encise ATC分類コード(第4レベル),Encise ATC分類名称(第4レベル),WHO ATC分類コード(第1レベル),WHO ATC分類名称(第1レベル),WHO ATC分類コード(第2レベル),WHO ATC分類名称(第2レベル),WHO ATC分類コード(第3レベル),WHO ATC分類名称(第3レベル),WHO ATC分類コード(第4レベル),WHO ATC分類名称(第4レベル),日本標準商品分類番号薬効分類コード(大),日本標準商品分類番号薬効分類名称(大),日本標準商品分類番号薬効分類コード(中),日本標準商品分類番号薬効分類名称(中),日本標準商品分類番号薬効分類コード(小),日本標準商品分類番号薬効分類名称(小),日本標準商品分類番号薬効分類コード(細),日本標準商品分類番号薬効分類名称(細),使用区分コード,使用区分名称,剤型区分コード,剤型区分名称,長期収載品区分コード,長期収載品区分名,薬価基準収載区分コード,薬価基準収載区分名,後発医薬品区分コード,後発医薬品区分名,有効成分一般名コード,有効成分一般名,新薬創出加算区分,更新日(西暦) -universal_product_code,seller_code,seller_name,manufacturer_code,manufacturer_name,product_brand_code,product_brand_name,product_item_code,product_item_name,product_SKU_code,product_SKU_name,Encise_ATC_1_code,Encise_ATC_1_name,Encise_ATC_2_code,Encise_ATC_2_name,Encise_ATC_3_code,Encise_ATC_3_name,Encise_ATC_4_code,Encise_ATC_4_name,WHO_ATC_1_code,WHO_ATC_1_name,WHO_ATC_2_code,WHO_ATC_2_name,WHO_ATC_3_code,WHO_ATC_3_name,WHO_ATC_4_code,WHO_ATC_4_name,JPN_pharma_category_1_code,JPN_pharma_category_1_name,JPN_pharma_category_2_code,JPN_pharma_category_2_name,JPN_pharma_category_3_code,JPN_pharma_category_3_name,JPN_pharma_category_4_code,JPN_pharma_category_4_name,drug_usage_code,drug_usage_name,drug_form_code,drug_form_name,long_listed_code,long_listed_flag,NHI_pricing_code,NHI_pricing_flag,generic_code,generic_flag,active_ingredient_code,active_ingredient_name,new_drug_premium_code,update_date -src01.en_natfm_proadd -org01.en_natfm_proadd - +encise +, +cp932 +" +CRLF +1 +49 +統一商品コード,販売元コード,販売元名称,製造販売元コード,製造販売元名称,製品分類コード(大),製品分類名称(大),製品分類コード(中),製品分類名称(中),製品分類コード(小),製品分類名称(小),Encise ATC分類コード(第1レベル),Encise ATC分類名称(第1レベル),Encise ATC分類コード(第2レベル),Encise ATC分類名称(第2レベル),Encise ATC分類コード(第3レベル),Encise ATC分類名称(第3レベル),Encise ATC分類コード(第4レベル),Encise ATC分類名称(第4レベル),WHO ATC分類コード(第1レベル),WHO ATC分類名称(第1レベル),WHO ATC分類コード(第2レベル),WHO ATC分類名称(第2レベル),WHO ATC分類コード(第3レベル),WHO ATC分類名称(第3レベル),WHO ATC分類コード(第4レベル),WHO ATC分類名称(第4レベル),日本標準商品分類番号薬効分類コード(大),日本標準商品分類番号薬効分類名称(大),日本標準商品分類番号薬効分類コード(中),日本標準商品分類番号薬効分類名称(中),日本標準商品分類番号薬効分類コード(小),日本標準商品分類番号薬効分類名称(小),日本標準商品分類番号薬効分類コード(細),日本標準商品分類番号薬効分類名称(細),使用区分コード,使用区分名称,剤型区分コード,剤型区分名称,長期収載品区分コード,長期収載品区分名,薬価基準収載区分コード,薬価基準収載区分名,後発医薬品区分コード,後発医薬品区分名,有効成分一般名コード,有効成分一般名,新薬創出加算区分,更新日(西暦) +universal_product_code,seller_code,seller_name,manufacturer_code,manufacturer_name,product_brand_code,product_brand_name,product_item_code,product_item_name,product_SKU_code,product_SKU_name,Encise_ATC_1_code,Encise_ATC_1_name,Encise_ATC_2_code,Encise_ATC_2_name,Encise_ATC_3_code,Encise_ATC_3_name,Encise_ATC_4_code,Encise_ATC_4_name,WHO_ATC_1_code,WHO_ATC_1_name,WHO_ATC_2_code,WHO_ATC_2_name,WHO_ATC_3_code,WHO_ATC_3_name,WHO_ATC_4_code,WHO_ATC_4_name,JPN_pharma_category_1_code,JPN_pharma_category_1_name,JPN_pharma_category_2_code,JPN_pharma_category_2_name,JPN_pharma_category_3_code,JPN_pharma_category_3_name,JPN_pharma_category_4_code,JPN_pharma_category_4_name,drug_usage_code,drug_usage_name,drug_form_code,drug_form_name,long_listed_code,long_listed_flag,NHI_pricing_code,NHI_pricing_flag,generic_code,generic_flag,active_ingredient_code,active_ingredient_name,new_drug_premium_code,update_date +src01.en_natfm_proadd +org01.en_natfm_proadd + diff --git a/config/data_import/encise/NATFM_SEGMNT.txt b/s3/data/encise/settings/NATFM_SEGMNT.txt similarity index 93% rename from config/data_import/encise/NATFM_SEGMNT.txt rename to s3/data/encise/settings/NATFM_SEGMNT.txt index 6269bbf8..298de016 100644 --- a/config/data_import/encise/NATFM_SEGMNT.txt +++ b/s3/data/encise/settings/NATFM_SEGMNT.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -3 -セグメントコード,セグメント名,更新日(西暦) -segment_code,segment_name,update_date -src01.en_natfm_segmnt -org01.en_natfm_segmnt - +ensice +, +cp932 +" +CRLF +1 +3 +セグメントコード,セグメント名,更新日(西暦) +segment_code,segment_name,update_date +src01.en_natfm_segmnt +org01.en_natfm_segmnt + diff --git a/config/data_import/encise/NATQD.txt b/s3/data/encise/settings/NATQD.txt similarity index 96% rename from config/data_import/encise/NATQD.txt rename to s3/data/encise/settings/NATQD.txt index 16bd0c49..7690f867 100644 --- a/config/data_import/encise/NATQD.txt +++ b/s3/data/encise/settings/NATQD.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -13 -地域コード,地域名,セグメントコード,セグメント名,施設コード,施設名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 -region_code,region_name,segment_code,segment_name,HCO_code,HCO_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month -src01.en_natqd -org01.en_natqd - +ensice +, +cp932 +" +CRLF +1 +13 +地域コード,地域名,セグメントコード,セグメント名,施設コード,施設名,統一商品コード,製品名,包装単位,数量,金額(薬価),年,月 +region_code,region_name,segment_code,segment_name,HCO_code,HCO_name,universal_product_code,product_SKU_name,package,qty,value_NHI,year,month +src01.en_natqd +org01.en_natqd + diff --git a/config/data_import/encise/NATQM_PROADD.txt b/s3/data/encise/settings/NATQM_PROADD.txt similarity index 99% rename from config/data_import/encise/NATQM_PROADD.txt rename to s3/data/encise/settings/NATQM_PROADD.txt index 1d483ad1..5a11c589 100644 --- a/config/data_import/encise/NATQM_PROADD.txt +++ b/s3/data/encise/settings/NATQM_PROADD.txt @@ -1,12 +1,12 @@ -encise -, -cp932 -" -CRLF -1 -49 -統一商品コード,販売元コード,販売元名称,製造販売元コード,製造販売元名称,製品分類コード(大),製品分類名称(大),製品分類コード(中),製品分類名称(中),製品分類コード(小),製品分類名称(小),Encise ATC分類コード(第1レベル),Encise ATC分類名称(第1レベル),Encise ATC分類コード(第2レベル),Encise ATC分類名称(第2レベル),Encise ATC分類コード(第3レベル),Encise ATC分類名称(第3レベル),Encise ATC分類コード(第4レベル),Encise ATC分類名称(第4レベル),WHO ATC分類コード(第1レベル),WHO ATC分類名称(第1レベル),WHO ATC分類コード(第2レベル),WHO ATC分類名称(第2レベル),WHO ATC分類コード(第3レベル),WHO ATC分類名称(第3レベル),WHO ATC分類コード(第4レベル),WHO ATC分類名称(第4レベル),日本標準商品分類番号薬効分類コード(大),日本標準商品分類番号薬効分類名称(大),日本標準商品分類番号薬効分類コード(中),日本標準商品分類番号薬効分類名称(中),日本標準商品分類番号薬効分類コード(小),日本標準商品分類番号薬効分類名称(小),日本標準商品分類番号薬効分類コード(細),日本標準商品分類番号薬効分類名称(細),使用区分コード,使用区分名称,剤型区分コード,剤型区分名称,長期収載品区分コード,長期収載品区分名,薬価基準収載区分コード,薬価基準収載区分名,後発医薬品区分コード,後発医薬品区分名,有効成分一般名コード,有効成分一般名,新薬創出加算区分,更新日(西暦) -universal_product_code,seller_code,seller_name,manufacturer_code,manufacturer_name,product_brand_code,product_brand_name,product_item_code,product_item_name,product_SKU_code,product_SKU_name,Encise_ATC_1_code,Encise_ATC_1_name,Encise_ATC_2_code,Encise_ATC_2_name,Encise_ATC_3_code,Encise_ATC_3_name,Encise_ATC_4_code,Encise_ATC_4_name,WHO_ATC_1_code,WHO_ATC_1_name,WHO_ATC_2_code,WHO_ATC_2_name,WHO_ATC_3_code,WHO_ATC_3_name,WHO_ATC_4_code,WHO_ATC_4_name,JPN_pharma_category_1_code,JPN_pharma_category_1_name,JPN_pharma_category_2_code,JPN_pharma_category_2_name,JPN_pharma_category_3_code,JPN_pharma_category_3_name,JPN_pharma_category_4_code,JPN_pharma_category_4_name,drug_usage_code,drug_usage_name,drug_form_code,drug_form_name,long_listed_code,long_listed_flag,NHI_pricing_code,NHI_pricing_flag,generic_code,generic_flag,active_ingredient_code,active_ingredient_name,new_drug_premium_code,update_date -src01.en_natqm_proadd -org01.en_natqm_proadd - +encise +, +cp932 +" +CRLF +1 +49 +統一商品コード,販売元コード,販売元名称,製造販売元コード,製造販売元名称,製品分類コード(大),製品分類名称(大),製品分類コード(中),製品分類名称(中),製品分類コード(小),製品分類名称(小),Encise ATC分類コード(第1レベル),Encise ATC分類名称(第1レベル),Encise ATC分類コード(第2レベル),Encise ATC分類名称(第2レベル),Encise ATC分類コード(第3レベル),Encise ATC分類名称(第3レベル),Encise ATC分類コード(第4レベル),Encise ATC分類名称(第4レベル),WHO ATC分類コード(第1レベル),WHO ATC分類名称(第1レベル),WHO ATC分類コード(第2レベル),WHO ATC分類名称(第2レベル),WHO ATC分類コード(第3レベル),WHO ATC分類名称(第3レベル),WHO ATC分類コード(第4レベル),WHO ATC分類名称(第4レベル),日本標準商品分類番号薬効分類コード(大),日本標準商品分類番号薬効分類名称(大),日本標準商品分類番号薬効分類コード(中),日本標準商品分類番号薬効分類名称(中),日本標準商品分類番号薬効分類コード(小),日本標準商品分類番号薬効分類名称(小),日本標準商品分類番号薬効分類コード(細),日本標準商品分類番号薬効分類名称(細),使用区分コード,使用区分名称,剤型区分コード,剤型区分名称,長期収載品区分コード,長期収載品区分名,薬価基準収載区分コード,薬価基準収載区分名,後発医薬品区分コード,後発医薬品区分名,有効成分一般名コード,有効成分一般名,新薬創出加算区分,更新日(西暦) +universal_product_code,seller_code,seller_name,manufacturer_code,manufacturer_name,product_brand_code,product_brand_name,product_item_code,product_item_name,product_SKU_code,product_SKU_name,Encise_ATC_1_code,Encise_ATC_1_name,Encise_ATC_2_code,Encise_ATC_2_name,Encise_ATC_3_code,Encise_ATC_3_name,Encise_ATC_4_code,Encise_ATC_4_name,WHO_ATC_1_code,WHO_ATC_1_name,WHO_ATC_2_code,WHO_ATC_2_name,WHO_ATC_3_code,WHO_ATC_3_name,WHO_ATC_4_code,WHO_ATC_4_name,JPN_pharma_category_1_code,JPN_pharma_category_1_name,JPN_pharma_category_2_code,JPN_pharma_category_2_name,JPN_pharma_category_3_code,JPN_pharma_category_3_name,JPN_pharma_category_4_code,JPN_pharma_category_4_name,drug_usage_code,drug_usage_name,drug_form_code,drug_form_name,long_listed_code,long_listed_flag,NHI_pricing_code,NHI_pricing_flag,generic_code,generic_flag,active_ingredient_code,active_ingredient_name,new_drug_premium_code,update_date +src01.en_natqm_proadd +org01.en_natqm_proadd + diff --git a/config/data_import/encise/NATQM_SEGMNT.txt b/s3/data/encise/settings/NATQM_SEGMNT.txt similarity index 93% rename from config/data_import/encise/NATQM_SEGMNT.txt rename to s3/data/encise/settings/NATQM_SEGMNT.txt index 63ea7316..ef44ee1c 100644 --- a/config/data_import/encise/NATQM_SEGMNT.txt +++ b/s3/data/encise/settings/NATQM_SEGMNT.txt @@ -1,12 +1,12 @@ -ensice -, -cp932 -" -CRLF -1 -3 -セグメントコード,セグメント名,更新日(西暦) -segment_code,segment_name,update_date -src01.en_natqm_segmnt -org01.en_natqm_segmnt - +ensice +, +cp932 +" +CRLF +1 +3 +セグメントコード,セグメント名,更新日(西暦) +segment_code,segment_name,update_date +src01.en_natqm_segmnt +org01.en_natqm_segmnt + diff --git a/config/data_import/encise/configmap.config b/s3/data/encise/settings/configmap.config similarity index 98% rename from config/data_import/encise/configmap.config rename to s3/data/encise/settings/configmap.config index 8aebcda8..377cf1af 100644 --- a/config/data_import/encise/configmap.config +++ b/s3/data/encise/settings/configmap.config @@ -1,37 +1,37 @@ -/* 第3営業日:速報データ */ -CITQD_Merck01_496_[0-9]{6}\.(CSV|csv) CITQD_Merck01.txt -CITQD_Merck06_496_[0-9]{6}\.(CSV|csv) CITQD_Merck06.txt -CITQD_Merck07_496_[0-9]{6}\.(CSV|csv) CITQD_Merck07.txt -CITQD_Merck10_496_[0-9]{6}\.(CSV|csv) CITQD_Merck10.txt -CITQM_PROADD_496_[0-9]{6}\.(CSV|csv) CITQM_PROADD.txt -CITQM_PROLST_496_[0-9]{6}\.(CSV|csv) CITQM_PROLST.txt -CITQM_REGION_496_[0-9]{6}\.(CSV|csv) CITQM_REGION.txt -CITQM_SEGMNT_496_[0-9]{6}\.(CSV|csv) CITQM_SEGMNT.txt -NATQD_496_[0-9]{6}\.(CSV|csv) NATQD.txt -NATQM_PROADD_496_[0-9]{6}\.(CSV|csv) NATQM_PROADD.txt -NATQM_SEGMNT_496_[0-9]{6}\.(CSV|csv) NATQM_SEGMNT.txt -/* 毎月15日:確定データ */ -CITFD_Merck01_496_[0-9]{6}\.(CSV|csv) CITFD_Merck01.txt -CITFD_Merck06_496_[0-9]{6}\.(CSV|csv) CITFD_Merck06.txt -CITFD_Merck07_496_[0-9]{6}\.(CSV|csv) CITFD_Merck07.txt -CITFD_Merck10_496_[0-9]{6}\.(CSV|csv) CITFD_Merck10.txt -CITFM_PROADD_496_[0-9]{6}\.(CSV|csv) CITFM_PROADD.txt -CITFM_PROLST_496_[0-9]{6}\.(CSV|csv) CITFM_PROLST.txt -CITFM_REGION_496_[0-9]{6}\.(CSV|csv) CITFM_REGION.txt -CITFM_SEGMNT_496_[0-9]{6}\.(CSV|csv) CITFM_SEGMNT.txt -MST_BRAND[0-9]{6}\.(CSV|csv) MST_BRAND.txt -NATFD_496_[0-9]{6}\.(CSV|csv) NATFD.txt -NATFM_PROADD_496_[0-9]{6}\.(CSV|csv) NATFM_PROADD.txt -NATFM_SEGMNT_496_[0-9]{6}\.(CSV|csv) NATFM_SEGMNT.txt -/* 毎月20日:En-Cluster */ -CLUFD_Merck02_496_[0-9]{6}\.(CSV|csv) CLUFD_Merck02.txt -CLUFD_Merck03_496_[0-9]{6}\.(CSV|csv) CLUFD_Merck03.txt -CLUFD_Merck04_496_[0-9]{6}\.(CSV|csv) CLUFD_Merck04.txt -CLUFM_CLUMST_496_01_[0-9]{6}\.(CSV|csv) CLUFM_CLUMST.txt -CLUFM_PROADD_496_[0-9]{6}\.(CSV|csv) CLUFM_PROADD.txt -CLUFM_PROLST_496_[0-9]{6}\.(CSV|csv) CLUFM_PROLST.txt -/* 直販データ */ -CLUFD_Merck02_496_[0-9]{6}D\.(CSV|csv) CLUFD_Merck02_D.txt -CLUFD_Merck03_496_[0-9]{6}D\.(CSV|csv) CLUFD_Merck03_D.txt -CLUFD_Merck04_496_[0-9]{6}D\.(CSV|csv) CLUFD_Merck04_D.txt -NATFD_496_[0-9]{6}D\.(CSV|csv) NATFD_D.txt +/* 第3営業日:速報データ */ +CITQD_Merck01_496_[0-9]{6}\.(CSV|csv) CITQD_Merck01.txt +CITQD_Merck06_496_[0-9]{6}\.(CSV|csv) CITQD_Merck06.txt +CITQD_Merck07_496_[0-9]{6}\.(CSV|csv) CITQD_Merck07.txt +CITQD_Merck10_496_[0-9]{6}\.(CSV|csv) CITQD_Merck10.txt +CITQM_PROADD_496_[0-9]{6}\.(CSV|csv) CITQM_PROADD.txt +CITQM_PROLST_496_[0-9]{6}\.(CSV|csv) CITQM_PROLST.txt +CITQM_REGION_496_[0-9]{6}\.(CSV|csv) CITQM_REGION.txt +CITQM_SEGMNT_496_[0-9]{6}\.(CSV|csv) CITQM_SEGMNT.txt +NATQD_496_[0-9]{6}\.(CSV|csv) NATQD.txt +NATQM_PROADD_496_[0-9]{6}\.(CSV|csv) NATQM_PROADD.txt +NATQM_SEGMNT_496_[0-9]{6}\.(CSV|csv) NATQM_SEGMNT.txt +/* 毎月15日:確定データ */ +CITFD_Merck01_496_[0-9]{6}\.(CSV|csv) CITFD_Merck01.txt +CITFD_Merck06_496_[0-9]{6}\.(CSV|csv) CITFD_Merck06.txt +CITFD_Merck07_496_[0-9]{6}\.(CSV|csv) CITFD_Merck07.txt +CITFD_Merck10_496_[0-9]{6}\.(CSV|csv) CITFD_Merck10.txt +CITFM_PROADD_496_[0-9]{6}\.(CSV|csv) CITFM_PROADD.txt +CITFM_PROLST_496_[0-9]{6}\.(CSV|csv) CITFM_PROLST.txt +CITFM_REGION_496_[0-9]{6}\.(CSV|csv) CITFM_REGION.txt +CITFM_SEGMNT_496_[0-9]{6}\.(CSV|csv) CITFM_SEGMNT.txt +MST_BRAND[0-9]{6}\.(CSV|csv) MST_BRAND.txt +NATFD_496_[0-9]{6}\.(CSV|csv) NATFD.txt +NATFM_PROADD_496_[0-9]{6}\.(CSV|csv) NATFM_PROADD.txt +NATFM_SEGMNT_496_[0-9]{6}\.(CSV|csv) NATFM_SEGMNT.txt +/* 毎月20日:En-Cluster */ +CLUFD_Merck02_496_[0-9]{6}\.(CSV|csv) CLUFD_Merck02.txt +CLUFD_Merck03_496_[0-9]{6}\.(CSV|csv) CLUFD_Merck03.txt +CLUFD_Merck04_496_[0-9]{6}\.(CSV|csv) CLUFD_Merck04.txt +CLUFM_CLUMST_496_01_[0-9]{6}\.(CSV|csv) CLUFM_CLUMST.txt +CLUFM_PROADD_496_[0-9]{6}\.(CSV|csv) CLUFM_PROADD.txt +CLUFM_PROLST_496_[0-9]{6}\.(CSV|csv) CLUFM_PROLST.txt +/* 直販データ */ +CLUFD_Merck02_496_[0-9]{6}D\.(CSV|csv) CLUFD_Merck02_D.txt +CLUFD_Merck03_496_[0-9]{6}D\.(CSV|csv) CLUFD_Merck03_D.txt +CLUFD_Merck04_496_[0-9]{6}D\.(CSV|csv) CLUFD_Merck04_D.txt +NATFD_496_[0-9]{6}D\.(CSV|csv) NATFD_D.txt