diff --git a/.gitignore b/.gitignore index 15860e8b..0e397fc3 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,4 @@ lambda/mbj-newdwh2021-staging-PublishFromLog/package-lock.json lambda/mbj-newdwh2021-staging-PublishFromLog/node_modules/* __pycache__/ .env -settings.json \ No newline at end of file +**/.vscode/settings.json diff --git a/ecs/crm-datafetch/.vscode/launch.json b/ecs/crm-datafetch/.vscode/launch.json new file mode 100644 index 00000000..2e39a541 --- /dev/null +++ b/ecs/crm-datafetch/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Current File", + "type": "python", + "request": "launch", + // エントリーポイントのファイルに変更すること + "program": "main.py", + "console": "integratedTerminal", + "justMyCode": true, + // 環境変数が必要な場合に読み込む環境変数ファイル + "envFile": "${workspaceFolder}/.env", + } + ] +} \ No newline at end of file diff --git a/ecs/crm-datafetch/.vscode/recommend_settings.json b/ecs/crm-datafetch/.vscode/recommend_settings.json new file mode 100644 index 00000000..66a8f2b5 --- /dev/null +++ b/ecs/crm-datafetch/.vscode/recommend_settings.json @@ -0,0 +1,16 @@ +{ + "[python]": { + "editor.defaultFormatter": null, + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.organizeImports": true + } + }, + "python.linting.lintOnSave": true, + "python.linting.enabled": true, + "python.linting.pylintEnabled": false, + "python.linting.flake8Enabled": true, + "python.linting.flake8Args": ["--max-line-length=150", "--ignore=F541"], + "python.formatting.provider": "autopep8", + "python.formatting.autopep8Args": ["--max-line-length", "150"] +} diff --git a/ecs/crm-datafetch/Dockerfile b/ecs/crm-datafetch/Dockerfile new file mode 100644 index 00000000..56087bf0 --- /dev/null +++ b/ecs/crm-datafetch/Dockerfile @@ -0,0 +1,19 @@ +FROM python:3.8 + +ENV TZ="Asia/Tokyo" + +WORKDIR /usr/src/app +COPY Pipfile Pipfile.lock ./ +RUN \ + apt update -y && \ + # パッケージのセキュリティアップデートのみを適用するコマンド + apt install -y unattended-upgrades && \ + unattended-upgrades && \ + pip install pipenv --no-cache-dir && \ + pipenv install --system --deploy && \ + pip uninstall -y pipenv virtualenv-clone virtualenv + +COPY main.py ./ +COPY src ./ + +CMD [ "python", "./main.py" ] diff --git a/ecs/crm-datafetch/Pipfile b/ecs/crm-datafetch/Pipfile new file mode 100644 index 00000000..33501d98 --- /dev/null +++ b/ecs/crm-datafetch/Pipfile @@ -0,0 +1,16 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +boto3 = "*" +simple-salesforce = "*" +tenacity = "*" + +[dev-packages] +autopep8 = "*" +flake8 = "*" + +[requires] +python_version = "3.8" diff --git a/ecs/crm-datafetch/Pipfile.lock b/ecs/crm-datafetch/Pipfile.lock new file mode 100644 index 00000000..c8c60540 --- /dev/null +++ b/ecs/crm-datafetch/Pipfile.lock @@ -0,0 +1,419 @@ +{ + "_meta": { + "hash": { + "sha256": "ec1d83143aff859500979be73f67196dcfe2298ad3553a7d81ad0605a277d672" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.8" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "attrs": { + "hashes": [ + "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4", + "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==21.4.0" + }, + "authlib": { + "hashes": [ + "sha256:1286e2d5ef5bfe5a11cc2d0a0d1031f0393f6ce4d61f5121cfe87fa0054e98bd", + "sha256:6e74a4846ac36dfc882b3cc2fbd3d9eb410a627f2f2dc11771276655345223b1" + ], + "version": "==1.0.1" + }, + "boto3": { + "hashes": [ + "sha256:5c775dcb12ca5d6be3f5aa3c49d77783faa64eb30fd3f4af93ff116bb42f9ffb", + "sha256:5d9bcc355cf6edd7f3849fedac4252e12a0aa2b436cdbc0d4371b16a0f852a30" + ], + "index": "pypi", + "version": "==1.24.34" + }, + "botocore": { + "hashes": [ + "sha256:0d824a5315f5f5c3bea53c14107a69695ef43190edf647f1281bac8f172ca77c", + "sha256:9c695d47f1f1212f3e306e51f7bacdf67e58055194ddcf7d8296660b124cf135" + ], + "markers": "python_version >= '3.7'", + "version": "==1.27.34" + }, + "cached-property": { + "hashes": [ + "sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130", + "sha256:df4f613cf7ad9a588cc381aaf4a512d26265ecebd5eb9e1ba12f1319eb85a6a0" + ], + "version": "==1.5.2" + }, + "certifi": { + "hashes": [ + "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d", + "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412" + ], + "markers": "python_version >= '3.6'", + "version": "==2022.6.15" + }, + "cffi": { + "hashes": [ + "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5", + "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef", + "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104", + "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426", + "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405", + "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375", + "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a", + "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e", + "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc", + "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf", + "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185", + "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497", + "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3", + "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35", + "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c", + "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83", + "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21", + "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca", + "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984", + "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac", + "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd", + "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee", + "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a", + "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2", + "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192", + "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7", + "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585", + "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f", + "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e", + "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27", + "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b", + "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e", + "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e", + "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d", + "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c", + "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415", + "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82", + "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02", + "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314", + "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325", + "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c", + "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3", + "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914", + "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045", + "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d", + "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9", + "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5", + "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2", + "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c", + "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3", + "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2", + "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8", + "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d", + "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d", + "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9", + "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162", + "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76", + "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4", + "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e", + "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9", + "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6", + "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b", + "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01", + "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0" + ], + "version": "==1.15.1" + }, + "charset-normalizer": { + "hashes": [ + "sha256:5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5", + "sha256:575e708016ff3a5e3681541cb9d79312c416835686d054a23accb873b254f413" + ], + "markers": "python_version >= '3.6'", + "version": "==2.1.0" + }, + "cryptography": { + "hashes": [ + "sha256:190f82f3e87033821828f60787cfa42bff98404483577b591429ed99bed39d59", + "sha256:2be53f9f5505673eeda5f2736bea736c40f051a739bfae2f92d18aed1eb54596", + "sha256:30788e070800fec9bbcf9faa71ea6d8068f5136f60029759fd8c3efec3c9dcb3", + "sha256:3d41b965b3380f10e4611dbae366f6dc3cefc7c9ac4e8842a806b9672ae9add5", + "sha256:4c590ec31550a724ef893c50f9a97a0c14e9c851c85621c5650d699a7b88f7ab", + "sha256:549153378611c0cca1042f20fd9c5030d37a72f634c9326e225c9f666d472884", + "sha256:63f9c17c0e2474ccbebc9302ce2f07b55b3b3fcb211ded18a42d5764f5c10a82", + "sha256:6bc95ed67b6741b2607298f9ea4932ff157e570ef456ef7ff0ef4884a134cc4b", + "sha256:7099a8d55cd49b737ffc99c17de504f2257e3787e02abe6d1a6d136574873441", + "sha256:75976c217f10d48a8b5a8de3d70c454c249e4b91851f6838a4e48b8f41eb71aa", + "sha256:7bc997818309f56c0038a33b8da5c0bfbb3f1f067f315f9abd6fc07ad359398d", + "sha256:80f49023dd13ba35f7c34072fa17f604d2f19bf0989f292cedf7ab5770b87a0b", + "sha256:91ce48d35f4e3d3f1d83e29ef4a9267246e6a3be51864a5b7d2247d5086fa99a", + "sha256:a958c52505c8adf0d3822703078580d2c0456dd1d27fabfb6f76fe63d2971cd6", + "sha256:b62439d7cd1222f3da897e9a9fe53bbf5c104fff4d60893ad1355d4c14a24157", + "sha256:b7f8dd0d4c1f21759695c05a5ec8536c12f31611541f8904083f3dc582604280", + "sha256:d204833f3c8a33bbe11eda63a54b1aad7aa7456ed769a982f21ec599ba5fa282", + "sha256:e007f052ed10cc316df59bc90fbb7ff7950d7e2919c9757fd42a2b8ecf8a5f67", + "sha256:f2dcb0b3b63afb6df7fd94ec6fbddac81b5492513f7b0436210d390c14d46ee8", + "sha256:f721d1885ecae9078c3f6bbe8a88bc0786b6e749bf32ccec1ef2b18929a05046", + "sha256:f7a6de3e98771e183645181b3627e2563dcde3ce94a9e42a3f427d2255190327", + "sha256:f8c0a6e9e1dd3eb0414ba320f85da6b0dcbd543126e30fcc546e7372a7fbf3b9" + ], + "markers": "python_version >= '3.6'", + "version": "==37.0.4" + }, + "idna": { + "hashes": [ + "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", + "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" + ], + "markers": "python_version >= '3.5'", + "version": "==3.3" + }, + "isodate": { + "hashes": [ + "sha256:0751eece944162659049d35f4f549ed815792b38793f07cf73381c1c87cbed96", + "sha256:48c5881de7e8b0a0d648cb024c8062dc84e7b840ed81e864c7614fd3c127bde9" + ], + "version": "==0.6.1" + }, + "jmespath": { + "hashes": [ + "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980", + "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe" + ], + "markers": "python_version >= '3.7'", + "version": "==1.0.1" + }, + "lxml": { + "hashes": [ + "sha256:04da965dfebb5dac2619cb90fcf93efdb35b3c6994fea58a157a834f2f94b318", + "sha256:0538747a9d7827ce3e16a8fdd201a99e661c7dee3c96c885d8ecba3c35d1032c", + "sha256:0645e934e940107e2fdbe7c5b6fb8ec6232444260752598bc4d09511bd056c0b", + "sha256:079b68f197c796e42aa80b1f739f058dcee796dc725cc9a1be0cdb08fc45b000", + "sha256:0f3f0059891d3254c7b5fb935330d6db38d6519ecd238ca4fce93c234b4a0f73", + "sha256:10d2017f9150248563bb579cd0d07c61c58da85c922b780060dcc9a3aa9f432d", + "sha256:1355755b62c28950f9ce123c7a41460ed9743c699905cbe664a5bcc5c9c7c7fb", + "sha256:13c90064b224e10c14dcdf8086688d3f0e612db53766e7478d7754703295c7c8", + "sha256:1423631e3d51008871299525b541413c9b6c6423593e89f9c4cfbe8460afc0a2", + "sha256:1436cf0063bba7888e43f1ba8d58824f085410ea2025befe81150aceb123e345", + "sha256:1a7c59c6ffd6ef5db362b798f350e24ab2cfa5700d53ac6681918f314a4d3b94", + "sha256:1e1cf47774373777936c5aabad489fef7b1c087dcd1f426b621fda9dcc12994e", + "sha256:206a51077773c6c5d2ce1991327cda719063a47adc02bd703c56a662cdb6c58b", + "sha256:21fb3d24ab430fc538a96e9fbb9b150029914805d551deeac7d7822f64631dfc", + "sha256:27e590352c76156f50f538dbcebd1925317a0f70540f7dc8c97d2931c595783a", + "sha256:287605bede6bd36e930577c5925fcea17cb30453d96a7b4c63c14a257118dbb9", + "sha256:2aaf6a0a6465d39b5ca69688fce82d20088c1838534982996ec46633dc7ad6cc", + "sha256:32a73c53783becdb7eaf75a2a1525ea8e49379fb7248c3eeefb9412123536387", + "sha256:41fb58868b816c202e8881fd0f179a4644ce6e7cbbb248ef0283a34b73ec73bb", + "sha256:4780677767dd52b99f0af1f123bc2c22873d30b474aa0e2fc3fe5e02217687c7", + "sha256:4878e667ebabe9b65e785ac8da4d48886fe81193a84bbe49f12acff8f7a383a4", + "sha256:487c8e61d7acc50b8be82bda8c8d21d20e133c3cbf41bd8ad7eb1aaeb3f07c97", + "sha256:4beea0f31491bc086991b97517b9683e5cfb369205dac0148ef685ac12a20a67", + "sha256:4cfbe42c686f33944e12f45a27d25a492cc0e43e1dc1da5d6a87cbcaf2e95627", + "sha256:4d5bae0a37af799207140652a700f21a85946f107a199bcb06720b13a4f1f0b7", + "sha256:4e285b5f2bf321fc0857b491b5028c5f276ec0c873b985d58d7748ece1d770dd", + "sha256:57e4d637258703d14171b54203fd6822fda218c6c2658a7d30816b10995f29f3", + "sha256:5974895115737a74a00b321e339b9c3f45c20275d226398ae79ac008d908bff7", + "sha256:5ef87fca280fb15342726bd5f980f6faf8b84a5287fcc2d4962ea8af88b35130", + "sha256:603a464c2e67d8a546ddaa206d98e3246e5db05594b97db844c2f0a1af37cf5b", + "sha256:6653071f4f9bac46fbc30f3c7838b0e9063ee335908c5d61fb7a4a86c8fd2036", + "sha256:6ca2264f341dd81e41f3fffecec6e446aa2121e0b8d026fb5130e02de1402785", + "sha256:6d279033bf614953c3fc4a0aa9ac33a21e8044ca72d4fa8b9273fe75359d5cca", + "sha256:6d949f53ad4fc7cf02c44d6678e7ff05ec5f5552b235b9e136bd52e9bf730b91", + "sha256:6daa662aba22ef3258934105be2dd9afa5bb45748f4f702a3b39a5bf53a1f4dc", + "sha256:6eafc048ea3f1b3c136c71a86db393be36b5b3d9c87b1c25204e7d397cee9536", + "sha256:830c88747dce8a3e7525defa68afd742b4580df6aa2fdd6f0855481e3994d391", + "sha256:86e92728ef3fc842c50a5cb1d5ba2bc66db7da08a7af53fb3da79e202d1b2cd3", + "sha256:8caf4d16b31961e964c62194ea3e26a0e9561cdf72eecb1781458b67ec83423d", + "sha256:8d1a92d8e90b286d491e5626af53afef2ba04da33e82e30744795c71880eaa21", + "sha256:8f0a4d179c9a941eb80c3a63cdb495e539e064f8054230844dcf2fcb812b71d3", + "sha256:9232b09f5efee6a495a99ae6824881940d6447debe272ea400c02e3b68aad85d", + "sha256:927a9dd016d6033bc12e0bf5dee1dde140235fc8d0d51099353c76081c03dc29", + "sha256:93e414e3206779ef41e5ff2448067213febf260ba747fc65389a3ddaa3fb8715", + "sha256:98cafc618614d72b02185ac583c6f7796202062c41d2eeecdf07820bad3295ed", + "sha256:9c3a88d20e4fe4a2a4a84bf439a5ac9c9aba400b85244c63a1ab7088f85d9d25", + "sha256:9f36de4cd0c262dd9927886cc2305aa3f2210db437aa4fed3fb4940b8bf4592c", + "sha256:a60f90bba4c37962cbf210f0188ecca87daafdf60271f4c6948606e4dabf8785", + "sha256:a614e4afed58c14254e67862456d212c4dcceebab2eaa44d627c2ca04bf86837", + "sha256:ae06c1e4bc60ee076292e582a7512f304abdf6c70db59b56745cca1684f875a4", + "sha256:b122a188cd292c4d2fcd78d04f863b789ef43aa129b233d7c9004de08693728b", + "sha256:b570da8cd0012f4af9fa76a5635cd31f707473e65a5a335b186069d5c7121ff2", + "sha256:bcaa1c495ce623966d9fc8a187da80082334236a2a1c7e141763ffaf7a405067", + "sha256:bd34f6d1810d9354dc7e35158aa6cc33456be7706df4420819af6ed966e85448", + "sha256:be9eb06489bc975c38706902cbc6888f39e946b81383abc2838d186f0e8b6a9d", + "sha256:c4b2e0559b68455c085fb0f6178e9752c4be3bba104d6e881eb5573b399d1eb2", + "sha256:c62e8dd9754b7debda0c5ba59d34509c4688f853588d75b53c3791983faa96fc", + "sha256:c852b1530083a620cb0de5f3cd6826f19862bafeaf77586f1aef326e49d95f0c", + "sha256:d9fc0bf3ff86c17348dfc5d322f627d78273eba545db865c3cd14b3f19e57fa5", + "sha256:dad7b164905d3e534883281c050180afcf1e230c3d4a54e8038aa5cfcf312b84", + "sha256:e5f66bdf0976ec667fc4594d2812a00b07ed14d1b44259d19a41ae3fff99f2b8", + "sha256:e8f0c9d65da595cfe91713bc1222af9ecabd37971762cb830dea2fc3b3bb2acf", + "sha256:edffbe3c510d8f4bf8640e02ca019e48a9b72357318383ca60e3330c23aaffc7", + "sha256:eea5d6443b093e1545ad0210e6cf27f920482bfcf5c77cdc8596aec73523bb7e", + "sha256:ef72013e20dd5ba86a8ae1aed7f56f31d3374189aa8b433e7b12ad182c0d2dfb", + "sha256:f05251bbc2145349b8d0b77c0d4e5f3b228418807b1ee27cefb11f69ed3d233b", + "sha256:f1be258c4d3dc609e654a1dc59d37b17d7fef05df912c01fc2e15eb43a9735f3", + "sha256:f9ced82717c7ec65a67667bb05865ffe38af0e835cdd78728f1209c8fffe0cad", + "sha256:fe17d10b97fdf58155f858606bddb4e037b805a60ae023c009f760d8361a4eb8", + "sha256:fe749b052bb7233fe5d072fcb549221a8cb1a16725c47c37e42b0b9cb3ff2c3f" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==4.9.1" + }, + "platformdirs": { + "hashes": [ + "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788", + "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19" + ], + "markers": "python_version >= '3.7'", + "version": "==2.5.2" + }, + "pycparser": { + "hashes": [ + "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", + "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206" + ], + "version": "==2.21" + }, + "python-dateutil": { + "hashes": [ + "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", + "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.8.2" + }, + "pytz": { + "hashes": [ + "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7", + "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c" + ], + "version": "==2022.1" + }, + "requests": { + "hashes": [ + "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983", + "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349" + ], + "markers": "python_version >= '3.7' and python_version < '4'", + "version": "==2.28.1" + }, + "requests-file": { + "hashes": [ + "sha256:07d74208d3389d01c38ab89ef403af0cfec63957d53a0081d8eca738d0247d8e", + "sha256:dfe5dae75c12481f68ba353183c53a65e6044c923e64c24b2209f6c7570ca953" + ], + "version": "==1.5.1" + }, + "requests-toolbelt": { + "hashes": [ + "sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f", + "sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0" + ], + "version": "==0.9.1" + }, + "s3transfer": { + "hashes": [ + "sha256:06176b74f3a15f61f1b4f25a1fc29a4429040b7647133a463da8fa5bd28d5ecd", + "sha256:2ed07d3866f523cc561bf4a00fc5535827981b117dd7876f036b0c1aca42c947" + ], + "markers": "python_version >= '3.7'", + "version": "==0.6.0" + }, + "simple-salesforce": { + "hashes": [ + "sha256:15d6943e52252c9cc28e1779803354f2a36c88b72056499e07eb06cd652f149c", + "sha256:7931038081c445e9459ddc014aaf7f540b1131a31596956cb5d7c0e7b7e0c4cb" + ], + "index": "pypi", + "version": "==1.12.1" + }, + "six": { + "hashes": [ + "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", + "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.16.0" + }, + "tenacity": { + "hashes": [ + "sha256:43242a20e3e73291a28bcbcacfd6e000b02d3857a9a9fff56b297a27afdc932f", + "sha256:f78f4ea81b0fabc06728c11dc2a8c01277bfc5181b321a4770471902e3eb844a" + ], + "index": "pypi", + "version": "==8.0.1" + }, + "urllib3": { + "hashes": [ + "sha256:8298d6d56d39be0e3bc13c1c97d133f9b45d797169a0e11cdd0e0489d786f7ec", + "sha256:879ba4d1e89654d9769ce13121e0f94310ea32e8d2f8cf587b77c08bbcdb30d6" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5' and python_version < '4'", + "version": "==1.26.10" + }, + "zeep": { + "hashes": [ + "sha256:5867f2eadd6b028d9751f4155af590d3aaf9280e3a0ed5e15a53343921c956e5", + "sha256:81c491092b71f5b276de8c63dfd452be3f322622c48a54f3a497cf913bdfb2f4" + ], + "markers": "python_version >= '3.6'", + "version": "==4.1.0" + } + }, + "develop": { + "autopep8": { + "hashes": [ + "sha256:44f0932855039d2c15c4510d6df665e4730f2b8582704fa48f9c55bd3e17d979", + "sha256:ed77137193bbac52d029a52c59bec1b0629b5a186c495f1eb21b126ac466083f" + ], + "index": "pypi", + "version": "==1.6.0" + }, + "flake8": { + "hashes": [ + "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d", + "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d" + ], + "index": "pypi", + "version": "==4.0.1" + }, + "mccabe": { + "hashes": [ + "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", + "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" + ], + "version": "==0.6.1" + }, + "pycodestyle": { + "hashes": [ + "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20", + "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.8.0" + }, + "pyflakes": { + "hashes": [ + "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c", + "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.4.0" + }, + "toml": { + "hashes": [ + "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", + "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.10.2" + } + } +} diff --git a/ecs/crm-datafetch/README.md b/ecs/crm-datafetch/README.md new file mode 100644 index 00000000..5a23e966 --- /dev/null +++ b/ecs/crm-datafetch/README.md @@ -0,0 +1,69 @@ +# CRMデータ連携 データ取得処理 ECSタスク + +## 前提事項 + +### ツールのバージョン + +- Python 3.8.x +- PipEnv(Pythonの依存関係管理用モジュール) + +### 開発環境 + +- Visual Studio Code + +## 開発環境構築 + +※下記の操作は基本的にVSCode上で行います。 + +- [ファイル]-[フォルダーを開く]から、当フォルダを選択して開く + +- [Wiki | Pythonの環境構築](https://nds-tyo.backlog.com/alias/wiki/1874930)にて、pyenvの導入まで完了させる + - **pyenvの導入はマストではないが、Pythonのバージョンが前提のバージョンと同一であることを確認して開発を進めてください** + - **確認しながら開発するのは煩わしいため、導入を強く推奨します。** + +- ローカルのPythonでPipEnvをインストールする + + ```sh + pip install pipenv + ``` + +- pipenvの仮想環境と依存パッケージをインストール。このとき、初回実行にはpythonの仮想環境のパスがターミナルに表示されるため、控えておく + + ```sh + # 開発用パッケージも含めてインストール + pipenv install --dev + ``` + +- VSCodeのコマンドパレットを[表示]-[コマンドパレット]から開き、`Python: Select interpreter`を選択して実行する +- Pythonの実行環境を聞かれるため、先に控えたパスと一致するものを選択する + - 出てこない場合、一度VSCodeを閉じて再度開き直す + +- 当フォルダ直下の`.vscode`フォルダ内にある`recommend_settings.json`をコピーし、同フォルダ内に`settings.json`を作成する + +## ローカルでの起動方法 + +- 当フォルダ直下の`.vscode`フォルダ内に`launch.json`を作成する +- 以下のJSONを入力して保存する + + ```json + { + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Current File", + "type": "python", + "request": "launch", + // エントリーポイントのファイルに変更すること + "program": "<エントリーポイントになるファイル>", + "console": "integratedTerminal", + "justMyCode": true, + // 環境変数が必要な場合に読み込む環境変数ファイル + "envFile": "${workspaceFolder}/.env", + } + ] + } + ``` + +- 環境変数が必要な場合、直接設定するか、上記JSONの`"envFile"`に設定されたパスに`.env`ファイルを作成し、環境変数を入力する +- キーボードの「F5」キーを押して起動する + - デバッグモードで実行されるため、適当なところにブレークポイントを置いてデバッグすることができる diff --git a/ecs/crm-datafetch/main.py b/ecs/crm-datafetch/main.py new file mode 100644 index 00000000..dcae9825 --- /dev/null +++ b/ecs/crm-datafetch/main.py @@ -0,0 +1,5 @@ +from src.controller import controller + +"""CRMデータ取得処理のエントリーポイント""" +if __name__ == '__main__': + controller() diff --git a/ecs/crm-datafetch/src/__init__.py b/ecs/crm-datafetch/src/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ecs/crm-datafetch/src/aws/__init__.py b/ecs/crm-datafetch/src/aws/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ecs/crm-datafetch/src/aws/s3.py b/ecs/crm-datafetch/src/aws/s3.py new file mode 100644 index 00000000..d5bd03f0 --- /dev/null +++ b/ecs/crm-datafetch/src/aws/s3.py @@ -0,0 +1,101 @@ +import json + +import boto3 +from src.system_var.constants import (AWS_RESOURCE_S3, S3_CHAR_CODE, + S3_RESPONSE_BODY) +from src.system_var.environments import (CRM_BACKUP_BUCKET, CRM_CONFIG_BUCKET, + CRM_IMPORT_DATA_BACKUP_FOLDER, + CRM_IMPORT_DATA_FOLDER, + IMPORT_DATA_BUCKET, + LAST_FETCH_DATE_FOLDER, + OBJECT_INFO_FILENAME, + OBJECT_INFO_FOLDER, + PROCESS_RESULT_FOLDER, + RESPONSE_JSON_BACKUP_FOLDER) + + +class S3Resource: + def __init__(self, bucket_name: str) -> None: + self.__s3_resource = boto3.resource(AWS_RESOURCE_S3) + self.__s3_bucket = self.__s3_resource.Bucket(bucket_name) + + def get_object(self, object_key: str) -> str: + response = self.__s3_bucket.Object(object_key).get() + body = response[S3_RESPONSE_BODY].read() + return body.decode(S3_CHAR_CODE) + + def put_object(self, object_key: str, data: str) -> None: + s3_object = self.__s3_bucket.Object(object_key) + s3_object.put(Body=data.encode(S3_CHAR_CODE), ContentEncoding=S3_CHAR_CODE) + return + + def copy(self, src_bucket: str, src_key: str, dest_bucket: str, dest_key: str) -> None: + copy_source = {'Bucket': src_bucket, 'Key': src_key} + self.__s3_resource.meta.client.copy(copy_source, dest_bucket, dest_key) + return + + +class ConfigBucket: + __s3_resource: S3Resource = None + + def __init__(self) -> None: + self.__s3_resource = S3Resource(CRM_CONFIG_BUCKET) + + def __str__(self) -> str: + return CRM_CONFIG_BUCKET + + def get_object_info_file(self) -> str: + return self.__s3_resource.get_object(f'{OBJECT_INFO_FOLDER}/{OBJECT_INFO_FILENAME}') + + def get_last_fetch_datetime_file(self, file_path: str) -> str: + return self.__s3_resource.get_object(f'{LAST_FETCH_DATE_FOLDER}/{file_path}') + + def put_last_fetch_datetime_file(self, file_path: str, data: str) -> None: + self.__s3_resource.put_object( + f'{LAST_FETCH_DATE_FOLDER}/{file_path}', data) + return + + +class DataBucket: + __s3_resource: S3Resource = None + + def __init__(self) -> None: + self.__s3_resource = S3Resource(IMPORT_DATA_BUCKET) + + def __str__(self) -> str: + return IMPORT_DATA_BUCKET + + def put_csv(self, file_path: str, data: str) -> None: + object_key = f'{CRM_IMPORT_DATA_FOLDER}/{file_path}' + self.__s3_resource.put_object(object_key, data) + return + + def put_csv_from(self, src_bucket: str, src_key: str): + dest_filename = src_key.split('/')[-1] + self.__s3_resource.copy(src_bucket, src_key, str(self), f'{CRM_IMPORT_DATA_FOLDER}/{dest_filename}') + return + + +class BackupBucket: + __s3_resource: S3Resource = None + + def __init__(self) -> None: + self.__s3_resource = S3Resource(CRM_BACKUP_BUCKET) + + def __str__(self) -> str: + return CRM_BACKUP_BUCKET + + def put_response_json(self, file_path: str, data: dict) -> None: + object_key = f'{RESPONSE_JSON_BACKUP_FOLDER}/{file_path}' + self.__s3_resource.put_object(object_key, json.dumps(data)) + return + + def put_csv(self, file_path: str, data: str) -> None: + object_key = f'{CRM_IMPORT_DATA_BACKUP_FOLDER}/{file_path}' + self.__s3_resource.put_object(object_key, data) + return + + def put_result_json(self, file_path: str, data: dict) -> None: + object_key = f'{PROCESS_RESULT_FOLDER}/{file_path}' + self.__s3_resource.put_object(object_key, json.dumps(data)) + return diff --git a/ecs/crm-datafetch/src/backup_crm_csv_data_process.py b/ecs/crm-datafetch/src/backup_crm_csv_data_process.py new file mode 100644 index 00000000..ba7bb8ea --- /dev/null +++ b/ecs/crm-datafetch/src/backup_crm_csv_data_process.py @@ -0,0 +1,47 @@ +from src.aws.s3 import BackupBucket +from src.config.objects import TargetObject +from src.error.exceptions import FileUploadException +from src.system_var.constants import CSVBK_JP_NAME +from src.util.execute_datetime import ExecuteDateTime +from src.util.logger import logger_instance as logger + + +def backup_crm_csv_data_process(target_object: TargetObject, execute_datetime: ExecuteDateTime, csv_string: str): + """CSVバックアップ処理 + + Args: + target_object (TargetObject): 取得対象オブジェクト情報インスタンス + execute_datetime (ExecuteDateTime): 実行日次取得インスタンス + csv_string (str): csvデータ + + Raises: + FileUploadException: S3のファイルアップロード失敗 + """ + + # ① CSVバックアップ処理の開始ログを出力する + target_object_name = target_object.object_name + upload_file_name = target_object.upload_file_name + + logger.info( + f'I-CSVBK-01 [{target_object_name}] のCSVデータのバックアップ処理を開始します ファイル名:[{upload_file_name}.csv]') + + try: + # ② CRMバックアップ保管用バケットに、変換後のCSVデータのバックアップを保管する + backup_bucket = BackupBucket() + backup_bucket.put_csv( + f'{execute_datetime.to_path()}/{upload_file_name}.csv', csv_string) + + logger.debug( + f'D-CSVBK-02 [{target_object_name}] のCSVデータバックアップ 正常終了') + + except Exception as e: + raise FileUploadException( + 'E-CSVBK-01', + CSVBK_JP_NAME, f'[{target_object_name}] CSVデータのバックアップに失敗しました ファイル名:[{upload_file_name}.csv] エラー内容:[{e}]') + + # ③ CSVバックアップ処理の終了ログを出力する + logger.info( + f'I-CSVBK-03 [{target_object_name}] のCSVデータのバックアップ処理を終了します') + + # ④ 次の処理へ移行する + return diff --git a/ecs/crm-datafetch/src/backup_crm_data_process.py b/ecs/crm-datafetch/src/backup_crm_data_process.py new file mode 100644 index 00000000..0375d927 --- /dev/null +++ b/ecs/crm-datafetch/src/backup_crm_data_process.py @@ -0,0 +1,40 @@ +from src.aws.s3 import BackupBucket +from src.error.exceptions import FileUploadException +from src.system_var.constants import RESBK_JP_NAME +from src.util.execute_datetime import ExecuteDateTime +from src.util.logger import logger_instance as logger + + +def backup_crm_data_process(object_name: str, sf_object_dict: dict, execute_datetime: ExecuteDateTime): + """CRM電文データバックアップ処理 + + Args: + object_name (str): 取得対象オブジェクト名 + sf_object_dict (dict): Salesforceオブジェクトデータ + execute_datetime (ExecuteDateTime): 実行日次取得インスタンス + + Raises: + FileUploadException: S3のファイルアップロード失敗 + """ + + # ① CRM電文データバックアップ処理の開始ログを出力する + logger.info(f'I-RESBK-01 [{object_name}] のCRM電文データバックアップ処理を開始します') + + try: + # ② CRMバックアップ保管用バケットに、CRMから取得したJSONの電文データのバックアップを保管する + file_name = f'{execute_datetime.to_path()}/{object_name}.json' + + backup_bucket = BackupBucket() + backup_bucket.put_response_json(file_name, sf_object_dict) + + logger.debug(f'D-RESBK-02 [{object_name}] のJSONデータバックアップ 正常終了') + + except Exception as e: + raise FileUploadException( + 'E-RESBK-01', RESBK_JP_NAME, f'[{object_name}] 電文データのバックアップに失敗しました ファイル名:[{object_name}.json] エラー内容:[{e}]') + + # ③ CRM電文データバックアップ処理の終了ログを出力する + logger.info(f'I-RESBK-03 [{object_name}] のCRM電文データバックアップ処理を終了します') + + # ④ 次の処理へ移行する + return diff --git a/ecs/crm-datafetch/src/check_object_info_process.py b/ecs/crm-datafetch/src/check_object_info_process.py new file mode 100644 index 00000000..84f0db40 --- /dev/null +++ b/ecs/crm-datafetch/src/check_object_info_process.py @@ -0,0 +1,37 @@ +from src.config.objects import TargetObject +from src.error.exceptions import InvalidConfigException +from src.system_var.constants import CHK_JP_NAME +from src.util.execute_datetime import ExecuteDateTime +from src.util.logger import logger_instance as logger + + +def check_object_info_process(object_info: dict, execute_datetime: ExecuteDateTime): + """オブジェクト情報形式チェック処理 + + Args: + object_info (dict): 取得対象オブジェクト情報 + execute_datetime (ExecuteDateTime): 実行日次取得インスタンス + + Raises: + InvalidConfigException: オブジェクト情報定義が不正だった場合 + + Returns: + target_object: 取得対象オブジェクト情報インスタンス + """ + + # ① オブジェクト情報形式チェック処理開始ログを出力する + logger.info('I-CHK-01 オブジェクト情報形式チェック処理を開始します') + + try: + # ② オブジェクト情報形式チェック + target_object = TargetObject(object_info, execute_datetime) + + except Exception as e: + raise InvalidConfigException( + 'E-CHK-01', CHK_JP_NAME, f'オブジェクト情報形式チェック処理が失敗しました エラー内容:[{e}]') + + # ③ チェック処理終了ログを出力する + logger.info('I-CHK-02 オブジェクト情報形式チェック処理を終了します') + + # ④ 次の処理へ移行する + return target_object diff --git a/ecs/crm-datafetch/src/config/__init__.py b/ecs/crm-datafetch/src/config/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ecs/crm-datafetch/src/config/objects.py b/ecs/crm-datafetch/src/config/objects.py new file mode 100644 index 00000000..41ca753b --- /dev/null +++ b/ecs/crm-datafetch/src/config/objects.py @@ -0,0 +1,139 @@ +from src.system_var.constants import (COLUMNS_KEY, COLUMNS_TYPE, + DATE_PATTERN_YYYYMMDDTHHMMSSTZ, + DATETIME_COLUMN_DEFAULT_VALUE, + DATETIME_COLUMN_KEY, + DATETIME_COLUMN_TYPE, IS_SKIP_KEY, + IS_SKIP_TYPE, + IS_UPDATE_LAST_FETCH_DATETIME_KEY, + IS_UPDATE_LAST_FETCH_DATETIME_TYPE, + LAST_FETCH_DATETIME_FILE_NAME_KEY, + LAST_FETCH_DATETIME_FILE_NAME_TYPE, + LAST_FETCH_DATETIME_FROM_KEY, + LAST_FETCH_DATETIME_TO_KEY, + OBJECT_NAME_KEY, OBJECT_NAME_TYPE, + OBJECTS_KEY, OBJECTS_TYPE, + UPLOAD_FILE_NAME_KEY, + UPLOAD_FILE_NAME_TYPE) +from src.util.dict_checker import DictChecker +from src.util.execute_datetime import ExecuteDateTime + + +class FetchTargetObjects(): + def __init__(self, object_info_file_dict) -> None: + self.__objects = object_info_file_dict + self.__dict_checker = DictChecker(self.__objects) + self.validate() + self.__i = 0 + + def __iter__(self): + return self + + def __next__(self): + if self.__i == len(self.__objects[OBJECTS_KEY]): + raise StopIteration() + value = self.__objects[OBJECTS_KEY][self.__i] + self.__i += 1 + return value + + def validate(self) -> None: + self.__dict_checker.assert_key_exist(OBJECTS_KEY) + self.__dict_checker.assert_data_type(OBJECTS_KEY, OBJECTS_TYPE) + + +class TargetObject(): + def __init__(self, object_info, execute_datetime: ExecuteDateTime) -> None: + self.__dict_checker = DictChecker(object_info) + self.__object_info = object_info + self.__execute_datetime = execute_datetime + self.__validate() + + def __validate(self) -> None: + self.__validate_required_properties() + self.__validate_optional_properties() + + return + + def __validate_required_properties(self) -> None: + self.__dict_checker.assert_key_exist(OBJECT_NAME_KEY) + self.__dict_checker.assert_data_type(OBJECT_NAME_KEY, OBJECT_NAME_TYPE) + self.__dict_checker.assert_key_exist(COLUMNS_KEY) + self.__dict_checker.assert_data_type(COLUMNS_KEY, COLUMNS_TYPE) + + return + + def __validate_optional_properties(self) -> None: + if self.__dict_checker.check_key_exist(IS_SKIP_KEY): + self.__dict_checker.assert_data_type(IS_SKIP_KEY, IS_SKIP_TYPE) + + if self.__dict_checker.check_key_exist(IS_UPDATE_LAST_FETCH_DATETIME_KEY): + self.__dict_checker.assert_data_type(IS_UPDATE_LAST_FETCH_DATETIME_KEY, IS_UPDATE_LAST_FETCH_DATETIME_TYPE) + + if self.__dict_checker.check_key_exist(LAST_FETCH_DATETIME_FILE_NAME_KEY): + self.__dict_checker.assert_data_type(LAST_FETCH_DATETIME_FILE_NAME_KEY, LAST_FETCH_DATETIME_FILE_NAME_TYPE) + + if self.__dict_checker.check_key_exist(UPLOAD_FILE_NAME_KEY): + self.__dict_checker.assert_data_type(UPLOAD_FILE_NAME_KEY, UPLOAD_FILE_NAME_TYPE) + + if self.__dict_checker.check_key_exist(DATETIME_COLUMN_KEY): + self.__dict_checker.assert_data_type(DATETIME_COLUMN_KEY, DATETIME_COLUMN_TYPE) + + return + + @property + def object_name(self) -> str: + return self.__object_info[OBJECT_NAME_KEY] + + @property + def columns(self) -> list: + return self.__object_info[COLUMNS_KEY] + + @property + def is_skip(self) -> bool: + return self.__object_info[IS_SKIP_KEY] if self.__dict_checker.check_key_exist(IS_SKIP_KEY) else False + + @property + def is_update_last_fetch_datetime(self) -> bool: + if self.__dict_checker.check_key_exist(IS_UPDATE_LAST_FETCH_DATETIME_KEY): + return self.__object_info[IS_UPDATE_LAST_FETCH_DATETIME_KEY] + return False + + @property + def last_fetch_datetime_file_name(self) -> str: + if self.__dict_checker.check_key_exist(LAST_FETCH_DATETIME_FILE_NAME_KEY): + return self.__object_info[LAST_FETCH_DATETIME_FILE_NAME_KEY] + return f'{self.__object_info[OBJECT_NAME_KEY]}.json' + + @property + def upload_file_name(self) -> str: + if self.__dict_checker.check_key_exist(UPLOAD_FILE_NAME_KEY): + return self.__object_info[UPLOAD_FILE_NAME_KEY].format(execute_datetime=self.__execute_datetime.format_date()) + return f'{self.__object_info[OBJECT_NAME_KEY]}_{self.__execute_datetime.format_date()}' + + @property + def datetime_column(self) -> str: + return self.__object_info[DATETIME_COLUMN_KEY] if self.__dict_checker.check_key_exist(DATETIME_COLUMN_KEY) else DATETIME_COLUMN_DEFAULT_VALUE + + +class LastFetchDatetime(): + def __init__(self, last_fetch_datetime_file_dict, execute_datetime) -> None: + self.__dict_checker = DictChecker(last_fetch_datetime_file_dict) + self.__execute_datetime = execute_datetime + self.__last_fetch_datetime_file_dict = last_fetch_datetime_file_dict + self.__validate() + + def __validate(self) -> None: + if self.__dict_checker.check_key_exist(LAST_FETCH_DATETIME_FROM_KEY): + self.__dict_checker.assert_match_pattern(LAST_FETCH_DATETIME_FROM_KEY, DATE_PATTERN_YYYYMMDDTHHMMSSTZ) + if self.__dict_checker.check_key_exist(LAST_FETCH_DATETIME_TO_KEY): + self.__dict_checker.assert_match_pattern(LAST_FETCH_DATETIME_TO_KEY, DATE_PATTERN_YYYYMMDDTHHMMSSTZ) + return + + @property + def last_fetch_datetime_from(self) -> str: + return self.__last_fetch_datetime_file_dict[LAST_FETCH_DATETIME_FROM_KEY] + + @property + def last_fetch_datetime_to(self) -> str: + if self.__dict_checker.check_key_exist(LAST_FETCH_DATETIME_TO_KEY): + return self.__last_fetch_datetime_file_dict[LAST_FETCH_DATETIME_TO_KEY] + return self.__execute_datetime diff --git a/ecs/crm-datafetch/src/controller.py b/ecs/crm-datafetch/src/controller.py new file mode 100644 index 00000000..3d0537b4 --- /dev/null +++ b/ecs/crm-datafetch/src/controller.py @@ -0,0 +1,176 @@ +import gc + +from src.backup_crm_csv_data_process import backup_crm_csv_data_process +from src.backup_crm_data_process import backup_crm_data_process +from src.check_object_info_process import check_object_info_process +from src.config.objects import FetchTargetObjects +from src.convert_crm_csv_data_process import convert_crm_csv_data_process +from src.copy_crm_csv_data_process import copy_crm_csv_data_process +from src.error.exceptions import MeDaCaCRMDataFetchException +from src.fetch_crm_data_process import fetch_crm_data_process +from src.prepare_data_fetch_process import prepare_data_fetch_process +from src.set_datetime_period_process import set_datetime_period_process +from src.system_var.constants import OBJECT_NAME_KEY +from src.upload_last_fetch_datetime_process import \ + upload_last_fetch_datetime_process +from src.upload_result_data_process import upload_result_data_process +from src.util.execute_datetime import ExecuteDateTime +from src.util.logger import logger_instance as logger + + +def controller() -> None: + """コントロール処理""" + + try: + # ① CRMデータ取得処理開始ログを出力する + logger.info('I-CTRL-01 CRMデータ取得処理を開始します') + + # ② データ取得準備処理を呼び出す + logger.info('I-CTRL-02 データ取得準備処理呼び出し') + + fetch_target_objects, execute_datetime, process_result = prepare_data_fetch_process() + + # ③ object_infoのobjectsキーの値の件数分ループする + logger.info('I-CTRL-03 取得対象オブジェクトのループ処理開始') + + process_result = fetch_crm_data(fetch_target_objects, execute_datetime, process_result) + + # ④ すべてのオブジェクトの処理が完了したことと、オブジェクト毎の処理結果をログに出力する + logger.info(f'I-CTRL-17 すべてのオブジェクトの処理が終了しました 実行結果:[{process_result}]') + + # ⑤ 取得処理実施結果アップロード処理を呼び出す + logger.info('I-CTRL-18 CRM_取得処理実施結果ファイルアップロード処理開始') + upload_result_data_process(process_result, execute_datetime) + + # ⑥ 最終結果をチェックし、チェック結果をログに出力 + if not all([v == 'success' for v in process_result.values()]): + logger.error('E-CTRL-01 一部のデータ取得に失敗しています 詳細はログをご確認ください') + else: + logger.info('I-CTRL-19 すべてのデータの取得に成功しました') + + # ⑦ CRMデータ取得処理終了ログを出力する + logger.info('I-CTRL-20 CRMデータ取得処理を終了します') + + return exit(0) + + except MeDaCaCRMDataFetchException as e: + logger.error(f'E-ERR-01 [{e.func_name}]でエラーが発生したため、処理を終了します') + logger.exception(f'{e.error_id} {e}') + return exit(0) + + except Exception as e: + logger.exception('E-ERR-02 予期せぬエラーが発生したため、処理を終了します', e) + return exit(0) + + +def fetch_crm_data(fetch_target_objects: FetchTargetObjects, execute_datetime: ExecuteDateTime, process_result: dict): + """取得対象オブジェクト情報をループし、1オブジェクトごとのデータを取得する + + Args: + fetch_target_objects (FetchTargetObjects): CRMオブジェクト情報インスタンス + execute_datetime (ExecuteDateTime): 実行日次取得インスタンス + process_result (dict): 取得処理実行結果辞書オブジェクト + + Returns: + process_result: 取得処理実行結果辞書オブジェクト + """ + + for object_info in fetch_target_objects: + try: + process_result[object_info.get(OBJECT_NAME_KEY)] = 'fail' + + fetch_crm_data_per_object(object_info, execute_datetime) + + process_result[object_info.get(OBJECT_NAME_KEY)] = 'success' + + except MeDaCaCRMDataFetchException as e: + logger.info(f'{e.error_id} {e}') + logger.info( + f'I-ERR-03 [{object_info.get(OBJECT_NAME_KEY)}] の[{e.func_name}]でエラーが発生しました 次のオブジェクトの処理に移行します', exc_info=True) + continue + + except Exception as e: + logger.info( + f'I-ERR-04 [{object_info.get(OBJECT_NAME_KEY)}] の処理中に予期せぬエラーが発生しました 次のオブジェクトの処理に移行します', e, exc_info=True) + continue + + return process_result + + +def fetch_crm_data_per_object(object_info: dict, execute_datetime: ExecuteDateTime) -> None: + """オブジェクトごとにCRMのデータを取得し、取込フォルダにアップロードする + + Args: + object_info (dict): 取得対象オブジェクト情報 + execute_datetime (ExecuteDateTime): 実行日次取得インスタンス + """ + + # 1. オブジェクト処理結果の初期化 + logger.debug(f'D-CTRL-04 対象のオブジェクト情報を出力します オブジェクト情報:[{object_info}]') + + # 2. オブジェクト情報形式チェック処理を呼び出す + logger.info('I-CTRL-05 オブジェクト情報形式チェック処理呼び出し') + + target_object = check_object_info_process(object_info, execute_datetime) + target_object_name = target_object.object_name + + # 3. 処理対象のオブジェクト名をログ出力する + logger.info( + f'I-CTRL-06 [{target_object_name}]のデータ取得を開始します') + + # 4. オブジェクト情報.is_skipがTrueの場合、次のオブジェクトの処理に移行する + if target_object.is_skip is True: + logger.info( + f'I-CTRL-07 [{target_object_name}]のデータ取得処理をスキップします') + return + + # 5. データ取得期間設定処理を呼び出す + logger.info( + f'I-CTRL-08 [{target_object_name}]のデータ取得期間設定処理呼び出し') + + last_fetch_datetime = set_datetime_period_process(target_object, execute_datetime) + + # 6. CRMデータ取得処理を呼び出す + logger.info( + f'I-CTRL-09 [{target_object_name}]のデータ取得処理呼び出し') + + crm_data_response = fetch_crm_data_process(target_object, last_fetch_datetime) + + # 7. 出力ファイル名をログ出力する + logger.info( + f'I-CTRL-10 [{target_object_name}] の出力ファイル名は [{target_object.upload_file_name}] となります') + + # 8. CRM電文データバックアップ処理を呼び出す + logger.info( + f'I-CTRL-11 [{target_object_name}] CRM電文データバックアップ処理呼び出し') + backup_crm_data_process(target_object_name, crm_data_response, execute_datetime) + + # 9. CSV変換処理を呼び出す + logger.info( + f'I-CTRL-12 [{target_object.object_name}] CSV変換処理呼び出し') + csv_string = convert_crm_csv_data_process(target_object, crm_data_response) + + # 10. CSVバックアップ処理を呼び出す + logger.info( + f'I-CTRL-13 [{target_object_name}] CSVデータバックアップ処理呼び出し') + backup_crm_csv_data_process(target_object, execute_datetime, csv_string) + + # 11. CSVアップロード処理を呼び出す + logger.info( + f'I-CTRL-14 [{target_object_name}] CSVデータアップロード処理呼び出し') + copy_crm_csv_data_process(target_object, execute_datetime) + + # 12. メモリ解放 + del crm_data_response + del csv_string + gc.collect() + + # 13. 前回取得日時ファイル更新処理を呼びだす + logger.info( + f'I-CTRL-15 [{target_object_name}] 前回取得日時ファイル更新処理呼び出し') + upload_last_fetch_datetime_process(target_object, last_fetch_datetime) + + # 14. オブジェクトのアップロードが完了した旨をログに出力する + logger.info(f'I-CTRL-16 [{target_object_name}] 処理正常終了') + + return diff --git a/ecs/crm-datafetch/src/convert_crm_csv_data_process.py b/ecs/crm-datafetch/src/convert_crm_csv_data_process.py new file mode 100644 index 00000000..fd6138b1 --- /dev/null +++ b/ecs/crm-datafetch/src/convert_crm_csv_data_process.py @@ -0,0 +1,42 @@ +from src.config.objects import TargetObject +from src.converter.converter import CSVStringConverter +from src.error.exceptions import DataConvertException +from src.system_var.constants import CONV_JP_NAME +from src.util.logger import logger_instance as logger + + +def convert_crm_csv_data_process(target_object: TargetObject, crm_data_response: dict): + """CSV変換処理 + + Args: + target_object (TargetObject): 取得対象オブジェクト情報インスタンス + crm_data_response (dict): Salesforceオブジェクトデータ + + Raises: + DataConvertException: データ変換が失敗した場合 + + Returns: + csv_string: csvデータ + """ + + # ① CSV変換処理の開始ログを出力する + target_object_name = target_object.object_name + + logger.info(f'I-CONV-01 [{target_object_name}] のCSV変換処理を開始します') + + try: + # ② CSV変換 + csv_string_converter = CSVStringConverter(target_object, crm_data_response) + csv_string = csv_string_converter.convert() + + logger.debug(f'D-CONV-02 [{target_object_name}] のCSV変換処理 正常終了') + + except Exception as e: + raise DataConvertException( + 'E-CONV-01', CONV_JP_NAME, f'[{target_object_name}] CSV変換に失敗しました エラー内容:[{e}]') + + # ③ CSV変換処理の終了ログを出力する + logger.info(f'I-CONV-03 [{target_object_name}] のCSV変換処理を終了します') + + # ④ 次の処理へ移行する + return csv_string diff --git a/ecs/crm-datafetch/src/converter/__init__.py b/ecs/crm-datafetch/src/converter/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ecs/crm-datafetch/src/converter/convert_strategy.py b/ecs/crm-datafetch/src/converter/convert_strategy.py new file mode 100644 index 00000000..8664d7cd --- /dev/null +++ b/ecs/crm-datafetch/src/converter/convert_strategy.py @@ -0,0 +1,63 @@ +import re +from datetime import datetime + +from dateutil.tz import gettz +from src.system_var.constants import (CRM_DATETIME_FORMAT, CSV_FALSE_VALUE, + CSV_TRUE_VALUE, + DATE_PATTERN_YYYYMMDDHHMMSSFFF_UTC, + YYYYMMDDHHMMSS) +from src.system_var.environments import CONVERT_TZ + + +class ConvertStrategyFactory: + def __init__(self) -> None: + self.__none_value_convert_strategy = NoneValueConvertStrategy() + self.__float_convert_strategy = FloatConvertStrategy() + self.__boolean_convert_strategy = BooleanConvertStrategy() + self.__datetime_convert_strategy = DatetimeConvertStrategy() + self.__non_convert_strategy = NonConvertStrategy() + + def create(self, value): + + if value is None: + convert_strategy = self.__none_value_convert_strategy + + elif type(value) == float: + convert_strategy = self.__float_convert_strategy + + elif type(value) == bool: + convert_strategy = self.__boolean_convert_strategy + + elif type(value) == str and re.fullmatch(DATE_PATTERN_YYYYMMDDHHMMSSFFF_UTC, value): + convert_strategy = self.__datetime_convert_strategy + + else: + convert_strategy = self.__non_convert_strategy + + return convert_strategy + + +class NoneValueConvertStrategy: + def convert_value(self, convert_value: None) -> str: + return '' + + +class BooleanConvertStrategy: + def convert_value(self, convert_value: str) -> bool: + return CSV_TRUE_VALUE if convert_value is True else CSV_FALSE_VALUE + + +class DatetimeConvertStrategy: + def convert_value(self, convert_value: str) -> str: + # データ登録処理がJSTとして登録するため、変換処理内で事前にJSTの日時文字列に変換する + return datetime.strptime(convert_value, CRM_DATETIME_FORMAT).astimezone(gettz(CONVERT_TZ)).strftime(YYYYMMDDHHMMSS) + + +class FloatConvertStrategy: + def convert_value(self, convert_value: str) -> int: + return int(convert_value) + + +class NonConvertStrategy: + def convert_value(self, convert_value: str): + return convert_value diff --git a/ecs/crm-datafetch/src/converter/converter.py b/ecs/crm-datafetch/src/converter/converter.py new file mode 100644 index 00000000..761f550e --- /dev/null +++ b/ecs/crm-datafetch/src/converter/converter.py @@ -0,0 +1,79 @@ +import csv +import io + +from src.config.objects import TargetObject +from src.converter.convert_strategy import ConvertStrategyFactory + + +class CSVStringConverter: + def __init__(self, target_object: TargetObject, sf_object_jsons: dict) -> None: + self.__target_object = target_object + self.__sf_object_jsons = sf_object_jsons + self.__convert_strategy_factory = ConvertStrategyFactory() + + def convert(self) -> str: + extracted_sf_object_jsons = self.__extract_sf_object_jsons() + csv_data = self.__convert_to_csv(extracted_sf_object_jsons) + csv_string = self.__write_csv_string(csv_data) + return csv_string + + def __extract_sf_object_jsons(self) -> list: + try: + extracted_sf_object_jsons = [] + for sf_object_json in self.__sf_object_jsons: + extracted_sf_object_jsons.append( + self.__extract_necessary_props_from(sf_object_json)) + + return extracted_sf_object_jsons + + except Exception as e: + raise Exception('必要なjsonのデータ抽出に失敗しました', e) + + def __extract_necessary_props_from(self, sf_object_json) -> dict: + try: + clone_sf_object = {**sf_object_json} + + del clone_sf_object['attributes'] + + uppercase_key_sf_object = { + k.upper(): v for k, v in clone_sf_object.items()} + + return uppercase_key_sf_object + + except Exception as e: + raise Exception('必要なjsonのデータ成形に失敗しました', e) + + def __convert_to_csv(self, extracted_sf_object_jsons) -> list: + try: + columns = self.__target_object.columns + csv_data = [] + for i, json_object in enumerate(extracted_sf_object_jsons, 1): + csv_row = [] + for column in columns: + v = json_object[column.upper()] + + convert_strategy = self.__convert_strategy_factory.create(v) + converted_value = convert_strategy.convert_value(v) + + csv_row.append(converted_value) + + csv_data.append(csv_row) + return csv_data + + except Exception as e: + raise Exception( + f'CSV変換に失敗しました カラム名:[{column}] 行番号: [{i}] エラー内容:[{e}]') + + def __write_csv_string(self, csv_data) -> str: + try: + with io.StringIO(newline='') as string_stream: + writer = csv.writer(string_stream, delimiter=',', lineterminator='\r\n', + doublequote=True, quotechar='"', quoting=csv.QUOTE_ALL, strict=True) + writer.writerow(self.__target_object.columns) + writer.writerows(csv_data) + csv_value = string_stream.getvalue() + + return csv_value + + except Exception as e: + raise Exception('csvデータの取得に失敗しました', e) diff --git a/ecs/crm-datafetch/src/copy_crm_csv_data_process.py b/ecs/crm-datafetch/src/copy_crm_csv_data_process.py new file mode 100644 index 00000000..ba2831ea --- /dev/null +++ b/ecs/crm-datafetch/src/copy_crm_csv_data_process.py @@ -0,0 +1,46 @@ +from src.aws.s3 import BackupBucket, DataBucket +from src.config.objects import TargetObject +from src.error.exceptions import FileUploadException +from src.system_var.constants import UPLD_JP_NAME +from src.system_var.environments import CRM_IMPORT_DATA_BACKUP_FOLDER +from src.util.execute_datetime import ExecuteDateTime +from src.util.logger import logger_instance as logger + + +def copy_crm_csv_data_process(target_object: TargetObject, execute_datetime: ExecuteDateTime): + """CSVアップロード処理 + + Args: + target_object (TargetObject): 取得対象オブジェクト情報インスタンス + execute_datetime (ExecuteDateTime): 実行日次取得インスタンス + + Raises: + FileUploadException: S3のファイルアップロード失敗 + """ + + # ① CSVデータアップロード処理の開始ログを出力する + target_object_name = target_object.object_name + upload_file_name = target_object.upload_file_name + + logger.info( + f'I-UPLD-01 [{target_object_name}] のCSVデータアップロード処理を開始します ファイル名:[{upload_file_name}.csv]') + + try: + # ② CRMバックアップ保管用バケットに保管した変換後のCSVデータをデータ取込バケットにコピーする + data_bucket = DataBucket() + backup_bucket = BackupBucket() + data_bucket.put_csv_from(str(backup_bucket), f'{CRM_IMPORT_DATA_BACKUP_FOLDER}/{execute_datetime.to_path()}/{upload_file_name}.csv') + + logger.debug( + f'D-UPLD-02 [{target_object_name}] のCSVデータアップロード 正常終了') + + except Exception as e: + raise FileUploadException( + 'E-UPLD-01', UPLD_JP_NAME, f'[{target_object_name}] CSVデータのアップロードに失敗しました ファイル名:[{upload_file_name}.csv] エラー内容:[{e}]') + + # ③ CSVデータアップロード処理の終了ログを出力する + logger.info( + f'I-UPLD-03 [{target_object_name}] のCSVデータのアップロード処理を終了します') + + # ④ 次の処理へ移行する + return diff --git a/ecs/crm-datafetch/src/error/__init__.py b/ecs/crm-datafetch/src/error/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ecs/crm-datafetch/src/error/exceptions.py b/ecs/crm-datafetch/src/error/exceptions.py new file mode 100644 index 00000000..5085dbca --- /dev/null +++ b/ecs/crm-datafetch/src/error/exceptions.py @@ -0,0 +1,35 @@ +from abc import ABCMeta + + +class MeDaCaCRMDataFetchException(Exception, metaclass=ABCMeta): + """MeDaCaシステム固有のカスタムエラークラス""" + + def __init__(self, error_id: str, func_name: str, message: str) -> None: + super().__init__(message) + self.func_name = func_name + self.error_id = error_id + + +class FileNotFoundException(MeDaCaCRMDataFetchException): + """S3のファイルが見つからない場合の例外""" + pass + + +class FileUploadException(MeDaCaCRMDataFetchException): + """S3のファイルアップロード失敗の例外""" + pass + + +class InvalidConfigException(MeDaCaCRMDataFetchException): + """Configのバリデーションチェック失敗の例外""" + pass + + +class DataConvertException(MeDaCaCRMDataFetchException): + """データ変換が失敗した場合の例外""" + pass + + +class SalesforceAPIException(MeDaCaCRMDataFetchException): + """SalesforceのAPI実行失敗が発生した場合の例外""" + pass diff --git a/ecs/crm-datafetch/src/fetch_crm_data_process.py b/ecs/crm-datafetch/src/fetch_crm_data_process.py new file mode 100644 index 00000000..8c66bf59 --- /dev/null +++ b/ecs/crm-datafetch/src/fetch_crm_data_process.py @@ -0,0 +1,147 @@ +from requests.exceptions import ConnectTimeout, ReadTimeout +from tenacity import retry, stop_after_attempt +from tenacity.wait import wait_exponential + +from src.config.objects import LastFetchDatetime, TargetObject +from src.error.exceptions import SalesforceAPIException +from src.salesforce.salesforce_api import SalesforceApiClient +from src.salesforce.soql_builder import SOQLBuilder +from src.system_var.constants import FETCH_JP_NAME +from src.system_var.environments import ( + CRM_AUTH_TIMEOUT, CRM_FETCH_RECORD_MAX_RETRY_ATTEMPT, + CRM_FETCH_RECORD_RETRY_INTERVAL, CRM_FETCH_RECORD_RETRY_MAX_INTERVAL, + CRM_FETCH_RECORD_RETRY_MIN_INTERVAL, CRM_FETCH_RECORD_TIMEOUT, + CRM_GET_RECORD_COUNT_MAX_RETRY_ATTEMPT, + CRM_GET_RECORD_COUNT_RETRY_INTERVAL, + CRM_GET_RECORD_COUNT_RETRY_MAX_INTERVAL, + CRM_GET_RECORD_COUNT_RETRY_MIN_INTERVAL, CRM_GET_RECORD_COUNT_TIMEOUT) +from src.util.counter_object import CounterObject +from src.util.logger import logger_instance as logger + + +def fetch_crm_data_process(target_object: TargetObject, last_fetch_datetime: LastFetchDatetime): + """CRMデータ取得処理 + + Args: + target_object (TargetObject): 取得対象オブジェクト情報インスタンス + last_fetch_datetime (LastFetchDatetime): データ取得期間設定インスタンス + + Raises: + SalesforceAPIException: SalesforceのAPI実行失敗が発生した場合 + + Returns: + crm_data_response: Salesforceオブジェクトデータ + """ + + # ① CRMデータ取得処理開始ログを出力する + logger.info( + f'I-FETCH-01 [{target_object.object_name}] のCRMからのデータ取得処理を開始します') + + target_object_name = target_object.object_name + + # リトライ回数判定用のカウンタオブジェクトを生成 + # @retryデコレータを利用した関数のリトライ処理で、基本データ型だとリトライ回数をカウントすることができないため、オブジェクト化する + count_counter = CounterObject(1) + data_counter = CounterObject(1) + + try: + # ② 取得対象オブジェクトの取得期間内のレコード件数を取得する + logger.info(f'I-FETCH-02 [{target_object_name}] の件数取得を開始します') + + soql_builder = SOQLBuilder(target_object, last_fetch_datetime) + count_soql = soql_builder.create_count_soql() + + record_count = fetch_record_count_retry(count_soql, target_object_name, count_counter) + + logger.info(f'I-FETCH-03 [{target_object_name}] の件数:[{record_count}]') + + except Exception as e: + raise SalesforceAPIException( + 'E-FETCH-01', FETCH_JP_NAME, f'[{target_object_name}] の件数取得に失敗しました エラー内容:[{e}]') + + try: + # ③ 取得対象オブジェクトのレコードを取得する + logger.info(f'I-FETCH-04 [{target_object_name}] のレコード取得を開始します') + + fetch_soql = soql_builder.create_fetch_soql() + + crm_data_response = fetch_sf_data_retry(fetch_soql, target_object_name, data_counter) + + logger.info(f'I-FETCH-05 [{target_object_name}] のレコード取得が成功しました') + + except Exception as e: + raise SalesforceAPIException( + 'E-FETCH-02', FETCH_JP_NAME, f'[{target_object_name}] のレコード取得に失敗しました エラー内容:[{e}]') + + # ④ CRMデータ取得処理終了ログを出力する + logger.info(f'I-FETCH-06 [{target_object_name}] のCRMからのデータ取得処理を終了します') + + # ⑤ 次の処理へ移行する + return crm_data_response + + +@retry( + wait=wait_exponential(multiplier=CRM_GET_RECORD_COUNT_RETRY_INTERVAL, + min=CRM_GET_RECORD_COUNT_RETRY_MIN_INTERVAL, max=CRM_GET_RECORD_COUNT_RETRY_MAX_INTERVAL), + stop=stop_after_attempt(CRM_GET_RECORD_COUNT_MAX_RETRY_ATTEMPT)) +def fetch_record_count_retry(soql: str, target_object_name: str, count_counter: CounterObject): + try: + salesforce_api_client = SalesforceApiClient() + return salesforce_api_client.fetch_sf_count(soql) + + except ConnectTimeout as e: + # 「リトライします」のメッセージ出力後、リトライせず例外終了になってしまうことを防ぐため、カウンタによる回数の判定を行う + if count_counter.describe() < CRM_GET_RECORD_COUNT_MAX_RETRY_ATTEMPT: + count_counter.increment(1) + logger.warning(f'W-FETCH-01 CRMの接続処理がタイムアウトしため、リトライします:[{CRM_AUTH_TIMEOUT}] エラー内容:[{e}]') + raise e + + except ReadTimeout as e: + + # 「リトライします」のメッセージ出力後、リトライせず例外終了になってしまうことを防ぐため、カウンタによる回数の判定を行う + if count_counter.describe() < CRM_GET_RECORD_COUNT_MAX_RETRY_ATTEMPT: + count_counter.increment(1) + logger.warning( + f'W-FETCH-02 [{target_object_name}] の件数取得処理がタイムアウトしたため、リトライします:[{CRM_GET_RECORD_COUNT_TIMEOUT}] エラー内容:[{e}]') + raise e + + except Exception as e: + # 「リトライします」のメッセージ出力後、リトライせず例外終了になってしまうことを防ぐため、カウンタによる回数の判定を行う + if count_counter.describe() < CRM_GET_RECORD_COUNT_MAX_RETRY_ATTEMPT: + count_counter.increment(1) + logger.warning( + f'W-FETCH-03 [{target_object_name}] の件数取得に失敗したため、リトライします エラー内容:[{e}]') + raise e + + +@retry( + wait=wait_exponential(multiplier=CRM_FETCH_RECORD_RETRY_INTERVAL, + min=CRM_FETCH_RECORD_RETRY_MIN_INTERVAL, max=CRM_FETCH_RECORD_RETRY_MAX_INTERVAL), + stop=stop_after_attempt(CRM_FETCH_RECORD_MAX_RETRY_ATTEMPT)) +def fetch_sf_data_retry(soql: str, target_object_name: str, data_counter: CounterObject): + try: + salesforce_api_client = SalesforceApiClient() + return salesforce_api_client.fetch_sf_data(soql) + + except ConnectTimeout as e: + # 「リトライします」のメッセージ出力後、リトライせず例外終了になってしまうことを防ぐため、カウンタによる回数の判定を行う + if data_counter.describe() < CRM_FETCH_RECORD_MAX_RETRY_ATTEMPT: + data_counter.increment(1) + logger.warning(f'W-FETCH-04 CRMの接続処理がタイムアウトしため、リトライします:[{CRM_AUTH_TIMEOUT}] エラー内容:[{e}]') + raise e + + except ReadTimeout as e: + # 「リトライします」のメッセージ出力後、リトライせず例外終了になってしまうことを防ぐため、カウンタによる回数の判定を行う + if data_counter.describe() < CRM_FETCH_RECORD_MAX_RETRY_ATTEMPT: + data_counter.increment(1) + logger.warning( + f'W-FETCH-05 [{target_object_name}] のレコード取得処理がタイムアウトしたため、リトライします:[{CRM_FETCH_RECORD_TIMEOUT}] エラー内容:[{e}]') + raise e + + except Exception as e: + # 「リトライします」のメッセージ出力後、リトライせず例外終了になってしまうことを防ぐため、カウンタによる回数の判定を行う + if data_counter.describe() < CRM_FETCH_RECORD_MAX_RETRY_ATTEMPT: + data_counter.increment(1) + logger.warning( + f'W-FETCH-06 [{target_object_name}] のレコード取得に失敗したため、リトライします エラー内容:[{e}]') + raise e diff --git a/ecs/crm-datafetch/src/parser/__init__.py b/ecs/crm-datafetch/src/parser/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ecs/crm-datafetch/src/parser/json_parse.py b/ecs/crm-datafetch/src/parser/json_parse.py new file mode 100644 index 00000000..ca1d8ed2 --- /dev/null +++ b/ecs/crm-datafetch/src/parser/json_parse.py @@ -0,0 +1,17 @@ +import json +import re + +from src.system_var.constants import EXCLUDE_SYMBOL + + +class JsonParser(): + def __init__(self, json_str) -> None: + self.__json_str = json_str + + def parse(self) -> dict: + for symbol in EXCLUDE_SYMBOL: + # コメントアウトシンボルを含む部分を置き換える正規表現 + replace_comment_regex = rf'\s(?!\"){symbol}[\s\S]*?.*' + self.__json_str = re.sub(replace_comment_regex, '', self.__json_str) + + return json.loads(self.__json_str) diff --git a/ecs/crm-datafetch/src/prepare_data_fetch_process.py b/ecs/crm-datafetch/src/prepare_data_fetch_process.py new file mode 100644 index 00000000..3488c71f --- /dev/null +++ b/ecs/crm-datafetch/src/prepare_data_fetch_process.py @@ -0,0 +1,82 @@ +from src.aws.s3 import ConfigBucket +from src.config.objects import FetchTargetObjects +from src.error.exceptions import FileNotFoundException, InvalidConfigException +from src.parser.json_parse import JsonParser +from src.system_var.constants import PRE_JP_NAME +from src.system_var.environments import (CRM_CONFIG_BUCKET, + OBJECT_INFO_FILENAME, + OBJECT_INFO_FOLDER) +from src.util.execute_datetime import ExecuteDateTime +from src.util.logger import logger_instance as logger + + +def prepare_data_fetch_process(): + """データ取得準備処理 + + Raises: + FileNotFoundException: S3上のファイルが存在しない場合 + InvalidConfigException: オブジェクト情報定義が不正だった場合 + + Returns: + fetch_target_objects : CRMオブジェクト情報インスタンス + execute_datetime : 実行日次取得インスタンス + process_result : 取得処理実行結果辞書オブジェクト + """ + + # ① データ取得準備処理の開始ログを出力する + logger.info('I-PRE-01 データ取得準備処理を開始します') + + # ② 取得処理開始年月日時分秒を控える + + execute_datetime = ExecuteDateTime() + + logger.info(f'I-PRE-02 データ取得処理開始日時:{execute_datetime}') + + try: + # ③ S3 設定ファイル保管用バケットから、CRM_取得オブジェクト情報ファイルを取得する + object_info_file_s3_path = f's3://{CRM_CONFIG_BUCKET}{OBJECT_INFO_FOLDER}/{OBJECT_INFO_FILENAME}' + logger.debug( + f'D-PRE-03 CRM_取得オブジェクト情報ファイルの取得開始します ファイルパス:[{object_info_file_s3_path}]') + + config_bucket = ConfigBucket() + object_info_file_str = config_bucket.get_object_info_file() + + logger.debug('D-PRE-04 CRM_取得オブジェクト情報ファイルの取得成功しました') + + except Exception as e: + raise FileNotFoundException( + 'E-PRE-01', PRE_JP_NAME, f'CRM_取得オブジェクト情報ファイルが存在しません ファイル名:[{OBJECT_INFO_FILENAME}] エラー内容:[{e}]') + + try: + # ④ CRM_取得オブジェクト情報ファイルをパースし、メモリ上に展開する + logger.debug('D-PRE-05 CRM_取得オブジェクト情報ファイルをパースします') + + json_parser = JsonParser(object_info_file_str) + object_info_file_dict = json_parser.parse() + + logger.debug('D-PRE-06 CRM_取得オブジェクト情報ファイルのパースに成功しました') + + except Exception as e: + raise InvalidConfigException( + 'E-PRE-02', PRE_JP_NAME, f'CRM_取得オブジェクト情報ファイルのパースに失敗しました エラー内容:[{e}]') + + # ⑤ メモリ上のCRM_取得オブジェクト情報のキーobjectsの形式チェックを行う + try: + logger.debug('D-PRE-07 CRM_取得オブジェクト情報ファイルの形式チェックを開始します') + + fetch_target_objects = FetchTargetObjects(object_info_file_dict) + + logger.debug('D-PRE-08 CRM_取得オブジェクト情報ファイルの形式チェック 正常終了') + + except Exception as e: + raise InvalidConfigException( + 'E-PRE-03', PRE_JP_NAME, f'CRM_取得オブジェクト情報ファイルの形式チェックに失敗しました ファイル名:[{OBJECT_INFO_FILENAME}] エラー内容:[{e}]') + + # ⑥ 処理結果出力用のマップを初期化 + process_result = {} + + # ⑦ データ取得準備処理の終了ログを出力する + logger.info('I-PRE-09 データ取得準備処理を終了します') + + # ⑧ 次の処理へ移行する + return(fetch_target_objects, execute_datetime, process_result) diff --git a/ecs/crm-datafetch/src/salesforce/__init__.py b/ecs/crm-datafetch/src/salesforce/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ecs/crm-datafetch/src/salesforce/salesforce_api.py b/ecs/crm-datafetch/src/salesforce/salesforce_api.py new file mode 100644 index 00000000..4e4bb267 --- /dev/null +++ b/ecs/crm-datafetch/src/salesforce/salesforce_api.py @@ -0,0 +1,28 @@ +from simple_salesforce import Salesforce +from src.system_var.environments import (CRM_AUTH_DOMAIN, CRM_AUTH_TIMEOUT, + CRM_FETCH_RECORD_TIMEOUT, + CRM_GET_RECORD_COUNT_TIMEOUT, + CRM_USER_NAME, CRM_USER_PASSWORD, + CRM_USER_SECURITY_TOKEN) + + +class SalesforceApiClient(): + def __init__(self) -> None: + self.__sf = Salesforce(username=CRM_USER_NAME, password=CRM_USER_PASSWORD, + security_token=CRM_USER_SECURITY_TOKEN, + domain=CRM_AUTH_DOMAIN + ) + + def query(self, soql, include_deleted=True, conn_timeout=100, read_timeout=300): + return self.__sf.query(soql, include_deleted, timeout=(float(conn_timeout), float(read_timeout))) + + def query_all(self, soql, include_deleted=True, conn_timeout=100, read_timeout=300): + return self.__sf.query_all(soql, include_deleted, timeout=(float(conn_timeout), float(read_timeout))) + + def fetch_sf_count(self, soql: str): + count_res = self.query(soql, conn_timeout=CRM_AUTH_TIMEOUT, read_timeout=CRM_GET_RECORD_COUNT_TIMEOUT) + return count_res.get('records')[0].get('expr0') + + def fetch_sf_data(self, soql: str): + data_res = self.query_all(soql, conn_timeout=CRM_AUTH_TIMEOUT, read_timeout=CRM_FETCH_RECORD_TIMEOUT) + return data_res.get('records') diff --git a/ecs/crm-datafetch/src/salesforce/soql_builder.py b/ecs/crm-datafetch/src/salesforce/soql_builder.py new file mode 100644 index 00000000..a84744a8 --- /dev/null +++ b/ecs/crm-datafetch/src/salesforce/soql_builder.py @@ -0,0 +1,34 @@ +from src.config.objects import TargetObject, LastFetchDatetime + + +class SOQLBuilder: + def __init__(self, target_object: TargetObject, last_fetch_datetime: LastFetchDatetime) -> None: + self.__SELECT_SOQL = """SELECT {column_or_expression} FROM {object_name} + WHERE {datetime_column} > {last_fetch_datetime_from} + AND {datetime_column} <= {last_fetch_datetime_to} + """ + self.__target_object = target_object + self.__last_fetch_datetime = last_fetch_datetime + + def create_count_soql(self): + count_soql = self.__SELECT_SOQL.format( + column_or_expression='COUNT(Id)', + object_name=self.__target_object.object_name, + last_fetch_datetime_from=self.__last_fetch_datetime.last_fetch_datetime_from, + last_fetch_datetime_to=self.__last_fetch_datetime.last_fetch_datetime_to, + datetime_column=self.__target_object.datetime_column + ) + + return count_soql + + def create_fetch_soql(self): + columns = ','.join(self.__target_object.columns) + fetch_soql = self.__SELECT_SOQL.format( + column_or_expression=columns, + object_name=self.__target_object.object_name, + last_fetch_datetime_from=self.__last_fetch_datetime.last_fetch_datetime_from, + last_fetch_datetime_to=self.__last_fetch_datetime.last_fetch_datetime_to, + datetime_column=self.__target_object.datetime_column + ) + + return fetch_soql diff --git a/ecs/crm-datafetch/src/set_datetime_period_process.py b/ecs/crm-datafetch/src/set_datetime_period_process.py new file mode 100644 index 00000000..bfebd5c2 --- /dev/null +++ b/ecs/crm-datafetch/src/set_datetime_period_process.py @@ -0,0 +1,69 @@ +from src.aws.s3 import ConfigBucket +from src.config.objects import LastFetchDatetime, TargetObject +from src.error.exceptions import FileNotFoundException, InvalidConfigException +from src.parser.json_parse import JsonParser +from src.system_var.constants import DATE_JP_NAME +from src.system_var.environments import (CRM_CONFIG_BUCKET, + LAST_FETCH_DATE_FOLDER) +from src.util.execute_datetime import ExecuteDateTime +from src.util.logger import logger_instance as logger + + +def set_datetime_period_process(target_object: TargetObject, execute_datetime: ExecuteDateTime): + """データ取得期間設定処理 + + Args: + target_object (TargetObject): 取得対象オブジェクト情報インスタンス + execute_datetime (ExecuteDateTime): 実行日次取得インスタンス + + Raises: + FileNotFoundException: S3上のファイルが存在しない場合 + InvalidConfigException: オブジェクト情報定義が不正だった場合 + + Returns: + last_fetch_datetime: データ取得期間設定インスタンス + """ + + # ① データ取得期間設定処理の開始ログを出力する + logger.info( + f'I-DATE-01 [{target_object.object_name}] のデータ取得期間設定処理を開始します') + + try: + # ② S3 設定ファイル保管用バケットから、前回取得日時ファイルを取得する + logger.info( + f'I-DATE-02 前回取得日時ファイルの取得開始します ファイルパス:[s3://{CRM_CONFIG_BUCKET}/{LAST_FETCH_DATE_FOLDER}/{target_object.last_fetch_datetime_file_name}]') + + s3_config_bucket = ConfigBucket() + last_fetch_datetime_file_str = s3_config_bucket.get_last_fetch_datetime_file( + target_object.last_fetch_datetime_file_name) + + logger.info(f'I-DATE-03 前回取得日時ファイルの取得成功しました') + + except Exception as e: + raise FileNotFoundException( + 'E-DATE-01', DATE_JP_NAME, f'前回取得日時ファイルが存在しません ファイル名:[{target_object.last_fetch_datetime_file_name}] エラー内容:[{e}]') + + try: + # ③ 取得した前回取得日時ファイルの形式チェックを行う + # ④ データの取得期間を設定する + logger.debug(f'D-DATE-04 前回取得日時ファイルの形式チェックを開始します') + + json_parser = JsonParser(last_fetch_datetime_file_str) + last_fetch_datetime_file_dict = json_parser.parse() + + last_fetch_datetime = LastFetchDatetime(last_fetch_datetime_file_dict, execute_datetime) + + logger.debug(f'D-DATE-05 前回取得日時ファイルの形式チェック 正常終了') + logger.info( + f'I-DATE-06 取得範囲 From: [{last_fetch_datetime.last_fetch_datetime_from}] To: [{last_fetch_datetime.last_fetch_datetime_to}]') + + except Exception as e: + raise InvalidConfigException( + 'E-DATE-02', DATE_JP_NAME, f'前回取得日時ファイルの形式チェック処理が失敗しました エラー内容:[{e}]') + + # ⑤ データ取得準備処理の終了ログを出力する + logger.info( + f'I-DATE-07 [{target_object.object_name}] のデータ取得期間設定処理を終了します') + + # ⑥ 次の処理へ移行する + return last_fetch_datetime diff --git a/ecs/crm-datafetch/src/system_var/constants.py b/ecs/crm-datafetch/src/system_var/constants.py new file mode 100644 index 00000000..bf65010c --- /dev/null +++ b/ecs/crm-datafetch/src/system_var/constants.py @@ -0,0 +1,96 @@ +# environments(task settings file) +LOG_LEVEL = 'LOG_LEVEL' # ログ出力レベル。DEBUG, INFO, WARNING, ERRORの4つから指定する +CRM_AUTH_TIMEOUT = 'CRM_AUTH_TIMEOUT' # CRMへの認証処理のタイムアウト秒数 +CRM_AUTH_MAX_RETRY_ATTEMPT = 'CRM_AUTH_MAX_RETRY_ATTEMPT' # CRMへの認証処理の最大リトライ試行回数 +CRM_AUTH_RETRY_INTERVAL = 'CRM_AUTH_RETRY_INTERVAL' # CRMへの認証処理のリトライ時の初回待ち秒数 +CRM_AUTH_RETRY_MIN_INTERVAL = 'CRM_AUTH_RETRY_MIN_INTERVAL' # CRMへの認証処理のリトライ時の最小待ち秒数 +CRM_AUTH_RETRY_MAX_INTERVAL = 'CRM_AUTH_RETRY_MAX_INTERVAL' # CRMへの認証処理のリトライ時の最大待ち秒数 +CRM_GET_RECORD_COUNT_TIMEOUT = 'CRM_GET_RECORD_COUNT_TIMEOUT' # CRMのレコード件数取得処理のタイムアウト秒数 +CRM_GET_RECORD_COUNT_MAX_RETRY_ATTEMPT = 'CRM_GET_RECORD_COUNT_MAX_RETRY_ATTEMPT' # CRMのレコード件数取得処理の最大リトライ試行回数 +CRM_GET_RECORD_COUNT_RETRY_INTERVAL = 'CRM_GET_RECORD_COUNT_RETRY_INTERVAL' # CRMのレコード件数取得処理のリトライ時の初回待ち秒数 +CRM_GET_RECORD_COUNT_RETRY_MIN_INTERVAL = 'CRM_GET_RECORD_COUNT_RETRY_MIN_INTERVAL' # CRMのレコード件数取得処理のリトライ時の最小待ち秒数 +CRM_GET_RECORD_COUNT_RETRY_MAX_INTERVAL = 'CRM_GET_RECORD_COUNT_RETRY_MAX_INTERVAL' # CRMのレコード件数取得処理のリトライ時の最大待ち秒数 +CRM_FETCH_RECORD_TIMEOUT = 'CRM_FETCH_RECORD_TIMEOUT' # CRMのレコード取得処理のタイムアウト秒数 +CRM_FETCH_RECORD_MAX_RETRY_ATTEMPT = 'CRM_FETCH_RECORD_MAX_RETRY_ATTEMPT' # CRMのレコード取得処理の最大リトライ試行回数 +CRM_FETCH_RECORD_RETRY_INTERVAL = 'CRM_FETCH_RECORD_RETRY_INTERVAL' # CRMのレコード取得処理のリトライ時の初回待ち秒数 +CRM_FETCH_RECORD_RETRY_MIN_INTERVAL = 'CRM_FETCH_RECORD_RETRY_MIN_INTERVAL' # CRMのレコード取得処理のリトライ時の最小待ち秒数 +CRM_FETCH_RECORD_RETRY_MAX_INTERVAL = 'CRM_FETCH_RECORD_RETRY_MAX_INTERVAL' # CRMのレコード取得処理のリトライ時の最大待ち秒数 +CONVERT_TZ = 'CONVERT_TZ' # CRMデータの日時を変換するときのタイムゾーン + +# environments(ECS Task Environment) +CRM_AUTH_DOMAIN = 'CRM_AUTH_DOMAIN' # CRMのAPI実行のための認証エンドポイントのドメイン +CRM_USER_NAME = 'CRM_USER_NAME' # CRMのAPI実行用ユーザ名 +CRM_USER_PASSWORD = 'CRM_USER_PASSWORD' # CRMのAPI実行用ユーザパスワード +CRM_USER_SECURITY_TOKEN = 'CRM_USER_SECURITY_TOKEN' # CRMのAPI実行用ユーザのセキュリティトークン +CRM_CONFIG_BUCKET = 'CRM_CONFIG_BUCKET' # CRMデータ取得用の設定ファイルを格納するバケット名 +CRM_BACKUP_BUCKET = 'CRM_BACKUP_BUCKET' # CRMのバックアップデータを格納するバケット名 +IMPORT_DATA_BUCKET = 'IMPORT_DATA_BUCKET' # CRMの取込データを格納するバケット名 +OBJECT_INFO_FOLDER = 'OBJECT_INFO_FOLDER' # CRM取得対象オブジェクトの情報を格納するフォルダパス +OBJECT_INFO_FILENAME = 'OBJECT_INFO_FILENAME' # CRM取得対象オブジェクトの情報のファイル名 +PROCESS_RESULT_FOLDER = 'PROCESS_RESULT_FOLDER' # CRMデータ取得結果を格納するフォルダパス +PROCESS_RESULT_FILENAME = 'PROCESS_RESULT_FILENAME' # CRMデータ取得結果を格納するファイル名 +LAST_FETCH_DATE_FOLDER = 'LAST_FETCH_DATE_FOLDER' # CRMからの最終取得日時ファイルを格納するフォルダパス +CRM_IMPORT_DATA_FOLDER = 'CRM_IMPORT_DATA_FOLDER' # CRMから取得し、取込用に変換したデータを格納するフォルダ +LAST_FETCH_DATE_BACKUP_FOLDER = 'LAST_FETCH_DATE_BACKUP_FOLDER' # CRMからの最終取得日時ファイルのバックアップを格納するフォルダパス +RESPONSE_JSON_BACKUP_FOLDER = 'RESPONSE_JSON_BACKUP_FOLDER' # CRMから取得した生データのバックアップを格納するフォルダパス +CRM_IMPORT_DATA_BACKUP_FOLDER = 'CRM_IMPORT_DATA_BACKUP_FOLDER' # CRMから取得し、取込用に変換したデータのバックアップを格納するフォルダ + +# 時刻フォーマット +# .000ZはUTCを表す。ミリ秒までの考慮は不要なので固定で指定 +YYYYMMDDTHHMMSSTZ = '%Y-%m-%dT%H:%M:%S.000Z' +CRM_DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S.000%z' +YYYYMMDDHHMMSS = '%Y-%m-%d %H:%M:%S' +MILLISEC_FORMAT = '000Z' + +# aws +AWS_RESOURCE_S3 = 's3' +S3_RESPONSE_BODY = 'Body' +S3_CHAR_CODE = 'utf-8' + +# 正規表現チェック +EXCLUDE_SYMBOL = ['#', '/'] +DATE_PATTERN_YYYYMMDDTHHMMSSTZ = r'[12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]\.000Z' +DATE_PATTERN_YYYYMMDDHHMMSSFFF_UTC = r'\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.000\+0000' + +# logger +LOG_FORMAT = '[%(levelname)s]\t%(asctime)s\t%(message)s\n' +LOG_DATE_FORMAT = '%Y-%m-%d %H:%M:%S' +LOG_LEVEL_INFO = 'INFO' + +# 処理名 +PROCESS_JP_NAME = 'コントロール処理' +PRE_JP_NAME = 'データ取得準備処理' +CHK_JP_NAME = 'オブジェクト情報形式チェック処理' +DATE_JP_NAME = 'データ取得期間設定処理' +FETCH_JP_NAME = 'CRMデータ取得処理' +RESBK_JP_NAME = 'CRM電文データバックアップ処理' +CONV_JP_NAME = 'CSV変換処理' +CSVBK_JP_NAME = 'CSVバックアップ処理' +UPLD_JP_NAME = 'CSVアップロード処理' +UPD_JP_NAME = '前回取得日時ファイル更新' +END_JP_NAME = '取得処理実施結果アップロード処理' + +# CSVチェック +CSV_TRUE_VALUE = '1' +CSV_FALSE_VALUE = '0' + +# オブジェクト変数 +OBJECTS_KEY = 'objects' +OBJECTS_TYPE = list +OBJECT_NAME_KEY = 'object_name' +OBJECT_NAME_TYPE = str +COLUMNS_KEY = 'columns' +COLUMNS_TYPE = list +IS_SKIP_KEY = 'is_skip' +IS_SKIP_TYPE = bool +IS_UPDATE_LAST_FETCH_DATETIME_KEY = 'is_update_last_fetch_datetime' +IS_UPDATE_LAST_FETCH_DATETIME_TYPE = bool +LAST_FETCH_DATETIME_FILE_NAME_KEY = 'last_fetch_datetime_file_name' +LAST_FETCH_DATETIME_FILE_NAME_TYPE = str +UPLOAD_FILE_NAME_KEY = 'upload_file_name' +UPLOAD_FILE_NAME_TYPE = str +DATETIME_COLUMN_KEY = 'datetime_column' +DATETIME_COLUMN_TYPE = str +DATETIME_COLUMN_DEFAULT_VALUE = 'SystemModstamp' +LAST_FETCH_DATETIME_TO_KEY = 'last_fetch_datetime_to' +LAST_FETCH_DATETIME_FROM_KEY = 'last_fetch_datetime_from' diff --git a/ecs/crm-datafetch/src/system_var/environments.py b/ecs/crm-datafetch/src/system_var/environments.py new file mode 100644 index 00000000..b290cc7b --- /dev/null +++ b/ecs/crm-datafetch/src/system_var/environments.py @@ -0,0 +1,73 @@ +import os + +import src.system_var.constants as constants + +# environments(task settings file) +# ログ出力レベル。DEBUG, INFO, WARNING, ERRORの4つから指定する +LOG_LEVEL = os.environ.get(constants.LOG_LEVEL, constants.LOG_LEVEL_INFO) +# CRMへの認証処理のタイムアウト秒数 +CRM_AUTH_TIMEOUT = int(os.environ.get(constants.CRM_AUTH_TIMEOUT, 100)) +# CRMへの認証処理の最大リトライ試行回数 +CRM_AUTH_MAX_RETRY_ATTEMPT = int(os.environ.get(constants.CRM_AUTH_MAX_RETRY_ATTEMPT, 3)) +# CRMへの認証処理のリトライ時の初回待ち秒数 +CRM_AUTH_RETRY_INTERVAL = int(os.environ.get(constants.CRM_AUTH_RETRY_INTERVAL, 5)) +# CRMへの認証処理のリトライ時の最小待ち秒数 +CRM_AUTH_RETRY_MIN_INTERVAL = int(os.environ.get(constants.CRM_AUTH_RETRY_MIN_INTERVAL, 5)) +# CRMへの認証処理のリトライ時の最大待ち秒数 +CRM_AUTH_RETRY_MAX_INTERVAL = int(os.environ.get(constants.CRM_AUTH_RETRY_MAX_INTERVAL, 50)) +# CRMのレコード件数取得処理のタイムアウト秒数 +CRM_GET_RECORD_COUNT_TIMEOUT = int(os.environ.get(constants.CRM_GET_RECORD_COUNT_TIMEOUT, 300)) +# CRMのレコード件数取得処理の最大リトライ試行回数 +CRM_GET_RECORD_COUNT_MAX_RETRY_ATTEMPT = int(os.environ.get(constants.CRM_GET_RECORD_COUNT_MAX_RETRY_ATTEMPT, 3)) +# CRMのレコード件数取得処理のリトライ時の初回待ち秒数 +CRM_GET_RECORD_COUNT_RETRY_INTERVAL = int(os.environ.get(constants.CRM_GET_RECORD_COUNT_RETRY_INTERVAL, 5)) +# CRMのレコード件数取得処理のリトライ時の最小待ち秒数 +CRM_GET_RECORD_COUNT_RETRY_MIN_INTERVAL = int(os.environ.get(constants.CRM_GET_RECORD_COUNT_RETRY_MIN_INTERVAL, 5)) +# CRMのレコード件数取得処理のリトライ時の最大待ち秒数 +CRM_GET_RECORD_COUNT_RETRY_MAX_INTERVAL = int(os.environ.get(constants.CRM_GET_RECORD_COUNT_RETRY_MAX_INTERVAL, 50)) +# CRMのレコード取得処理のタイムアウト秒数 +CRM_FETCH_RECORD_TIMEOUT = int(os.environ.get(constants.CRM_FETCH_RECORD_TIMEOUT, 300)) +# CRMのレコード取得処理の最大リトライ試行回数 +CRM_FETCH_RECORD_MAX_RETRY_ATTEMPT = int(os.environ.get(constants.CRM_FETCH_RECORD_MAX_RETRY_ATTEMPT, 3)) +# CRMのレコード取得処理のリトライ時の初回待ち秒数 +CRM_FETCH_RECORD_RETRY_INTERVAL = int(os.environ.get(constants.CRM_FETCH_RECORD_RETRY_INTERVAL, 5)) +# CRMのレコード取得処理のリトライ時の最小待ち秒数 +CRM_FETCH_RECORD_RETRY_MIN_INTERVAL = int(os.environ.get(constants.CRM_FETCH_RECORD_RETRY_MIN_INTERVAL, 5)) +# CRMのレコード取得処理のリトライ時の最大待ち秒数 +CRM_FETCH_RECORD_RETRY_MAX_INTERVAL = int(os.environ.get(constants.CRM_FETCH_RECORD_RETRY_MAX_INTERVAL, 50)) +# CRMデータの日時を変換するときのタイムゾーン +CONVERT_TZ = os.environ.get(constants.CONVERT_TZ, 'Asia/Tokyo') + +# environments(ECS Task Environment) +# CRMのAPI実行のための認証エンドポイントのドメイン +CRM_AUTH_DOMAIN = os.environ[constants.CRM_AUTH_DOMAIN] +# CRMのAPI実行用ユーザ名 +CRM_USER_NAME = os.environ[constants.CRM_USER_NAME] +# CRMのAPI実行用ユーザパスワード +CRM_USER_PASSWORD = os.environ[constants.CRM_USER_PASSWORD] +# CRMのAPI実行用ユーザのセキュリティトークン +CRM_USER_SECURITY_TOKEN = os.environ[constants.CRM_USER_SECURITY_TOKEN] +# CRMデータ取得用の設定ファイルを格納するバケット名 +CRM_CONFIG_BUCKET = os.environ[constants.CRM_CONFIG_BUCKET] +# CRMのバックアップデータを格納するバケット名 +CRM_BACKUP_BUCKET = os.environ[constants.CRM_BACKUP_BUCKET] +# CRMの取込データを格納するバケット名 +IMPORT_DATA_BUCKET = os.environ[constants.IMPORT_DATA_BUCKET] +# CRM取得対象オブジェクトの情報を格納するフォルダパス +OBJECT_INFO_FOLDER = os.environ.get(constants.OBJECT_INFO_FOLDER, 'crm/object_info') +# CRM取得対象オブジェクトの情報のファイル名 +OBJECT_INFO_FILENAME = os.environ[constants.OBJECT_INFO_FILENAME] +# CRMデータ取得結果を格納するフォルダパス +PROCESS_RESULT_FOLDER = os.environ.get(constants.PROCESS_RESULT_FOLDER, 'data_import') +# CRMデータ取得結果を格納するファイル名 +PROCESS_RESULT_FILENAME = os.environ.get(constants.PROCESS_RESULT_FILENAME, 'process_result.json') +# CRMからの最終取得日時ファイルを格納するフォルダパス +LAST_FETCH_DATE_FOLDER = os.environ.get(constants.LAST_FETCH_DATE_FOLDER, 'crm/last_fetch_datetime') +# CRMから取得し、取込用に変換したデータを格納するフォルダ +CRM_IMPORT_DATA_FOLDER = os.environ.get(constants.CRM_IMPORT_DATA_FOLDER, 'crm/target') +# CRMからの最終取得日時ファイルのバックアップを格納するフォルダパス +LAST_FETCH_DATE_BACKUP_FOLDER = os.environ.get(constants.LAST_FETCH_DATE_BACKUP_FOLDER, 'last_fetch_datetime') +# CRMから取得した生データのバックアップを格納するフォルダパス +RESPONSE_JSON_BACKUP_FOLDER = os.environ.get(constants.RESPONSE_JSON_BACKUP_FOLDER, 'response_json') +# CRMから取得し、取込用に変換したデータのバックアップを格納するフォルダ +CRM_IMPORT_DATA_BACKUP_FOLDER = os.environ.get(constants.CRM_IMPORT_DATA_BACKUP_FOLDER, 'data_import') diff --git a/ecs/crm-datafetch/src/upload_last_fetch_datetime_process.py b/ecs/crm-datafetch/src/upload_last_fetch_datetime_process.py new file mode 100644 index 00000000..e6b34c53 --- /dev/null +++ b/ecs/crm-datafetch/src/upload_last_fetch_datetime_process.py @@ -0,0 +1,57 @@ +import json + +from src.aws.s3 import ConfigBucket +from src.config.objects import LastFetchDatetime, TargetObject +from src.error.exceptions import FileUploadException +from src.system_var.constants import UPD_JP_NAME +from src.util.logger import logger_instance as logger + + +def upload_last_fetch_datetime_process(target_object: TargetObject, last_fetch_datetime: LastFetchDatetime): + """前回取得日時ファイル更新 + + Args: + target_object (TargetObject): 取得対象オブジェクト情報インスタンス + last_fetch_datetime (LastFetchDatetime): データ取得期間設定インスタンス + + Raises: + FileUploadException: S3のファイルアップロード失敗 + """ + + # ① 前回取得日時ファイル更新処理の開始ログを出力する + logger.info( + f'I-UPD-01 [{target_object.object_name}] の前回取得日時ファイルの更新処理を開始します') + + try: + if target_object.is_update_last_fetch_datetime is False: + # ② オブジェクト情報.is_update_last_fetch_datetimeがfalseの場合、以降の処理をスキップする + logger.info( + f'I-UPD-02 [{target_object.object_name}] の前回取得日時ファイルの更新処理をスキップします') + return + + # ③ 前回取得日時ファイル.last_fetch_datetime_fromに取得処理開始年月日時分秒を設定する + # 前回取得日時ファイル.last_fetch_datetime_toに空文字を設定する + last_fetch_datetime_dict = { + 'last_fetch_datetime_from': last_fetch_datetime.last_fetch_datetime_to, + 'last_fetch_datetime_to': '' + } + + config_bucket = ConfigBucket() + config_bucket.put_last_fetch_datetime_file( + target_object.last_fetch_datetime_file_name, json.dumps(last_fetch_datetime_dict)) + + logger.info( + f'D-UPD-03 [{target_object.object_name}] の前回取得日時ファイル更新処理 正常終了') + + except Exception as e: + raise FileUploadException( + 'E-UPD-01', + UPD_JP_NAME, + f'[{target_object.object_name}] 前回処理日時ファイルのアップロードに失敗しました ファイル名:[{target_object.last_fetch_datetime_file_name}] エラー内容:[{e}]') + + # ④ 前回取得日時ファイル更新処理の終了ログを出力する + logger.info( + f'I-UPD-04 [{target_object.object_name}] の前回取得日時ファイルの更新処理を終了します') + + # ⑤ 次の処理へ移行する + return diff --git a/ecs/crm-datafetch/src/upload_result_data_process.py b/ecs/crm-datafetch/src/upload_result_data_process.py new file mode 100644 index 00000000..8248fb78 --- /dev/null +++ b/ecs/crm-datafetch/src/upload_result_data_process.py @@ -0,0 +1,39 @@ +from src.aws.s3 import BackupBucket +from src.error.exceptions import FileUploadException +from src.system_var.constants import END_JP_NAME +from src.system_var.environments import PROCESS_RESULT_FILENAME +from src.util.execute_datetime import ExecuteDateTime +from src.util.logger import logger_instance as logger + + +def upload_result_data_process(process_result: dict, execute_datetime: ExecuteDateTime): + """取得処理実施結果アップロード処理 + + Args: + process_result (dict): 取得処理実行結果辞書オブジェクト + execute_datetime (ExecuteDateTime): データ取得期間設定インスタンス + + Raises: + FileUploadException: S3のファイルアップロード失敗 + """ + + # ① 取得処理実施結果アップロード処理のログを出力する + logger.info( + f'I-END-01 取得処理実施結果アップロード処理を開始します') + + try: + # ② CRMバックアップ保管用バケットに、取得処理実施結果のJSONデータを保管する + backup_bucket = BackupBucket() + backup_bucket.put_result_json( + f'{execute_datetime.to_path()}/{PROCESS_RESULT_FILENAME}', process_result) + + logger.debug(f'D-END-02 取得処理実施結果アップロード 正常終了') + + except Exception as e: + raise FileUploadException( + 'E-END-01', END_JP_NAME, f'取得処理実施結果のアップロードに失敗しました ファイル名:[{PROCESS_RESULT_FILENAME}] エラー内容:[{e}]') + + # ③ 取得処理実施結果アップロード処理の終了ログを出力する + logger.info(f'I-END-03 取得処理実施結果アップロード処理を終了します') + + return diff --git a/ecs/crm-datafetch/src/util/__init__.py b/ecs/crm-datafetch/src/util/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ecs/crm-datafetch/src/util/counter_object.py b/ecs/crm-datafetch/src/util/counter_object.py new file mode 100644 index 00000000..23da4f82 --- /dev/null +++ b/ecs/crm-datafetch/src/util/counter_object.py @@ -0,0 +1,14 @@ +class CounterObject: + def __init__(self, base_num=1) -> None: + self.__counter = base_num + + def describe(self) -> int: + return self.__counter + + def increment(self, num=1) -> int: + self.__counter += num + return self.__counter + + def decrement(self, num=1) -> int: + self.__counter -= num + return self.__counter diff --git a/ecs/crm-datafetch/src/util/dict_checker.py b/ecs/crm-datafetch/src/util/dict_checker.py new file mode 100644 index 00000000..39ebf9f0 --- /dev/null +++ b/ecs/crm-datafetch/src/util/dict_checker.py @@ -0,0 +1,43 @@ +import re + + +class DictChecker: + def __init__(self, object_dict: dict) -> None: + self.__object_dict = object_dict + + def is_empty(self, check_key): + """辞書型バリュー空文字チェック""" + return self.__object_dict[check_key] != '' and self.__object_dict[check_key] is not None + + def check_key_exist(self, check_key: str) -> bool: + """辞書型キー存在チェック""" + return check_key in self.__object_dict and self.is_empty(check_key) + + def check_data_type(self, check_key: str, check_type: type) -> bool: + """辞書型バリュー型チェック""" + return isinstance(self.__object_dict[check_key], check_type) + + def check_match_pattern(self, regex_str: str, check_key: str) -> bool: + """辞書型バリュー正規表現チェック""" + return True if re.fullmatch(regex_str, self.__object_dict[check_key]) else False + + def assert_key_exist(self, check_key: str) -> None: + """辞書型キー存在検査""" + if not self.check_key_exist(check_key): + raise Exception(f'「{check_key}」キーは必須です') + + return + + def assert_data_type(self, check_key: str, check_type: type) -> None: + """バリュー型検査""" + if not self.check_data_type(check_key, check_type): + raise Exception(f'「{check_key}」キーの値は「{check_type}」でなければなりません') + + return + + def assert_match_pattern(self, check_key: str, regex_str: str): + """正規表現検査""" + if not self.check_match_pattern(regex_str, check_key): + raise Exception(f'「{check_key}」キーの値の正規表現「{regex_str}」チェックに失敗しました') + + return diff --git a/ecs/crm-datafetch/src/util/execute_datetime.py b/ecs/crm-datafetch/src/util/execute_datetime.py new file mode 100644 index 00000000..5a608013 --- /dev/null +++ b/ecs/crm-datafetch/src/util/execute_datetime.py @@ -0,0 +1,17 @@ +from datetime import datetime, timezone + +from src.system_var.constants import MILLISEC_FORMAT, YYYYMMDDTHHMMSSTZ + + +class ExecuteDateTime: + def __init__(self): + self.__execute_datetime = datetime.now(timezone.utc).strftime(YYYYMMDDTHHMMSSTZ) + + def __str__(self) -> str: + return self.__execute_datetime + + def to_path(self) -> str: + return self.__execute_datetime.rstrip(MILLISEC_FORMAT).translate(str.maketrans({'-': '/', 'T': '/', ':': None, '.': None})) + + def format_date(self) -> str: + return self.__execute_datetime.rstrip(MILLISEC_FORMAT).translate(str.maketrans({'-': None, 'T': None, ':': None, '.': None})) diff --git a/ecs/crm-datafetch/src/util/logger.py b/ecs/crm-datafetch/src/util/logger.py new file mode 100644 index 00000000..47fd2e45 --- /dev/null +++ b/ecs/crm-datafetch/src/util/logger.py @@ -0,0 +1,37 @@ +import logging + +from src.system_var.environments import LOG_LEVEL + +# boto3関連モジュールのログレベルを事前に個別指定し、モジュール内のDEBUGログの表示を抑止する +for name in ["boto3", "botocore", "s3transfer", "urllib3"]: + logging.getLogger(name).setLevel(logging.WARNING) + + +class Logger(): + __logger: logging.Logger + + def __init__(self): + self.__logger = logging.getLogger() + + level = logging.getLevelName(LOG_LEVEL) + if not isinstance(level, int): + level = logging.INFO + self.__logger.setLevel(level) + + if not self.__logger.hasHandlers(): + handler = logging.StreamHandler() + self.__logger.addHandler(handler) + + formatter = logging.Formatter( + '[%(levelname)s]\t%(asctime)s\t%(message)s\n', + '%Y-%m-%d %H:%M:%S' + ) + + for handler in self.__logger.handlers: + handler.setFormatter(formatter) + + def get_logger(self) -> logging.Logger: + return self.__logger + + +logger_instance = Logger().get_logger() diff --git a/s3/config/crm/last_fetch_datetime/Account.json b/s3/config/crm/last_fetch_datetime/Account.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Account.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/AccountShare.json b/s3/config/crm/last_fetch_datetime/AccountShare.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/AccountShare.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Account_Territory_Loader_vod__c.json b/s3/config/crm/last_fetch_datetime/Account_Territory_Loader_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Account_Territory_Loader_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Approved_Document_vod__c.json b/s3/config/crm/last_fetch_datetime/Approved_Document_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Approved_Document_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Call2_Detail_vod__c.json b/s3/config/crm/last_fetch_datetime/Call2_Detail_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Call2_Detail_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Call2_Discussion_vod__c.json b/s3/config/crm/last_fetch_datetime/Call2_Discussion_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Call2_Discussion_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Call2_Key_Message_vod__c.json b/s3/config/crm/last_fetch_datetime/Call2_Key_Message_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Call2_Key_Message_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Call2_vod__c.json b/s3/config/crm/last_fetch_datetime/Call2_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Call2_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Call_Clickstream_vod__c.json b/s3/config/crm/last_fetch_datetime/Call_Clickstream_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Call_Clickstream_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Child_Account_vod__c.json b/s3/config/crm/last_fetch_datetime/Child_Account_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Child_Account_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Clm_Presentation_Slide_vod__c.json b/s3/config/crm/last_fetch_datetime/Clm_Presentation_Slide_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Clm_Presentation_Slide_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Clm_Presentation_vod__c.json b/s3/config/crm/last_fetch_datetime/Clm_Presentation_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Clm_Presentation_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Coaching_Report_vod__c.json b/s3/config/crm/last_fetch_datetime/Coaching_Report_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Coaching_Report_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Consent_Header_vod__c.json b/s3/config/crm/last_fetch_datetime/Consent_Header_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Consent_Header_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Consent_Line_vod__c.json b/s3/config/crm/last_fetch_datetime/Consent_Line_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Consent_Line_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Consent_Type_vod__c.json b/s3/config/crm/last_fetch_datetime/Consent_Type_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Consent_Type_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Contact.json b/s3/config/crm/last_fetch_datetime/Contact.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Contact.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Dynamic_Attribute_Configuration_vod__c.json b/s3/config/crm/last_fetch_datetime/Dynamic_Attribute_Configuration_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Dynamic_Attribute_Configuration_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Dynamic_Attribute_vod__c.json b/s3/config/crm/last_fetch_datetime/Dynamic_Attribute_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Dynamic_Attribute_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Email_Activity_vod__c.json b/s3/config/crm/last_fetch_datetime/Email_Activity_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Email_Activity_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Event_Attendee_vod__c.json b/s3/config/crm/last_fetch_datetime/Event_Attendee_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Event_Attendee_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Group.json b/s3/config/crm/last_fetch_datetime/Group.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Group.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Key_Message_vod__c.json b/s3/config/crm/last_fetch_datetime/Key_Message_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Key_Message_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/MSJ_Hospital_Medical_Regimen__c.json b/s3/config/crm/last_fetch_datetime/MSJ_Hospital_Medical_Regimen__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/MSJ_Hospital_Medical_Regimen__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/MSJ_Inquiry_Assignment__c.json b/s3/config/crm/last_fetch_datetime/MSJ_Inquiry_Assignment__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/MSJ_Inquiry_Assignment__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/MSJ_MR_Weekly_Report__c.json b/s3/config/crm/last_fetch_datetime/MSJ_MR_Weekly_Report__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/MSJ_MR_Weekly_Report__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/MSJ_Medical_Event_Evaluation__c.json b/s3/config/crm/last_fetch_datetime/MSJ_Medical_Event_Evaluation__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/MSJ_Medical_Event_Evaluation__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/MSJ_Medical_Regimen__c.json b/s3/config/crm/last_fetch_datetime/MSJ_Medical_Regimen__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/MSJ_Medical_Regimen__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/MSJ_Patient__c.json b/s3/config/crm/last_fetch_datetime/MSJ_Patient__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/MSJ_Patient__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Medical_Event_vod__c.json b/s3/config/crm/last_fetch_datetime/Medical_Event_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Medical_Event_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Medical_Inquiry_vod__c.json b/s3/config/crm/last_fetch_datetime/Medical_Inquiry_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Medical_Inquiry_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Medical_Insight_vod__c.json b/s3/config/crm/last_fetch_datetime/Medical_Insight_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Medical_Insight_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Multichannel_Activity_Line_vod__c.json b/s3/config/crm/last_fetch_datetime/Multichannel_Activity_Line_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Multichannel_Activity_Line_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Multichannel_Activity_vod__c.json b/s3/config/crm/last_fetch_datetime/Multichannel_Activity_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Multichannel_Activity_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Multichannel_Consent_vod__c.json b/s3/config/crm/last_fetch_datetime/Multichannel_Consent_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Multichannel_Consent_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/My_Setup_Products_vod__c.json b/s3/config/crm/last_fetch_datetime/My_Setup_Products_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/My_Setup_Products_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/ObjectTerritory2Association.json b/s3/config/crm/last_fetch_datetime/ObjectTerritory2Association.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/ObjectTerritory2Association.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Product_Group_vod__c.json b/s3/config/crm/last_fetch_datetime/Product_Group_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Product_Group_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Product_Metrics_vod__c.json b/s3/config/crm/last_fetch_datetime/Product_Metrics_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Product_Metrics_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Product_vod__c.json b/s3/config/crm/last_fetch_datetime/Product_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Product_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Profile.json b/s3/config/crm/last_fetch_datetime/Profile.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Profile.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Question_Response_vod__c.json b/s3/config/crm/last_fetch_datetime/Question_Response_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Question_Response_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/RecordType.json b/s3/config/crm/last_fetch_datetime/RecordType.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/RecordType.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Remote_Meeting_vod__c.json b/s3/config/crm/last_fetch_datetime/Remote_Meeting_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Remote_Meeting_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Sent_Email_vod__c.json b/s3/config/crm/last_fetch_datetime/Sent_Email_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Sent_Email_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Sent_Fragment_vod__c.json b/s3/config/crm/last_fetch_datetime/Sent_Fragment_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Sent_Fragment_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Survey_Question_vod__c.json b/s3/config/crm/last_fetch_datetime/Survey_Question_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Survey_Question_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Survey_Target_vod__c.json b/s3/config/crm/last_fetch_datetime/Survey_Target_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Survey_Target_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Survey_vod__c.json b/s3/config/crm/last_fetch_datetime/Survey_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Survey_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Territory2.json b/s3/config/crm/last_fetch_datetime/Territory2.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Territory2.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Territory2_ALL.json b/s3/config/crm/last_fetch_datetime/Territory2_ALL.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Territory2_ALL.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/Time_Off_Territory_vod__c.json b/s3/config/crm/last_fetch_datetime/Time_Off_Territory_vod__c.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/Time_Off_Territory_vod__c.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/User.json b/s3/config/crm/last_fetch_datetime/User.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/User.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/UserRole.json b/s3/config/crm/last_fetch_datetime/UserRole.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/UserRole.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/UserTerritory2Association.json b/s3/config/crm/last_fetch_datetime/UserTerritory2Association.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/UserTerritory2Association.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/last_fetch_datetime/UserTerritory2Association_ALL.json b/s3/config/crm/last_fetch_datetime/UserTerritory2Association_ALL.json new file mode 100644 index 00000000..7453dc17 --- /dev/null +++ b/s3/config/crm/last_fetch_datetime/UserTerritory2Association_ALL.json @@ -0,0 +1,4 @@ +{ + "last_fetch_datetime_from": "1900-01-01T00:00:00.000Z", + "last_fetch_datetime_to": "" +} diff --git a/s3/config/crm/object_info/crm_object_list_all.json b/s3/config/crm/object_info/crm_object_list_all.json new file mode 100644 index 00000000..0792da37 --- /dev/null +++ b/s3/config/crm/object_info/crm_object_list_all.json @@ -0,0 +1,47 @@ +{ + "objects": [ + { + "object_name": "Territory2", + "columns": [ + "Id", + "Name", + "Territory2TypeId", + "Territory2ModelId", + "ParentTerritory2Id", + "Description", + "ForecastUserId", + "AccountAccessLevel", + "OpportunityAccessLevel", + "CaseAccessLevel", + "ContactAccessLevel", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "DeveloperName", + "MSJ_Territory_Type__c", + "MSJ_Level__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": false, + "last_fetch_datetime_file_name": "Territory2_ALL.json", + "upload_file_name": "CRM_Territory2_ALL_{execute_datetime}" + }, + { + "object_name": "UserTerritory2Association", + "columns": [ + "Id", + "UserId", + "Territory2Id", + "IsActive", + "RoleInTerritory2", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp" + ], + "is_skip": false, + "is_update_last_fetch_datetime": false, + "last_fetch_datetime_file_name": "UserTerritory2Association_ALL.json", + "upload_file_name": "CRM_UserTerritory2Association_ALL_{execute_datetime}" + } + ] +} diff --git a/s3/config/crm/object_info/crm_object_list_diff.json b/s3/config/crm/object_info/crm_object_list_diff.json new file mode 100644 index 00000000..aa20d187 --- /dev/null +++ b/s3/config/crm/object_info/crm_object_list_diff.json @@ -0,0 +1,3009 @@ +{ + "objects": [ + { + "object_name": "Clm_Presentation_vod__c", + "columns": [ + "Id", + "OwnerId", + "IsDeleted", + "Name", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "Mobile_ID_vod__c", + "Presentation_Id_vod__c", + "Product_vod__c", + "Default_Presentation_vod__c", + "Training_vod__c", + "ParentId_vod__c", + "Hidden_vod__c", + "Type_vod__c", + "Approved_vod__c", + "Copied_From_vod__c", + "Copy_Date_vod__c", + "Survey_vod__c", + "Original_Record_ID_vod__c", + "Directory_vod__c", + "End_Date_vod__c", + "Start_Date_vod__c", + "Status_vod__c", + "VExternal_Id_vod__c", + "Vault_DNS_vod__c", + "Vault_Doc_Id_vod__c", + "Vault_External_Id_vod__c", + "Vault_GUID_vod__c", + "Vault_Last_Modified_Date_Time_vod__c", + "Version_vod__c", + "Enable_Survey_Overlay_vod__c", + "Description_vod__c", + "Keywords_vod__c", + "Content_Channel_vod__c", + "original_material_approved_in_veritas__c", + "keywords__c", + "trade_team__c", + "ewizard_link__c", + "business_function__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Clm_Presentation_Slide_vod__c", + "columns": [ + "Id", + "IsDeleted", + "Name", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "Clm_Presentation_vod__c", + "Key_Message_vod__c", + "Display_Order_vod__c", + "Sub_Presentation_vod__c", + "Mobile_ID_vod__c", + "External_ID_vod__c", + "VExternal_Id_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Medical_Insight_vod__c", + "columns": [ + "Id", + "OwnerId", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "Account_vod__c", + "Clinical_Trial_vod__c", + "Date_vod__c", + "Description_vod__c", + "Entity_Reference_Id_vod__c", + "Interaction_vod__c", + "Medical_Event_vod__c", + "Mobile_ID_vod__c", + "Other_Source_vod__c", + "Override_Lock_vod__c", + "Publication_vod__c", + "Status_vod__c", + "Summary_vod__c", + "Unlock_vod__c", + "Commercial_Medical__c", + "MSJ_Level_1A__c", + "MSJ_Level_1B__c", + "MSJ_Level_2A__c", + "MSJ_Level_2B__c", + "MSJ_Level_3A__c", + "MSJ_Level_3B__c", + "MSJ_Level_4A__c", + "MSJ_Level_4B__c", + "MSJ_SubStatus__c", + "MSJ_Type_A__c", + "MSJ_Type_B__c", + "MSJ_Description_Backup__c", + "MSJ_Country__c", + "MSJ_Received_at_Boomi__c", + "MSJ_Level_1A_Value__c", + "MSJ_Level_1B_Value__c", + "MSJ_Level_2A_Value__c", + "MSJ_Level_2B_Value__c", + "MSJ_Level_3A_Value__c", + "MSJ_Level_3B_Value__c", + "MSJ_Level_4A_Value__c", + "MSJ_Level_4B_Value__c", + "MSJ_Hospital_ID__c", + "MSJ_Hospital_Name__c", + "MSJ_Hospital__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "MSJ_MR_Weekly_Report__c", + "columns": [ + "Id", + "OwnerId", + "IsDeleted", + "Name", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "MSJ_Account_Name__c", + "MSJ_Activity_Results_Summary__c", + "MSJ_MUID__c", + "MSJ_Next_Week_Action_What__c", + "MSJ_Next_Week_Action_When__c", + "MSJ_Next_Week_Action_Where__c", + "MSJ_Next_Week_Action_Who__c", + "MSJ_Report_Week__c", + "MSJ_Target_Patient_Count__c", + "Mobile_ID_vod__c", + "MSJ_Activity_Results_Summary_HN__c", + "MSJ_Next_Week_Action_Where_HN__c", + "MSJ_Next_Week_Action_Who_HN__c", + "MSJ_Next_Week_Action_What_HN__c", + "MSJ_Next_Week_Action_When_HN__c", + "MSJ_Target_Patient_Count_HN__c", + "MSJ_Activity_Results_Summary_MCC__c", + "MSJ_Next_Week_Action_Where_MCC__c", + "MSJ_Next_Week_Action_Who_MCC__c", + "MSJ_Next_Week_Action_What_MCC__c", + "MSJ_Next_Week_Action_When_MCC__c", + "MSJ_Target_Patient_Count_MCC__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Account_Territory_Loader_vod__c", + "columns": [ + "Id", + "OwnerId", + "IsDeleted", + "Name", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "Account_vod__c", + "External_ID_vod__c", + "Territory_vod__c", + "Mobile_ID_vod__c", + "Territory_To_Add_vod__c", + "Territory_to_Drop_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Event_Attendee_vod__c", + "columns": [ + "Id", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "Attendee_vod__c", + "User_vod__c", + "Medical_Event_vod__c", + "Attendee_Type_vod__c", + "Status_vod__c", + "Contact_vod__c", + "Attendee_Name_vod__c", + "Account_vod__c", + "Start_Date_vod__c", + "Signature_vod__c", + "Signature_Datetime_vod__c", + "MSJ_Copy_Account_Type__c", + "MSJ_Evaluation__c", + "MSJ_Hospital__c", + "MSJ_Role__c", + "Mobile_ID_vod__c", + "MSJ_Evaluation_Comment__c", + "Position_vod__c", + "Talk_Title_vod__c", + "MSJ_Attendee_Reaction__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "ObjectTerritory2Association", + "columns": [ + "Id", + "ObjectId", + "Territory2Id", + "AssociationCause", + "SobjectType", + "IsDeleted", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Key_Message_vod__c", + "columns": [ + "Id", + "OwnerId", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "Description_vod__c", + "Product_vod__c", + "Product_Strategy_vod__c", + "Display_Order_vod__c", + "Active_vod__c", + "Category_vod__c", + "Vehicle_vod__c", + "CLM_ID_vod__c", + "Custom_Reaction_vod__c", + "Slide_Version_vod__c", + "Language_vod__c", + "Media_File_CRC_vod__c", + "Media_File_Name_vod__c", + "Media_File_Size_vod__c", + "Segment_vod__c", + "Disable_Actions_vod__c", + "VExternal_Id_vod__c", + "CDN_Path_vod__c", + "Status_vod__c", + "Vault_DNS_vod__c", + "Vault_Doc_Id_vod__c", + "Vault_External_Id_vod__c", + "Vault_GUID_vod__c", + "Vault_Last_Modified_Date_Time_vod__c", + "Is_Shared_Resource_vod__c", + "iOS_Viewer_vod__c", + "iOS_Resolution_vod__c", + "approved_for_distribution_date__c", + "approved_for_use_date__c", + "ewizard_link__c", + "expiration_date__c", + "keywords__c", + "trade_team__c", + "business_function__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Group", + "columns": [ + "Id", + "Name", + "DeveloperName", + "RelatedId", + "Type", + "Email", + "OwnerId", + "DoesSendEmailToMembers", + "DoesIncludeBosses", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Medical_Event_vod__c", + "columns": [ + "Id", + "OwnerId", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "LastActivityDate", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "Primary_Product__c", + "Description_vod__c", + "Start_Date_vod__c", + "Location__c", + "End_Date_vod__c", + "Secondary_Product__c", + "Website__c", + "Active_vod__c", + "Event_Type__c", + "MSJ_Area__c", + "MSJ_Business_Unit__c", + "MSJ_Comment__c", + "MSJ_Company__c", + "MSJ_Expense_App_No__c", + "MSJ_Form__c", + "MSJ_HQ_Area__c", + "MSJ_Location__c", + "MSJ_MR__c", + "MSJ_Number_of_Attendee__c", + "MSJ_Product__c", + "MSJ_Site__c", + "MSJ_Type__c", + "MSJ_Number_of_Attendee_Auto_Calc__c", + "MSJ_Number_of_Attendee_Invited__c", + "Account_vod__c", + "MSJ_MUID__c", + "Country_Name_vod__c", + "MSJ_CE_SIPAGL_Updater__c", + "MSJ_CE_SIPAGL_1A__c", + "MSJ_CE_SIPAGL_1B__c", + "MSJ_CE_SIPAGL_2__c", + "MSJ_CE_SIPAGL_3__c", + "MSJ_CE_SIPAGL_4__c", + "MSJ_CE_SIPAGL_5__c", + "MSJ_CE_SIPAGL_Comment__c", + "MSJ_CE_SIPAGL_1A_date__c", + "MSJ_CE_SIPAGL_6__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "MSJ_Medical_Event_Evaluation__c", + "columns": [ + "Id", + "IsDeleted", + "Name", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "MSJ_Medical_Event__c", + "MSJ_Evaluation_Comment__c", + "MSJ_Evaluation__c", + "Mobile_ID_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Coaching_Report_vod__c", + "columns": [ + "Id", + "OwnerId", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "Mobile_ID_vod__c", + "Manager_vod__c", + "Employee_vod__c", + "Review_Date__c", + "Review_Period__c", + "Status__c", + "Comments__c", + "Strategic_Planning__c", + "Customer_Focus__c", + "Knowledge_Expertise__c", + "Business_Account_Planning__c", + "Call_Productivity__c", + "Overall_Rating__c", + "MSJ_A01__c", + "MSJ_A02__c", + "MSJ_A03__c", + "MSJ_AM_Memo__c", + "MSJ_Aid_Total__c", + "MSJ_C0_GC__c", + "MSJ_C1_GC__c", + "MSJ_C2_GC__c", + "MSJ_Countermeasure__c", + "MSJ_Deadline__c", + "MSJ_Double_Visit_Time__c", + "MSJ_Hospital__c", + "MSJ_K01_FE__c", + "MSJ_K01_ONC__c", + "MSJ_K02_FE__c", + "MSJ_K02_ONC__c", + "MSJ_K03_FE__c", + "MSJ_K03_ONC__c", + "MSJ_K04_FE__c", + "MSJ_K04_ONC__c", + "MSJ_K05_FE__c", + "MSJ_K05_ONC__c", + "MSJ_K06_FE__c", + "MSJ_K06_ONC__c", + "MSJ_K0_GC__c", + "MSJ_K1_GC__c", + "MSJ_K2_GC__c", + "MSJ_Knowledge_Total__c", + "MSJ_L0_GC__c", + "MSJ_L1_GC__c", + "MSJ_L2_GC__c", + "MSJ_MR_GC__c", + "MSJ_MR_Problems__c", + "MSJ_N0_GC__c", + "MSJ_N1_GC__c", + "MSJ_N2_GC__c", + "MSJ_Num_of_DTL__c", + "MSJ_P01__c", + "MSJ_P02__c", + "MSJ_P03__c", + "MSJ_P04__c", + "MSJ_P05__c", + "MSJ_P0_GC__c", + "MSJ_P1_GC__c", + "MSJ_P2_GC__c", + "MSJ_PlanningTotal__c", + "MSJ_R0_GC__c", + "MSJ_R1_GC__c", + "MSJ_R2_GC__c", + "MSJ_S01__c", + "MSJ_S02__c", + "MSJ_S03__c", + "MSJ_S04__c", + "MSJ_S05__c", + "MSJ_S06__c", + "MSJ_S07__c", + "MSJ_S08__c", + "MSJ_S09__c", + "MSJ_S10__c", + "MSJ_S11__c", + "MSJ_S12__c", + "MSJ_Skill_Total__c", + "MSJ_After_Call_01__c", + "MSJ_After_Call_02__c", + "MSJ_After_Call_03__c", + "MSJ_After_Call_04__c", + "MSJ_Closing__c", + "MSJ_Comment_by_MR__c", + "MSJ_Confirmed_by_MR__c", + "MSJ_Createdby__c", + "MSJ_FT_AM_Name__c", + "MSJ_Interview_Preparation__c", + "MSJ_Interview_Reflection__c", + "MSJ_Notify_To_MR__c", + "MSJ_Opening__c", + "MSJ_Others_01_Result__c", + "MSJ_Others_01__c", + "MSJ_Others_02_Result__c", + "MSJ_Others_02__c", + "MSJ_Patient_Thinking__c", + "MSJ_Probing__c", + "MSJ_Supporting__c", + "MSJ_Patient_Thinking_for_FE__c", + "MSJ_After_Call_05__c", + "MSJ_After_Call_06__c", + "MSJ_After_Call_07__c", + "MSJ_After_Call_08__c", + "MSJ_Createdby_FE__c", + "MSJ_Createdby_ONC__c", + "MSJ_Development_Level__c", + "MSJ_Interview_Prep_01__c", + "MSJ_Interview_Prep_02__c", + "MSJ_Leadership_Style__c", + "MSJ_Overcome_01__c", + "MSJ_Overcome_02__c", + "MSJ_Overcome_03__c", + "MSJ_Overcome_04__c", + "MSJ_Review_01__c", + "MSJ_Review_02__c", + "MSJ_SK_01__c", + "MSJ_SK_02__c", + "MSJ_SK_03__c", + "MSJ_SK_04__c", + "MSJ_SK_05__c", + "MSJ_SK_06__c", + "MSJ_SK_07__c", + "MSJ_SK_08__c", + "MSJ_SK_09__c", + "MSJ_SK_10__c", + "MSJ_Specific_Action__c", + "MSJ_Training_Point__c", + "MSJ_Efforts_of_Year__c", + "MSJ_Efforts_of_Month__c", + "MSJ_Skill_Task__c", + "MSJ_Action_of_This_Month__c", + "MSJ_Achievement_of_This_Month__c", + "MSJ_Comment_from_AM__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Call2_vod__c", + "columns": [ + "Id", + "OwnerId", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "LastActivityDate", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "Call_Comments_vod__c", + "Sample_Card_vod__c", + "Add_Detail_vod__c", + "Property_vod__c", + "Account_vod__c", + "zvod_Product_Discussion_vod__c", + "Status_vod__c", + "Parent_Address_vod__c", + "Account_Plan_vod__c", + "zvod_SaveNew_vod__c", + "Next_Call_Notes_vod__c", + "Pre_Call_Notes_vod__c", + "Mobile_ID_vod__c", + "zvod_Account_Credentials_vod_c_vod__c", + "zvod_Account_Preferred_Name_vod_c_vod__c", + "zvod_Account_Sample_Status_vod_c_vod__c", + "zvod_Attendees_vod__c", + "zvod_Key_Messages_vod__c", + "zvod_Detailing_vod__c", + "zvod_Expenses_vod__c", + "zvod_Followup_vod__c", + "zvod_Samples_vod__c", + "zvod_Save_vod__c", + "zvod_Submit_vod__c", + "zvod_Delete_vod__c", + "Activity_Type__c", + "Significant_Event__c", + "Location_vod__c", + "Subject_vod__c", + "Unlock_vod__c", + "Call_Datetime_vod__c", + "Disbursed_To_vod__c", + "Disclaimer_vod__c", + "Request_Receipt_vod__c", + "Signature_Date_vod__c", + "Signature_vod__c", + "Territory_vod__c", + "Submitted_By_Mobile_vod__c", + "Call_Type_vod__c", + "Add_Key_Message_vod__c", + "Address_vod__c", + "Attendees_vod__c", + "Attendee_Type_vod__c", + "Call_Date_vod__c", + "Detailed_Products_vod__c", + "No_Disbursement_vod__c", + "Parent_Call_vod__c", + "User_vod__c", + "Contact_vod__c", + "zvod_Entity_vod__c", + "Medical_Event_vod__c", + "Mobile_Created_Datetime_vod__c", + "Mobile_Last_Modified_Datetime_vod__c", + "License_vod__c", + "Is_Parent_Call_vod__c", + "Entity_Display_Name_vod__c", + "Override_Lock_vod__c", + "Last_Device_vod__c", + "Ship_Address_Line_1_vod__c", + "Ship_Address_Line_2_vod__c", + "Ship_City_vod__c", + "Ship_Country_vod__c", + "Ship_License_Expiration_Date_vod__c", + "Ship_License_Status_vod__c", + "Ship_License_vod__c", + "Ship_State_vod__c", + "Ship_To_Address_vod__c", + "Ship_Zip_vod__c", + "Ship_To_Address_Text_vod__c", + "CLM_vod__c", + "zvod_CLMDetails_vod__c", + "Is_Sampled_Call_vod__c", + "zvod_Surveys_vod__c", + "Presentations_vod__c", + "Entity_Reference_Id_vod__c", + "Error_Reference_Call_vod__c", + "Duration_vod__c", + "Color_vod__c", + "Allowed_Products_vod__c", + "zvod_Attachments_vod__c", + "Sample_Card_Reason_vod__c", + "ASSMCA_vod__c", + "Address_Line_1_vod__c", + "Address_Line_2_vod__c", + "City_vod__c", + "DEA_Address_Line_1_vod__c", + "DEA_Address_Line_2_vod__c", + "DEA_Address_vod__c", + "DEA_City_vod__c", + "DEA_Expiration_Date_vod__c", + "DEA_State_vod__c", + "DEA_Zip_4_vod__c", + "DEA_Zip_vod__c", + "DEA_vod__c", + "Ship_Zip_4_vod__c", + "State_vod__c", + "Zip_4_vod__c", + "Zip_vod__c", + "Sample_Send_Card_vod__c", + "zvod_Address_vod_c_DEA_Status_vod_c_vod__c", + "Signature_Page_Image_vod__c", + "Credentials_vod__c", + "Salutation_vod__c", + "zvod_Account_Call_Reminder_vod_c_vod__c", + "MSJ_Meeting_Duration__c", + "MSJ_Double_Visit_AM__c", + "zvod_Business_Account_vod__c", + "Product_Priority_1_vod__c", + "Product_Priority_2_vod__c", + "Product_Priority_3_vod__c", + "Product_Priority_4_vod__c", + "Product_Priority_5_vod__c", + "zvod_More_Actions_vod__c", + "zvod_Call_Conflict_Status_vod__c", + "Signature_Timestamp_vod__c", + "Expense_Amount_vod__c", + "Total_Expense_Attendees_Count_vod__c", + "Attendee_list_vod__c", + "Expense_Post_Status_vod__c", + "Attendee_Post_Status_vod__c", + "Expense_System_External_ID_vod__c", + "Incurred_Expense_vod__c", + "Assigner_vod__c", + "Assignment_Datetime_vod__c", + "zvod_Call_Objective_vod__c", + "Signature_Location_Longitude_vod__c", + "Signature_Location_Latitude_vod__c", + "Location_Services_Status_vod__c", + "MSJ_Double_Visit_Other__c", + "MSJ_Comment__c", + "MSJ_For_Reporting__c", + "MSJ_Number_of_Attendees__c", + "MSJ_Main_Dept__c", + "Planned_Type_vjh__c", + "Cobrowse_URL_Participant_vod__c", + "MSJ_Activity_Method_Text__c", + "MSJ_Activity_Method__c", + "MSJ_Classification__c", + "MSJ_Double_Visit_MSL__c", + "MSJ_MSL_Comment_for_MR__c", + "MSJ_APD__c", + "Medical_Inquiry_vod__c", + "MSJ_Call_Type_MSJ__c", + "MSJ_Prescription_Request__c", + "MSJ_Patient_Follow__c", + "Child_Account_Id_vod__c", + "Child_Account_vod__c", + "Location_Id_vod__c", + "Location_Name_vod__c", + "MSJ_Comments_about_technology__c", + "Remote_Meeting_vod__c", + "Veeva_Remote_Meeting_Id_vod__c", + "MSJ_Activity_Type_Report__c", + "MSJ_Activity_Type__c", + "MSJ_Activity__c", + "MSJ_Comments__c", + "MSJ_Therapy__c", + "MSJ_Time_Hrs__c", + "EMDS_CO_Reference__c", + "EMDS_Call_Sub_Type__c", + "EMDS_Call_Type__c", + "EMDS_Call_Unsuccessful__c", + "EMDS_Congress_Type__c", + "EMDS_Date_of_Service__c", + "EMDS_Fertility_DisInterest__c", + "EMDS_Fertility_Interest__c", + "EMDS_Installed_Equipment__c", + "EMDS_Pipeline_Stage_Value__c", + "EMDS_Pipeline_Stage__c", + "EMDS_Pipeline__c", + "EMDS_Reason_for_Call__c", + "EMDS_Training_Completed__c", + "MSJ_BrainStorming__c", + "MSJ_SIPAGL_1A__c", + "MSJ_SIPAGL_1B__c", + "MSJ_SIPAGL_2__c", + "MSJ_SIPAGL_3__c", + "MSJ_SIPAGL_4A__c", + "MSJ_SIPAGL_5A__c", + "MSJ_SIPAGL_comment__c", + "MSJ_SIPAGL_4B__c", + "MSJ_SIPAGL_5B__c", + "Location_Text_vod__c", + "Call_Channel_vod__c", + "MSJ_Scientific_Interaction__c", + "MSJ_Activity_Email_Reply__c", + "MSJ_Interaction_Duration__c", + "MSJ_SIPAGL_1A_date__c", + "MSJ_CoPromotion__c", + "Call_Channel_Formula_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Call2_Detail_vod__c", + "columns": [ + "Id", + "IsDeleted", + "Name", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "Is_Parent_Call_vod__c", + "Call2_vod__c", + "Product_vod__c", + "Detail_Priority_vod__c", + "Mobile_ID_vod__c", + "Override_Lock_vod__c", + "Type_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Call2_Key_Message_vod__c", + "columns": [ + "Id", + "IsDeleted", + "Name", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "Account_vod__c", + "Call2_vod__c", + "Reaction_vod__c", + "Product_vod__c", + "Key_Message_vod__c", + "Mobile_ID_vod__c", + "Contact_vod__c", + "Call_Date_vod__c", + "User_vod__c", + "Category_vod__c", + "Vehicle_vod__c", + "Is_Parent_Call_vod__c", + "Override_Lock_vod__c", + "CLM_ID_vod__c", + "Slide_Version_vod__c", + "Duration_vod__c", + "Presentation_ID_vod__c", + "Start_Time_vod__c", + "Attendee_Type_vod__c", + "Entity_Reference_Id_vod__c", + "Segment_vod__c", + "Display_Order_vod__c", + "Clm_Presentation_Name_vod__c", + "Clm_Presentation_Version_vod__c", + "Clm_Presentation_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Call_Clickstream_vod__c", + "columns": [ + "Id", + "IsDeleted", + "Name", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "Answer_vod__c", + "Call_vod__c", + "Key_Message_vod__c", + "Mobile_ID_vod__c", + "Popup_Opened_vod__c", + "Possible_Answers_vod__c", + "Presentation_ID_vod__c", + "Product_vod__c", + "Range_Value_vod__c", + "Rollover_Entered_vod__c", + "Selected_Items_vod__c", + "CLM_ID_vod__c", + "Question_vod__c", + "Survey_Type_vod__c", + "Text_Entered_vod__c", + "Toggle_Button_On_vod__c", + "Track_Element_Description_vod__c", + "Track_Element_Id_vod__c", + "Track_Element_Type_vod__c", + "Usage_Duration_vod__c", + "Usage_Start_Time_vod__c", + "AuxillaryId_vod__c", + "ParentId_vod__c", + "Revision_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Call2_Discussion_vod__c", + "columns": [ + "Id", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "Account_vod__c", + "Call2_vod__c", + "Activity__c", + "Comments__c", + "Contact_vod__c", + "Call_Date_vod__c", + "Product_Strategy_vod__c", + "Product_Tactic_vod__c", + "Restricted_Comments__c", + "Product_vod__c", + "Presentation__c", + "Discussion_Topics__c", + "Slides__c", + "User_vod__c", + "Indication__c", + "Mobile_ID_vod__c", + "Medical_Event_vod__c", + "Is_Parent_Call_vod__c", + "Override_Lock_vod__c", + "zvod_Product_Map_vod__c", + "Attendee_Type_vod__c", + "Entity_Reference_Id_vod__c", + "Account_Tactic_vod__c", + "MSJ_Material_Type__c", + "MSJ_Discussion_Contents__c", + "MSJ_IST_Minutes__c", + "MSJ_Off_Label_Minutes__c", + "MSJ_Discussion_Objectives__c", + "MSJ_Insight__c", + "EMDS_Materials__c", + "EMDS_Topic__c", + "MSJ_Visit_Purpose__c", + "MSJ_Insight_Count__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Time_Off_Territory_vod__c", + "columns": [ + "Id", + "OwnerId", + "IsDeleted", + "Name", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "LastActivityDate", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "Reason_vod__c", + "Territory_vod__c", + "Date_vod__c", + "Status_vod__c", + "Time_vod__c", + "Hours_vod__c", + "Mobile_ID_vod__c", + "Hours_off_vod__c", + "Start_Time_vod__c", + "MSJ_Day__c", + "MSJ_Comment__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Dynamic_Attribute_vod__c", + "columns": [ + "Id", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "Account_vod__c", + "Active_vod__c", + "Dynamic_Attribute_Configuration_vod__c", + "Dynamic_Attribute_Description_vod__c", + "Dynamic_Attribute_Help_Text_vod__c", + "Dynamic_Attribute_Label_vod__c", + "Dynamic_Attribute_Name_vod__c", + "Dynamic_Attribute_Record_Type_vod__c", + "Dynamic_Attribute_Value_Checkbox_vod__c", + "Dynamic_Attribute_Value_Date_Time_vod__c", + "Dynamic_Attribute_Value_Date_vod__c", + "Dynamic_Attribute_Value_Number_vod__c", + "Dynamic_Attribute_Value_Text_Area_vod__c", + "Dynamic_Attribute_Value_Text_vod__c", + "Mobile_ID_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Dynamic_Attribute_Configuration_vod__c", + "columns": [ + "Id", + "OwnerId", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "Applies_To_vod__c", + "Attribute_Label_vod__c", + "Attribute_Name_vod__c", + "Available_Values_vod__c", + "Description_vod__c", + "Detail_Group_vod__c", + "Display_Order_vod__c", + "External_ID_vod__c", + "Help_Text_vod__c", + "Product_vod__c", + "Read_Only_vod__c", + "Section_Name_vod__c", + "Sharing_Group_vod__c", + "Status_vod__c", + "Track_Changes_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Territory2", + "columns": [ + "Id", + "Name", + "Territory2TypeId", + "Territory2ModelId", + "ParentTerritory2Id", + "Description", + "ForecastUserId", + "AccountAccessLevel", + "OpportunityAccessLevel", + "CaseAccessLevel", + "ContactAccessLevel", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "DeveloperName", + "MSJ_Territory_Type__c", + "MSJ_Level__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Profile", + "columns": [ + "Id", + "Name", + "PermissionsEmailSingle", + "PermissionsEmailMass", + "PermissionsEditTask", + "PermissionsEditEvent", + "PermissionsExportReport", + "PermissionsImportPersonal", + "PermissionsDataExport", + "PermissionsManageUsers", + "PermissionsEditPublicFilters", + "PermissionsEditPublicTemplates", + "PermissionsModifyAllData", + "PermissionsManageCases", + "PermissionsManageSolutions", + "PermissionsCustomizeApplication", + "PermissionsEditReadonlyFields", + "PermissionsRunReports", + "PermissionsViewSetup", + "PermissionsTransferAnyEntity", + "PermissionsNewReportBuilder", + "PermissionsManageSelfService", + "PermissionsManageCssUsers", + "PermissionsActivateContract", + "PermissionsApproveContract", + "PermissionsImportLeads", + "PermissionsManageLeads", + "PermissionsTransferAnyLead", + "PermissionsViewAllData", + "PermissionsEditPublicDocuments", + "PermissionsViewEncryptedData", + "PermissionsEditBrandTemplates", + "PermissionsEditHtmlTemplates", + "PermissionsManageTranslation", + "PermissionsDeleteActivatedContract", + "PermissionsSendSitRequests", + "PermissionsApiUserOnly", + "PermissionsManageRemoteAccess", + "PermissionsCanUseNewDashboardBuilder", + "PermissionsManageCategories", + "PermissionsConvertLeads", + "PermissionsTestInstanceCreate", + "PermissionsPasswordNeverExpires", + "PermissionsUseTeamReassignWizards", + "PermissionsInstallMultiforce", + "PermissionsPublishMultiforce", + "PermissionsEditOppLineItemUnitPrice", + "PermissionsManageTerritories", + "PermissionsCreateMultiforce", + "PermissionsBulkApiHardDelete", + "PermissionsInboundMigrationToolsUser", + "PermissionsSolutionImport", + "PermissionsManageCallCenters", + "PermissionsManageSynonyms", + "PermissionsOutboundMigrationToolsUser", + "PermissionsViewContent", + "PermissionsManageEmailClientConfig", + "PermissionsEnableNotifications", + "PermissionsManageDataIntegrations", + "PermissionsDistributeFromPersWksp", + "PermissionsViewDataCategories", + "PermissionsManageDataCategories", + "PermissionsAuthorApex", + "PermissionsManageMobile", + "PermissionsApiEnabled", + "PermissionsManageCustomReportTypes", + "PermissionsEditCaseComments", + "PermissionsTransferAnyCase", + "PermissionsContentAdministrator", + "PermissionsCreateWorkspaces", + "PermissionsManageContentPermissions", + "PermissionsManageContentProperties", + "PermissionsManageContentTypes", + "PermissionsScheduleJob", + "PermissionsManageExchangeConfig", + "PermissionsManageAnalyticSnapshots", + "PermissionsScheduleReports", + "PermissionsManageBusinessHourHolidays", + "PermissionsManageDynamicDashboards", + "PermissionsManageInteraction", + "PermissionsViewMyTeamsDashboards", + "PermissionsResetPasswords", + "PermissionsFlowUFLRequired", + "PermissionsActivitiesAccess", + "PermissionsEmailTemplateManagement", + "PermissionsEmailAdministration", + "PermissionsChatterFileLink", + "PermissionsForceTwoFactor", + "PermissionsViewEventLogFiles", + "PermissionsManageNetworks", + "PermissionsManageAuthProviders", + "PermissionsRunFlow", + "PermissionsCreateCustomizeDashboards", + "PermissionsCreateDashboardFolders", + "PermissionsViewPublicDashboards", + "PermissionsManageDashbdsInPubFolders", + "PermissionsCreateCustomizeReports", + "PermissionsCreateReportFolders", + "PermissionsViewPublicReports", + "PermissionsManageReportsInPubFolders", + "PermissionsEditMyDashboards", + "PermissionsEditMyReports", + "PermissionsViewAllUsers", + "PermissionsConnectOrgToEnvironmentHub", + "PermissionsCreateCustomizeFilters", + "PermissionsContentHubUser", + "PermissionsGovernNetworks", + "PermissionsSalesConsole", + "PermissionsTwoFactorApi", + "PermissionsDeleteTopics", + "PermissionsEditTopics", + "PermissionsCreateTopics", + "PermissionsAssignTopics", + "PermissionsIdentityEnabled", + "PermissionsIdentityConnect", + "PermissionsContentWorkspaces", + "PermissionsCustomMobileAppsAccess", + "PermissionsViewHelpLink", + "PermissionsManageProfilesPermissionsets", + "PermissionsAssignPermissionSets", + "PermissionsManageRoles", + "PermissionsManageIpAddresses", + "PermissionsManageSharing", + "PermissionsManageInternalUsers", + "PermissionsManagePasswordPolicies", + "PermissionsManageLoginAccessPolicies", + "PermissionsManageCustomPermissions", + "PermissionsStdAutomaticActivityCapture", + "PermissionsManageTwoFactor", + "PermissionsDebugApex", + "PermissionsLightningExperienceUser", + "PermissionsConfigCustomRecs", + "PermissionsSubmitMacrosAllowed", + "PermissionsBulkMacrosAllowed", + "PermissionsManageSessionPermissionSets", + "PermissionsCreateAuditFields", + "PermissionsUpdateWithInactiveOwner", + "PermissionsManageSandboxes", + "PermissionsAutomaticActivityCapture", + "PermissionsImportCustomObjects", + "PermissionsDelegatedTwoFactor", + "PermissionsSelectFilesFromSalesforce", + "PermissionsModerateNetworkUsers", + "PermissionsMergeTopics", + "PermissionsSubscribeToLightningReports", + "PermissionsManagePvtRptsAndDashbds", + "PermissionsAllowLightningLogin", + "PermissionsCampaignInfluence2", + "PermissionsViewDataAssessment", + "PermissionsCanApproveFeedPost", + "PermissionsAllowViewEditConvertedLeads", + "PermissionsShowCompanyNameAsUserBadge", + "PermissionsAccessCMC", + "PermissionsViewHealthCheck", + "PermissionsManageHealthCheck", + "PermissionsPackaging2", + "PermissionsManageCertificates", + "PermissionsCreateReportInLightning", + "PermissionsPreventClassicExperience", + "PermissionsListEmailSend", + "PermissionsChangeDashboardColors", + "PermissionsManageRecommendationStrategies", + "PermissionsManagePropositions", + "PermissionsSubscribeReportRolesGrps", + "PermissionsSubscribeDashboardRolesGrps", + "PermissionsUseWebLink", + "PermissionsHasUnlimitedNBAExecutions", + "PermissionsViewOnlyEmbeddedAppUser", + "PermissionsViewAllActivities", + "PermissionsSubscribeReportToOtherUsers", + "PermissionsLightningConsoleAllowedForUser", + "PermissionsSubscribeReportsRunAsUser", + "PermissionsSubscribeToLightningDashboards", + "PermissionsSubscribeDashboardToOtherUsers", + "PermissionsCreateLtngTempInPub", + "PermissionsTransactionalEmailSend", + "PermissionsViewPrivateStaticResources", + "PermissionsCreateLtngTempFolder", + "PermissionsApexRestServices", + "PermissionsEnableCommunityAppLauncher", + "PermissionsGiveRecognitionBadge", + "PermissionsUseMySearch", + "PermissionsLtngPromoReserved01UserPerm", + "PermissionsManageSubscriptions", + "PermissionsManageSurveys", + "PermissionsUseAssistantDialog", + "PermissionsUseQuerySuggestions", + "PermissionsViewRoles", + "PermissionsLMOutboundMessagingUserPerm", + "PermissionsModifyDataClassification", + "PermissionsPrivacyDataAccess", + "PermissionsQueryAllFiles", + "PermissionsModifyMetadata", + "PermissionsManageCMS", + "PermissionsSandboxTestingInCommunityApp", + "PermissionsCanEditPrompts", + "PermissionsViewUserPII", + "PermissionsManageHubConnections", + "PermissionsB2BMarketingAnalyticsUser", + "PermissionsTraceXdsQueries", + "PermissionsViewAllCustomSettings", + "PermissionsViewAllForeignKeyNames", + "PermissionsHeadlessCMSAccess", + "PermissionsLMEndMessagingSessionUserPerm", + "PermissionsConsentApiUpdate", + "PermissionsAccessContentBuilder", + "PermissionsAccountSwitcherUser", + "PermissionsManageC360AConnections", + "PermissionsManageReleaseUpdates", + "PermissionsViewAllProfiles", + "PermissionsSkipIdentityConfirmation", + "PermissionsSendCustomNotifications", + "PermissionsPackaging2Delete", + "PermissionsFSCComprehensiveUserAccess", + "PermissionsManageTrustMeasures", + "PermissionsViewTrustMeasures", + "PermissionsIsotopeCToCUser", + "PermissionsIsotopeAccess", + "PermissionsIsotopeLEX", + "PermissionsQuipMetricsAccess", + "PermissionsQuipUserEngagementMetrics", + "PermissionsManageExternalConnections", + "PermissionsAIViewInsightObjects", + "PermissionsAICreateInsightObjects", + "PermissionsNativeWebviewScrolling", + "PermissionsViewDeveloperName", + "Type", + "UserLicenseId", + "UserType", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "Description", + "LastViewedDate", + "LastReferencedDate" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "My_Setup_Products_vod__c", + "columns": [ + "Id", + "OwnerId", + "IsDeleted", + "Name", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "Product_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Multichannel_Activity_vod__c", + "columns": [ + "Id", + "OwnerId", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "Account_External_ID_Map_vod__c", + "Account_vod__c", + "Call_vod__c", + "City_vod__c", + "Client_Name_vod__c", + "Client_OS_vod__c", + "Client_Type_vod__c", + "Country_vod__c", + "Debug_vod__c", + "Device_vod__c", + "IP_Address_vod__c", + "Multichannel_Activity_vod__c", + "Referring_Site_vod__c", + "Region_vod__c", + "Sent_Email_vod__c", + "Session_Id_vod__c", + "Site_vod__c", + "Start_DateTime_vod__c", + "Total_Duration_vod__c", + "URL_vod__c", + "User_Agent_vod__c", + "VExternal_Id_vod__c", + "Viewport_Height_vod__c", + "Viewport_Width_vod__c", + "Color_vod__c", + "Icon_vod__c", + "MCD_Primary_Key_vod__c", + "Record_Type_Name_vod__c", + "MSJ_Date_Opened__c", + "MSJ_Sent_Date__c", + "MSJ_Email_Subject__c", + "MSJ_Opens__c", + "MSJ_Email_Status__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Multichannel_Activity_Line_vod__c", + "columns": [ + "Id", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "Multichannel_Activity_vod__c", + "Call_vod__c", + "Custom_vod__c", + "DateTime_vod__c", + "Debug_vod__c", + "Detail_Group_VExternal_Id_vod__c", + "Detail_Group_vod__c", + "Duration_vod__c", + "Event_Subtype_vod__c", + "Event_Type_vod__c", + "Key_Message_VExternal_Id_vod__c", + "Key_Message_vod__c", + "Multichannel_Content_Asset_Id_vod__c", + "Multichannel_Content_Asset_Version_vod__c", + "Multichannel_Content_Asset_vod__c", + "Multichannel_Content_vod__c", + "Product_VExternal_Id_vod__c", + "Product_vod__c", + "Sent_Email_vod__c", + "VExternal_Id_vod__c", + "Video_Last_Viewed_Time_vod__c", + "Video_Length_vod__c", + "Video_Total_Time_Spent_vod__c", + "View_Order_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Multichannel_Consent_vod__c", + "columns": [ + "Id", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "Account_vod__c", + "Capture_Datetime_vod__c", + "Channel_Value_vod__c", + "Detail_Group_vod__c", + "External_ID_vod__c", + "Last_Device_vod__c", + "Mobile_ID_vod__c", + "Opt_Expiration_Date_vod__c", + "Opt_Type_vod__c", + "Optout_Event_Type_vod__c", + "Product_vod__c", + "Signature_Datetime_vod__c", + "Signature_ID_vod__c", + "Signature_vod__c", + "Sample_Consent_Template_Data_vod__c", + "Sample_Consent_Template_vod__c", + "Consent_Line_vod__c", + "Consent_Type_vod__c", + "Default_Consent_Text_vod__c", + "Disclaimer_Text_vod__c", + "Sub_Channel_Key_vod__c", + "Consent_Confirm_Datetime_vod__c", + "Related_Transaction_Id_vod__c", + "Sent_Email_vod__c", + "Content_Type_vod__c", + "Receipt_Email_vod__c", + "Receipt_Sent_Email_Transaction_Id_vod__c", + "Receipt_Sent_Email_vod__c", + "Captured_By_vod__c", + "Opt_Out_Disclaimer_Text_vod__c", + "Channel_Source_vod__c", + "Union_Id_vod__c", + "User_Last_Notified_vod__c", + "Sub_Channel_Display_Name__c", + "MSJ_Consent_Source__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Medical_Inquiry_vod__c", + "columns": [ + "Id", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "Account_vod__c", + "Address_Line_1_vod__c", + "Address_Line_2_vod__c", + "City_vod__c", + "Delivery_Method_vod__c", + "Email_vod__c", + "Fax_Number_vod__c", + "Inquiry_Text__c", + "Lock_vod__c", + "Mobile_ID_vod__c", + "Phone_Number_vod__c", + "Product__c", + "Rush_Delivery__c", + "Signature_Date_vod__c", + "Signature_vod__c", + "State_vod__c", + "Status_vod__c", + "Zip_vod__c", + "zvod_Delivery_Method_vod__c", + "zvod_Disclaimer_vod__c", + "Submitted_By_Mobile_vod__c", + "Disclaimer_vod__c", + "Entity_Reference_Id_vod__c", + "Call2_vod__c", + "Country_vod__c", + "Override_Lock_vod__c", + "MSJ_Department__c", + "MSJ_Doctor_Name__c", + "MSJ_Hospital_Name__c", + "MSJ_Indication__c", + "MSJ_Inquiry_Assignment__c", + "MSJ_Inquiry_Date__c", + "MSJ_Inquiry_Input_Manager__c", + "MSJ_Inquiry_Input_User__c", + "MSJ_MSL_Manager__c", + "MSJ_Notice_to_MR__c", + "MSJ_Person_in_charge_1__c", + "MSJ_Person_in_charge_2__c", + "MSJ_Product_for_MEC__c", + "MSJ_Product_for_MR__c", + "MSJ_Reply_Date__c", + "MSJ_Reply_User__c", + "MSJ_Reply__c", + "MSJ_Title__c", + "MSJ_AE_Infomation__c", + "MSJ_FAQ_Number_Report__c", + "MSJ_Return_Call_Report__c", + "MSJ_Inquiry_Origin_Report__c", + "MSJ_AE_Report__c", + "MSJ_Background__c", + "MSJ_MSL_Support__c", + "MSJ_Material_Requirement__c", + "MSJ_Hospital_Name_Disp__c", + "MSJ_Hospital__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Email_Activity_vod__c", + "columns": [ + "Id", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "LastActivityDate", + "MayEdit", + "IsLocked", + "Sent_Email_vod__c", + "Activity_DateTime_vod__c", + "City_vod__c", + "Click_URL_vod__c", + "Client_Name_vod__c", + "Client_OS_vod__c", + "Client_Type_vod__c", + "Country_vod__c", + "Device_Type_vod__c", + "Event_Msg_vod__c", + "Event_type_vod__c", + "IP_Address_vod__c", + "Region_vod__c", + "User_Agent_vod__c", + "Vault_Doc_ID_vod__c", + "Vault_Doc_Name_vod__c", + "Vault_Document_Major_Version_vod__c", + "Vault_Document_Minor_Version_vod__c", + "Vault_Document_Number_vod__c", + "Vault_Document_Title_vod__c", + "Vault_Instance_ID_vod__c", + "Preference_Modification_vod__c", + "Approved_Document_vod__c", + "Link_Name_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "User", + "columns": [ + "Id", + "Username", + "LastName", + "FirstName", + "Name", + "CompanyName", + "Division", + "Department", + "Title", + "Street", + "City", + "State", + "PostalCode", + "Country", + "Latitude", + "Longitude", + "GeocodeAccuracy", + "Address", + "Email", + "EmailPreferencesAutoBcc", + "EmailPreferencesAutoBccStayInTouch", + "EmailPreferencesStayInTouchReminder", + "SenderEmail", + "SenderName", + "Signature", + "StayInTouchSubject", + "StayInTouchSignature", + "StayInTouchNote", + "Phone", + "Fax", + "MobilePhone", + "Alias", + "CommunityNickname", + "BadgeText", + "IsActive", + "TimeZoneSidKey", + "UserRoleId", + "LocaleSidKey", + "ReceivesInfoEmails", + "ReceivesAdminInfoEmails", + "EmailEncodingKey", + "ProfileId", + "UserType", + "LanguageLocaleKey", + "EmployeeNumber", + "DelegatedApproverId", + "ManagerId", + "LastLoginDate", + "LastPasswordChangeDate", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "NumberOfFailedLogins", + "OfflineTrialExpirationDate", + "OfflinePdaTrialExpirationDate", + "UserPermissionsMarketingUser", + "UserPermissionsOfflineUser", + "UserPermissionsWirelessUser", + "UserPermissionsAvantgoUser", + "UserPermissionsCallCenterAutoLogin", + "UserPermissionsSFContentUser", + "UserPermissionsInteractionUser", + "UserPermissionsSupportUser", + "UserPermissionsChatterAnswersUser", + "ForecastEnabled", + "UserPreferencesActivityRemindersPopup", + "UserPreferencesEventRemindersCheckboxDefault", + "UserPreferencesTaskRemindersCheckboxDefault", + "UserPreferencesReminderSoundOff", + "UserPreferencesDisableAllFeedsEmail", + "UserPreferencesApexPagesDeveloperMode", + "UserPreferencesReceiveNoNotificationsAsApprover", + "UserPreferencesReceiveNotificationsAsDelegatedApprover", + "UserPreferencesHideCSNGetChatterMobileTask", + "UserPreferencesHideCSNDesktopTask", + "UserPreferencesHideChatterOnboardingSplash", + "UserPreferencesHideSecondChatterOnboardingSplash", + "UserPreferencesShowTitleToExternalUsers", + "UserPreferencesShowManagerToExternalUsers", + "UserPreferencesShowEmailToExternalUsers", + "UserPreferencesShowWorkPhoneToExternalUsers", + "UserPreferencesShowMobilePhoneToExternalUsers", + "UserPreferencesShowFaxToExternalUsers", + "UserPreferencesShowStreetAddressToExternalUsers", + "UserPreferencesShowCityToExternalUsers", + "UserPreferencesShowStateToExternalUsers", + "UserPreferencesShowPostalCodeToExternalUsers", + "UserPreferencesShowCountryToExternalUsers", + "UserPreferencesShowProfilePicToGuestUsers", + "UserPreferencesShowTitleToGuestUsers", + "UserPreferencesShowCityToGuestUsers", + "UserPreferencesShowStateToGuestUsers", + "UserPreferencesShowPostalCodeToGuestUsers", + "UserPreferencesShowCountryToGuestUsers", + "UserPreferencesHideInvoicesRedirectConfirmation", + "UserPreferencesHideStatementsRedirectConfirmation", + "UserPreferencesPathAssistantCollapsed", + "UserPreferencesCacheDiagnostics", + "UserPreferencesShowEmailToGuestUsers", + "UserPreferencesShowManagerToGuestUsers", + "UserPreferencesShowWorkPhoneToGuestUsers", + "UserPreferencesShowMobilePhoneToGuestUsers", + "UserPreferencesShowFaxToGuestUsers", + "UserPreferencesShowStreetAddressToGuestUsers", + "UserPreferencesLightningExperiencePreferred", + "UserPreferencesPreviewLightning", + "UserPreferencesHideEndUserOnboardingAssistantModal", + "UserPreferencesHideLightningMigrationModal", + "UserPreferencesHideSfxWelcomeMat", + "UserPreferencesHideBiggerPhotoCallout", + "UserPreferencesGlobalNavBarWTShown", + "UserPreferencesGlobalNavGridMenuWTShown", + "UserPreferencesCreateLEXAppsWTShown", + "UserPreferencesFavoritesWTShown", + "UserPreferencesRecordHomeSectionCollapseWTShown", + "UserPreferencesRecordHomeReservedWTShown", + "UserPreferencesFavoritesShowTopFavorites", + "UserPreferencesExcludeMailAppAttachments", + "UserPreferencesSuppressTaskSFXReminders", + "UserPreferencesSuppressEventSFXReminders", + "UserPreferencesPreviewCustomTheme", + "UserPreferencesHasCelebrationBadge", + "UserPreferencesUserDebugModePref", + "UserPreferencesSRHOverrideActivities", + "UserPreferencesNewLightningReportRunPageEnabled", + "UserPreferencesReverseOpenActivitiesView", + "UserPreferencesNativeEmailClient", + "UserPreferencesHideBrowseProductRedirectConfirmation", + "UserPreferencesHideOnlineSalesAppWelcomeMat", + "ContactId", + "AccountId", + "CallCenterId", + "Extension", + "FederationIdentifier", + "AboutMe", + "FullPhotoUrl", + "SmallPhotoUrl", + "IsExtIndicatorVisible", + "OutOfOfficeMessage", + "MediumPhotoUrl", + "DigestFrequency", + "DefaultGroupNotificationFrequency", + "LastViewedDate", + "LastReferencedDate", + "BannerPhotoUrl", + "SmallBannerPhotoUrl", + "MediumBannerPhotoUrl", + "IsProfilePhotoActive", + "IndividualId", + "Last_Mobile_Connect_vod__c", + "Last_Tablet_Connect_vod__c", + "Last_Mobile_Connect_Version_vod__c", + "Last_Tablet_Connect_Version_vod__c", + "Last_Mobile_Sync_vod__c", + "Last_Tablet_Sync_vod__c", + "RaiseLoggingLevel_vod__c", + "SendDetailedLog_vod__c", + "Last_Blackberry_Connect_vod__c", + "Last_Blackberry_Connect_Version_vod__c", + "Last_Blackberry_Sync_vod__c", + "Force_Full_Refresh_vod__c", + "Override_SystemModstamp_Timestamp_vod__c", + "Facetime_Email_vod__c", + "Facetime_Phone_vod__c", + "Product_Expertise_vod__c", + "Available_vod__c", + "Available_Last_Update_vod__c", + "Last_iPad_Connect_Version_vod__c", + "Last_iPad_Connect_vod__c", + "Last_iPad_Sync_vod__c", + "Inventory_Order_Allocation_Group_vod__c", + "Concur_User_Id_vod__c", + "Last_iPad_iOS_Version_vod__c", + "Approved_Email_Admin_vod__c", + "Last_WinModern_Connect_Version_vod__c", + "Last_WinModern_Connect_vod__c", + "Last_WinModern_Sync_vod__c", + "Primary_Territory_vod__c", + "Analytics_Admin_vod__c", + "Content_Admin_vod__c", + "Last_WinModern_Windows_Version_vod__c", + "Upload_VTrans_vod__c", + "Sync_Frequency_vjh__c", + "Clear_Client_Sync_Errors_vod__c", + "Remote_Meeting_Host_Id_vod__c", + "Remote_Meeting_Host_Token_vod__c", + "Last_iPhone_Connect_Version_vod__c", + "Last_iPhone_Connect_vod__c", + "Last_iPhone_Sync_vod__c", + "Last_iPhone_iOS_Version_vod__c", + "Remote_Meeting_Start_From_CRM_Online_vod__c", + "Country_Code_vod__c", + "User_Type_vod__c", + "Engage_Group_Provisioning_Status_vod__c", + "Engage_Group_Request_vod__c", + "Engage_Group_vod__c", + "Last_CRMDesktop_Mac_Sync_vod__c", + "Last_CRMDesktop_Mac_Version_vod__c", + "Last_CRMDesktop_Windows_Sync_vod__c", + "Last_CRMDesktop_Windows_Version_vod__c", + "MSJ_Test_User__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "UserTerritory2Association", + "columns": [ + "Id", + "UserId", + "Territory2Id", + "IsActive", + "RoleInTerritory2", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Remote_Meeting_vod__c", + "columns": [ + "Id", + "OwnerId", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "Meeting_Id_vod__c", + "Meeting_Name_vod__c", + "Mobile_ID_vod__c", + "Scheduled_DateTime_vod__c", + "Scheduled_vod__c", + "Attendance_Report_Process_Status_vod__c", + "Latest_Meeting_Start_Datetime_vod__c", + "Meeting_Password_vod__c", + "Meeting_Outcome_Status_vod__c", + "Allow_for_Joining_via_Zoom_vod__c", + "Zoom_Join_Token_vod__c", + "VExternal_Id_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "RecordType", + "columns": [ + "Id", + "Name", + "DeveloperName", + "NamespacePrefix", + "Description", + "BusinessProcessId", + "SobjectType", + "IsActive", + "IsPersonType", + "CreatedById", + "CreatedDate", + "LastModifiedById", + "LastModifiedDate", + "SystemModstamp" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "UserRole", + "columns": [ + "Id", + "Name", + "ParentRoleId", + "RollupDescription", + "OpportunityAccessForAccountOwner", + "CaseAccessForAccountOwner", + "ContactAccessForAccountOwner", + "ForecastUserId", + "MayForecastManagerShare", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "DeveloperName", + "PortalAccountId", + "PortalType", + "PortalAccountOwnerId" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Account", + "columns": [ + "Id", + "IsDeleted", + "MasterRecordId", + "Name", + "LastName", + "FirstName", + "Salutation", + "RecordTypeId", + "Phone", + "Fax", + "Website", + "PhotoUrl", + "NumberOfEmployees", + "Ownership", + "OwnerId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "LastActivityDate", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "IsExcludedFromRealign", + "PersonContactId", + "IsPersonAccount", + "PersonMailingStreet", + "PersonMailingCity", + "PersonMailingState", + "PersonMailingPostalCode", + "PersonMailingCountry", + "PersonMailingLatitude", + "PersonMailingLongitude", + "PersonMailingGeocodeAccuracy", + "PersonMailingAddress", + "PersonOtherStreet", + "PersonOtherCity", + "PersonOtherState", + "PersonOtherPostalCode", + "PersonOtherCountry", + "PersonOtherLatitude", + "PersonOtherLongitude", + "PersonOtherGeocodeAccuracy", + "PersonOtherAddress", + "PersonMobilePhone", + "PersonHomePhone", + "PersonOtherPhone", + "PersonAssistantPhone", + "PersonEmail", + "PersonTitle", + "PersonDepartment", + "PersonAssistantName", + "PersonBirthdate", + "PersonHasOptedOutOfEmail", + "PersonHasOptedOutOfFax", + "PersonDoNotCall", + "PersonLastCURequestDate", + "PersonLastCUUpdateDate", + "PersonEmailBouncedReason", + "PersonEmailBouncedDate", + "PersonIndividualId", + "Jigsaw", + "JigsawCompanyId", + "AccountSource", + "SicDesc", + "External_ID_vod__c", + "Credentials_vod__c", + "Territory_vod__c", + "Exclude_from_Zip_to_Terr_Processing_vod__c", + "Group_Specialty_1_vod__c", + "Group_Specialty_2_vod__c", + "Specialty_1_vod__c", + "Specialty_2_vod__c", + "Formatted_Name_vod__c", + "Territory_Test_vod__c", + "Mobile_ID_vod__c", + "Gender_vod__c", + "ID_vod__c", + "Do_Not_Sync_Sales_Data_vod__c", + "ID2_vod__c", + "Preferred_Name_vod__c", + "Sample_Default_vod__c", + "Segmentations_vod__c", + "Restricted_Products_vod__c", + "Payer_Id_vod__c", + "Alternate_Name_vod__c", + "Do_Not_Call_vod__c", + "MSJ_Beds__c", + "Spend_Amount__c", + "PDRP_Opt_Out_vod__c", + "Spend_Status_Value_vod__c", + "PDRP_Opt_Out_Date_vod__c", + "Spend_Status_vod__c", + "Enable_Restricted_Products_vod__c", + "Call_Reminder_vod__c", + "Account_Group_vod__c", + "Primary_Parent_vod__c", + "Color_vod__c", + "Middle_vod__c", + "Suffix_vod__c", + "MSJ_Type__c", + "No_Orders_vod__c", + "MSJ_BU_ONC__c", + "MSJ_BU_FE__c", + "Account_Search_FirstLast_vod__c", + "Account_Search_LastFirst_vod__c", + "MSJ_Operation__c", + "Practice_at_Hospital_vod__c", + "Practice_Near_Hospital_vod__c", + "Do_Not_Create_Child_Account_vod__c", + "Total_MDs_DOs__c", + "AHA__c", + "Order_Type_vod__c", + "NPI_vod__c", + "ME__c", + "Speaker__c", + "Investigator_vod__c", + "Default_Order_Type_vod__c", + "Tax_Status__c", + "Model__c", + "Offerings__c", + "Departments__c", + "Account_Type__c", + "MSJ_ONC_Tier__c", + "Account_Search_Business_vod__c", + "Business_Professional_Person_vod__c", + "Hospital_Type_vod__c", + "Account_Class_vod__c", + "Furigana_vod__c", + "MSJ_JISART__c", + "Total_Revenue_000__c", + "Net_Income_Loss_000__c", + "PMPM_Income_Loss_000__c", + "Commercial_Premiums_PMPM__c", + "Medical_Loss_Ratio__c", + "Medical_Expenses_PMPM__c", + "Commercial_Patient_Days_1000__c", + "HMO_Market_Shr__c", + "HMO__c", + "HMO_POS__c", + "PPO__c", + "PPO_POS__c", + "Medicare__c", + "Medicaid__c", + "MSJ_HP_Name_E__c", + "MSJ_Department__c", + "MSJ_Date_Of_Birth__c", + "MSJ_FE_GF_Potential__c", + "MSJ_FE_SZ_Potential__c", + "MSJ_EB_CRC_Ladder__c", + "MSJ_EB_CRC_Segment__c", + "MSJ_EB_HN_Segment__c", + "Business_Description__c", + "Regional_Strategy__c", + "Contracts_Process__c", + "MSJ_GF_segment__c", + "MSJ_DCF_DR_Code__c", + "MSJ_SZ_Segment__c", + "MSJ_Remark__c", + "MSJ_Title__c", + "MSJ_Role__c", + "MSJ_Kana__c", + "MSJ_Specialism__c", + "MSJ_Graduated_from__c", + "MSJ_Year_Graduation__c", + "Target__c", + "KOL_vod__c", + "MSJ_EPPV_Code__c", + "MSJ_DCF_HP_Code__c", + "Total_Lives__c", + "Total_Physicians_Enrolled__c", + "MSJ_Delete__c", + "MSJ_KOL_LOL__c", + "MSJ_ONC_Status__c", + "Account_Identifier_vod__c", + "Approved_Email_Opt_Type_vod__c", + "Language_vod__c", + "MSJ_KRAS_Routine_Date__c", + "MSJ_KRAS_Routine__c", + "MSJ_DRP_Target__c", + "MSJ_Fertility_Evaluation_Score__c", + "MSJ_Fertility_Tracking_Last_Modify_Date__c", + "Total_Pharmacists__c", + "MSJ_Number_of_Gonadotropin__c", + "MSJ_Number_of_IUI_cycle__c", + "MSJ_Number_of_OI_monthly_cycle__c", + "MSJ_OI_Protocol_learning_level__c", + "MSJ_H_N_Tier__c", + "MSJ_XLK_Segment__c", + "MSJ_XLK_Tier__c", + "Career_Status_vod__c", + "Photo_vod__c", + "MSJ_EB_H_N_LA_Segment__c", + "MSJ_EB_H_N_RM_Segment__c", + "MSJ_FE_CE_Potential__c", + "MSJ_FE_1C_potential__c", + "MSJ_FE_OV_potential__c", + "MSJ_FE_Tech_potential__c", + "MSJ_CE_segment__c", + "MSJ_1C_segment__c", + "MSJ_OV_segment__c", + "MSJ_Tech_segment__c", + "MSJ_Target_Call_Num__c", + "MSJ_DR_Change_Log__c", + "MSJ_Global_scientific_exposure__c", + "MSJ_H_index__c", + "MSJ_Num_of_Article_3Y__c", + "MSJ_Num_of_Article__c", + "MSJ_Num_of_Article_as_1st_Author_3Y__c", + "MSJ_Num_of_article_growth_rate_3Y__c", + "MSJ_Num_of_cited_3Y__c", + "MSJ_Num_of_impact_factor_3Y__c", + "MSJ_impact_factor_as_1st_Author_3Y__c", + "EMDS_Has_Pipeline_Opportunity__c", + "EMDS_Pipeline_Count__c", + "MSJ_BVC_Segment__c", + "MSJ_BVC_Tier__c", + "MSJ_BVC_AcctOpen__c", + "MSJ_BVC_MCC_Patients__c", + "MSJ_ONC_HP_Segment__c", + "MSJ_AE_Department__c", + "MSJ_AE_Facility__c", + "MSJ_AE_Name__c", + "MSJ_AE_Title__c", + "MSJ_Email__c", + "MSJ_FE_GF2_Potential__c", + "MSJ_FE_Location_potential__c", + "MSJ_GF2_segment__c", + "MSJ_OPTIN_target__c", + "MSJ_Merck_Specialty1__c", + "MSJ_Merck_Specialty2__c", + "MSJ_Marketing_Cloud_Integration__c", + "MSJ_Marketing_Cloud1__c", + "MSJ_Marketing_Cloud2__c", + "MSJ_Marketing_Cloud3__c", + "MSJ_Marketing_Cloud4__c", + "MSJ_Medical_Department__c", + "MSJ_Marketing_Cloud0__c", + "Mobile_ID_vod__pc", + "H1Insights__H1_NPI_Value_for_Testing__pc", + "H1Insights__H1_Person_ID__pc", + "H1Insights__H1_Request_Status__pc", + "H1Insights__H1_URL__pc", + "H1Insights__NPI_Number__pc", + "H1Insights__NPI_Number_for_H1_Insights__pc", + "MSJ_Marketing_Cloud_Integration__pc" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "AccountShare", + "columns": [ + "Id", + "AccountId", + "UserOrGroupId", + "AccountAccessLevel", + "OpportunityAccessLevel", + "CaseAccessLevel", + "ContactAccessLevel", + "RowCause", + "LastModifiedDate", + "LastModifiedById", + "IsDeleted" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true, + "datetime_column": "LastModifiedDate" + }, + { + "object_name": "Contact", + "columns": [ + "Id", + "IsDeleted", + "MasterRecordId", + "AccountId", + "IsPersonAccount", + "LastName", + "FirstName", + "Salutation", + "Name", + "OtherStreet", + "OtherCity", + "OtherState", + "OtherPostalCode", + "OtherCountry", + "OtherLatitude", + "OtherLongitude", + "OtherGeocodeAccuracy", + "OtherAddress", + "MailingStreet", + "MailingCity", + "MailingState", + "MailingPostalCode", + "MailingCountry", + "MailingLatitude", + "MailingLongitude", + "MailingGeocodeAccuracy", + "MailingAddress", + "Phone", + "Fax", + "MobilePhone", + "HomePhone", + "OtherPhone", + "AssistantPhone", + "ReportsToId", + "Email", + "Title", + "Department", + "AssistantName", + "Birthdate", + "Description", + "OwnerId", + "HasOptedOutOfEmail", + "HasOptedOutOfFax", + "DoNotCall", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "LastActivityDate", + "LastCURequestDate", + "LastCUUpdateDate", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "EmailBouncedReason", + "EmailBouncedDate", + "IsEmailBounced", + "PhotoUrl", + "Jigsaw", + "JigsawContactId", + "IndividualId", + "Mobile_ID_vod__c", + "H1Insights__H1_NPI_Value_for_Testing__c", + "H1Insights__H1_Person_ID__c", + "H1Insights__H1_Request_Status__c", + "H1Insights__H1_URL__c", + "H1Insights__NPI_Number__c", + "H1Insights__NPI_Number_for_H1_Insights__c", + "MSJ_Marketing_Cloud_Integration__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Consent_Type_vod__c", + "columns": [ + "Id", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "Consent_Header_vod__c", + "Channel_Label_vod__c", + "Channel_Source_vod__c", + "Consent_Expires_In_vod__c", + "Default_Consent_Type_vod__c", + "Disclaimer_Text_vod__c", + "Display_Order_vod__c", + "Product_Preference_vod__c", + "zvod_Consent_Default_Consent_Text_vod__c", + "zvod_Consent_Line_vod__c", + "zvod_Signature_Capture_vod__c", + "Double_Opt_In_vod__c", + "zvod_Consent_Activity_Tracking_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Consent_Header_vod__c", + "columns": [ + "Id", + "OwnerId", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "Consent_Header_Help_Text_vod__c", + "Country_vod__c", + "Inactive_Datetime_vod__c", + "Language_vod__c", + "Status_vod__c", + "Signature_Required_On_Opt_Out_vod__c", + "Request_Receipt_vod__c", + "Subscription_Option_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Consent_Line_vod__c", + "columns": [ + "Id", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "Consent_Type_vod__c", + "Detail_Group_Display_Name_vod__c", + "Detail_Group_vod__c", + "Display_Order_vod__c", + "End_Date_vod__c", + "Group_By_vod__c", + "Product_Display_Name_vod__c", + "Product_vod__c", + "Start_Date_vod__c", + "Sub_Channel_Description_vod__c", + "Sub_Channel_Display_Name_vod__c", + "Sub_Channel_Key_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "MSJ_Inquiry_Assignment__c", + "columns": [ + "Id", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "MSJ_Medical_Inquiry__c", + "MSJ_Close__c", + "MSJ_Doctor_Name__c", + "MSJ_Hospital_Name__c", + "MSJ_Indication__c", + "MSJ_Inquiry_Text__c", + "MSJ_MEC_User__c", + "MSJ_MSL_Manager__c", + "MSJ_MSL_User__c", + "MSJ_Notice_to_MR__c", + "MSJ_Product_for_MEC__c", + "MSJ_Product_for_MR__c", + "MSJ_Reply_Date__c", + "MSJ_Reply__c", + "MSJ_AE_Infomation__c", + "MSJ_Cancel__c", + "MSJ_FAQ_number_c__c", + "MSJ_Return_Call__c", + "MSJ_Inquiry_Origin__c", + "First_Response__c", + "Inquiry_Created_Date__c", + "Inquiry_Type_1__c", + "Inquiry_Type_2__c", + "MSJ_First_User__c", + "MSJ_MEC_Comment__c", + "MSJ_Send_Email__c", + "MSJ_Temp_Aggregated_Info__c", + "MSJ_AE_Report__c", + "MSJ_Background__c", + "MSJ_Inquiry_Date__c", + "MSJ_MSL_Support__c", + "MSJ_Handover_Comment__c", + "MSJ_Handover_Email__c", + "MSJ_Material_Requirement__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Approved_Document_vod__c", + "columns": [ + "Id", + "OwnerId", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "LastActivityDate", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "Detail_Group_vod__c", + "Document_Description_vod__c", + "Document_Host_URL_vod__c", + "Document_ID_vod__c", + "Document_Last_Mod_DateTime_vod__c", + "Email_Allows_Documents_vod__c", + "Email_Domain_vod__c", + "Email_Fragment_HTML_vod__c", + "Email_From_Address_vod__c", + "Email_From_Name_vod__c", + "Email_HTML_1_vod__c", + "Email_HTML_2_vod__c", + "Email_ReplyTo_Address_vod__c", + "Email_ReplyTo_Name_vod__c", + "Email_Subject_vod__c", + "Email_Template_Fragment_Document_ID_vod__c", + "Email_Template_Fragment_HTML_vod__c", + "ISI_Document_ID_vod__c", + "Language_vod__c", + "Other_Document_ID_List_vod__c", + "PI_Document_ID_vod__c", + "Piece_Document_ID_vod__c", + "Product_vod__c", + "Status_vod__c", + "Territory_vod__c", + "Vault_Instance_ID_vod__c", + "Allow_Any_Product_Fragment_vod__c", + "Allowed_Document_IDs_vod__c", + "Engage_Document_Id_vod__c", + "Vault_Document_ID_vod__c", + "Key_Message_vod__c", + "Events_Management_Subtype_vod__c", + "Survey_vod__c", + "Content_Type_vod__c", + "Bcc_vod__c", + "Audience_vod__c", + "WeChat_Template_ID_vod__c", + "Check_Consent_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Child_Account_vod__c", + "columns": [ + "Id", + "IsDeleted", + "Name", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "Parent_Account_vod__c", + "Child_Account_vod__c", + "External_ID_vod__c", + "Mobile_ID_vod__c", + "Primary_vod__c", + "Copy_Address_vod__c", + "Child_Name_vod__c", + "Parent_Name_vod__c", + "Parent_Child_Name_vod__c", + "Account_Code__c", + "Child_Department__c", + "Child_Role__c", + "Child_Title__c", + "Child_Remark__c", + "MSJ_1C_segment__c", + "MSJ_BU_FE__c", + "MSJ_BU_ONC__c", + "MSJ_BVC_Segment__c", + "MSJ_CE_segment__c", + "MSJ_Child_Account_Link__c", + "MSJ_DCF_DR_Code__c", + "MSJ_DCF_HP_Code__c", + "MSJ_DR_Change_Log__c", + "MSJ_Delete__c", + "MSJ_Department__c", + "MSJ_EB_CRC_Segment__c", + "MSJ_EB_HN_Segment__c", + "MSJ_EB_H_N_LA_Segment__c", + "MSJ_EB_H_N_RM_Segment__c", + "MSJ_External_ID__c", + "MSJ_Fax__c", + "MSJ_GF2_segment__c", + "MSJ_GF_segment__c", + "MSJ_KOL_LOL__c", + "MSJ_KOL__c", + "MSJ_ONC_HP_Segment__c", + "MSJ_OPTIN_target__c", + "MSJ_OV_segment__c", + "MSJ_Parent_Child_Name__c", + "MSJ_Phone__c", + "MSJ_Remark__c", + "MSJ_Target_Call_Num__c", + "MSJ_Tech_segment__c", + "MSJ_Title__c", + "MSJ_XLK_Segment__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "MSJ_Hospital_Medical_Regimen__c", + "columns": [ + "Id", + "OwnerId", + "IsDeleted", + "Name", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "MSJ_Account_Name__c", + "MSJ_Delete_Date__c", + "MSJ_Delete_Flag__c", + "MSJ_Indication__c", + "MSJ_Line__c", + "MSJ_Medical_Regimen__c", + "Mobile_ID_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "MSJ_Medical_Regimen__c", + "columns": [ + "Id", + "OwnerId", + "IsDeleted", + "Name", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "MSJ_Delete_Date__c", + "MSJ_Delete_Flag__c", + "MSJ_Indication__c", + "MSJ_Remark__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "MSJ_Patient__c", + "columns": [ + "Id", + "OwnerId", + "IsDeleted", + "Name", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "MSJ_Account_Name__c", + "MSJ_CRC_Group__c", + "MSJ_Casus_or_Transfer_Point__c", + "MSJ_Entry_Date__c", + "MSJ_IST_Name__c", + "MSJ_Indication__c", + "MSJ_Line__c", + "MSJ_MR_Comments__c", + "MSJ_MUID__c", + "MSJ_Medical_Regimen__c", + "MSJ_Month__c", + "MSJ_Report_Comments__c", + "MSJ_Start_Date_Of_Administration__c", + "MSJ_Year__c", + "Mobile_ID_vod__c", + "MSJ_CRC_RAS_KRAS__c", + "MSJ_End_Date_Of_Administration__c", + "MSJ_End_Date_of_Stop_Administration__c", + "MSJ_HN_Hospitalized_Type__c", + "MSJ_Start_Date_of_Stop_Administration__c", + "MSJ_Patient_Status__c", + "MSJ_Patient_TA__c", + "MSJ_Child_Account_Name__c", + "MSJ_Child_Account__c", + "MSJ_Parent_Account_Name__c", + "MSJ_Parent_Child_Name__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Product_vod__c", + "columns": [ + "Id", + "OwnerId", + "IsDeleted", + "Name", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "Consumer_site__c", + "Product_info__c", + "Therapeutic_Class_vod__c", + "Parent_Product_vod__c", + "Therapeutic_Area_vod__c", + "Product_Type_vod__c", + "Require_Key_Message_vod__c", + "Cost_vod__c", + "External_ID_vod__c", + "Manufacturer_vod__c", + "Company_Product_vod__c", + "Controlled_Substance_vod__c", + "Description_vod__c", + "Sample_Quantity_Picklist_vod__c", + "Display_Order_vod__c", + "No_Metrics_vod__c", + "Distributor_vod__c", + "Sample_Quantity_Bound_vod__c", + "Sample_U_M_vod__c", + "No_Details_vod__c", + "Quantity_Per_Case_vod__c", + "Schedule_vod__c", + "Restricted_vod__c", + "Pricing_Rule_Quantity_Bound_vod__c", + "No_Promo_Items_vod__c", + "User_Aligned_vod__c", + "Restricted_States_vod__c", + "Sort_Code_vod__c", + "No_Cycle_Plans_vod__c", + "Inventory_Order_UOM_vod__c", + "Inventory_Quantity_Per_Case_vod__c", + "VExternal_Id_vod__c", + "Country__c", + "MSJ_Product_Classification__c", + "MSJ_Indication__c", + "MSJ_Therapeutic_Area__c", + "MSJ_Global_Brand__c", + "MSJ_Global_Business_Unit__c", + "MSJ_Molecules__c", + "MSJ_SBU__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Product_Group_vod__c", + "columns": [ + "Id", + "IsDeleted", + "Name", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "Description_vod__c", + "Product_vod__c", + "Product_Catalog_vod__c", + "Start_Date_vod__c", + "End_Date_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Product_Metrics_vod__c", + "columns": [ + "Id", + "IsDeleted", + "Name", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "Account_vod__c", + "Awareness__c", + "Selling_Stage__c", + "Formulary_Status__c", + "Movement__c", + "Products_vod__c", + "Segment__c", + "X12_mo_trx_chg__c", + "Speaker_Skills__c", + "Investigator_Readiness__c", + "Engagements__c", + "Mobile_ID_vod__c", + "External_ID_vod__c", + "MSJ_Patient__c", + "Detail_Group_vod__c", + "MSJ_EB_1st_Line_Liver_Meta__c", + "MSJ_EB_1st_Line_Multi_Meta__c", + "MSJ_EB_2nd_Line_Mono__c", + "MSJ_EB_2nd_Line_Combination__c", + "MSJ_EB_3rd_Line_Mono__c", + "MSJ_EB_3rd_Line_Combination__c", + "EMDS_Ability__c", + "EMDS_Brand_Loyalty__c", + "EMDS_Decision_Maker__c", + "EMDS_Early_Tech_Adopter__c", + "EMDS_Influence__c", + "EMDS_Main_Driver__c", + "EMDS_Priority__c", + "EMDS_Willingness__c", + "MSJ_KTL_Type__c", + "MSJ_KTL_Tier__c", + "MSJ_Publications__c", + "MSJ_Clinical_Trials__c", + "MSJ_Speaker_for_Medical_Events__c", + "MSJ_Advisor_to_Medical_Affairs__c", + "MSJ_Guidelines_Treatment_Standards__c", + "MSJ_Therapeutic_Area_Expertise__c", + "MSJ_MAP_GAP__c", + "MSJ_Associations__c", + "MSJ_Tier_Score__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Survey_vod__c", + "columns": [ + "Id", + "OwnerId", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "Assignment_Type_vod__c", + "Channels_vod__c", + "End_Date_vod__c", + "Expired_vod__c", + "External_ID_vod__c", + "Language_vod__c", + "Lock_vod__c", + "Open_vod__c", + "Product_vod__c", + "Region_vod__c", + "Segment_vod__c", + "Start_Date_vod__c", + "Status_vod__c", + "Territory_vod__c", + "zvod_Questions_vod__c", + "zvod_Segments_vod__c", + "zvod_Targets_vod__c", + "Max_Score_vod__c", + "Min_Score_vod__c", + "Autotarget_vod__c", + "Territories_vod__c", + "Target_Type_vod__c", + "MSJ_External_ID__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Survey_Target_vod__c", + "columns": [ + "Id", + "OwnerId", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "LastViewedDate", + "LastReferencedDate", + "Account_Display_Name_vod__c", + "Account_vod__c", + "Channels_vod__c", + "End_Date_vod__c", + "Entity_Reference_Id_vod__c", + "External_ID_vod__c", + "Language_vod__c", + "Lock_vod__c", + "Mobile_ID_vod__c", + "No_Autoassign_vod__c", + "Not_Completed_vod__c", + "Region_vod__c", + "Segment_vod__c", + "Start_Date_vod__c", + "Status_vod__c", + "Survey_vod__c", + "Territory_vod__c", + "zvod_Address_vod__c", + "zvod_Specialty_vod__c", + "Score_vod__c", + "User_vod__c", + "Child_Account_vod__c", + "Location_Entity_Reference_Id_vod__c", + "Location_vod__c", + "Target_Type_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Survey_Question_vod__c", + "columns": [ + "Id", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "Survey_vod__c", + "Answer_Choice_vod__c", + "External_ID_vod__c", + "Max_Score_vod__c", + "Min_Score_vod__c", + "Order_vod__c", + "Question_vod__c", + "Required_vod__c", + "Text_vod__c", + "Condition_vod__c", + "Source_ID_vod__c", + "MSJ_External_ID__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Question_Response_vod__c", + "columns": [ + "Id", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "MayEdit", + "IsLocked", + "Survey_Target_vod__c", + "Answer_Choice_vod__c", + "Date_vod__c", + "Datetime_vod__c", + "External_ID_vod__c", + "Mobile_ID_vod__c", + "Number_vod__c", + "Order_vod__c", + "Question_Text_vod__c", + "Required_vod__c", + "Response_Hash_vod__c", + "Response_vod__c", + "Score_vod__c", + "Survey_Question_vod__c", + "Text_vod__c", + "Type_vod__c", + "Condition_vod__c", + "Inactive_Condition_vod__c", + "Source_ID_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Sent_Fragment_vod__c", + "columns": [ + "Id", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "LastActivityDate", + "MayEdit", + "IsLocked", + "Sent_Email_vod__c", + "Account_vod__c", + "Email_Template_vod__c", + "Sent_Fragment_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + }, + { + "object_name": "Sent_Email_vod__c", + "columns": [ + "Id", + "OwnerId", + "IsDeleted", + "Name", + "RecordTypeId", + "CreatedDate", + "CreatedById", + "LastModifiedDate", + "LastModifiedById", + "SystemModstamp", + "LastActivityDate", + "MayEdit", + "IsLocked", + "Account_Email_vod__c", + "Account_vod__c", + "Approved_Email_Template_vod__c", + "Capture_Datetime_vod__c", + "Detail_Group_vod__c", + "Email_Config_Values_vod__c", + "Email_Content2_vod__c", + "Email_Content_vod__c", + "Email_Fragments_vod__c", + "Email_Sent_Date_vod__c", + "Failure_Msg_vod__c", + "Last_Activity_Date_vod__c", + "Last_Device_vod__c", + "MC_Capture_Datetime_vod__c", + "Mobile_ID_vod__c", + "Opened_vod__c", + "Product_Display_vod__c", + "Product_vod__c", + "Sender_Email_vod__c", + "Status_vod__c", + "Valid_Consent_Exists_vod__c", + "Approved_Document_Views_vod__c", + "Click_Count_vod__c", + "Last_Click_Date_vod__c", + "Last_Open_Date_vod__c", + "Open_Count_vod__c", + "Receipt_Entity_Type_vod__c", + "Receipt_Record_Id_vod__c", + "Territory_vod__c", + "Call2_vod__c", + "Medical_Inquiry_vod__c", + "Parent_Email_vod__c", + "Related_Transaction_ID_vod__c", + "Case_vod__c", + "Key_Message_vod__c", + "Suggestion_vod__c", + "EM_Attendee_vod__c", + "EM_Event_Speaker_vod__c", + "EM_Event_Team_Member_vod__c", + "Event_Attendee_vod__c", + "Event_vod__c", + "Medical_Event_vod__c", + "Scheduled_Send_Datetime_vod__c", + "User_vod__c", + "Content_Type_vod__c", + "Bcc_vod__c", + "Event_Attendee_Mobile_Id_vod__c", + "Event_Mobile_Id_vod__c", + "Activity_Tracking_Mode_vod__c", + "Email_Source_vod__c", + "Subject_vod__c", + "User_Input_Text_vod__c" + ], + "is_skip": false, + "is_update_last_fetch_datetime": true + } + ] +} \ No newline at end of file diff --git a/s3/config/crm/task_settings/task_settings.env b/s3/config/crm/task_settings/task_settings.env new file mode 100644 index 00000000..1998012c --- /dev/null +++ b/s3/config/crm/task_settings/task_settings.env @@ -0,0 +1,17 @@ +LOG_LEVEL=INFO +CRM_AUTH_TIMEOUT=100 +CRM_AUTH_MAX_RETRY_ATTEMPT=3 +CRM_AUTH_RETRY_INTERVAL=5 +CRM_AUTH_RETRY_MIN_INTERVAL=5 +CRM_AUTH_RETRY_MAX_INTERVAL=50 +CRM_GET_RECORD_COUNT_TIMEOUT=300 +CRM_GET_RECORD_COUNT_MAX_RETRY_ATTEMPT=3 +CRM_GET_RECORD_COUNT_RETRY_INTERVAL=5 +CRM_GET_RECORD_COUNT_RETRY_MIN_INTERVAL=5 +CRM_GET_RECORD_COUNT_RETRY_MAX_INTERVAL=50 +CRM_FETCH_RECORD_TIMEOUT=300 +CRM_FETCH_RECORD_MAX_RETRY_ATTEMPT=3 +CRM_FETCH_RECORD_RETRY_INTERVAL=5 +CRM_FETCH_RECORD_RETRY_MIN_INTERVAL=5 +CRM_FETCH_RECORD_RETRY_MAX_INTERVAL=50 +CONVERT_TZ='Asia/Tokyo' \ No newline at end of file