diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..e4f6d9fb --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +lambda/mbj-newdwh2021-staging-NoticeToSlack/package-lock.json +lambda/mbj-newdwh2021-staging-NoticeToSlack/node_modules/* +lambda/mbj-newdwh2021-staging-PublishFromLog/package-lock.json +lambda/mbj-newdwh2021-staging-PublishFromLog/node_modules/* \ No newline at end of file diff --git a/config/data_import/encise/CITFD_Merck01.txt b/config/data_import/encise/CITFD_Merck01.txt new file mode 100644 index 00000000..229d1550 --- /dev/null +++ b/config/data_import/encise/CITFD_Merck01.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/CITFD_Merck06.txt b/config/data_import/encise/CITFD_Merck06.txt new file mode 100644 index 00000000..e6c8955f --- /dev/null +++ b/config/data_import/encise/CITFD_Merck06.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/CITFD_Merck07.txt b/config/data_import/encise/CITFD_Merck07.txt new file mode 100644 index 00000000..03dd1512 --- /dev/null +++ b/config/data_import/encise/CITFD_Merck07.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/CITFD_Merck10.txt b/config/data_import/encise/CITFD_Merck10.txt new file mode 100644 index 00000000..1a6d9b28 --- /dev/null +++ b/config/data_import/encise/CITFD_Merck10.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/CITFM_PROADD.txt b/config/data_import/encise/CITFM_PROADD.txt new file mode 100644 index 00000000..4858d296 --- /dev/null +++ b/config/data_import/encise/CITFM_PROADD.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/CITFM_PROLST.txt b/config/data_import/encise/CITFM_PROLST.txt new file mode 100644 index 00000000..dac87a8b --- /dev/null +++ b/config/data_import/encise/CITFM_PROLST.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/CITFM_REGION.txt b/config/data_import/encise/CITFM_REGION.txt new file mode 100644 index 00000000..75d4ae36 --- /dev/null +++ b/config/data_import/encise/CITFM_REGION.txt @@ -0,0 +1,12 @@ +ensice +, +cp932 +" +CRLF +1 +3 +地域コード,地域名,更新日(西暦) +region_code,region_name,update_date +src01.en_citfm_region +org01.en_citfm_region + diff --git a/config/data_import/encise/CITFM_SEGMNT.txt b/config/data_import/encise/CITFM_SEGMNT.txt new file mode 100644 index 00000000..2a936099 --- /dev/null +++ b/config/data_import/encise/CITFM_SEGMNT.txt @@ -0,0 +1,12 @@ +ensice +, +cp932 +" +CRLF +1 +3 +セグメントコード,セグメント名,更新日(西暦) +segment_code,segment_name,update_date +src01.en_citfm_segmnt +org01.en_citfm_segmnt + diff --git a/config/data_import/encise/CITQD_Merck01.txt b/config/data_import/encise/CITQD_Merck01.txt new file mode 100644 index 00000000..891d5c2c --- /dev/null +++ b/config/data_import/encise/CITQD_Merck01.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/CITQD_Merck06.txt b/config/data_import/encise/CITQD_Merck06.txt new file mode 100644 index 00000000..09423f1f --- /dev/null +++ b/config/data_import/encise/CITQD_Merck06.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/CITQD_Merck07.txt b/config/data_import/encise/CITQD_Merck07.txt new file mode 100644 index 00000000..71443d89 --- /dev/null +++ b/config/data_import/encise/CITQD_Merck07.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/CITQD_Merck10.txt b/config/data_import/encise/CITQD_Merck10.txt new file mode 100644 index 00000000..087164c2 --- /dev/null +++ b/config/data_import/encise/CITQD_Merck10.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/CITQM_PROADD.txt b/config/data_import/encise/CITQM_PROADD.txt new file mode 100644 index 00000000..d62e0f00 --- /dev/null +++ b/config/data_import/encise/CITQM_PROADD.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/CITQM_PROLST.txt b/config/data_import/encise/CITQM_PROLST.txt new file mode 100644 index 00000000..a12c8d9e --- /dev/null +++ b/config/data_import/encise/CITQM_PROLST.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/CITQM_REGION.txt b/config/data_import/encise/CITQM_REGION.txt new file mode 100644 index 00000000..e618e526 --- /dev/null +++ b/config/data_import/encise/CITQM_REGION.txt @@ -0,0 +1,12 @@ +ensice +, +cp932 +" +CRLF +1 +3 +地域コード,地域名,更新日(西暦) +region_code,region_name,update_date +src01.en_citqm_region +org01.en_citqm_region + diff --git a/config/data_import/encise/CITQM_SEGMNT.txt b/config/data_import/encise/CITQM_SEGMNT.txt new file mode 100644 index 00000000..0ccc7faf --- /dev/null +++ b/config/data_import/encise/CITQM_SEGMNT.txt @@ -0,0 +1,12 @@ +ensice +, +cp932 +" +CRLF +1 +3 +セグメントコード,セグメント名,更新日(西暦) +segment_code,segment_name,update_date +src01.en_citqm_segmnt +org01.en_citqm_segmnt + diff --git a/config/data_import/encise/CLUFD_Merck02.txt b/config/data_import/encise/CLUFD_Merck02.txt new file mode 100644 index 00000000..ec73fad8 --- /dev/null +++ b/config/data_import/encise/CLUFD_Merck02.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/CLUFD_Merck02_D.txt b/config/data_import/encise/CLUFD_Merck02_D.txt new file mode 100644 index 00000000..992b88c7 --- /dev/null +++ b/config/data_import/encise/CLUFD_Merck02_D.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/CLUFD_Merck03.txt b/config/data_import/encise/CLUFD_Merck03.txt new file mode 100644 index 00000000..c456b163 --- /dev/null +++ b/config/data_import/encise/CLUFD_Merck03.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/CLUFD_Merck03_D.txt b/config/data_import/encise/CLUFD_Merck03_D.txt new file mode 100644 index 00000000..ad37c208 --- /dev/null +++ b/config/data_import/encise/CLUFD_Merck03_D.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/CLUFD_Merck04.txt b/config/data_import/encise/CLUFD_Merck04.txt new file mode 100644 index 00000000..7727273e --- /dev/null +++ b/config/data_import/encise/CLUFD_Merck04.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/CLUFD_Merck04_D.txt b/config/data_import/encise/CLUFD_Merck04_D.txt new file mode 100644 index 00000000..765bd4a5 --- /dev/null +++ b/config/data_import/encise/CLUFD_Merck04_D.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/CLUFM_CLUMST.txt b/config/data_import/encise/CLUFM_CLUMST.txt new file mode 100644 index 00000000..c3b2598a --- /dev/null +++ b/config/data_import/encise/CLUFM_CLUMST.txt @@ -0,0 +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 diff --git a/config/data_import/encise/CLUFM_CLUMST_ex.sql b/config/data_import/encise/CLUFM_CLUMST_ex.sql new file mode 100644 index 00000000..2b6f8b5d --- /dev/null +++ b/config/data_import/encise/CLUFM_CLUMST_ex.sql @@ -0,0 +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; + diff --git a/config/data_import/encise/CLUFM_PROADD.txt b/config/data_import/encise/CLUFM_PROADD.txt new file mode 100644 index 00000000..8cb378b4 --- /dev/null +++ b/config/data_import/encise/CLUFM_PROADD.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/CLUFM_PROLST.txt b/config/data_import/encise/CLUFM_PROLST.txt new file mode 100644 index 00000000..ce4c4dcb --- /dev/null +++ b/config/data_import/encise/CLUFM_PROLST.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/MST_BRAND.txt b/config/data_import/encise/MST_BRAND.txt new file mode 100644 index 00000000..032c6a87 --- /dev/null +++ b/config/data_import/encise/MST_BRAND.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/NATFD.txt b/config/data_import/encise/NATFD.txt new file mode 100644 index 00000000..7529f0c9 --- /dev/null +++ b/config/data_import/encise/NATFD.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/NATFD_D.txt b/config/data_import/encise/NATFD_D.txt new file mode 100644 index 00000000..080cceab --- /dev/null +++ b/config/data_import/encise/NATFD_D.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/NATFM_PROADD.txt b/config/data_import/encise/NATFM_PROADD.txt new file mode 100644 index 00000000..43bfe5f9 --- /dev/null +++ b/config/data_import/encise/NATFM_PROADD.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/NATFM_SEGMNT.txt b/config/data_import/encise/NATFM_SEGMNT.txt new file mode 100644 index 00000000..6269bbf8 --- /dev/null +++ b/config/data_import/encise/NATFM_SEGMNT.txt @@ -0,0 +1,12 @@ +ensice +, +cp932 +" +CRLF +1 +3 +セグメントコード,セグメント名,更新日(西暦) +segment_code,segment_name,update_date +src01.en_natfm_segmnt +org01.en_natfm_segmnt + diff --git a/config/data_import/encise/NATQD.txt b/config/data_import/encise/NATQD.txt new file mode 100644 index 00000000..16bd0c49 --- /dev/null +++ b/config/data_import/encise/NATQD.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/NATQM_PROADD.txt b/config/data_import/encise/NATQM_PROADD.txt new file mode 100644 index 00000000..1d483ad1 --- /dev/null +++ b/config/data_import/encise/NATQM_PROADD.txt @@ -0,0 +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 + diff --git a/config/data_import/encise/NATQM_SEGMNT.txt b/config/data_import/encise/NATQM_SEGMNT.txt new file mode 100644 index 00000000..63ea7316 --- /dev/null +++ b/config/data_import/encise/NATQM_SEGMNT.txt @@ -0,0 +1,12 @@ +ensice +, +cp932 +" +CRLF +1 +3 +セグメントコード,セグメント名,更新日(西暦) +segment_code,segment_name,update_date +src01.en_natqm_segmnt +org01.en_natqm_segmnt + diff --git a/config/data_import/encise/configmap.config b/config/data_import/encise/configmap.config new file mode 100644 index 00000000..8aebcda8 --- /dev/null +++ b/config/data_import/encise/configmap.config @@ -0,0 +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 diff --git a/ecs/Dockerfile/Dockerfile b/ecs/Dockerfile/Dockerfile new file mode 100644 index 00000000..ec5fb0e0 --- /dev/null +++ b/ecs/Dockerfile/Dockerfile @@ -0,0 +1,10 @@ +FROM python:3.9 + +ENV TZ="Asia/Tokyo" + +WORKDIR /usr/src/app +COPY requirements.txt ./ +RUN pip install --no-cache-dir -r requirements.txt +COPY dataimport ./ + +CMD [ "python", "./controller.py" ] diff --git a/ecs/Dockerfile/dataimport/chk.py b/ecs/Dockerfile/dataimport/chk.py new file mode 100644 index 00000000..a0bf2ced --- /dev/null +++ b/ecs/Dockerfile/dataimport/chk.py @@ -0,0 +1,116 @@ +from datetime import datetime +import boto3 +import io +import csv +import sys +from end import end +from error import error +from common import debug_log + +# 定数 +DIRECTORY_WORK = '/work/' +LOG_LEVEL = {'i': 'Info', 'e': 'Error'} +SETTINGS_ITEM = { + 'dataSource': 0, + 'delimiter': 1, + 'charCode': 2, + 'quotechar': 3, + 'lineFeedCode': 4, + 'headerFlag': 5, + 'csvNumItems': 6, + 'csvNameItems': 7, + 'dbColumuName': 8, + 'storageSchemaName': 9, + 'loadSchemaName': 10, + 'exSqlFileName': 11, +} +LINE_FEED_CODE = { + 'CR': '\r', + 'LF': '\n', + 'CRLF': '\r\n', +} + +# クラス変数 +s3_resource = boto3.resource('s3') + + +# チェック例外クラス +class CheckError(Exception): + pass + + +def check(bucket_name, target_data_source, target_file_name, settings_key, log_info, mode): + """チェック処理 + Args: + bucket_name : バケット名 + target_data_source : 投入データのディレクトリ名よりデータソースに該当する部分 + target_file_name : 投入データのファイル名 + settings_key : 投入データに該当する個別設定ファイルのフルパス + log_info : ログに記載するデータソース名とファイル名 + mode : 処理モード + Raises: + CheckError : チェックでエラーがあった場合に発生する例外 + """ + + try: + debug_log(f'引数 bucket_name : {bucket_name}', log_info, mode) + debug_log(f'引数 target_data_source : {target_data_source}', log_info, mode) + debug_log(f'引数 target_file_name : {target_file_name}', log_info, mode) + debug_log(f'引数 settings_key : {settings_key}', log_info, mode) + debug_log(f'引数 log_info : {log_info}', log_info, mode) + debug_log(f'引数 mode : {mode}', log_info, mode) + + # ① チェック処理開始ログを出力する + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-CHK-01 - チェック処理を開始します') + + # データ読込 + settings_obj = s3_resource.Object(bucket_name, settings_key) + settings_response = settings_obj.get() + settings_list = [] + for line in io.TextIOWrapper(io.BytesIO(settings_response["Body"].read()), encoding='utf-8'): + settings_list.append(line.rstrip('\n')) + + work_key = target_data_source + DIRECTORY_WORK + target_file_name + work_obj = s3_resource.Object(bucket_name, work_key) + work_response = work_obj.get() + work_data = io.TextIOWrapper(io.BytesIO(work_response["Body"].read()), encoding=settings_list[SETTINGS_ITEM["charCode"]], newline=LINE_FEED_CODE[settings_list[SETTINGS_ITEM["lineFeedCode"]]]) + work_header_list = [] + for line in csv.reader(work_data, quotechar=settings_list[SETTINGS_ITEM["quotechar"]], delimiter=settings_list[SETTINGS_ITEM["delimiter"]]): + work_header_list = line + break + + # ② C-0のデータ件数チェックを開始する + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-CHK-02 - C-0のチェックを開始します') + if not len(work_header_list): + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-CHK-03 - 投入ファイルが0バイトのため処理を終了します') + end(bucket_name, target_data_source, target_file_name, '', log_info, mode) + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-CHK-04 - 終了処理完了') + sys.exit() + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-CHK-05 - C-0:正常終了') + + # ③ C-1の項目数チェックを開始する + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-CHK-06 - C-1のチェックを開始します') + work_header_list_len = len(work_header_list) + if work_header_list_len == int(settings_list[SETTINGS_ITEM["csvNumItems"]]): + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-CHK-07 - C-1:正常終了') + else: + raise CheckError(f'E-CHK-01 - 項目数が一致しません 個別設定ファイル項目数:{settings_list[SETTINGS_ITEM["csvNumItems"]]} 投入データ項目数:{work_header_list_len}') + + # ④ C-2の項目並び順チェック開始する + if int(settings_list[SETTINGS_ITEM["headerFlag"]]) == True: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-CHK-08 - C-2のチェックを開始します') + settings_header_list = settings_list[SETTINGS_ITEM["csvNameItems"]].rstrip().split(',') + for i in range(len(settings_header_list)): + if not settings_header_list[i] == work_header_list[i]: + raise CheckError(f'E-CHK-02 - 項目順序が一致しません {i + 1}番目の項目 個別設定ファイル項目:{settings_header_list[i]} 投入データ項目:{work_header_list[i]}') + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-CHK-09 - C-2:正常終了') + + # ⑤ チェック処理終了ログを出力する + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-CHK-10 - チェック処理を終了します') + except CheckError as e: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["e"]} {e}') + error(bucket_name, target_data_source, target_file_name, log_info) + + except Exception as e: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["e"]} E-CHK-99 - エラー内容:{e}') + error(bucket_name, target_data_source, target_file_name, log_info) diff --git a/ecs/Dockerfile/dataimport/common.py b/ecs/Dockerfile/dataimport/common.py new file mode 100644 index 00000000..8b8eeed6 --- /dev/null +++ b/ecs/Dockerfile/dataimport/common.py @@ -0,0 +1,13 @@ +from datetime import datetime + +# 定数 +LOG_LEVEL = {"d": 'Debug'} +MODE_TYPE = { + 'n': 'normal', + 'd': 'debug', +} + + +def debug_log(log, log_info, mode): + if MODE_TYPE['d'] == mode: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["d"]} {log}') diff --git a/ecs/Dockerfile/dataimport/controller.py b/ecs/Dockerfile/dataimport/controller.py new file mode 100644 index 00000000..79b54717 --- /dev/null +++ b/ecs/Dockerfile/dataimport/controller.py @@ -0,0 +1,58 @@ +import os +from datetime import datetime +from ini import init +from chk import check +from main import main +from end import end +from error import error + +# 引数 +BUCKET_NAME = os.environ["BUCKET_NAME"] +TARGET_KEY = os.environ["TARGET_KEY"] +DATA_SOURCE_NAME = os.environ["DATA_SOURCE_NAME"] +FILE_NAME = os.environ["FILE_NAME"] +MODE = os.environ["MODE"] + +# 環境変数 +DB_HOST = os.environ["DB_HOST"] +DB_NAME = os.environ["DB_NAME"] +DB_PASS = os.environ["DB_PASS"] +DB_USER = os.environ["DB_USER"] +DB_INFO = {"host": DB_HOST, "name": DB_NAME, "pass": DB_PASS, "user": DB_USER} + +# 定数 +LOG_LEVEL = {"i": 'Info'} +LOG_INFO = f'{DATA_SOURCE_NAME} {FILE_NAME}' + + +"""コントロール処理 + +各処理を呼び出すコントローラー + +""" + +try: + # ① データ取込処理開始ログを出力する + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {LOG_INFO} {LOG_LEVEL["i"]} I-CTRL-01 - データ取込処理を開始します') + + # ② 初期処理を呼び出す + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {LOG_INFO} {LOG_LEVEL["i"]} I-CTRL-02 - 初期処理の呼び出し') + settings_key = init(BUCKET_NAME, TARGET_KEY, DATA_SOURCE_NAME, FILE_NAME, LOG_INFO, MODE) + + # ③ チェック処理を呼び出す + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {LOG_INFO} {LOG_LEVEL["i"]} I-CTRL-03 - チェック処理の呼び出し') + check(BUCKET_NAME, DATA_SOURCE_NAME, FILE_NAME, settings_key, LOG_INFO, MODE) + + # ④ メイン処理を呼び出す + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {LOG_INFO} {LOG_LEVEL["i"]} I-CTRL-04 - メイン処理の呼び出し') + warning_info = main(BUCKET_NAME, DATA_SOURCE_NAME, FILE_NAME, settings_key, DB_INFO, LOG_INFO, MODE) + + # ⑤ 終了処理を呼び出す + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {LOG_INFO} {LOG_LEVEL["i"]} I-CTRL-05 - 終了処理の呼び出し') + end(BUCKET_NAME, DATA_SOURCE_NAME, FILE_NAME, warning_info, LOG_INFO, MODE) + + # ⑥ データ取込処理終了ログを出力する + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {LOG_INFO} {LOG_LEVEL["i"]} I-CTRL-06 - データ取込処理を終了します') +except Exception as e: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {LOG_INFO} {LOG_LEVEL["e"]} E-CTRL-99 - エラー内容:{e}') + error(BUCKET_NAME, DATA_SOURCE_NAME, FILE_NAME, LOG_INFO) diff --git a/ecs/Dockerfile/dataimport/end.py b/ecs/Dockerfile/dataimport/end.py new file mode 100644 index 00000000..e4d53482 --- /dev/null +++ b/ecs/Dockerfile/dataimport/end.py @@ -0,0 +1,90 @@ +from datetime import datetime +import boto3 +from error import error +from common import debug_log + +# 定数 +LOG_LEVEL = {'i': 'Info', 'e': 'Error'} +DIRECTORY_TARGET = '/target/' +DIRECTORY_WORK = '/work/' +DIRECTORY_DONE = '/done/' +DIRECTORY_WARNING = '/warning/' + +# クラス変数 +s3_client = boto3.client('s3') +s3_resource = boto3.resource('s3') + + +def end(bucket_name, target_data_source, target_file_name, warning_info, log_info, mode): + """終了処理 + Args: + bucket_name : バケット名 + target_data_source : 投入データのディレクトリ名よりデータソースに該当する部分 + target_file_name : 投入データのファイル名 + warning_info : Warning情報 + log_info : ログに記載するデータソース名とファイル名 + mode : 処理モード + """ + + try: + debug_log(f'引数 bucket_name : {bucket_name}', log_info, mode) + debug_log(f'引数 target_data_source : {target_data_source}', log_info, mode) + debug_log(f'引数 target_file_name : {target_file_name}', log_info, mode) + debug_log(f'引数 warning_info : {warning_info}', log_info, mode) + debug_log(f'引数 log_info : {log_info}', log_info, mode) + debug_log(f'引数 mode : {mode}', log_info, mode) + + # ① 終了処理開始ログを出力する + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-END-01 - 終了処理を開始します') + + # ② 投入データファイルをS3バケット内のworkディレクトリから、以下ファイル名でdoneディレクトリに移動(コピー削除)する + work_key = target_data_source + DIRECTORY_WORK + target_file_name + copy_source = { + 'Bucket': bucket_name, + 'Key': work_key + } + done_file_name = f'{datetime.now():%Y%m%d%H%M%S}_{target_file_name}' + done_key = target_data_source + DIRECTORY_DONE + done_file_name + done_obj = s3_resource.Object(bucket_name, done_key) + done_obj.copy(copy_source) + s3_client.delete_object(Bucket=bucket_name, Key=work_key) + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-END-02 - workディレクトリの {target_file_name} をdoneディレクトリに移動しました 移動後ファイル名:{done_file_name}') + + # ③ S3バケット内のtargetディレクトリに存在する「投入データファイル名.doing」ファイルを削除する + doing_file_name = target_file_name + '.doing' + doing_key = target_data_source + DIRECTORY_TARGET + doing_file_name + s3_client.delete_object(Bucket=bucket_name, Key=doing_key) + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-END-03 - targetディレクトリの {doing_file_name} を削除しました') + + # ④ Warning情報が存在するか確認する + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-END-04 - Warning情報の存在チェック') + if warning_info: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-END-05 - Warning情報は存在しました') + + # warningファイルの作成 + warning_file_name = f'{datetime.now():%Y%m%d%H%M%S}_{target_file_name}_war.log' + warning_key = target_data_source + DIRECTORY_WARNING + warning_file_name + warning_obj = s3_resource.Object(bucket_name, warning_key) + warning_obj.put(Body=warning_info) + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-END-06 - warningディレクトリに {warning_file_name} を作成しました') + + # warning処理結果ファイルの作成 + result_warning_file_name = target_file_name + '.warning' + result_warning_key = target_data_source + DIRECTORY_TARGET + result_warning_file_name + result_warning_obj = s3_resource.Object(bucket_name, result_warning_key) + result_warning_obj.put(Body='') + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-END-07 - targetディレクトリに {result_warning_file_name} を作成しました') + else: + # done処理結果ファイルの作成 + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-END-08 - Warning情報は存在しませんでした') + result_done_file_name = target_file_name + '.done' + result_done_key = target_data_source + DIRECTORY_TARGET + result_done_file_name + result_done_obj = s3_resource.Object(bucket_name, result_done_key) + result_done_obj.put(Body='') + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-END-09 - targetディレクトリに {result_done_file_name} を作成しました') + + # ⑤ 終了処理終了ログを出力する + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-END-10 - 終了処理を終了します') + except Exception as e: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["e"]} E-END-99 - エラー内容:{e}') + error(bucket_name, target_data_source, target_file_name, log_info) diff --git a/ecs/Dockerfile/dataimport/error.py b/ecs/Dockerfile/dataimport/error.py new file mode 100644 index 00000000..c81eca65 --- /dev/null +++ b/ecs/Dockerfile/dataimport/error.py @@ -0,0 +1,102 @@ +from datetime import datetime +import boto3 +import sys + +# 定数 +LOG_LEVEL = {'i': 'Info', 'e': 'Error'} +DIRECTORY_TARGET = '/target/' +DIRECTORY_WORK = '/work/' +DIRECTORY_ERROR = '/error/' + +# クラス変数 +s3_client = boto3.client('s3') +s3_resource = boto3.resource('s3') + + +def error(bucket_name, target_data_source, target_file_name, log_info): + """エラー処理 + Args: + bucket_name : バケット名 + target_data_source : 投入データのディレクトリ名よりデータソースに該当する部分 + target_file_name : 投入データのファイル名 + log_info : ログに記載するデータソース名とファイル名 + """ + + try: + # ① エラー処理開始ログを出力する + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-ERR-01 - エラー処理を開始します') + + # ② 投入データファイルをS3バケット内のworkディレクトリから、以下ファイル名でerrorディレクトリに移動(コピー削除)する + work_key = target_data_source + DIRECTORY_WORK + target_file_name + copy_source = { + 'Bucket': bucket_name, + 'Key': work_key + } + error_file_name = f'{datetime.now():%Y%m%d%H%M%S}_{target_file_name}' + error_key = target_data_source + DIRECTORY_ERROR + error_file_name + error_obj = s3_resource.Object(bucket_name, error_key) + error_obj.copy(copy_source) + s3_client.delete_object(Bucket=bucket_name, Key=work_key) + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-ERR-02 - workディレクトリの {target_file_name} をerrorディレクトリに移動しました 移動後ファイル名:{error_file_name}') + + # ③ S3バケット内のtargetディレクトリに存在する「投入データファイル名.doing」ファイルを削除する + doing_file_name = target_file_name + '.doing' + doing_key = target_data_source + DIRECTORY_TARGET + doing_file_name + s3_client.delete_object(Bucket=bucket_name, Key=doing_key) + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-ERR-03 - targetディレクトリの {doing_file_name} を削除しました') + + # ④ S3バケット内のtargetディレクトリに、「投入データファイル名.error」ファイルを作成する + result_error_file_name = target_file_name + '.error' + result_error_key = target_data_source + DIRECTORY_TARGET + result_error_file_name + result_error_obj = s3_resource.Object(bucket_name, result_error_key) + result_error_obj.put(Body='') + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-ERR-04 - targetディレクトリに {result_error_file_name} を作成しました') + except Exception as e: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["e"]} E-ERR-99 - エラー内容:{e}') + finally: + # ⑤ 終了処理終了ログを出力する + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-ERR-05 - エラー処理を終了します') + + # ⑥ 処理を終了する + sys.exit() + +def error_doing_file_exists(bucket_name, target_key, target_data_source, target_file_name, log_info): + """.doingファイルが存在した時のエラー処理 + Args: + bucket_name : バケット名 + target_key : 投入データのフルパス + target_data_source : 投入データのディレクトリ名よりデータソースに該当する部分 + target_file_name : 投入データのファイル名 + log_info : ログに記載するデータソース名とファイル名 + """ + + try: + # ① エラー処理開始ログを出力する + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-ERR-06 - doingファイルが存在した時のエラー処理を開始します') + + # ② 投入データファイルをS3バケット内のtargetディレクトリから、以下ファイル名でerrorディレクトリに移動(コピー削除)する + copy_source = { + 'Bucket': bucket_name, + 'Key': target_key + } + error_file_name = f'{datetime.now():%Y%m%d%H%M%S}_{target_file_name}' + error_key = target_data_source + DIRECTORY_ERROR + error_file_name + error_obj = s3_resource.Object(bucket_name, error_key) + error_obj.copy(copy_source) + s3_client.delete_object(Bucket=bucket_name, Key=target_key) + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-ERR-07 - targetディレクトリの {target_file_name} をerrorディレクトリに移動しました 移動後ファイル名:{error_file_name}') + + # ③ S3バケット内のtargetディレクトリに、「投入データファイル名.exclusive_error」ファイルを作成する + result_error_file_name = target_file_name + '.exclusive_error' + result_error_key = target_data_source + DIRECTORY_TARGET + result_error_file_name + result_error_obj = s3_resource.Object(bucket_name, result_error_key) + result_error_obj.put(Body='') + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-ERR-08 - targetディレクトリに {result_error_file_name} を作成しました') + except Exception as e: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["e"]} E-ERR-99 - エラー内容:{e}') + finally: + # ④ 終了処理終了ログを出力する + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-ERR-09 - doingファイルが存在した時のエラー処理を終了します') + + # ⑤ 処理を終了する + sys.exit() \ No newline at end of file diff --git a/ecs/Dockerfile/dataimport/ini.py b/ecs/Dockerfile/dataimport/ini.py new file mode 100644 index 00000000..30d2ef93 --- /dev/null +++ b/ecs/Dockerfile/dataimport/ini.py @@ -0,0 +1,161 @@ +from datetime import datetime +import boto3 +import io +import csv +import re +import sys +from error import error +from error import error_doing_file_exists +from common import debug_log + +# 定数 +LOG_LEVEL = {"i": 'Info', "e": 'Error'} +MAPPING_FILE_NAME = 'configmap.config' +DIRECTORY_TARGET = '/target/' +DIRECTORY_WORK = '/work/' +DIRECTORY_SETTINGS = '/settings/' + +# クラス変数 +s3_client = boto3.client('s3') +s3_resource = boto3.resource('s3') + + +def init(bucket_name, target_key, target_data_source, target_file_name, log_info, mode): + """初期処理 + Args: + bucket_name : バケット名 + target_key : 投入データのフルパス + target_data_source : 投入データのディレクトリ名よりデータソースに該当する部分 + target_file_name : 投入データのファイル名 + log_info : ログに記載するデータソース名とファイル名 + mode : 処理モード + Returns: + settings_key : 投入データに該当する個別設定ファイルのフルパス + """ + + try: + debug_log(f'引数 bucket_name : {bucket_name}', log_info, mode) + debug_log(f'引数 target_key : {target_key}', log_info, mode) + debug_log(f'引数 target_data_source : {target_data_source}', log_info, mode) + debug_log(f'引数 target_file_name : {target_file_name}', log_info, mode) + debug_log(f'引数 log_info : {log_info}', log_info, mode) + debug_log(f'引数 mode : {mode}', log_info, mode) + + # ① 初期処理開始ログを出力する + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-INI-01 - 初期処理を開始します') + except Exception as e: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["e"]} E-INI-99 - エラー内容:{e}') + error(bucket_name, target_data_source, target_file_name, log_info) + + try: + # ② S3バケット内のtargetディレクトリに「投入データファイル名.doing」ファイルが存在するかチェックする + doing_file_name = target_file_name + '.doing' + doing_key = target_data_source + DIRECTORY_TARGET + doing_file_name + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-INI-02 - doingファイル:{doing_file_name} の存在チェック') + s3_client.head_object(Bucket=bucket_name, Key=doing_key) + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["e"]} E-INI-01 - 投入データ {target_file_name} は既に処理中です') + error_doing_file_exists(bucket_name, target_key, target_data_source, target_file_name, log_info) + except Exception as e: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-INI-03 - doingファイルは存在しませんでした') + + try: + # ③ S3バケット内のtargetディレクトリに、「投入データファイル名.doing」ファイルを作成する + doing_obj = s3_resource.Object(bucket_name, doing_key) + doing_obj.put(Body='') + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-INI-04 - targetディレクトリに {doing_file_name} を作成しました') + + # ④ 投入データファイルをS3バケット内のtargetディレクトリから、workディレクトリに移動(コピー削除)する + copy_source = { + 'Bucket': bucket_name, + 'Key': target_key + } + work_key = target_data_source + DIRECTORY_WORK + target_file_name + work_obj = s3_resource.Object(bucket_name, work_key) + work_obj.copy(copy_source) + s3_client.delete_object(Bucket=bucket_name, Key=target_key) + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-INI-05 - 投入データ {target_file_name} をworkディレクトリに移動しました') + except Exception as e: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["e"]} E-INI-99 - エラー内容:{e}') + error(bucket_name, target_data_source, target_file_name, log_info) + + try: + # ⑤ S3バケット内のtargetディレクトリの以下ファイル群を削除(前回分の削除)する + # doneファイルの存在確認 + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-INI-06 - doneファイル:{target_file_name}.done の存在チェック') + result_done_key = target_data_source + DIRECTORY_TARGET + target_file_name + '.done' + s3_client.head_object(Bucket=bucket_name, Key=result_done_key) + s3_client.delete_object(Bucket=bucket_name, Key=result_done_key) + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-INI-07 - doneファイルが存在したため削除しました') + except Exception as e: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-INI-08 - doneファイルは存在しませんでした') + + try: + # warningファイルの存在確認 + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-INI-09 - warningファイル:{target_file_name}.warning の存在チェック') + result_warning_key = target_data_source + DIRECTORY_TARGET + target_file_name + '.warning' + s3_client.head_object(Bucket=bucket_name, Key=result_warning_key) + s3_client.delete_object(Bucket=bucket_name, Key=result_warning_key) + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-INI-10 - warningファイルが存在したため削除しました') + except Exception as e: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-INI-11 - warningファイルは存在しませんでした') + + try: + # errorファイルの存在確認 + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-INI-12 - errorファイル:{target_file_name}.error の存在チェック') + result_error_key = target_data_source + DIRECTORY_TARGET + target_file_name + '.error' + s3_client.head_object(Bucket=bucket_name, Key=result_error_key) + s3_client.delete_object(Bucket=bucket_name, Key=result_error_key) + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-INI-13 - errorファイルが存在したため削除しました') + except Exception as e: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-INI-14 - errorファイルは存在しませんでした') + + try: + # ⑥ 個別設定マッピングリストが存在するかチェックする + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-INI-15 - 個別設定マッピングリスト:{MAPPING_FILE_NAME} の存在チェック') + mapping_key = target_data_source + DIRECTORY_SETTINGS + MAPPING_FILE_NAME + s3_client.head_object(Bucket=bucket_name, Key=mapping_key) + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-INI-16 - 個別設定マッピングリストの存在を確認しました') + except Exception as e: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["e"]} E-INI-02 - 個別設定マッピングリストが存在しません') + error(bucket_name, target_data_source, target_file_name, log_info) + + try: + # ⑦ 個別設定ファイルを特定する + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-INI-17 - 個別設定ファイルを検索します') + mapping_obj = s3_resource.Object(bucket_name, mapping_key) + mapping_response = mapping_obj.get() + mapping_body = io.TextIOWrapper(io.BytesIO(mapping_response["Body"].read()), encoding='utf-8') + settings_file_name = '' + for row in csv.reader(mapping_body, delimiter='\t'): + if row: + match_result = re.fullmatch(row[0], target_file_name) + if match_result is not None: + settings_file_name = row[1].rstrip() + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-INI-18 - 個別設定ファイル:{settings_file_name} を特定しました') + break + + if not settings_file_name: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["e"]} E-INI-03 - 個別設定ファイルが特定出来ません') + error(bucket_name, target_data_source, target_file_name, log_info) + except Exception as e: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["e"]} E-INI-99 - エラー内容:{e}') + error(bucket_name, target_data_source, target_file_name, log_info) + + try: + # ⑧ ⑦の個別設定ファイルが存在するかチェックする + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-INI-19 - 個別設定ファイル:{settings_file_name} の存在チェック') + settings_key = target_data_source + DIRECTORY_SETTINGS + settings_file_name + s3_client.head_object(Bucket=bucket_name, Key=settings_key) + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-INI-20 - 個別設定ファイルの存在を確認しました') + except Exception as e: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["e"]} E-INI-04 - 個別設定ファイルが存在しません') + error(bucket_name, target_data_source, target_file_name, log_info) + + try: + # ⑨ 初期処理終了ログを出力する + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-INI-21 - 初期処理を終了します') + + return settings_key + except Exception as e: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["e"]} E-INI-99 - エラー内容:{e}') + error(bucket_name, target_data_source, target_file_name, log_info) diff --git a/ecs/Dockerfile/dataimport/main.py b/ecs/Dockerfile/dataimport/main.py new file mode 100644 index 00000000..730a7be8 --- /dev/null +++ b/ecs/Dockerfile/dataimport/main.py @@ -0,0 +1,274 @@ +from datetime import datetime +import boto3 +import pymysql +from pymysql.constants import CLIENT +import io +import csv +from error import error +from common import debug_log + +# 定数 +DIRECTORY_WORK = '/work/' +LOG_LEVEL = {"i": 'Info', "e": 'Error', "w": 'Warning'} +SETTINGS_ITEM = { + 'dataSource': 0, + 'delimiter': 1, + 'charCode': 2, + 'quotechar': 3, + 'lineFeedCode': 4, + 'headerFlag': 5, + 'csvNumItems': 6, + 'csvNameItems': 7, + 'dbColumuName': 8, + 'storageSchemaName': 9, + 'loadSchemaName': 10, + 'exSqlFileName': 11, +} +LINE_FEED_CODE = { + 'CR': '\r', + 'LF': '\n', + 'CRLF': '\r\n', +} +DIRECTORY_SETTINGS = '/settings/' + +# クラス変数 +s3_client = boto3.client('s3') +s3_resource = boto3.resource('s3') + + +def main(bucket_name, target_data_source, target_file_name, settings_key, db_info, log_info, mode): + """メイン処理 + Args: + bucket_name : バケット名 + target_data_source : 投入データのディレクトリ名よりデータソースに該当する部分 + target_file_name : 投入データのファイル名 + settings_key : 投入データに該当する個別設定ファイルのフルパス + db_info : データベース情報 + log_info : ログに記載するデータソース名とファイル名 + mode : 処理モード + Returns: + warning_info : Warning情報 + """ + + try: + debug_log(f'引数 bucket_name : {bucket_name}', log_info, mode) + debug_log(f'引数 target_data_source : {target_data_source}', log_info, mode) + debug_log(f'引数 target_file_name : {target_file_name}', log_info, mode) + debug_log(f'引数 settings_key : {settings_key}', log_info, mode) + debug_log(f'引数 db_info : {db_info}', log_info, mode) + debug_log(f'引数 log_info : {log_info}', log_info, mode) + debug_log(f'引数 mode : {mode}', log_info, mode) + + # ① メイン処理開始ログを出力する + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-MAIN-01 - メイン処理を開始します') + + # ② DB接続を開始する + conn = pymysql.connect(host=db_info["host"], user=db_info["user"], passwd=db_info["pass"], db=db_info["name"], connect_timeout=5, client_flag=CLIENT.MULTI_STATEMENTS) + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-MAIN-02 - DB接続を開始しました') + except Exception as e: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["e"]} E-MAIN-99 - エラー内容:{e}') + error(bucket_name, target_data_source, target_file_name, log_info) + + try: + # ③ タイムゾーンを変更する + with conn.cursor() as cur: + cur.execute(f'SET time_zone = "+9:00"') + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-MAIN-03 - タイムゾーンを変更しました') + + # ④ 個別設定ファイルのロードスキーマのテーブル名に記載されているテーブルをTRUNCATEする + settings_obj = s3_resource.Object(bucket_name, settings_key) + settings_response = settings_obj.get() + settings_list = [] + for line in io.TextIOWrapper(io.BytesIO(settings_response["Body"].read()), encoding='utf-8'): + settings_list.append(line.rstrip('\n')) + + with conn.cursor() as cur: + sql_truncate = f'TRUNCATE table {settings_list[SETTINGS_ITEM["loadSchemaName"]]}' + cur.execute(sql_truncate) + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-MAIN-04 - {settings_list[SETTINGS_ITEM["loadSchemaName"]]} をTRUNCATEしました') + + # ⑤ 投入データファイルを1行ごとにループする + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-MAIN-05 - 投入データ {target_file_name} の読み込みを開始します') + work_key = target_data_source + DIRECTORY_WORK + target_file_name + work_obj = s3_resource.Object(bucket_name, work_key) + work_response = work_obj.get() + work_data = io.TextIOWrapper(io.BytesIO(work_response["Body"].read()), encoding=settings_list[SETTINGS_ITEM["charCode"]], newline=LINE_FEED_CODE[settings_list[SETTINGS_ITEM["lineFeedCode"]]]) + + process_count = 0 # 処理件数カウンタ + normal_count = 0 # 正常終了件数カウンタ + warning_count = 0 # ワーニング終了件数カウンター + warning_info = '' # ワーニング情報 + index = 0 # ループインデックス + settings_db_columu_list = settings_list[SETTINGS_ITEM["dbColumuName"]].rstrip().split(',') + + for line in csv.reader(work_data, quotechar=settings_list[SETTINGS_ITEM["quotechar"]], delimiter=settings_list[SETTINGS_ITEM["delimiter"]]): + try: + if int(settings_list[SETTINGS_ITEM["headerFlag"]]) == True and index == 0: + index += 1 + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-MAIN-06 - ヘッダー行をスキップします') + continue + + # 処理件数カウント + process_count += 1 + + # SQL文生成 + sql = f'INSERT INTO {settings_list[SETTINGS_ITEM["loadSchemaName"]]} (' + for i in range(len(settings_db_columu_list)): + sql = f'{sql} {settings_db_columu_list[i]},' + sql = f'{sql} file_name,' # システム項目:取込ファイル名 + sql = f'{sql} file_row_cnt,' # システム項目:取込ファイル行番号 + sql = f'{sql} delete_flg,' # システム項目:論理削除フラグ + sql = f'{sql} ins_user,' # システム項目:登録者 + sql = f'{sql} ins_date,' # システム項目:登録日時 + sql = f'{sql} upd_user,' # システム項目:更新者 + sql = f'{sql} upd_date)' # システム項目:更新日時 + sql = f'{sql} VALUES (' + for i in range(len(line)): + # データ項目値が0桁より大きいかチェックする + if len(line[i]) > 0: + # 0桁より大きい場合 + replace_line = line[i].replace('\\', '\\\\') + sql = f'{sql} "{replace_line}",' + else: + # 上記以外の場合 + sql = f'{sql} NULL,' + sql = f'{sql} "{target_file_name}",' # システム項目:取込ファイル名 + sql = f'{sql} "{index + 1}",' # システム項目:取込ファイル行番号 + sql = f'{sql} "0",' # システム項目:論理削除フラグ + sql = f'{sql} CURRENT_USER(),' # システム項目:登録者 + sql = f'{sql} CURRENT_TIMESTAMP(),' # システム項目:登録日時 + sql = f'{sql} NULL,' # システム項目:更新者 + sql = f'{sql} NULL)' # システム項目:更新日時 + + index += 1 + + debug_log(sql, log_info, mode) + + # ロードスキーマのトランザクション開始 + with conn.cursor() as cur: + cur.execute(sql) + conn.commit() + normal_count += 1 + except Exception as e: + warning_count += 1 + warning_info = f'{warning_info}{index} ロードスキーマ登録時にエラーが発生しました {line} {e}\n' + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["w"]} W-MAIN-01 {index} ロードスキーマ登録時にエラーが発生しました {line} {e}') + + # ⑥ ⑤の処理結果件数をログ出力する + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-MAIN-07 - 投入データ件数:{process_count} 正常終了件数:{normal_count}') + if warning_info: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["w"]} W-MAIN-02 - Warning終了件数:{warning_count}') + + # ⑦ ロードスキーマのデータを蓄積スキーマにUPSERTする + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-MAIN-08 - ロードスキーマ({settings_list[SETTINGS_ITEM["loadSchemaName"]]})のデータを蓄積スキーマ({settings_list[SETTINGS_ITEM["storageSchemaName"]]})に登録します') + + # SQL文生成 + sql = f'INSERT INTO {settings_list[SETTINGS_ITEM["storageSchemaName"]]} (' + for i in range(len(settings_db_columu_list)): + sql = f'{sql} {settings_db_columu_list[i]},' + sql = f'{sql} file_name,' # システム項目:取込ファイル名 + sql = f'{sql} file_row_cnt,' # システム項目:取込ファイル行番号 + sql = f'{sql} delete_flg,' # システム項目:論理削除フラグ + sql = f'{sql} ins_user,' # システム項目:登録者 + sql = f'{sql} ins_date,' # システム項目:登録日時 + sql = f'{sql} upd_user,' # システム項目:更新者 + sql = f'{sql} upd_date)' # システム項目:更新日時 + sql = f'{sql} SELECT' + for i in range(len(settings_db_columu_list)): + sql = f'{sql} t.{settings_db_columu_list[i]},' + sql = f'{sql} t.file_name,' # システム項目:取込ファイル名 + sql = f'{sql} t.file_row_cnt,' # システム項目:取込ファイル行番号 + sql = f'{sql} t.delete_flg,' # システム項目:論理削除フラグ + sql = f'{sql} t.ins_user,' # システム項目:登録者 + sql = f'{sql} t.ins_date,' # システム項目:登録日時 + sql = f'{sql} t.upd_user,' # システム項目:更新者 + sql = f'{sql} t.upd_date' # システム項目:更新日時 + sql = f'{sql} FROM {settings_list[SETTINGS_ITEM["loadSchemaName"]]} as t' + sql = f'{sql} ON DUPLICATE KEY UPDATE' + for i in range(len(settings_db_columu_list)): + sql = f'{sql} {settings_db_columu_list[i]}=t.{settings_db_columu_list[i]},' + sql = f'{sql} file_name=t.file_name,' # システム項目:取込ファイル名 + sql = f'{sql} file_row_cnt=t.file_row_cnt,' # システム項目:取込ファイル行番号 + sql = f'{sql} delete_flg={settings_list[SETTINGS_ITEM["storageSchemaName"]]}.delete_flg,' # システム項目:論理削除フラグ + sql = f'{sql} ins_user=t.ins_user,' # システム項目:登録者 + sql = f'{sql} ins_date=t.ins_date,' # システム項目:登録日時 + sql = f'{sql} upd_user={settings_list[SETTINGS_ITEM["storageSchemaName"]]}.upd_user,' # システム項目:更新者 + sql = f'{sql} upd_date={settings_list[SETTINGS_ITEM["storageSchemaName"]]}.upd_date' # システム項目:更新日時 + + debug_log(sql, log_info, mode) + + # トランザクション開始 + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-MAIN-09 - 標準SQL:{settings_list[SETTINGS_ITEM["storageSchemaName"]]} のトランザクションを開始します') + with conn.cursor() as cur: + cur.execute(sql) + conn.commit() + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-MAIN-10 - 標準SQL:{settings_list[SETTINGS_ITEM["storageSchemaName"]]} のCOMIIT処理が正常終了しました') + + # ⑧ 個別設定ファイルに拡張SQLファイル名が設定されているかチェック + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-MAIN-11 - 拡張SQL設定が存在するかチェックします') + if settings_list[SETTINGS_ITEM["exSqlFileName"]]: + try: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-MAIN-12 - 拡張SQL設定の存在を確認しました') + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-MAIN-13 - 拡張SQLファイル名:{settings_list[SETTINGS_ITEM["exSqlFileName"]]} の存在チェック') + ex_sql_key = target_data_source + DIRECTORY_SETTINGS + settings_list[SETTINGS_ITEM["exSqlFileName"]] + s3_client.head_object(Bucket=bucket_name, Key=ex_sql_key) + ex_sql_file_exists = True + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-MAIN-14 - 拡張SQLファイル名の存在を確認しました') + except Exception as e: + warning_info = f'{warning_info}- 拡張SQLファイルが存在しません\n' + ex_sql_file_exists = False + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["w"]} W-MAIN-03 - 拡張SQLファイルが存在しません') + + try: + if ex_sql_file_exists: + # 拡張SQLファイルからSQL文生成 + ex_sqls_obj = s3_resource.Object(bucket_name, ex_sql_key) + ex_sql_response = ex_sqls_obj.get() + ex_sql = '' + for line in io.TextIOWrapper(io.BytesIO(ex_sql_response["Body"].read()), encoding='utf-8'): + ex_sql = f'{ex_sql} {line.rstrip()}' + + # トランザクション開始 + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-MAIN-15 - 拡張SQL:{settings_list[SETTINGS_ITEM["storageSchemaName"]]} のトランザクションを開始します') + with conn.cursor() as cur: + cur.execute(ex_sql) + conn.commit() + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-MAIN-16 - 拡張SQL:{settings_list[SETTINGS_ITEM["storageSchemaName"]]} のCOMIIT処理が正常終了しました') + except Exception as e: + warning_info = f'{warning_info}- 拡張SQLにエラーが発生しました:{e}\n' + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["w"]} W-MAIN-04 - 拡張SQLにエラーが発生しました:{e}') + else: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-MAIN-17 - 拡張SQL設定の存在はありませんでした') + + # ⑨ DB接続を終了する + connection_close(conn, bucket_name, target_data_source, target_file_name, log_info) + except Exception as e: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["e"]} E-MAIN-99 - エラー内容:{e}') + connection_close(conn, bucket_name, target_data_source, target_file_name, log_info) + error(bucket_name, target_data_source, target_file_name, log_info) + + try: + # ⑩ メイン処理終了ログを出力する + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-MAIN-19 - メイン処理を終了します') + + return warning_info + except Exception as e: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["e"]} E-MAIN-99 - エラー内容:{e}') + error(bucket_name, target_data_source, target_file_name, log_info) + + +def connection_close(conn, bucket_name, target_data_source, target_file_name, log_info): + """DB接続切断処理 + Args: + conn : DBコネクション + bucket_name : バケット名 + target_data_source : 投入データのディレクトリ名よりデータソースに該当する部分 + target_file_name : 投入データのファイル名 + log_info : ログに記載するデータソース名とファイル名 + """ + try: + conn.close() + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["i"]} I-MAIN-18 - DB接続を終了しました') + except Exception as e: + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} {log_info} {LOG_LEVEL["e"]} E-MAIN-99 - エラー内容:{e}') + error(bucket_name, target_data_source, target_file_name, log_info) diff --git a/ecs/Dockerfile/requirements.txt b/ecs/Dockerfile/requirements.txt new file mode 100644 index 00000000..7253f919 --- /dev/null +++ b/ecs/Dockerfile/requirements.txt @@ -0,0 +1,2 @@ +boto3 +PyMySQL \ No newline at end of file diff --git a/lambda/mbj-newdwh2021-staging-NoticeToSlack/index.js b/lambda/mbj-newdwh2021-staging-NoticeToSlack/index.js new file mode 100644 index 00000000..5c0a7226 --- /dev/null +++ b/lambda/mbj-newdwh2021-staging-NoticeToSlack/index.js @@ -0,0 +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}.` + }); + }) + +}; diff --git a/lambda/mbj-newdwh2021-staging-NoticeToSlack/mbj-newdwh2021-staging-NoticeToSlack.zip b/lambda/mbj-newdwh2021-staging-NoticeToSlack/mbj-newdwh2021-staging-NoticeToSlack.zip new file mode 100644 index 00000000..53f0c160 Binary files /dev/null and b/lambda/mbj-newdwh2021-staging-NoticeToSlack/mbj-newdwh2021-staging-NoticeToSlack.zip differ diff --git a/lambda/mbj-newdwh2021-staging-NoticeToSlack/package.json b/lambda/mbj-newdwh2021-staging-NoticeToSlack/package.json new file mode 100644 index 00000000..1495f188 --- /dev/null +++ b/lambda/mbj-newdwh2021-staging-NoticeToSlack/package.json @@ -0,0 +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" + } +} diff --git a/lambda/mbj-newdwh2021-staging-PublishFromLog/index.js b/lambda/mbj-newdwh2021-staging-PublishFromLog/index.js new file mode 100644 index 00000000..f0b608f8 --- /dev/null +++ b/lambda/mbj-newdwh2021-staging-PublishFromLog/index.js @@ -0,0 +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); + } + }); + } + }); +}; \ No newline at end of file diff --git a/lambda/mbj-newdwh2021-staging-PublishFromLog/mbj-newdwh2021-staging-PublishFromLog.zip b/lambda/mbj-newdwh2021-staging-PublishFromLog/mbj-newdwh2021-staging-PublishFromLog.zip new file mode 100644 index 00000000..6a8526bc Binary files /dev/null and b/lambda/mbj-newdwh2021-staging-PublishFromLog/mbj-newdwh2021-staging-PublishFromLog.zip differ diff --git a/lambda/mbj-newdwh2021-staging-PublishFromLog/package.json b/lambda/mbj-newdwh2021-staging-PublishFromLog/package.json new file mode 100644 index 00000000..1e0d12e7 --- /dev/null +++ b/lambda/mbj-newdwh2021-staging-PublishFromLog/package.json @@ -0,0 +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" + } +} diff --git a/lambda/mbj-newdwh2021-staging-lambda-dataimport.py b/lambda/mbj-newdwh2021-staging-lambda-dataimport.py new file mode 100644 index 00000000..fb79ede5 --- /dev/null +++ b/lambda/mbj-newdwh2021-staging-lambda-dataimport.py @@ -0,0 +1,71 @@ +import os +from datetime import datetime +import boto3 + +# 環境変数 +CLUSTER_NAME = os.environ["CLUSTER_NAME"] +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"] +MODE = os.environ["MODE"] + +# クラス変数 +ecs_client = boto3.client('ecs') + + +def lambda_handler(event, context): + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} Info I-1 駆動処理開始') + + # イベント情報を取得する + s3_event = event["Records"][0]["s3"] + event_bucket_name = s3_event["bucket"]["name"] + event_object_key = s3_event["object"]["key"] + event_file_name = os.path.basename(event_object_key) + event_data_source_name = os.path.dirname(event_object_key).split('/')[0] + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} Info I-2 バケット名:{event_bucket_name}') + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} Info I-3 ファイル名:{event_file_name}') + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} Info I-4 データソース名:{event_data_source_name}') + + # ECSを起動する + response = ecs_client.run_task( + launchType='FARGATE', + cluster=CLUSTER_NAME, + taskDefinition=TASK_NAME, + networkConfiguration={ + "awsvpcConfiguration": { + "subnets": [ + SUBNET_ID_AP_NORTHEAST_1A, + SUBNET_ID_AP_NORTHEAST_1D, + ], + "securityGroups": [ + SECURITY_GROUP_ID_ECRAPI, + SECURITY_GROUP_ID_ECRDKR, + SECURITY_GROUP_ID_LOGS, + SECURITY_GROUP_ID_RDS, + ], + "assignPublicIp": 'ENABLED', + } + }, + overrides={ + "containerOverrides": [ + { + "name": CONTAINER_NAME, + "environment": [ + {"name": 'BUCKET_NAME', "value": event_bucket_name}, + {"name": 'TARGET_KEY', "value": event_object_key}, + {"name": 'DATA_SOURCE_NAME', "value": event_data_source_name}, + {"name": 'FILE_NAME', "value": event_file_name}, + {"name": 'MODE', "value": MODE}, + ], + }, + ], + }, + ) + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} Info I-5 ECS起動レスポンス:{str(response)}') + + print(f'{datetime.now():%Y-%m-%d %H:%M:%S} Info I-6 駆動処理終了')