Merge pull request #92 develop into master
This commit is contained in:
commit
ab579ee812
11
.gitignore
vendored
11
.gitignore
vendored
@ -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/*
|
||||
# Node.jsで実装されたLambdaの管理対象外ファイル群
|
||||
package-lock.json
|
||||
node_modules/
|
||||
# ローカル確認用環境変数ファイル
|
||||
.env
|
||||
# pythonのキャッシュファイル
|
||||
__pycache__/
|
||||
@ -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" ]
|
||||
15
ecs/dataimport/Dockerfile
Normal file
15
ecs/dataimport/Dockerfile
Normal file
@ -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" ]
|
||||
@ -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}.`
|
||||
});
|
||||
})
|
||||
|
||||
};
|
||||
@ -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"
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
@ -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"
|
||||
}
|
||||
}
|
||||
@ -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={
|
||||
16
lambda/sap-data-decrypt/Dockerfile
Normal file
16
lambda/sap-data-decrypt/Dockerfile
Normal file
@ -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" ]
|
||||
268
lambda/sap-data-decrypt/datadecrypt/main.py
Normal file
268
lambda/sap-data-decrypt/datadecrypt/main.py
Normal file
@ -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
|
||||
3
lambda/sap-data-decrypt/requirements.txt
Normal file
3
lambda/sap-data-decrypt/requirements.txt
Normal file
@ -0,0 +1,3 @@
|
||||
awslambdaric
|
||||
boto3
|
||||
python-gnupg
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
7
s3/config/SAP/monthly_check_day_list.config
Normal file
7
s3/config/SAP/monthly_check_day_list.config
Normal file
@ -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
|
||||
@ -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
|
||||
@ -0,0 +1,6 @@
|
||||
宛先各位
|
||||
SAP月次I/Fである以下のファイルを受領しましたので、通知いたします。
|
||||
{notice_file_names}
|
||||
|
||||
尚、本メールはシステム自動送信のため、返信は出来ません。
|
||||
本件に関する問い合わせは、IT部門 ゴザリ様にお願いいたします。
|
||||
@ -0,0 +1 @@
|
||||
【MeDaCa連携通知】SAP Finance 月次I/Fファイルを受領しました
|
||||
@ -0,0 +1 @@
|
||||
WBSList_[0-9]{8}_[0-9]{6}\.tsv WBS List
|
||||
@ -0,0 +1,8 @@
|
||||
宛先各位
|
||||
SAP日次I/Fである以下のファイルを受領できておりません。
|
||||
{notice_file_names}
|
||||
|
||||
SAPシステム側のSFTP送信状況のご確認をお願いいたします。
|
||||
|
||||
尚、本メールはシステム自動送信のため、返信は出来ません。
|
||||
本件に関する問い合わせは、IT部門 ゴザリ様にお願いいたします。
|
||||
@ -0,0 +1,8 @@
|
||||
宛先各位
|
||||
SAP月次I/Fである以下のファイルを受領できておりません。
|
||||
{notice_file_names}
|
||||
|
||||
SAPシステム側のSFTP送信状況のご確認をお願いいたします。
|
||||
|
||||
尚、本メールはシステム自動送信のため、返信は出来ません。
|
||||
本件に関する問い合わせは、IT部門 ゴザリ様にお願いいたします。
|
||||
@ -0,0 +1 @@
|
||||
【MeDaCa連携エラー通知】SAP Finance 日次I/Fファイル未受領
|
||||
@ -0,0 +1 @@
|
||||
【MeDaCa連携エラー通知】SAP Finance 月次I/Fファイル未受領
|
||||
@ -0,0 +1 @@
|
||||
StockList_[0-9]{8}_[0-9]{6}\.tsv Stock List
|
||||
@ -0,0 +1,6 @@
|
||||
宛先各位
|
||||
SAP月次I/Fである以下のファイルを受領しましたので、通知いたします。
|
||||
{notice_file_names}
|
||||
|
||||
尚、本メールはシステム自動送信のため、返信は出来ません。
|
||||
本件に関する問い合わせは、IT部門 ゴザリ様にお願いいたします。
|
||||
@ -0,0 +1 @@
|
||||
【MeDaCa連携通知】SAP SupplyChain 月次I/Fファイルを受領しました
|
||||
@ -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
|
||||
@ -0,0 +1,8 @@
|
||||
宛先各位
|
||||
SAP日次I/Fである以下のファイルを受領できておりません。
|
||||
{notice_file_names}
|
||||
|
||||
SAPシステム側のSFTP送信状況のご確認をお願いいたします。
|
||||
|
||||
尚、本メールはシステム自動送信のため、返信は出来ません。
|
||||
本件に関する問い合わせは、IT部門 ゴザリ様にお願いいたします。
|
||||
@ -0,0 +1,8 @@
|
||||
宛先各位
|
||||
SAP月次I/Fである以下のファイルを受領できておりません。
|
||||
{notice_file_names}
|
||||
|
||||
SAPシステム側のSFTP送信状況のご確認をお願いいたします。
|
||||
|
||||
尚、本メールはシステム自動送信のため、返信は出来ません。
|
||||
本件に関する問い合わせは、IT部門 ゴザリ様にお願いいたします。
|
||||
@ -0,0 +1 @@
|
||||
【MeDaCa連携エラー通知】SAP SupplyChain 日次I/Fファイル未受領
|
||||
@ -0,0 +1 @@
|
||||
【MeDaCa連携エラー通知】SAP SupplyChain 月次I/Fファイル未受領
|
||||
73
s3/config/non_business_day_list.config
Normal file
73
s3/config/non_business_day_list.config
Normal file
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
Loading…
x
Reference in New Issue
Block a user