diff --git a/Pipfile b/Pipfile deleted file mode 100644 index a149c08..0000000 --- a/Pipfile +++ /dev/null @@ -1,47 +0,0 @@ -[[source]] -name = "pypi" -url = "https://pypi.org/simple" -verify_ssl = true - -[dev-packages] -pylint = "*" -black = "*" -isort = "*" - -[packages] -celery = "==4.3.0" -django-simple-pagination = "==1.3" -django-compressor = "==2.3" -sorl-thumbnail = "==12.5.0" -django-phonenumber-field = "==2.2.0" -phonenumbers = "==8.10.4" -django-storages = "==1.7" -psycopg2-binary = "==2.8.3" -arrow = "==0.14.5" -requests = "==2.22.0" -boto3 = "==1.9.212" -lxml = "==4.4.1" -cssselect = "==1.1.0" -xlrd = "==1.2.0" -xlwt = "==1.3.0" -openpyxl = "==2.6.3" -pdfkit = "==0.6.1" -redis = "==3.3.8" -coverage = "==4.5.4" -raven = "==6.10.0" -pytest = "==5.1.1" -pytest-django = "==3.5.1" -codacy-coverage = "==1.3.11" -django-haystack = "==2.8.0" -elasticsearch = "==2.3" -python-memcached = "==1.59" -boto = "==2.49.0" -Django = "==2.2.10" -django-settings-export = "==1.2.1" -tblib = "*" - -[requires] -python_version = "3.6" - -[pipenv] -allow_prereleases = true diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index 0dcf095..0000000 --- a/Pipfile.lock +++ /dev/null @@ -1,741 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "3e52c0805e70467c8f163cdb354b94d095951ef69904b0b189396629079be11c" - }, - "pipfile-spec": 6, - "requires": { - "python_version": "3.6" - }, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "amqp": { - "hashes": [ - "sha256:6e649ca13a7df3faacdc8bbb280aa9a6602d22fd9d545336077e573a1f4ff3b8", - "sha256:77f1aef9410698d20eaeac5b73a87817365f457a507d82edf292e12cbb83b08d" - ], - "version": "==2.5.2" - }, - "arrow": { - "hashes": [ - "sha256:0186026cfd94ca4fb773f30cc5398289a3027480d335e0e5c0d2772643763137", - "sha256:a12de0124d812d15061ed36c7eb4a421fa1b95026a502a0b2062e9ea00fc4446" - ], - "index": "pypi", - "version": "==0.14.5" - }, - "atomicwrites": { - "hashes": [ - "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", - "sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6" - ], - "version": "==1.3.0" - }, - "attrs": { - "hashes": [ - "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", - "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72" - ], - "version": "==19.3.0" - }, - "babel": { - "hashes": [ - "sha256:1aac2ae2d0d8ea368fa90906567f5c08463d98ade155c0c4bfedd6a0f7160e38", - "sha256:d670ea0b10f8b723672d3a6abeb87b565b244da220d76b4dba1b66269ec152d4" - ], - "version": "==2.8.0" - }, - "billiard": { - "hashes": [ - "sha256:bff575450859a6e0fbc2f9877d9b715b0bbc07c3565bb7ed2280526a0cdf5ede", - "sha256:d91725ce6425f33a97dfa72fb6bfef0e47d4652acd98a032bd1a7fbf06d5fa6a" - ], - "version": "==3.6.3.0" - }, - "boto": { - "hashes": [ - "sha256:147758d41ae7240dc989f0039f27da8ca0d53734be0eb869ef16e3adcfa462e8", - "sha256:ea0d3b40a2d852767be77ca343b58a9e3a4b00d9db440efb8da74b4e58025e5a" - ], - "index": "pypi", - "version": "==2.49.0" - }, - "boto3": { - "hashes": [ - "sha256:1a228661611cb99c3c54f5bdbdc29d9d7ef5341676a644d2508eeeff7b8b2fe3", - "sha256:c25d1089676213bda140c5b6faacd008b93203d27f1707cf0efc827d46cd719d" - ], - "index": "pypi", - "version": "==1.9.212" - }, - "botocore": { - "hashes": [ - "sha256:3baf129118575602ada9926f5166d82d02273c250d0feb313fc270944b27c48b", - "sha256:dc080aed4f9b220a9e916ca29ca97a9d37e8e1d296fe89cbaeef929bf0c8066b" - ], - "version": "==1.12.253" - }, - "celery": { - "hashes": [ - "sha256:4c4532aa683f170f40bd76f928b70bc06ff171a959e06e71bf35f2f9d6031ef9", - "sha256:528e56767ae7e43a16cfef24ee1062491f5754368d38fcfffa861cdb9ef219be" - ], - "index": "pypi", - "version": "==4.3.0" - }, - "certifi": { - "hashes": [ - "sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304", - "sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519" - ], - "version": "==2020.4.5.1" - }, - "chardet": { - "hashes": [ - "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", - "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" - ], - "version": "==3.0.4" - }, - "codacy-coverage": { - "hashes": [ - "sha256:b94651934745c638a980ad8d67494077e60f71e19e29aad1c275b66e0a070cbc", - "sha256:d8a1ce56b0dd156d6b1de14fa6217d32ec86097902f08a17ff2f95ba27264474" - ], - "index": "pypi", - "version": "==1.3.11" - }, - "coverage": { - "hashes": [ - "sha256:08907593569fe59baca0bf152c43f3863201efb6113ecb38ce7e97ce339805a6", - "sha256:0be0f1ed45fc0c185cfd4ecc19a1d6532d72f86a2bac9de7e24541febad72650", - "sha256:141f08ed3c4b1847015e2cd62ec06d35e67a3ac185c26f7635f4406b90afa9c5", - "sha256:19e4df788a0581238e9390c85a7a09af39c7b539b29f25c89209e6c3e371270d", - "sha256:23cc09ed395b03424d1ae30dcc292615c1372bfba7141eb85e11e50efaa6b351", - "sha256:245388cda02af78276b479f299bbf3783ef0a6a6273037d7c60dc73b8d8d7755", - "sha256:331cb5115673a20fb131dadd22f5bcaf7677ef758741312bee4937d71a14b2ef", - "sha256:386e2e4090f0bc5df274e720105c342263423e77ee8826002dcffe0c9533dbca", - "sha256:3a794ce50daee01c74a494919d5ebdc23d58873747fa0e288318728533a3e1ca", - "sha256:60851187677b24c6085248f0a0b9b98d49cba7ecc7ec60ba6b9d2e5574ac1ee9", - "sha256:63a9a5fc43b58735f65ed63d2cf43508f462dc49857da70b8980ad78d41d52fc", - "sha256:6b62544bb68106e3f00b21c8930e83e584fdca005d4fffd29bb39fb3ffa03cb5", - "sha256:6ba744056423ef8d450cf627289166da65903885272055fb4b5e113137cfa14f", - "sha256:7494b0b0274c5072bddbfd5b4a6c6f18fbbe1ab1d22a41e99cd2d00c8f96ecfe", - "sha256:826f32b9547c8091679ff292a82aca9c7b9650f9fda3e2ca6bf2ac905b7ce888", - "sha256:93715dffbcd0678057f947f496484e906bf9509f5c1c38fc9ba3922893cda5f5", - "sha256:9a334d6c83dfeadae576b4d633a71620d40d1c379129d587faa42ee3e2a85cce", - "sha256:af7ed8a8aa6957aac47b4268631fa1df984643f07ef00acd374e456364b373f5", - "sha256:bf0a7aed7f5521c7ca67febd57db473af4762b9622254291fbcbb8cd0ba5e33e", - "sha256:bf1ef9eb901113a9805287e090452c05547578eaab1b62e4ad456fcc049a9b7e", - "sha256:c0afd27bc0e307a1ffc04ca5ec010a290e49e3afbe841c5cafc5c5a80ecd81c9", - "sha256:dd579709a87092c6dbee09d1b7cfa81831040705ffa12a1b248935274aee0437", - "sha256:df6712284b2e44a065097846488f66840445eb987eb81b3cc6e4149e7b6982e1", - "sha256:e07d9f1a23e9e93ab5c62902833bf3e4b1f65502927379148b6622686223125c", - "sha256:e2ede7c1d45e65e209d6093b762e98e8318ddeff95317d07a27a2140b80cfd24", - "sha256:e4ef9c164eb55123c62411f5936b5c2e521b12356037b6e1c2617cef45523d47", - "sha256:eca2b7343524e7ba246cab8ff00cab47a2d6d54ada3b02772e908a45675722e2", - "sha256:eee64c616adeff7db37cc37da4180a3a5b6177f5c46b187894e633f088fb5b28", - "sha256:ef824cad1f980d27f26166f86856efe11eff9912c4fed97d3804820d43fa550c", - "sha256:efc89291bd5a08855829a3c522df16d856455297cf35ae827a37edac45f466a7", - "sha256:fa964bae817babece5aa2e8c1af841bebb6d0b9add8e637548809d040443fee0", - "sha256:ff37757e068ae606659c28c3bd0d923f9d29a85de79bf25b2b34b148473b5025" - ], - "index": "pypi", - "version": "==4.5.4" - }, - "cssselect": { - "hashes": [ - "sha256:f612ee47b749c877ebae5bb77035d8f4202c6ad0f0fc1271b3c18ad6c4468ecf", - "sha256:f95f8dedd925fd8f54edb3d2dfb44c190d9d18512377d3c1e2388d16126879bc" - ], - "index": "pypi", - "version": "==1.1.0" - }, - "django": { - "hashes": [ - "sha256:1226168be1b1c7efd0e66ee79b0e0b58b2caa7ed87717909cd8a57bb13a7079a", - "sha256:9a4635813e2d498a3c01b10c701fe4a515d76dd290aaa792ccb65ca4ccb6b038" - ], - "index": "pypi", - "version": "==2.2.10" - }, - "django-appconf": { - "hashes": [ - "sha256:1b1d0e1069c843ebe8ae5aa48ec52403b1440402b320c3e3a206a0907e97bb06", - "sha256:be58deb54a43d77d2e1621fe59f787681376d3cd0b8bd8e4758ef6c3a6453380" - ], - "version": "==1.0.4" - }, - "django-compressor": { - "hashes": [ - "sha256:47c86347f75c64954a06afbbfc820a750619e10c23a49272b865020a407b7edd", - "sha256:da9ee5ce4fc8b9211dcecd2229520514a4ba9ac3bcdc59b48092ec4d7f6b96b0" - ], - "index": "pypi", - "version": "==2.3" - }, - "django-haystack": { - "hashes": [ - "sha256:579cd2080f7ad508e909a46c027078e278aeebd133973c1c4efcf0dc57d85c10", - "sha256:5951a2f4059ee6d3f142186ea63cab65b28d7a758c969506a564553e479ceab4" - ], - "index": "pypi", - "version": "==2.8.0" - }, - "django-phonenumber-field": { - "hashes": [ - "sha256:2ae79857113b500f733885b2ebacf8d6fbf21970f2416bd4a3160ec9b91ce831" - ], - "index": "pypi", - "version": "==2.2.0" - }, - "django-settings-export": { - "hashes": [ - "sha256:fceeae49fc597f654c1217415d8e049fc81c930b7154f5d8f28c432db738ff79" - ], - "index": "pypi", - "version": "==1.2.1" - }, - "django-simple-pagination": { - "hashes": [ - "sha256:a12ff1f159c9481030b29dbb996eda44c2a7338c317043feea5b28df122e7c6f" - ], - "index": "pypi", - "version": "==1.3" - }, - "django-storages": { - "hashes": [ - "sha256:9e0f3423cdf8fabe74c174380de6cd65b9343b5c83c08f35ace57213f17fb083", - "sha256:e021ae94c0ca39c683260fa0065cae0df041d795dd79fee8f7bf4ba31798640d" - ], - "index": "pypi", - "version": "==1.7" - }, - "docutils": { - "hashes": [ - "sha256:6c4f696463b79f1fb8ba0c594b63840ebd41f059e92b31957c46b74a4599b6d0", - "sha256:9e4d7ecfc600058e07ba661411a2b7de2fd0fafa17d1a7f7361cd47b1175c827", - "sha256:a2aeea129088da402665e92e0b25b04b073c04b2dce4ab65caaa38b7ce2e1a99" - ], - "version": "==0.15.2" - }, - "elasticsearch": { - "hashes": [ - "sha256:6f184507c151bf8b093b86c0b7cd576a1d730acee03e8213cae367f196ad4c5c", - "sha256:be3080a2bf32dff0a9f9fcc1c087515a25a357645673a976d25ef77166134d81" - ], - "index": "pypi", - "version": "==2.3" - }, - "et-xmlfile": { - "hashes": [ - "sha256:614d9722d572f6246302c4491846d2c393c199cfa4edc9af593437691683335b" - ], - "version": "==1.0.1" - }, - "idna": { - "hashes": [ - "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", - "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" - ], - "version": "==2.8" - }, - "importlib-metadata": { - "hashes": [ - "sha256:2a688cbaa90e0cc587f1df48bdc97a6eadccdcd9c35fb3f976a09e3b5016d90f", - "sha256:34513a8a0c4962bc66d35b359558fd8a5e10cd472d37aec5f66858addef32c1e" - ], - "markers": "python_version < '3.8'", - "version": "==1.6.0" - }, - "jdcal": { - "hashes": [ - "sha256:1abf1305fce18b4e8aa248cf8fe0c56ce2032392bc64bbd61b5dff2a19ec8bba", - "sha256:472872e096eb8df219c23f2689fc336668bdb43d194094b5cc1707e1640acfc8" - ], - "version": "==1.4.1" - }, - "jmespath": { - "hashes": [ - "sha256:695cb76fa78a10663425d5b73ddc5714eb711157e52704d69be03b1a02ba4fec", - "sha256:cca55c8d153173e21baa59983015ad0daf603f9cb799904ff057bfb8ff8dc2d9" - ], - "version": "==0.9.5" - }, - "kombu": { - "hashes": [ - "sha256:2d1cda774126a044d91a7ff5fa6d09edf99f46924ab332a810760fe6740e9b76", - "sha256:598e7e749d6ab54f646b74b2d2df67755dee13894f73ab02a2a9feb8870c7cb2" - ], - "version": "==4.6.8" - }, - "lxml": { - "hashes": [ - "sha256:02ca7bf899da57084041bb0f6095333e4d239948ad3169443f454add9f4e9cb4", - "sha256:096b82c5e0ea27ce9138bcbb205313343ee66a6e132f25c5ed67e2c8d960a1bc", - "sha256:0a920ff98cf1aac310470c644bc23b326402d3ef667ddafecb024e1713d485f1", - "sha256:1409b14bf83a7d729f92e2a7fbfe7ec929d4883ca071b06e95c539ceedb6497c", - "sha256:17cae1730a782858a6e2758fd20dd0ef7567916c47757b694a06ffafdec20046", - "sha256:17e3950add54c882e032527795c625929613adbd2ce5162b94667334458b5a36", - "sha256:1f4f214337f6ee5825bf90a65d04d70aab05526c08191ab888cb5149501923c5", - "sha256:2e8f77db25b0a96af679e64ff9bf9dddb27d379c9900c3272f3041c4d1327c9d", - "sha256:4dffd405390a45ecb95ab5ab1c1b847553c18b0ef8ed01e10c1c8b1a76452916", - "sha256:6b899931a5648862c7b88c795eddff7588fb585e81cecce20f8d9da16eff96e0", - "sha256:726c17f3e0d7a7200718c9a890ccfeab391c9133e363a577a44717c85c71db27", - "sha256:760c12276fee05c36f95f8040180abc7fbebb9e5011447a97cdc289b5d6ab6fc", - "sha256:796685d3969815a633827c818863ee199440696b0961e200b011d79b9394bbe7", - "sha256:891fe897b49abb7db470c55664b198b1095e4943b9f82b7dcab317a19116cd38", - "sha256:9277562f175d2334744ad297568677056861070399cec56ff06abbe2564d1232", - "sha256:a471628e20f03dcdfde00770eeaf9c77811f0c331c8805219ca7b87ac17576c5", - "sha256:a63b4fd3e2cabdcc9d918ed280bdde3e8e9641e04f3c59a2a3109644a07b9832", - "sha256:ae88588d687bd476be588010cbbe551e9c2872b816f2da8f01f6f1fda74e1ef0", - "sha256:b0b84408d4eabc6de9dd1e1e0bc63e7731e890c0b378a62443e5741cfd0ae90a", - "sha256:be78485e5d5f3684e875dab60f40cddace2f5b2a8f7fede412358ab3214c3a6f", - "sha256:c27eaed872185f047bb7f7da2d21a7d8913457678c9a100a50db6da890bc28b9", - "sha256:c7fccd08b14aa437fe096c71c645c0f9be0655a9b1a4b7cffc77bcb23b3d61d2", - "sha256:c81cb40bff373ab7a7446d6bbca0190bccc5be3448b47b51d729e37799bb5692", - "sha256:d11874b3c33ee441059464711cd365b89fa1a9cf19ae75b0c189b01fbf735b84", - "sha256:e9c028b5897901361d81a4718d1db217b716424a0283afe9d6735fe0caf70f79", - "sha256:fe489d486cd00b739be826e8c1be188ddb74c7a1ca784d93d06fda882a6a1681" - ], - "index": "pypi", - "version": "==4.4.1" - }, - "more-itertools": { - "hashes": [ - "sha256:5dd8bcf33e5f9513ffa06d5ad33d78f31e1931ac9a18f33d37e77a180d393a7c", - "sha256:b1ddb932186d8a6ac451e1d95844b382f55e12686d51ca0c68b6f61f2ab7a507" - ], - "version": "==8.2.0" - }, - "openpyxl": { - "hashes": [ - "sha256:72d1ed243972cad0b3c236230083cac00d9c72804e64a2ae93d7901aec1a8f1c" - ], - "index": "pypi", - "version": "==2.6.3" - }, - "packaging": { - "hashes": [ - "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3", - "sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752" - ], - "version": "==20.3" - }, - "pdfkit": { - "hashes": [ - "sha256:05f1c631e8d9ab877886955da825e48b459e097886a21448ab17b34c60cfd66c", - "sha256:6a866c9659e62a81abd72cdb32b400762d76085b964beb0b15106d573a539677", - "sha256:ef1da35b78d534197e7ce4a604a4a190e9aa769e56634957535f3479a50d8cd1" - ], - "index": "pypi", - "version": "==0.6.1" - }, - "phonenumbers": { - "hashes": [ - "sha256:127706b1743d2c0cf575be025262c9e45e687dfebd4b114ca231c9df1e713874", - "sha256:60a93df03db5170ae589a734f68a95c0646aa98fdf4c1591cb7c15c9da758e05" - ], - "index": "pypi", - "version": "==8.10.4" - }, - "pluggy": { - "hashes": [ - "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", - "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d" - ], - "version": "==0.13.1" - }, - "psycopg2-binary": { - "hashes": [ - "sha256:080c72714784989474f97be9ab0ddf7b2ad2984527e77f2909fcd04d4df53809", - "sha256:110457be80b63ff4915febb06faa7be002b93a76e5ba19bf3f27636a2ef58598", - "sha256:171352a03b22fc099f15103959b52ee77d9a27e028895d7e5fde127aa8e3bac5", - "sha256:19d013e7b0817087517a4b3cab39c084d78898369e5c46258aab7be4f233d6a1", - "sha256:249b6b21ae4eb0f7b8423b330aa80fab5f821b9ffc3f7561a5e2fd6bb142cf5d", - "sha256:2ac0731d2d84b05c7bb39e85b7e123c3a0acd4cda631d8d542802c88deb9e87e", - "sha256:2b6d561193f0dc3f50acfb22dd52ea8c8dfbc64bcafe3938b5f209cc17cb6f00", - "sha256:2bd23e242e954214944481124755cbefe7c2cf563b1a54cd8d196d502f2578bf", - "sha256:3e1239242ca60b3725e65ab2f13765fc199b03af9eaf1b5572f0e97bdcee5b43", - "sha256:3eb70bb697abbe86b1d2b1316370c02ba320bfd1e9e35cf3b9566a855ea8e4e5", - "sha256:51a2fc7e94b98bd1bb5d4570936f24fc2b0541b63eccadf8fdea266db8ad2f70", - "sha256:52f1bdafdc764b7447e393ed39bb263eccb12bfda25a4ac06d82e3a9056251f6", - "sha256:5b3581319a3951f1e866f4f6c5e42023db0fae0284273b82e97dfd32c51985cd", - "sha256:63c1b66e3b2a3a336288e4bcec499e0dc310cd1dceaed1c46fa7419764c68877", - "sha256:8123a99f24ecee469e5c1339427bcdb2a33920a18bb5c0d58b7c13f3b0298ba3", - "sha256:85e699fcabe7f817c0f0a412d4e7c6627e00c412b418da7666ff353f38e30f67", - "sha256:8dbff4557bbef963697583366400822387cccf794ccb001f1f2307ed21854c68", - "sha256:908d21d08d6b81f1b7e056bbf40b2f77f8c499ab29e64ec5113052819ef1c89b", - "sha256:af39d0237b17d0a5a5f638e9dffb34013ce2b1d41441fd30283e42b22d16858a", - "sha256:af51bb9f055a3f4af0187149a8f60c9d516cf7d5565b3dac53358796a8fb2a5b", - "sha256:b2ecac57eb49e461e86c092761e6b8e1fd9654dbaaddf71a076dcc869f7014e2", - "sha256:cd37cc170678a4609becb26b53a2bc1edea65177be70c48dd7b39a1149cabd6e", - "sha256:d17e3054b17e1a6cb8c1140f76310f6ede811e75b7a9d461922d2c72973f583e", - "sha256:d305313c5a9695f40c46294d4315ed3a07c7d2b55e48a9010dad7db7a66c8b7f", - "sha256:dd0ef0eb1f7dd18a3f4187226e226a7284bda6af5671937a221766e6ef1ee88f", - "sha256:e1adff53b56db9905db48a972fb89370ad5736e0450b96f91bcf99cadd96cfd7", - "sha256:f0d43828003c82dbc9269de87aa449e9896077a71954fbbb10a614c017e65737", - "sha256:f78e8b487de4d92640105c1389e5b90be3496b1d75c90a666edd8737cc2dbab7" - ], - "index": "pypi", - "version": "==2.8.3" - }, - "py": { - "hashes": [ - "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa", - "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0" - ], - "version": "==1.8.1" - }, - "pyparsing": { - "hashes": [ - "sha256:67199f0c41a9c702154efb0e7a8cc08accf830eb003b4d9fa42c4059002e2492", - "sha256:700d17888d441604b0bd51535908dcb297561b040819cccde647a92439db5a2a" - ], - "version": "==3.0.0a1" - }, - "pytest": { - "hashes": [ - "sha256:95b1f6db806e5b1b5b443efeb58984c24945508f93a866c1719e1a507a957d7c", - "sha256:c3d5020755f70c82eceda3feaf556af9a341334414a8eca521a18f463bcead88" - ], - "index": "pypi", - "version": "==5.1.1" - }, - "pytest-django": { - "hashes": [ - "sha256:264fb4c506db5d48a6364c311a0b00b7b48a52715bad8839b2d8bee9b99ed6bb", - "sha256:4adfe5fb3ed47f0ba55506dd3daf688b1f74d5e69148c10ad2dd2f79f40c0d62" - ], - "index": "pypi", - "version": "==3.5.1" - }, - "python-dateutil": { - "hashes": [ - "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", - "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" - ], - "markers": "python_version >= '2.7'", - "version": "==2.8.1" - }, - "python-memcached": { - "hashes": [ - "sha256:4dac64916871bd3550263323fc2ce18e1e439080a2d5670c594cf3118d99b594", - "sha256:a2e28637be13ee0bf1a8b6843e7490f9456fd3f2a4cb60471733c7b5d5557e4f" - ], - "index": "pypi", - "version": "==1.59" - }, - "pytz": { - "hashes": [ - "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d", - "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be" - ], - "version": "==2019.3" - }, - "raven": { - "hashes": [ - "sha256:3fa6de6efa2493a7c827472e984ce9b020797d0da16f1db67197bcc23c8fae54", - "sha256:44a13f87670836e153951af9a3c80405d36b43097db869a36e92809673692ce4" - ], - "index": "pypi", - "version": "==6.10.0" - }, - "rcssmin": { - "hashes": [ - "sha256:ca87b695d3d7864157773a61263e5abb96006e9ff0e021eff90cbe0e1ba18270" - ], - "version": "==1.0.6" - }, - "redis": { - "hashes": [ - "sha256:98a22fb750c9b9bb46e75e945dc3f61d0ab30d06117cbb21ff9cd1d315fedd3b", - "sha256:c504251769031b0dd7dd5cf786050a6050197c6de0d37778c80c08cb04ae8275" - ], - "index": "pypi", - "version": "==3.3.8" - }, - "requests": { - "hashes": [ - "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", - "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31" - ], - "index": "pypi", - "version": "==2.22.0" - }, - "rjsmin": { - "hashes": [ - "sha256:0ab825839125eaca57cc59581d72e596e58a7a56fbc0839996b7528f0343a0a8", - "sha256:211c2fe8298951663bbc02acdffbf714f6793df54bfc50e1c6c9e71b3f2559a3", - "sha256:466fe70cc5647c7c51b3260c7e2e323a98b2b173564247f9c89e977720a0645f", - "sha256:585e75a84d9199b68056fd4a083d9a61e2a92dfd10ff6d4ce5bdb04bc3bdbfaf", - "sha256:6044ca86e917cd5bb2f95e6679a4192cef812122f28ee08c677513de019629b3", - "sha256:714329db774a90947e0e2086cdddb80d5e8c4ac1c70c9f92436378dedb8ae345", - "sha256:799890bd07a048892d8d3deb9042dbc20b7f5d0eb7da91e9483c561033b23ce2", - "sha256:975b69754d6a76be47c0bead12367a1ca9220d08e5393f80bab0230d4625d1f4", - "sha256:b15dc75c71f65d9493a8c7fa233fdcec823e3f1b88ad84a843ffef49b338ac32", - "sha256:dd0f4819df4243ffe4c964995794c79ca43943b5b756de84be92b445a652fb86", - "sha256:e3908b21ebb584ce74a6ac233bdb5f29485752c9d3be5e50c5484ed74169232c", - "sha256:e487a7783ac4339e79ec610b98228eb9ac72178973e3dee16eba0e3feef25924", - "sha256:ecd29f1b3e66a4c0753105baec262b331bcbceefc22fbe6f7e8bcd2067bcb4d7" - ], - "version": "==1.1.0" - }, - "s3transfer": { - "hashes": [ - "sha256:6efc926738a3cd576c2a79725fed9afde92378aa5c6a957e3af010cb019fac9d", - "sha256:b780f2411b824cb541dbcd2c713d0cb61c7d1bcadae204cdddda2b35cef493ba" - ], - "version": "==0.2.1" - }, - "six": { - "hashes": [ - "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", - "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" - ], - "version": "==1.14.0" - }, - "sorl-thumbnail": { - "hashes": [ - "sha256:8dfe5fda91a5047d1d35a0b9effe7b000764a01d648e15ca076f44e9c34b6dbd", - "sha256:d9e3f018d19293824803e4ffead96b19dfcd44fa7987cea392f50436817bef34" - ], - "index": "pypi", - "version": "==12.5.0" - }, - "sqlparse": { - "hashes": [ - "sha256:022fb9c87b524d1f7862b3037e541f68597a730a8843245c349fc93e1643dc4e", - "sha256:e162203737712307dfe78860cc56c8da8a852ab2ee33750e33aeadf38d12c548" - ], - "version": "==0.3.1" - }, - "tblib": { - "hashes": [ - "sha256:229bee3754cb5d98b4837dd5c4405e80cfab57cb9f93220410ad367f8b352344", - "sha256:e222f44485d45ed13fada73b57775e2ff9bd8af62160120bbb6679f5ad80315b" - ], - "index": "pypi", - "version": "==1.6.0" - }, - "urllib3": { - "hashes": [ - "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc", - "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc" - ], - "markers": "python_version >= '3.4'", - "version": "==1.25.8" - }, - "vine": { - "hashes": [ - "sha256:133ee6d7a9016f177ddeaf191c1f58421a1dcc6ee9a42c58b34bed40e1d2cd87", - "sha256:ea4947cc56d1fd6f2095c8d543ee25dad966f78692528e68b4fada11ba3f98af" - ], - "version": "==1.3.0" - }, - "wcwidth": { - "hashes": [ - "sha256:cafe2186b3c009a04067022ce1dcd79cb38d8d65ee4f4791b8888d6599d1bbe1", - "sha256:ee73862862a156bf77ff92b09034fc4825dd3af9cf81bc5b360668d425f3c5f1" - ], - "version": "==0.1.9" - }, - "xlrd": { - "hashes": [ - "sha256:546eb36cee8db40c3eaa46c351e67ffee6eeb5fa2650b71bc4c758a29a1b29b2", - "sha256:e551fb498759fa3a5384a94ccd4c3c02eb7c00ea424426e212ac0c57be9dfbde" - ], - "index": "pypi", - "version": "==1.2.0" - }, - "xlwt": { - "hashes": [ - "sha256:a082260524678ba48a297d922cc385f58278b8aa68741596a87de01a9c628b2e", - "sha256:c59912717a9b28f1a3c2a98fd60741014b06b043936dcecbc113eaaada156c88" - ], - "index": "pypi", - "version": "==1.3.0" - }, - "zipp": { - "hashes": [ - "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b", - "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96" - ], - "version": "==3.1.0" - } - }, - "develop": { - "appdirs": { - "hashes": [ - "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92", - "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e" - ], - "version": "==1.4.3" - }, - "astroid": { - "hashes": [ - "sha256:71ea07f44df9568a75d0f354c49143a4575d90645e9fead6dfb52c26a85ed13a", - "sha256:840947ebfa8b58f318d42301cf8c0a20fd794a33b61cc4638e28e9e61ba32f42" - ], - "version": "==2.3.3" - }, - "attrs": { - "hashes": [ - "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", - "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72" - ], - "version": "==19.3.0" - }, - "black": { - "hashes": [ - "sha256:1b30e59be925fafc1ee4565e5e08abef6b03fe455102883820fe5ee2e4734e0b", - "sha256:c2edb73a08e9e0e6f65a0e6af18b059b8b1cdd5bef997d7a0b181df93dc81539" - ], - "index": "pypi", - "version": "==19.10b0" - }, - "click": { - "hashes": [ - "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc", - "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a" - ], - "version": "==7.1.1" - }, - "isort": { - "hashes": [ - "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1", - "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd" - ], - "index": "pypi", - "version": "==4.3.21" - }, - "lazy-object-proxy": { - "hashes": [ - "sha256:0c4b206227a8097f05c4dbdd323c50edf81f15db3b8dc064d08c62d37e1a504d", - "sha256:194d092e6f246b906e8f70884e620e459fc54db3259e60cf69a4d66c3fda3449", - "sha256:1be7e4c9f96948003609aa6c974ae59830a6baecc5376c25c92d7d697e684c08", - "sha256:4677f594e474c91da97f489fea5b7daa17b5517190899cf213697e48d3902f5a", - "sha256:48dab84ebd4831077b150572aec802f303117c8cc5c871e182447281ebf3ac50", - "sha256:5541cada25cd173702dbd99f8e22434105456314462326f06dba3e180f203dfd", - "sha256:59f79fef100b09564bc2df42ea2d8d21a64fdcda64979c0fa3db7bdaabaf6239", - "sha256:8d859b89baf8ef7f8bc6b00aa20316483d67f0b1cbf422f5b4dc56701c8f2ffb", - "sha256:9254f4358b9b541e3441b007a0ea0764b9d056afdeafc1a5569eee1cc6c1b9ea", - "sha256:9651375199045a358eb6741df3e02a651e0330be090b3bc79f6d0de31a80ec3e", - "sha256:97bb5884f6f1cdce0099f86b907aa41c970c3c672ac8b9c8352789e103cf3156", - "sha256:9b15f3f4c0f35727d3a0fba4b770b3c4ebbb1fa907dbcc046a1d2799f3edd142", - "sha256:a2238e9d1bb71a56cd710611a1614d1194dc10a175c1e08d75e1a7bcc250d442", - "sha256:a6ae12d08c0bf9909ce12385803a543bfe99b95fe01e752536a60af2b7797c62", - "sha256:ca0a928a3ddbc5725be2dd1cf895ec0a254798915fb3a36af0964a0a4149e3db", - "sha256:cb2c7c57005a6804ab66f106ceb8482da55f5314b7fcb06551db1edae4ad1531", - "sha256:d74bb8693bf9cf75ac3b47a54d716bbb1a92648d5f781fc799347cfc95952383", - "sha256:d945239a5639b3ff35b70a88c5f2f491913eb94871780ebfabb2568bd58afc5a", - "sha256:eba7011090323c1dadf18b3b689845fd96a61ba0a1dfbd7f24b921398affc357", - "sha256:efa1909120ce98bbb3777e8b6f92237f5d5c8ea6758efea36a473e1d38f7d3e4", - "sha256:f3900e8a5de27447acbf900b4750b0ddfd7ec1ea7fbaf11dfa911141bc522af0" - ], - "version": "==1.4.3" - }, - "mccabe": { - "hashes": [ - "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", - "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" - ], - "version": "==0.6.1" - }, - "pathspec": { - "hashes": [ - "sha256:7d91249d21749788d07a2d0f94147accd8f845507400749ea19c1ec9054a12b0", - "sha256:da45173eb3a6f2a5a487efba21f050af2b41948be6ab52b6a1e3ff22bb8b7061" - ], - "version": "==0.8.0" - }, - "pylint": { - "hashes": [ - "sha256:3db5468ad013380e987410a8d6956226963aed94ecb5f9d3a28acca6d9ac36cd", - "sha256:886e6afc935ea2590b462664b161ca9a5e40168ea99e5300935f6591ad467df4" - ], - "index": "pypi", - "version": "==2.4.4" - }, - "regex": { - "hashes": [ - "sha256:08119f707f0ebf2da60d2f24c2f39ca616277bb67ef6c92b72cbf90cbe3a556b", - "sha256:0ce9537396d8f556bcfc317c65b6a0705320701e5ce511f05fc04421ba05b8a8", - "sha256:1cbe0fa0b7f673400eb29e9ef41d4f53638f65f9a2143854de6b1ce2899185c3", - "sha256:2294f8b70e058a2553cd009df003a20802ef75b3c629506be20687df0908177e", - "sha256:23069d9c07e115537f37270d1d5faea3e0bdded8279081c4d4d607a2ad393683", - "sha256:24f4f4062eb16c5bbfff6a22312e8eab92c2c99c51a02e39b4eae54ce8255cd1", - "sha256:295badf61a51add2d428a46b8580309c520d8b26e769868b922750cf3ce67142", - "sha256:2a3bf8b48f8e37c3a40bb3f854bf0121c194e69a650b209628d951190b862de3", - "sha256:4385f12aa289d79419fede43f979e372f527892ac44a541b5446617e4406c468", - "sha256:5635cd1ed0a12b4c42cce18a8d2fb53ff13ff537f09de5fd791e97de27b6400e", - "sha256:5bfed051dbff32fd8945eccca70f5e22b55e4148d2a8a45141a3b053d6455ae3", - "sha256:7e1037073b1b7053ee74c3c6c0ada80f3501ec29d5f46e42669378eae6d4405a", - "sha256:90742c6ff121a9c5b261b9b215cb476eea97df98ea82037ec8ac95d1be7a034f", - "sha256:a58dd45cb865be0ce1d5ecc4cfc85cd8c6867bea66733623e54bd95131f473b6", - "sha256:c087bff162158536387c53647411db09b6ee3f9603c334c90943e97b1052a156", - "sha256:c162a21e0da33eb3d31a3ac17a51db5e634fc347f650d271f0305d96601dc15b", - "sha256:c9423a150d3a4fc0f3f2aae897a59919acd293f4cb397429b120a5fcd96ea3db", - "sha256:ccccdd84912875e34c5ad2d06e1989d890d43af6c2242c6fcfa51556997af6cd", - "sha256:e91ba11da11cf770f389e47c3f5c30473e6d85e06d7fd9dcba0017d2867aab4a", - "sha256:ea4adf02d23b437684cd388d557bf76e3afa72f7fed5bbc013482cc00c816948", - "sha256:fb95debbd1a824b2c4376932f2216cc186912e389bdb0e27147778cf6acb3f89" - ], - "version": "==2020.4.4" - }, - "six": { - "hashes": [ - "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", - "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" - ], - "version": "==1.14.0" - }, - "toml": { - "hashes": [ - "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", - "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e" - ], - "version": "==0.10.0" - }, - "typed-ast": { - "hashes": [ - "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355", - "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919", - "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa", - "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652", - "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75", - "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01", - "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d", - "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1", - "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907", - "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c", - "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3", - "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b", - "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614", - "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb", - "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b", - "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41", - "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6", - "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34", - "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe", - "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4", - "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7" - ], - "markers": "implementation_name == 'cpython' and python_version < '3.8'", - "version": "==1.4.1" - }, - "wrapt": { - "hashes": [ - "sha256:565a021fd19419476b9362b05eeaa094178de64f8361e44468f9e9d7843901e1" - ], - "version": "==1.11.2" - } - } -} diff --git a/accounts/api_urls.py b/accounts/api_urls.py index f7a7360..8eafc44 100644 --- a/accounts/api_urls.py +++ b/accounts/api_urls.py @@ -1,7 +1,7 @@ from django.urls import path from accounts import api_views -app_name = 'api_accounts' +app_name = "api_accounts" urlpatterns = [ path("", api_views.AccountsListView.as_view()), diff --git a/accounts/api_views.py b/accounts/api_views.py index b06f45c..2e52318 100644 --- a/accounts/api_views.py +++ b/accounts/api_views.py @@ -9,7 +9,11 @@ from accounts.models import Account, Tags from accounts.tasks import send_email_to_assigned_user from accounts import swagger_params -from accounts.serializer import AccountSerializer, TagsSerailizer, AccountCreateSerializer +from accounts.serializer import ( + AccountSerializer, + TagsSerailizer, + AccountCreateSerializer, +) from common.models import User, Attachments from common.utils import ( COUNTRIES, @@ -53,24 +57,24 @@ class AccountsListView(APIView): model = Account def get_queryset(self): - params = self.request.query_params if len( - self.request.data) == 0 else self.request.data + params = ( + self.request.query_params + if len(self.request.data) == 0 + else self.request.data + ) queryset = self.model.objects.all() if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: queryset = queryset.filter( - Q(created_by=self.request.user) | Q( - assigned_to=self.request.user) + Q(created_by=self.request.user) | Q(assigned_to=self.request.user) ).distinct() if self.request.GET.get("tag", None): - queryset = queryset.filter( - tags__in=self.request.GET.getlist("tag")) - if params.get('is_filter'): + queryset = queryset.filter(tags__in=self.request.GET.getlist("tag")) + if params.get("is_filter"): request_post = params if request_post: if request_post.get("name"): - queryset = queryset.filter( - name__icontains=request_post.get("name")) + queryset = queryset.filter(name__icontains=request_post.get("name")) if request_post.get("city"): queryset = queryset.filter( billing_city__contains=request_post.get("city") @@ -80,28 +84,32 @@ def get_queryset(self): industry__icontains=request_post.get("industry") ) if request_post.get("tag"): - queryset = queryset.filter( - tags__in=request_post.getlist("tag")) + queryset = queryset.filter(tags__in=request_post.getlist("tag")) return queryset.filter(company=self.request.company).distinct() def get_context_data(self, **kwargs): context = {} open_accounts = AccountSerializer( - self.get_queryset().filter(status="open"), many=True).data + self.get_queryset().filter(status="open"), many=True + ).data close_accounts = AccountSerializer( - self.get_queryset().filter(status="close"), many=True).data + self.get_queryset().filter(status="close"), many=True + ).data context["accounts_list"] = AccountSerializer( - self.get_queryset(), many=True).data - context["users"] = UserSerializer(User.objects.filter( - is_active=True).order_by("email"), many=True).data + self.get_queryset(), many=True + ).data + context["users"] = UserSerializer( + User.objects.filter(is_active=True).order_by("email"), many=True + ).data context["open_accounts"] = open_accounts context["close_accounts"] = close_accounts context["industries"] = INDCHOICES context["per_page"] = self.request.POST.get("per_page") tag_ids = list(set(Account.objects.values_list("tags", flat=True))) context["tags"] = TagsSerailizer( - Tags.objects.filter(id__in=tag_ids), many=True).data + Tags.objects.filter(id__in=tag_ids), many=True + ).data if self.request.POST.get("tag", None): context["request_tags"] = self.request.POST.getlist("tag") elif self.request.GET.get("tag", None): @@ -130,15 +138,18 @@ def get_context_data(self, **kwargs): return context - @swagger_auto_schema(tags=["accounts"], manual_parameters=swagger_params.account_list_get_params) + @swagger_auto_schema( + tags=["accounts"], manual_parameters=swagger_params.account_list_get_params + ) def get(self, request, *args, **kwargs): context = self.get_context_data(**kwargs) return Response(context) - @swagger_auto_schema(tags=["accounts"], manual_parameters=swagger_params.account_create_post_params) + @swagger_auto_schema( + tags=["accounts"], manual_parameters=swagger_params.account_create_post_params + ) def post(self, request, *args, **kwargs): - params = request.query_params if len( - request.data) == 0 else request.data + params = request.query_params if len(request.data) == 0 else request.data context = {} serializer = AccountCreateSerializer( data=params, request_obj=request, account=True @@ -146,7 +157,8 @@ def post(self, request, *args, **kwargs): # Save Account if serializer.is_valid(): account_object = serializer.save( - created_by=request.user, company=request.company) + created_by=request.user, company=request.company + ) if self.request.POST.get("tags", ""): tags = params.get("tags") @@ -159,19 +171,15 @@ def post(self, request, *args, **kwargs): tag = Tags.objects.create(name=t) account_object.tags.add(tag) if params.getlist("contacts", []): - account_object.contacts.add( - *params.getlist("contacts")) + account_object.contacts.add(*params.getlist("contacts")) if params.getlist("assigned_to", []): - account_object.assigned_to.add( - *params.getlist("assigned_to")) + account_object.assigned_to.add(*params.getlist("assigned_to")) if self.request.FILES.get("account_attachment"): attachment = Attachments() attachment.created_by = request.user - attachment.file_name = request.FILES.get( - "account_attachment").name + attachment.file_name = request.FILES.get("account_attachment").name attachment.account = account_object - attachment.attachment = request.FILES.get( - "account_attachment") + attachment.attachment = request.FILES.get("account_attachment") attachment.save() if params.getlist("teams", []): user_ids = Teams.objects.filter( @@ -197,8 +205,7 @@ def post(self, request, *args, **kwargs): domain=current_site.domain, protocol=self.request.scheme, ) - return Response({'error': False, - 'message': 'Account Created Successfully'}) + return Response({"error": False, "message": "Account Created Successfully"}) context["errors"] = serializer.errors return Response(context, status=status.HTTP_400_BAD_REQUEST) @@ -211,19 +218,19 @@ def get_object(self, pk): return Account.objects.filter(id=pk).first() def dispatch(self, request, *args, **kwargs): - self.account = self.get_object(pk=kwargs.get('pk')) + self.account = self.get_object(pk=kwargs.get("pk")) if self.account.company != request.company: raise PermissionDenied return super(AccountDetailView, self).dispatch(request, *args, **kwargs) - @swagger_auto_schema(tags=["accounts"], manual_parameters=swagger_params.account_update_post_params) + @swagger_auto_schema( + tags=["accounts"], manual_parameters=swagger_params.account_update_post_params + ) def put(self, request, pk, format=None): - params = request.query_params if len( - request.data) == 0 else request.data + params = request.query_params if len(request.data) == 0 else request.data context = {} serializer = AccountCreateSerializer( - data=params, instance=self.account, - request_obj=request, account=True + data=params, instance=self.account, request_obj=request, account=True ) if serializer.is_valid(): account_object = serializer.save() @@ -243,22 +250,18 @@ def put(self, request, pk, format=None): account_object.tags.add(tag) if params.getlist("contacts", []): account_object.contacts.clear() - account_object.contacts.add( - *params.getlist("contacts")) + account_object.contacts.add(*params.getlist("contacts")) if params.getlist("assigned_to", []): account_object.assigned_to.clear() - account_object.assigned_to.add( - *params.getlist("assigned_to")) + account_object.assigned_to.add(*params.getlist("assigned_to")) else: account_object.assigned_to.clear() if self.request.FILES.get("account_attachment"): attachment = Attachments() attachment.created_by = self.request.user - attachment.file_name = self.request.FILES.get( - "account_attachment").name + attachment.file_name = self.request.FILES.get("account_attachment").name attachment.account = account_object - attachment.attachment = self.request.FILES.get( - "account_attachment") + attachment.attachment = self.request.FILES.get("account_attachment") attachment.save() if params.getlist("teams", []): @@ -281,20 +284,20 @@ def put(self, request, pk, format=None): account_object.assigned_to.all().values_list("id", flat=True) ) current_site = get_current_site(self.request) - recipients = list(set(assigned_to_list) - - set(previous_assigned_to_users)) + recipients = list(set(assigned_to_list) - set(previous_assigned_to_users)) send_email_to_assigned_user.delay( recipients, account_object.id, domain=current_site.domain, protocol=self.request.scheme, ) - return Response({'error': False, - 'message': 'Account Updated Successfully'}) - context['errors'] = serializer.errors + return Response({"error": False, "message": "Account Updated Successfully"}) + context["errors"] = serializer.errors return Response(context, status=status.HTTP_400_BAD_REQUEST) - @swagger_auto_schema(tags=["accounts"], manual_parameters=swagger_params.company_params) + @swagger_auto_schema( + tags=["accounts"], manual_parameters=swagger_params.company_params + ) def delete(self, request, pk, format=None): self.object = self.get_object(pk) if self.object.company != request.company: @@ -303,9 +306,11 @@ def delete(self, request, pk, format=None): if self.request.user != self.object.created_by: raise PermissionDenied self.object.delete() - return Response({'status': 'success'}, status=status.HTTP_204_NO_CONTENT) + return Response({"status": "success"}, status=status.HTTP_204_NO_CONTENT) - @swagger_auto_schema(tags=["accounts"], manual_parameters=swagger_params.account_list_get_params) + @swagger_auto_schema( + tags=["accounts"], manual_parameters=swagger_params.account_list_get_params + ) def get(self, request, pk, format=None): context = {} context["account_obj"] = AccountSerializer(self.account).data @@ -329,13 +334,13 @@ def get(self, request, pk, format=None): if self.request.user.is_superuser or self.request.user.role == "ADMIN": users_mention = list( User.objects.filter( - is_active=True, company=self.request.company, + is_active=True, + company=self.request.company, ).values("username") ) elif self.request.user != self.account.created_by: if self.account.created_by: - users_mention = [ - {"username": self.account.created_by.username}] + users_mention = [{"username": self.account.created_by.username}] else: users_mention = [] else: @@ -344,20 +349,27 @@ def get(self, request, pk, format=None): context.update( { "comments": CommentSerializer( - self.account.accounts_comments.all(), many=True).data, + self.account.accounts_comments.all(), many=True + ).data, "attachments": AttachmentsSerializer( - self.account.account_attachment.all(), many=True).data, + self.account.account_attachment.all(), many=True + ).data, "opportunity_list": OpportunitySerializer( - Opportunity.objects.filter( - account=self.account), many=True).data, + Opportunity.objects.filter(account=self.account), many=True + ).data, "contacts": ContactSerializer( - self.account.contacts.all(), many=True).data, - "users": UserSerializer(User.objects.filter( - is_active=True, company=self.request.company, - ).order_by("email"), many=True).data, + self.account.contacts.all(), many=True + ).data, + "users": UserSerializer( + User.objects.filter( + is_active=True, + company=self.request.company, + ).order_by("email"), + many=True, + ).data, "cases": CaseSerializer( - Case.objects.filter( - account=self.account), many=True).data, + Case.objects.filter(account=self.account), many=True + ).data, "stages": STAGES, "sources": SOURCES, "countries": COUNTRIES, @@ -367,11 +379,14 @@ def get(self, request, pk, format=None): "case_status": STATUS_CHOICE, "comment_permission": comment_permission, "tasks": TaskSerializer( - self.account.accounts_tasks.all(), many=True).data, + self.account.accounts_tasks.all(), many=True + ).data, "invoices": InvoiceSerailizer( - self.account.accounts_invoices.all(), many=True).data, + self.account.accounts_invoices.all(), many=True + ).data, "emails": EmailSerailizer( - self.account.sent_email.all(), many=True).data, + self.account.sent_email.all(), many=True + ).data, "users_mention": users_mention, } ) diff --git a/accounts/forms.py b/accounts/forms.py index 754d0a9..795d090 100644 --- a/accounts/forms.py +++ b/accounts/forms.py @@ -86,20 +86,19 @@ def __init__(self, *args, **kwargs): self.fields["lead"].required = False self.company = request_obj.company - def clean_name(self): name = self.cleaned_data.get("name") if self.instance.id: if self.instance.name != name: if not Account.objects.filter( - name__iexact=self.cleaned_data.get("name"), - company=self.company + name__iexact=self.cleaned_data.get("name"), company=self.company ).exists(): return self.cleaned_data.get("name") - raise forms.ValidationError( - "Account already exists with this name") + raise forms.ValidationError("Account already exists with this name") return self.cleaned_data.get("name") - if not Account.objects.filter(name__iexact=self.cleaned_data.get("name"), company=self.company).exists(): + if not Account.objects.filter( + name__iexact=self.cleaned_data.get("name"), company=self.company + ).exists(): return self.cleaned_data.get("name") raise forms.ValidationError("Account already exists with this name") diff --git a/accounts/migrations/0001_initial.py b/accounts/migrations/0001_initial.py index 4907b3d..99074af 100644 --- a/accounts/migrations/0001_initial.py +++ b/accounts/migrations/0001_initial.py @@ -86,6 +86,8 @@ class Migration(migrations.Migration): ), ("is_active", models.BooleanField(default=False)), ], - options={"ordering": ["-created_on"],}, + options={ + "ordering": ["-created_on"], + }, ), ] diff --git a/accounts/migrations/0005_auto_20190212_1334.py b/accounts/migrations/0005_auto_20190212_1334.py index c7223ed..6f87ec3 100644 --- a/accounts/migrations/0005_auto_20190212_1334.py +++ b/accounts/migrations/0005_auto_20190212_1334.py @@ -14,8 +14,14 @@ class Migration(migrations.Migration): ] operations = [ - migrations.RemoveField(model_name="account", name="assigned_to",), - migrations.RemoveField(model_name="account", name="teams",), + migrations.RemoveField( + model_name="account", + name="assigned_to", + ), + migrations.RemoveField( + model_name="account", + name="teams", + ), migrations.AddField( model_name="account", name="contacts", diff --git a/accounts/migrations/0006_auto_20190212_1708.py b/accounts/migrations/0006_auto_20190212_1708.py index 3812e88..1d4f032 100644 --- a/accounts/migrations/0006_auto_20190212_1708.py +++ b/accounts/migrations/0006_auto_20190212_1708.py @@ -11,10 +11,18 @@ class Migration(migrations.Migration): operations = [ migrations.RenameField( - model_name="account", old_name="leads", new_name="lead", + model_name="account", + old_name="leads", + new_name="lead", + ), + migrations.RemoveField( + model_name="account", + name="billing_address", + ), + migrations.RemoveField( + model_name="account", + name="shipping_address", ), - migrations.RemoveField(model_name="account", name="billing_address",), - migrations.RemoveField(model_name="account", name="shipping_address",), migrations.AddField( model_name="account", name="billing_address_line", diff --git a/accounts/migrations/0009_auto_20190809_1659.py b/accounts/migrations/0009_auto_20190809_1659.py index 2852b40..e40d735 100644 --- a/accounts/migrations/0009_auto_20190809_1659.py +++ b/accounts/migrations/0009_auto_20190809_1659.py @@ -14,12 +14,19 @@ class Migration(migrations.Migration): operations = [ migrations.RenameField( - model_name="email", old_name="sent_at", new_name="created_on", + model_name="email", + old_name="sent_at", + new_name="created_on", ), migrations.RenameField( - model_name="email", old_name="sender", new_name="from_account", + model_name="email", + old_name="sender", + new_name="from_account", + ), + migrations.RemoveField( + model_name="email", + name="recipient", ), - migrations.RemoveField(model_name="email", name="recipient",), migrations.AddField( model_name="email", name="from_email", diff --git a/accounts/serializer.py b/accounts/serializer.py index 69ae0be..2335e87 100644 --- a/accounts/serializer.py +++ b/accounts/serializer.py @@ -7,13 +7,9 @@ class TagsSerailizer(serializers.ModelSerializer): - class Meta: model = Tags - fields = ( - "name", - "slug" - ) + fields = ("name", "slug") class AccountSerializer(serializers.ModelSerializer): @@ -29,7 +25,7 @@ class Meta: model = Account # fields = ‘__all__’ fields = ( - 'id', + "id", "name", "email", "phone", @@ -52,12 +48,11 @@ class Meta: "contacts", "assigned_to", "teams", - "company" + "company", ) class EmailSerializer(serializers.ModelSerializer): - class Meta: model = Email fields = ( @@ -79,15 +74,10 @@ class EmailLogSerializer(serializers.ModelSerializer): class Meta: model = Email - fields = ( - "email" - "contact" - "is_sent" - ) + fields = "email" "contact" "is_sent" class AccountCreateSerializer(serializers.ModelSerializer): - def __init__(self, *args, **kwargs): account_view = kwargs.pop("account", False) request_obj = kwargs.pop("request_obj", None) @@ -110,19 +100,16 @@ def validate_name(self, name): if self.instance: if self.instance.name != name: if not Account.objects.filter( - name__iexact=name, - company=self.company + name__iexact=name, company=self.company ).exists(): return name raise serializers.ValidationError( - "Account already exists with this name") + "Account already exists with this name" + ) return name - if not Account.objects.filter( - name__iexact=name, - company=self.company).exists(): + if not Account.objects.filter(name__iexact=name, company=self.company).exists(): return name - raise serializers.ValidationError( - "Account already exists with this name") + raise serializers.ValidationError("Account already exists with this name") class Meta: model = Account diff --git a/accounts/swagger_params.py b/accounts/swagger_params.py index c5ed189..dc409d5 100644 --- a/accounts/swagger_params.py +++ b/accounts/swagger_params.py @@ -1,7 +1,8 @@ from drf_yasg import openapi company_params_in_header = openapi.Parameter( - 'company', openapi.IN_HEADER, required=True, type=openapi.TYPE_STRING) + "company", openapi.IN_HEADER, required=True, type=openapi.TYPE_STRING +) account_list_get_params = [company_params_in_header] @@ -12,26 +13,39 @@ account_create_post_params = [ company_params_in_header, - openapi.Parameter('name', openapi.IN_QUERY, - required=True, type=openapi.TYPE_STRING), - openapi.Parameter('phone', openapi.IN_QUERY, - required=True, type=openapi.TYPE_STRING), - openapi.Parameter('email', openapi.IN_QUERY, - required=True, type=openapi.TYPE_STRING), - openapi.Parameter('billing_address_line', openapi.IN_QUERY, - required=True, type=openapi.TYPE_STRING), - openapi.Parameter('billing_street', openapi.IN_QUERY, - required=True, type=openapi.TYPE_STRING), - openapi.Parameter('billing_city', openapi.IN_QUERY, - required=True, type=openapi.TYPE_STRING), - openapi.Parameter('billing_state', openapi.IN_QUERY, - required=True, type=openapi.TYPE_STRING), - openapi.Parameter('billing_postcode', openapi.IN_QUERY, - required=True, type=openapi.TYPE_STRING), - openapi.Parameter('billing_country', openapi.IN_QUERY, - required=True, type=openapi.TYPE_STRING), - openapi.Parameter('contacts', openapi.IN_QUERY, - required=True, type=openapi.TYPE_STRING), + openapi.Parameter( + "name", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "phone", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "email", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "billing_address_line", + openapi.IN_QUERY, + required=True, + type=openapi.TYPE_STRING, + ), + openapi.Parameter( + "billing_street", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "billing_city", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "billing_state", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "billing_postcode", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "billing_country", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "contacts", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), ] @@ -39,26 +53,39 @@ account_update_post_params = [ company_params_in_header, - openapi.Parameter('name', openapi.IN_QUERY, - required=True, type=openapi.TYPE_STRING), - openapi.Parameter('phone', openapi.IN_QUERY, - required=True, type=openapi.TYPE_STRING), - openapi.Parameter('email', openapi.IN_QUERY, - required=True, type=openapi.TYPE_STRING), - openapi.Parameter('billing_address_line', openapi.IN_QUERY, - required=True, type=openapi.TYPE_STRING), - openapi.Parameter('billing_street', openapi.IN_QUERY, - required=True, type=openapi.TYPE_STRING), - openapi.Parameter('billing_city', openapi.IN_QUERY, - required=True, type=openapi.TYPE_STRING), - openapi.Parameter('billing_state', openapi.IN_QUERY, - required=True, type=openapi.TYPE_STRING), - openapi.Parameter('billing_postcode', openapi.IN_QUERY, - required=True, type=openapi.TYPE_STRING), - openapi.Parameter('billing_country', openapi.IN_QUERY, - required=True, type=openapi.TYPE_STRING), - openapi.Parameter('contacts', openapi.IN_QUERY, - required=True, type=openapi.TYPE_STRING), + openapi.Parameter( + "name", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "phone", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "email", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "billing_address_line", + openapi.IN_QUERY, + required=True, + type=openapi.TYPE_STRING, + ), + openapi.Parameter( + "billing_street", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "billing_city", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "billing_state", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "billing_postcode", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "billing_country", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "contacts", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), ] company_params = [ diff --git a/accounts/tasks.py b/accounts/tasks.py index a53032a..2f61dbd 100644 --- a/accounts/tasks.py +++ b/accounts/tasks.py @@ -45,7 +45,9 @@ def send_email(email_obj_id): subject, html_content, from_email=from_email, - to=[contact_obj.email, ], + to=[ + contact_obj.email, + ], ) msg.content_subtype = "html" res = msg.send() diff --git a/accounts/tests.py b/accounts/tests.py index 90ba5cf..49da5ad 100644 --- a/accounts/tests.py +++ b/accounts/tests.py @@ -283,7 +283,9 @@ def test_account_creation_invalid_data(self): class AccountModelTest(AccountCreateTest, TestCase): def test_string_representation(self): - account = Account(name="Account name",) + account = Account( + name="Account name", + ) self.assertEqual(str(account), account.name) def setUp(self): @@ -291,7 +293,9 @@ def setUp(self): name="test company", address="IN", sub_domain="test", country="IN" ) self.user = User.objects.create( - username="username", email="email@email.com", company=self.company, + username="username", + email="email@email.com", + company=self.company, ) @@ -596,7 +600,13 @@ def test_account_views(self): self.assertEqual(200, response.status_code) response = self.client.post( reverse("accounts:list"), - {"industry": "industry", "tag": [1,], "tab_status": "true"}, + { + "industry": "industry", + "tag": [ + 1, + ], + "tab_status": "true", + }, ) self.assertEqual(200, response.status_code) self.tag_name = Tags.objects.create(name="tag name") @@ -619,10 +629,16 @@ def test_account_views(self): "website": "www.example.com", "industry": "SOFTWARE", "description": "Testing", - "contacts": [self.contact_user1.id,], + "contacts": [ + self.contact_user1.id, + ], "tags": self.tag_name.name, - "assigned_to": [self.user.id,], - "teams": [self.team_account.id,], + "assigned_to": [ + self.user.id, + ], + "teams": [ + self.team_account.id, + ], }, HTTP_X_REQUESTED_WITH="XMLHttpRequest", ) @@ -642,10 +658,16 @@ def test_account_views(self): "website": "www.example.com", "industry": "SOFTWARE", "description": "Testing", - "contacts": [self.contact_user1.id,], + "contacts": [ + self.contact_user1.id, + ], "tags": self.tag_name.name, - "assigned_to": [self.user.id,], - "teams": [self.team_account.id,], + "assigned_to": [ + self.user.id, + ], + "teams": [ + self.team_account.id, + ], }, ) self.assertEqual(response.status_code, 302) @@ -665,10 +687,16 @@ def test_account_views(self): "website": "www.example.com", "industry": "SOFTWARE", "description": "Testing", - "contacts": [self.contact_user1.id,], + "contacts": [ + self.contact_user1.id, + ], "tags": self.tag_name.name, - "assigned_to": [self.user.id,], - "teams": [self.team_account.id,], + "assigned_to": [ + self.user.id, + ], + "teams": [ + self.team_account.id, + ], "savenewform": "true", }, ) @@ -690,8 +718,12 @@ def test_account_views(self): "industry": "SOFTWARE", "description": "Testing", "tags": self.tag_name.name, - "assigned_to": [0,], - "teams": [0,], + "assigned_to": [ + 0, + ], + "teams": [ + 0, + ], }, HTTP_X_REQUESTED_WITH="XMLHttpRequest", ) @@ -721,10 +753,16 @@ def test_account_views(self): "website": "www.example.com", "industry": "SOFTWARE", "description": "Testing", - "contacts": [self.contact_user1.id,], + "contacts": [ + self.contact_user1.id, + ], "tags": self.tag_name.name, - "assigned_to": [self.user.id,], - "teams": [self.team_account.id,], + "assigned_to": [ + self.user.id, + ], + "teams": [ + self.team_account.id, + ], }, HTTP_X_REQUESTED_WITH="XMLHttpRequest", ) @@ -778,10 +816,16 @@ def test_account_views(self): "website": "www.example.com", "industry": "SOFTWARE", "description": "Testing", - "contacts": [self.contact_user1.id,], + "contacts": [ + self.contact_user1.id, + ], "tags": self.tag_name.name + ", another tag edit", - "assigned_to": [self.user.id,], - "teams": [self.team_account.id,], + "assigned_to": [ + self.user.id, + ], + "teams": [ + self.team_account.id, + ], "savenewform": "true", "account_attachment": SimpleUploadedFile( upload_file.name, upload_file.read() @@ -804,9 +848,13 @@ def test_account_views(self): "website": "www.example.com", "industry": "SOFTWARE", "description": "Testing", - "contacts": [self.contact_user1.id,], + "contacts": [ + self.contact_user1.id, + ], "tags": self.tag_name.name + ", another tag edit", - "teams": [self.team_account.id,], + "teams": [ + self.team_account.id, + ], "savenewform": "true", }, HTTP_X_REQUESTED_WITH="XMLHttpRequest", @@ -827,9 +875,13 @@ def test_account_views(self): "website": "www.example.com", "industry": "SOFTWARE", "description": "Testing", - "contacts": [self.contact_user1.id,], + "contacts": [ + self.contact_user1.id, + ], "tags": self.tag_name.name + ", another tag edit", - "teams": [self.team_account.id,], + "teams": [ + self.team_account.id, + ], "savenewform": "true", }, HTTP_X_REQUESTED_WITH="XMLHttpRequest", @@ -944,7 +996,10 @@ def test_account_views(self): class TestAccountUserMentions(AccountCreateTest, TestCase): def test_account_views(self): self.company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN", + name="test company", + address="IN", + sub_domain="test", + country="IN", ) self.user_created_by = User.objects.create( first_name="jane", diff --git a/accounts/tests_celery_tasks.py b/accounts/tests_celery_tasks.py index 62a3ccf..4185e14 100644 --- a/accounts/tests_celery_tasks.py +++ b/accounts/tests_celery_tasks.py @@ -36,6 +36,12 @@ def test_celery_tasks(self): self.assertEqual("SUCCESS", task.state) task = send_email_to_assigned_user.apply( - ([self.user.id, self.user1.id,], self.account.id,), + ( + [ + self.user.id, + self.user1.id, + ], + self.account.id, + ), ) self.assertEqual("SUCCESS", task.state) diff --git a/accounts/views.py b/accounts/views.py index e9d93d7..3280ecc 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -236,8 +236,11 @@ def form_valid(self, form): return redirect("accounts:new_account") if self.request.is_ajax(): - data = {"success_url": reverse_lazy("accounts:list"), "error": False, - "message": "Account created successfully"} + data = { + "success_url": reverse_lazy("accounts:list"), + "error": False, + "message": "Account created successfully", + } return JsonResponse(data) return redirect("accounts:list") @@ -256,9 +259,12 @@ def get_context_data(self, **kwargs): # context["contact_count"] = Contact.objects.count() if self.request.user.role == "ADMIN" or self.request.user.is_superuser: context["leads"] = Lead.objects.exclude( - status__in=["converted", "closed"], company=self.request.company, + status__in=["converted", "closed"], + company=self.request.company, + ) + context["contacts"] = Contact.objects.filter( + company=self.request.company, ) - context["contacts"] = Contact.objects.filter(company=self.request.company,) else: context["leads"] = ( Lead.objects.filter( @@ -266,7 +272,9 @@ def get_context_data(self, **kwargs): | Q(created_by=self.request.user) ) .exclude(status__in=["converted", "closed"]) - .filter(company=self.request.company,) + .filter( + company=self.request.company, + ) ) context["lead_count"] = context["leads"].count() if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: @@ -275,15 +283,21 @@ def get_context_data(self, **kwargs): Q(assigned_to__in=[self.request.user]) | Q(created_by=self.request.user) ) - .filter(company=self.request.company,) + .filter( + company=self.request.company, + ) .exclude(status="closed") .count() ) context["contacts"] = Contact.objects.filter( Q(assigned_to__in=[self.request.user]) | Q(created_by=self.request.user) - ).filter(company=self.request.company,) + ).filter( + company=self.request.company, + ) context["contact_count"] = context["contacts"].count() - context["teams"] = Teams.objects.filter(company=self.request.company,) + context["teams"] = Teams.objects.filter( + company=self.request.company, + ) return context @@ -321,7 +335,8 @@ def get_context_data(self, **kwargs): if self.request.user.is_superuser or self.request.user.role == "ADMIN": users_mention = list( User.objects.filter( - is_active=True, company=self.request.company, + is_active=True, + company=self.request.company, ).values("username") ) elif self.request.user != account_record.created_by: @@ -339,7 +354,8 @@ def get_context_data(self, **kwargs): "opportunity_list": Opportunity.objects.filter(account=account_record), "contacts": account_record.contacts.all(), "users": User.objects.filter( - is_active=True, company=self.request.company, + is_active=True, + company=self.request.company, ).order_by("email"), "cases": Case.objects.filter(account=account_record), "stages": STAGES, @@ -462,8 +478,11 @@ def form_valid(self, form): else: message = "Account closed successfully" if self.request.is_ajax(): - data = {"success_url": reverse_lazy("accounts:list"), "error": False, - "message": message} + data = { + "success_url": reverse_lazy("accounts:list"), + "error": False, + "message": message, + } return JsonResponse(data) return redirect("accounts:list") @@ -483,7 +502,12 @@ def get_context_data(self, **kwargs): context["account_form"] = context["form"] if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: self.users = self.users.filter( - Q(role="ADMIN") | Q(id__in=[self.request.user.id,]) + Q(role="ADMIN") + | Q( + id__in=[ + self.request.user.id, + ] + ) ) context["users"] = self.users context["industries"] = INDCHOICES @@ -602,7 +626,10 @@ def form_valid(self, form): protocol=self.request.scheme, ) return JsonResponse( - {"comment_id": self.comment_obj.id, "comment": self.comment_obj.comment,} + { + "comment_id": self.comment_obj.id, + "comment": self.comment_obj.comment, + } ) def form_invalid(self, form): diff --git a/cases/migrations/0001_initial.py b/cases/migrations/0001_initial.py index e13d23e..9fc0693 100644 --- a/cases/migrations/0001_initial.py +++ b/cases/migrations/0001_initial.py @@ -83,6 +83,8 @@ class Migration(migrations.Migration): ), ), ], - options={"ordering": ["-created_on"],}, + options={ + "ordering": ["-created_on"], + }, ), ] diff --git a/cases/migrations/0003_auto_20190212_1334.py b/cases/migrations/0003_auto_20190212_1334.py index dd4dea0..0a7b52d 100644 --- a/cases/migrations/0003_auto_20190212_1334.py +++ b/cases/migrations/0003_auto_20190212_1334.py @@ -12,7 +12,10 @@ class Migration(migrations.Migration): ] operations = [ - migrations.RemoveField(model_name="case", name="teams",), + migrations.RemoveField( + model_name="case", + name="teams", + ), migrations.AlterField( model_name="case", name="created_by", diff --git a/cases/serializer.py b/cases/serializer.py index 6d652a3..87862b2 100644 --- a/cases/serializer.py +++ b/cases/serializer.py @@ -17,27 +17,26 @@ class CaseSerializer(serializers.ModelSerializer): get_team_and_assigned_users = UserSerializer(read_only=True, many=True) get_assigned_users_not_in_teams = UserSerializer(read_only=True, many=True) - class Meta: model = Case fields = ( - 'id', - 'name', - 'status', - 'priority', - 'case_type', - 'account', - 'contacts', - 'closed_on', - 'description', - 'assigned_to', - 'created_by', - 'created_on', - 'is_active', - 'teams', - 'company', - 'get_team_users', - 'get_team_and_assigned_users', + "id", + "name", + "status", + "priority", + "case_type", + "account", + "contacts", + "closed_on", + "description", + "assigned_to", + "created_by", + "created_on", + "is_active", + "teams", + "company", + "get_team_users", + "get_team_and_assigned_users", "get_assigned_users_not_in_teams", "created_on_arrow", ) diff --git a/cases/tests.py b/cases/tests.py index cac6b98..918c429 100644 --- a/cases/tests.py +++ b/cases/tests.py @@ -208,7 +208,9 @@ def test_case_update_html(self): class CaseModelTestCase(CaseCreation, TestCase): def test_string_representation(self): - case = Case(name="name",) + case = Case( + name="name", + ) self.assertEqual(str(case), case.name) diff --git a/cases/tests_celery_tasks.py b/cases/tests_celery_tasks.py index b639c4c..444bcb6 100644 --- a/cases/tests_celery_tasks.py +++ b/cases/tests_celery_tasks.py @@ -13,6 +13,12 @@ class TestCeleryTasks(CaseCreation, TestCase): ) def test_celery_tasks(self): task = send_email_to_assigned_user.apply( - ([self.user.id, self.user1.id,], self.case.id,), + ( + [ + self.user.id, + self.user1.id, + ], + self.case.id, + ), ) self.assertEqual("SUCCESS", task.state) diff --git a/cases/views.py b/cases/views.py index b97c06a..a4707f4 100644 --- a/cases/views.py +++ b/cases/views.py @@ -606,7 +606,10 @@ def form_valid(self, form): protocol=self.request.scheme, ) return JsonResponse( - {"comment_id": self.comment_obj.id, "comment": self.comment_obj.comment,} + { + "comment_id": self.comment_obj.id, + "comment": self.comment_obj.comment, + } ) def form_invalid(self, form): diff --git a/common/api_urls.py b/common/api_urls.py index e379263..575335a 100644 --- a/common/api_urls.py +++ b/common/api_urls.py @@ -17,5 +17,5 @@ path("auth/reset-password/", api_views.ResetPasswordView.as_view()), path("users/", api_views.UsersListView.as_view()), path("users//", api_views.UserDetailView.as_view()), - path("documents/create/", api_views.DocumentCreate.as_view()), + path("documents/", api_views.DocumentListView.as_view()), ] diff --git a/common/api_views.py b/common/api_views.py index 1b35b37..4b26a1c 100644 --- a/common/api_views.py +++ b/common/api_views.py @@ -10,14 +10,14 @@ from teams.serializer import TeamsSerializer from common.serializer import * from cases.serializer import CaseSerializer -from accounts.models import (Account, Contact) +from accounts.models import Account, Contact from opportunity.models import Opportunity from cases.models import Case from leads.models import Lead from teams.models import Teams from common.forms import DocumentForm from common.utils import ROLES -from common.models import User, Company +from common.models import User, Company, Document from common.access_decorators_mixins import ( MarketingAccessRequiredMixin, SalesAccessRequiredMixin, @@ -30,7 +30,7 @@ send_email_to_new_user, send_email_user_delete, send_email_user_status, - send_email_to_reset_password + send_email_to_reset_password, ) from django.utils.translation import gettext as _ @@ -51,7 +51,9 @@ class GetTeamsAndUsersView(APIView): authentication_classes = (JSONWebTokenAuthentication,) permission_classes = (IsAuthenticated,) - @swagger_auto_schema(tags=["Users"], manual_parameters=swagger_params.dashboard_params) + @swagger_auto_schema( + tags=["Users"], manual_parameters=swagger_params.dashboard_params + ) def get(self, request, *args, **kwargs): data = {} teams = Teams.objects.filter(company=request.company) @@ -76,7 +78,9 @@ def get_object(self, pk): except User.DoesNotExist: raise Http404 - @swagger_auto_schema(tags=["Users"], manual_parameters=swagger_params.dashboard_params) + @swagger_auto_schema( + tags=["Users"], manual_parameters=swagger_params.dashboard_params + ) def get(self, request, pk, format=None): user_obj = self.get_object(pk) users_data = [] @@ -89,7 +93,8 @@ def get(self, request, pk, format=None): context["user_obj"] = UserSerializer(user_obj).data opportunity_list = Opportunity.objects.filter(assigned_to=user_obj) context["opportunity_list"] = OpportunitySerializer( - opportunity_list, many=True).data + opportunity_list, many=True + ).data contacts = Contact.objects.filter(assigned_to=user_obj) context["contacts"] = ContactSerializer(contacts, many=True).data cases = Case.objects.filter(assigned_to=user_obj) @@ -97,20 +102,20 @@ def get(self, request, pk, format=None): context["assigned_data"] = users_data comments = user_obj.user_comments.all() context["comments"] = CommentSerializer(comments, many=True).data - return Response({'error': False, 'data': context}) + return Response({"error": False, "data": context}) - @swagger_auto_schema(tags=["Users"], manual_parameters=swagger_params.user_update_params) + @swagger_auto_schema( + tags=["Users"], manual_parameters=swagger_params.user_update_params + ) def put(self, request, pk, format=None): - params = request.query_params if len( - request.data) == 0 else request.data + params = request.query_params if len(request.data) == 0 else request.data user = self.get_object(pk) - serializer = CreateUserSerializer( - user, data=params, request_user=request.user) + serializer = CreateUserSerializer(user, data=params, request_user=request.user) if serializer.is_valid(): user = serializer.save() if request.user.role != "ADMIN" and not request.user.is_superuser: if request.user.id != self.user.id: - return Response({'error': True}, status=status.HTTP_403_FORBIDDEN) + return Response({"error": True}, status=status.HTTP_403_FORBIDDEN) if user.role == "USER": user.is_superuser = False user.save() @@ -122,18 +127,27 @@ def put(self, request, pk, format=None): for team in params.getlist("teams"): team_obj = Teams.objects.filter(id=team).first() team_obj.users.add(user) - return Response({'error': False, - 'message': 'User Updated Successfully'}, - status=status.HTTP_200_OK) - return Response({'error': True, 'errors': user_serializer.errors}, status=status.HTTP_400_BAD_REQUEST) + return Response( + {"error": False, "message": "User Updated Successfully"}, + status=status.HTTP_200_OK, + ) + return Response( + {"error": True, "errors": user_serializer.errors}, + status=status.HTTP_400_BAD_REQUEST, + ) - @swagger_auto_schema(tags=["Users"], manual_parameters=swagger_params.dashboard_params) + @swagger_auto_schema( + tags=["Users"], manual_parameters=swagger_params.dashboard_params + ) def delete(self, request, pk, format=None): self.object = self.get_object(pk) if self.object.company != request.company: return Response( - {"error": True, - "message": "You don't have permission to delete this user"}) + { + "error": True, + "message": "You don't have permission to delete this user", + } + ) current_site = request.get_host() deleted_by = self.request.user.email send_email_user_delete.delay( @@ -143,19 +157,21 @@ def delete(self, request, pk, format=None): protocol=request.scheme, ) self.object.delete() - return Response({'status': 'success'}, status=status.HTTP_204_NO_CONTENT) + return Response({"status": "success"}, status=status.HTTP_204_NO_CONTENT) class ChangePasswordView(APIView): authentication_classes = (JSONWebTokenAuthentication,) permission_classes = (IsAuthenticated,) - @swagger_auto_schema(tags=["Profile"], operation_description="This is change password api", - manual_parameters=swagger_params.change_password_params) + @swagger_auto_schema( + tags=["Profile"], + operation_description="This is change password api", + manual_parameters=swagger_params.change_password_params, + ) def post(self, request, format=None): - params = request.query_params if len( - request.data) == 0 else request.data - company = request.headers['company'] + params = request.query_params if len(request.data) == 0 else request.data + company = request.headers["company"] old_password = params.get("old_password", None) new_password = params.get("new_password", None) retype_password = params.get("retype_password", None) @@ -169,21 +185,23 @@ def post(self, request, format=None): if new_password: if len(new_password) < 8: - errors['new_password'] = "Password must be at least 8 characters long!" + errors["new_password"] = "Password must be at least 8 characters long!" if new_password == old_password: errors[ - 'new_password'] = "New password and old password should not be same" + "new_password" + ] = "New password and old password should not be same" if retype_password: if new_password != retype_password: errors[ - 'retype_password'] = "new_password and retype_password did not match." + "retype_password" + ] = "new_password and retype_password did not match." if errors: - return Response({'status': 'failure', 'errors': errors}, status=400) + return Response({"status": "failure", "errors": errors}, status=400) user = request.user user.set_password(new_password) user.save() - return Response({'status': 'success'}, status=200) + return Response({"status": "success"}, status=200) # check_header not working @@ -192,25 +210,34 @@ class ApiHomeView(APIView): authentication_classes = (JSONWebTokenAuthentication,) permission_classes = (IsAuthenticated,) - @swagger_auto_schema(tags=["dashboard"], manual_parameters=swagger_params.dashboard_params) + @swagger_auto_schema( + tags=["dashboard"], manual_parameters=swagger_params.dashboard_params + ) def get(self, request, format=None): accounts = Account.objects.filter(status="open") contacts = Contact.objects.all() - leads = Lead.objects.exclude( - status="converted").exclude(status="closed") + leads = Lead.objects.exclude(status="converted").exclude(status="closed") opportunities = Opportunity.objects.all() if self.request.user.role == "ADMIN" or self.request.user.is_superuser: pass else: - accounts = accounts.filter(Q(assigned_to__id__in=[self.request.user.id]) | Q( - created_by=self.request.user.id)) - contacts = contacts.filter(Q(assigned_to__id__in=[self.request.user.id]) | Q( - created_by=self.request.user.id)) - leads = leads.filter(Q(assigned_to__id__in=[self.request.user.id]) | Q( - created_by=self.request.user.id)).exclude(status="closed") + accounts = accounts.filter( + Q(assigned_to__id__in=[self.request.user.id]) + | Q(created_by=self.request.user.id) + ) + contacts = contacts.filter( + Q(assigned_to__id__in=[self.request.user.id]) + | Q(created_by=self.request.user.id) + ) + leads = leads.filter( + Q(assigned_to__id__in=[self.request.user.id]) + | Q(created_by=self.request.user.id) + ).exclude(status="closed") opportunities = opportunities.filter( - Q(assigned_to__id__in=[self.request.user.id]) | Q(created_by=self.request.user.id)) + Q(assigned_to__id__in=[self.request.user.id]) + | Q(created_by=self.request.user.id) + ) context = {} context["leads_count"] = leads.count() context["accounts_count"] = accounts.count() @@ -224,55 +251,60 @@ def get(self, request, format=None): class LoginView(APIView): - - @swagger_auto_schema(tags=["Auth"], operation_description="This is login api", - manual_parameters=swagger_params.login_page_params) + @swagger_auto_schema( + tags=["Auth"], + operation_description="This is login api", + manual_parameters=swagger_params.login_page_params, + ) def post(self, request, format=None): - params = request.query_params if len( - request.data) == 0 else request.data - company = request.headers['company'] + params = request.query_params if len(request.data) == 0 else request.data + company = request.headers["company"] username = params.get("email", None) password = params.get("password", None) company_obj = Company.objects.filter(sub_domain=company).first() if not company_obj: company_field = "doesnot exit" - msg = _('company with this subdomin {company_field}') + msg = _("company with this subdomin {company_field}") msg = msg.format(company_field=company_field) - return Response({'status': 'failure', 'message': msg}, status=400) + return Response({"status": "failure", "message": msg}, status=400) # raise APIException(msg) if not username: username_field = "User Name/Email" msg = _('Must include "{username_field}"') msg = msg.format(username_field=username_field) - return Response({'status': 'failure', 'message': msg}, status=400) + return Response({"status": "failure", "message": msg}, status=400) # raise APIException(msg) user = User.objects.filter(email=username, company=company_obj).first() if not user: - return Response({'status': 'failure', 'message': 'user not avaliable in our records'}, status=400) + return Response( + {"status": "failure", "message": "user not avaliable in our records"}, + status=400, + ) if user.check_password(password): payload = jwt_payload_handler(user) response_data = { - 'token': jwt_encode_handler(payload), - 'status': 'success', - 'company': user.company.id, - 'subdomin': company_obj.sub_domain + "token": jwt_encode_handler(payload), + "status": "success", + "company": user.company.id, + "subdomin": company_obj.sub_domain, } return Response(response_data) else: password_field = "doesnot match" - msg = _('Email and password {password_field}') + msg = _("Email and password {password_field}") msg = msg.format(password_field=password_field) - return Response({'status': 'failure', 'message': msg}, status=400) + return Response({"status": "failure", "message": msg}, status=400) class RegistrationView(APIView): - - @swagger_auto_schema(tags=["Auth"], operation_description="This is registration api", - manual_parameters=swagger_params.registration_page_params) + @swagger_auto_schema( + tags=["Auth"], + operation_description="This is registration api", + manual_parameters=swagger_params.registration_page_params, + ) def post(self, request, format=None): - params = request.query_params if len( - request.data) == 0 else request.data + params = request.query_params if len(request.data) == 0 else request.data sub_domain = params.get("sub_domain", None) username = params.get("username", None) email = params.get("email", None) @@ -284,17 +316,17 @@ def post(self, request, format=None): if username: if User.objects.filter(username__iexact=username): - errors['username'] = "User name already exit." + errors["username"] = "User name already exit." if email: if User.objects.filter(email__iexact=email): - errors['email'] = "Email already exit." + errors["email"] = "Email already exit." if password: if len(password) < 8: - errors['password'] = "Password must be at least 8 characters long!" + errors["password"] = "Password must be at least 8 characters long!" if errors: - return Response({'status': 'failure', 'errors': errors}, status=400) + return Response({"status": "failure", "errors": errors}, status=400) else: user = User.objects.create(username=username, email=email) company = Company.objects.create(sub_domain=sub_domain) @@ -307,17 +339,20 @@ def post(self, request, format=None): user.is_admin = True user.set_password(password) user.save() - return Response({'status': 'success'}, status=201) + return Response({"status": "success"}, status=201) -@swagger_auto_schema(method='post', tags=["Auth"], manual_parameters=swagger_params.check_sub_domain_params) -@api_view(['POST']) +@swagger_auto_schema( + method="post", + tags=["Auth"], + manual_parameters=swagger_params.check_sub_domain_params, +) +@api_view(["POST"]) def check_sub_domain(request): if request.method == "POST": - params = request.query_params if len( - request.data) == 0 else request.data + params = request.query_params if len(request.data) == 0 else request.data sub_domain = params.get("sub_domain", None) - msg = _('Given sub_domain {domain_name} is {validity_status}') + msg = _("Given sub_domain {domain_name} is {validity_status}") company = Company.objects.filter(sub_domain=sub_domain).first() if company: request.session["company"] = company.id @@ -328,14 +363,16 @@ def check_sub_domain(request): msg = msg.format(domain_name=sub_domain, validity_status="Invalid") status_code = 400 status_msg = "failure" - return Response({'status': status_msg, 'message': msg}, status=status_code) + return Response({"status": status_msg, "message": msg}, status=status_code) class ProfileView(APIView): authentication_classes = (JSONWebTokenAuthentication,) permission_classes = (IsAuthenticated,) - @swagger_auto_schema(tags=["Profile"], manual_parameters=swagger_params.dashboard_params) + @swagger_auto_schema( + tags=["Profile"], manual_parameters=swagger_params.dashboard_params + ) def get(self, request, format=None): context = {} context["user_obj"] = UserSerializer(request.user).data @@ -347,35 +384,32 @@ class UsersListView(APIView): authentication_classes = (JSONWebTokenAuthentication,) permission_classes = (IsAuthenticated,) - @swagger_auto_schema(tags=["Users"], manual_parameters=swagger_params.user_create_params) + @swagger_auto_schema( + tags=["Users"], manual_parameters=swagger_params.user_create_params + ) def post(self, request, format=None): - params = request.query_params if len( - request.data) == 0 else request.data - if params.get('is_filter'): + params = request.query_params if len(request.data) == 0 else request.data + if params.get("is_filter"): context = {} queryset = User.objects.filter(company=self.request.company) if params.get("username"): - queryset = queryset.filter( - username__icontains=params.get("username") - ) + queryset = queryset.filter(username__icontains=params.get("username")) if params.get("email"): - queryset = queryset.filter( - email__icontains=params.get("email")) + queryset = queryset.filter(email__icontains=params.get("email")) if params.get("role"): queryset = queryset.filter(role=params.get("role")) if params.get("status"): queryset = queryset.filter(is_active=params.get("status")) active_users = queryset.filter(is_active=True) inactive_users = queryset.filter(is_active=False) - context["active_users"] = UserSerializer( - active_users, many=True).data - context["inactive_users"] = UserSerializer( - inactive_users, many=True).data + context["active_users"] = UserSerializer(active_users, many=True).data + context["inactive_users"] = UserSerializer(inactive_users, many=True).data return Response(context) else: user_serializer = CreateUserSerializer( - data=params, request_user=request.user) + data=params, request_user=request.user + ) if user_serializer.is_valid(): user = user_serializer.save() if params.get("password"): @@ -389,17 +423,23 @@ def post(self, request, format=None): current_site = request.get_host() protocol = request.scheme send_email_to_new_user.delay( - user.email, self.request.user.email, domain=current_site, - protocol=protocol + user.email, + self.request.user.email, + domain=current_site, + protocol=protocol, + ) + return Response( + {"error": False, "message": "User Created Successfully"}, + status=status.HTTP_201_CREATED, ) - return Response({'error': False, - 'message': 'User Created Successfully'}, - status=status.HTTP_201_CREATED) - return Response({'error': True, - 'errors': user_serializer.errors}, - status=status.HTTP_400_BAD_REQUEST) - - @swagger_auto_schema(tags=["Users"], manual_parameters=swagger_params.dashboard_params) + return Response( + {"error": True, "errors": user_serializer.errors}, + status=status.HTTP_400_BAD_REQUEST, + ) + + @swagger_auto_schema( + tags=["Users"], manual_parameters=swagger_params.dashboard_params + ) def get(self, request, format=None): queryset = User.objects.filter(company=self.request.company) @@ -407,8 +447,7 @@ def get(self, request, format=None): active_users = queryset.filter(is_active=True) inactive_users = queryset.filter(is_active=False) context["active_users"] = UserSerializer(active_users, many=True).data - context["inactive_users"] = UserSerializer( - inactive_users, many=True).data + context["inactive_users"] = UserSerializer(inactive_users, many=True).data context["per_page"] = self.request.POST.get("per_page") context["admin_email"] = settings.ADMIN_EMAIL context["roles"] = ROLES @@ -416,46 +455,92 @@ def get(self, request, format=None): return Response(context) -class DocumentCreate(APIView): +class DocumentListView(APIView): authentication_classes = (JSONWebTokenAuthentication,) permission_classes = (IsAuthenticated,) - - @swagger_auto_schema(tags=["documents"], manual_parameters=swagger_params.dashboard_params) - def get(self, request, format=None): - users = [] - if request.user.role == "ADMIN" or request.user.is_superuser: - users = User.objects.filter(is_active=True, company=request.company).order_by( - "email" - ) + model = Document + + def get_queryset(self): + params = self.request.query_params if len( + self.request.data) == 0 else self.request.data + queryset = self.model.objects.all() + if self.request.user.is_superuser or self.request.user.role == "ADMIN": + queryset = queryset else: - users = User.objects.filter(role="ADMIN", company=request.company).order_by( - "email" - ) + if self.request.user.documents(): + doc_ids = self.request.user.documents().values_list("id", flat=True) + shared_ids = queryset.filter( + Q(status="active") & Q( + shared_to__id__in=[self.request.user.id]) + ).values_list("id", flat=True) + queryset = queryset.filter( + Q(id__in=doc_ids) | Q(id__in=shared_ids)) + else: + queryset = queryset.filter( + Q(status="active") & Q( + shared_to__id__in=[self.request.user.id]) + ) + + request_post = params + if request_post and params.get('is_filter'): + if request_post.get("doc_name"): + queryset = queryset.filter( + title__icontains=request_post.get("doc_name") + ) + if request_post.get("status"): + queryset = queryset.filter(status=request_post.get("status")) + + if request_post.getlist("shared_to"): + queryset = queryset.filter( + shared_to__id__in=request_post.getlist("shared_to") + ) + return queryset.filter(company=self.request.company) + + def get_context_data(self, **kwargs): + params = self.request.query_params if len( + self.request.data) == 0 else self.request.data context = {} - context["users"] = UserSerializer(users, many=True).data - teams = Teams.objects.filter(company=request.company) - context["teams"] = TeamsSerializer(teams, many=True).data - context['status'] = (("active", "active"), ("inactive", "inactive")) + context["users"] = UserSerializer(User.objects.filter( + is_active=True, company=self.request.company + ).order_by("username"), many=True).data + context["documents"] = DocumentSerializer(self.get_queryset(), many=True).data + context["status_choices"] = Document.DOCUMENT_STATUS_CHOICE + context["sharedto_list"] = [ + int(i) for i in params.getlist("shared_to", []) if i + ] + search = False + if ( + params.get("doc_name") + or params.get("status") + or params.get("shared_to") + ): + search = True + + context["search"] = search + return context + + @swagger_auto_schema(tags=["documents"], manual_parameters=swagger_params.dashboard_params) + def get(self, request, *args, **kwargs): + context = self.get_context_data(**kwargs) return Response(context) # to be checked file upload - @swagger_auto_schema(tags=["documents"], manual_parameters=swagger_params.document_create_params) + @swagger_auto_schema( + tags=["documents"], manual_parameters=swagger_params.document_create_params + ) def post(self, request, format=None): - params = request.query_params if len( - request.data) == 0 else request.data + params = request.query_params if len(request.data) == 0 else request.data context = {} users = [] if request.user.role == "ADMIN" or request.user.is_superuser: - users = User.objects.filter(is_active=True, company=request.company).order_by( - "email" - ) + users = User.objects.filter( + is_active=True, company=request.company + ).order_by("email") else: users = User.objects.filter(role="ADMIN", company=request.company).order_by( "email" ) - form = DocumentForm( - params, request.FILES, users=users, request_obj=request - ) + form = DocumentForm(params, request.FILES, users=users, request_obj=request) if form.is_valid(): doc = form.save(commit=False) doc.created_by = request.user @@ -483,20 +568,23 @@ def post(self, request, format=None): class ForgotPasswordView(APIView): - - @swagger_auto_schema(tags=["Auth"], manual_parameters=swagger_params.forgot_password_params) + @swagger_auto_schema( + tags=["Auth"], manual_parameters=swagger_params.forgot_password_params + ) def post(self, request, format=None): - params = request.query_params if len( - request.data) == 0 else request.data + params = request.query_params if len(request.data) == 0 else request.data serializer = ForgotPasswordSerializer(data=params) if serializer.is_valid(): - user = get_object_or_404(User, email=params.get('email')) + user = get_object_or_404(User, email=params.get("email")) current_site = self.request.get_host() protocol = self.request.scheme send_email_to_reset_password.delay( - user.email, protocol=protocol, domain=current_site) - data = {"error": False, - "message": "We have sent you an email. please reset password"} + user.email, protocol=protocol, domain=current_site + ) + data = { + "error": False, + "message": "We have sent you an email. please reset password", + } return Response(data) else: data = {"error": True, "errors": serializer.errors} @@ -505,19 +593,21 @@ def post(self, request, format=None): class ResetPasswordView(APIView): - - @swagger_auto_schema(tags=["Auth"], manual_parameters=swagger_params.reset_password_params) + @swagger_auto_schema( + tags=["Auth"], manual_parameters=swagger_params.reset_password_params + ) def post(self, request, format=None): - params = request.query_params if len( - request.data) == 0 else request.data + params = request.query_params if len(request.data) == 0 else request.data serializer = ResetPasswordSerailizer(data=params) if serializer.is_valid(): - password = params.get('new_password1') + password = params.get("new_password1") user = serializer.user user.set_password(password) user.save() - data = {"error": False, - "message": "Password Updated Successfully. Please login"} + data = { + "error": False, + "message": "Password Updated Successfully. Please login", + } else: data = {"error": True, "errors": serializer.errors} return Response(data, status=status.HTTP_400_BAD_REQUEST) diff --git a/common/app_urls/__init__.py b/common/app_urls/__init__.py index 84eb29a..5e82267 100644 --- a/common/app_urls/__init__.py +++ b/common/app_urls/__init__.py @@ -1,8 +1,8 @@ from django.urls import include, path -app_name = 'common_urls' +app_name = "common_urls" urlpatterns = [ - path('', include(('common.api_urls'))), + path("", include(("common.api_urls"))), path("accounts/", include("accounts.api_urls", namespace="api_accounts")), path("contacts/", include("contacts.api_urls", namespace="api_contacts")), ] diff --git a/common/custom_auth.py b/common/custom_auth.py index 82992b0..e7a44a9 100644 --- a/common/custom_auth.py +++ b/common/custom_auth.py @@ -6,9 +6,7 @@ from django.utils.encoding import smart_text from django.utils.translation import ugettext as _ from rest_framework import exceptions -from rest_framework.authentication import ( - BaseAuthentication -) +from rest_framework.authentication import BaseAuthentication from rest_framework.authentication import get_authorization_header from django.conf import settings from rest_framework_jwt.settings import api_settings @@ -37,43 +35,46 @@ def authenticate(self, request): supplied using JWT-based authentication. Otherwise returns None. """ - authorization = request.META.get('HTTP_AUTHORIZATION', None) - self.company = request.META.get('HTTP_COMPANY', None) + authorization = request.META.get("HTTP_AUTHORIZATION", None) + self.company = request.META.get("HTTP_COMPANY", None) jwt_value = self.get_jwt_value(request) if jwt_value is None: return None try: payload = jwt_decode_handler(jwt_value) except jwt.ExpiredSignature: - msg = _('Signature has expired.') + msg = _("Signature has expired.") raise exceptions.AuthenticationFailed(msg) except jwt.DecodeError: - msg = _('Error decoding signature.') + msg = _("Error decoding signature.") raise exceptions.AuthenticationFailed(msg) except jwt.InvalidTokenError: raise exceptions.AuthenticationFailed() account = self.authenticate_credentials(payload) - set_current_instance_field('authorization', True) + set_current_instance_field("authorization", True) return account, payload def authenticate_credentials(self, payload): """ Returns an active user that matches the payload's user id and email. """ - account_id = payload['id'] + account_id = payload["id"] from common.models import User + if not account_id: - msg = _('Invalid payload.') + msg = _("Invalid payload.") raise exceptions.AuthenticationFailed(msg) try: account = User.objects.get(pk=account_id) if account.company.sub_domain != self.company: - raise exceptions.AuthenticationFailed("user company doesnot match with header....") + raise exceptions.AuthenticationFailed( + "user company doesnot match with header...." + ) except User.DoesNotExist: - msg = _('Invalid signature.') + msg = _("Invalid signature.") raise exceptions.AuthenticationFailed(msg) return account # return True @@ -86,7 +87,8 @@ class JSONWebTokenAuthentication(BaseJSONWebTokenAuthentication): `JWT_AUTH_HEADER_PREFIX`. For example: Authorization: JWT eyJhbGciOiAiSFMyNTYiLCAidHlwIj """ - www_authenticate_realm = 'api' + + www_authenticate_realm = "api" def get_jwt_value(self, request): auth = get_authorization_header(request).split() @@ -101,11 +103,13 @@ def get_jwt_value(self, request): return None if len(auth) == 1: - msg = _('Invalid Authorization header. No credentials provided.') + msg = _("Invalid Authorization header. No credentials provided.") raise exceptions.AuthenticationFailed(msg) elif len(auth) > 2: - msg = _('Invalid Authorization header. Credentials string ' - 'should not contain spaces.') + msg = _( + "Invalid Authorization header. Credentials string " + "should not contain spaces." + ) raise exceptions.AuthenticationFailed(msg) return auth[1] @@ -116,4 +120,6 @@ def authenticate_header(self, request): header in a `401 Unauthenticated` response, or `None` if the authentication scheme should return `403 Permission Denied` responses. """ - return '{0} realm="{1}"'.format(api_settings.JWT_AUTH_HEADER_PREFIX, self.www_authenticate_realm) + return '{0} realm="{1}"'.format( + api_settings.JWT_AUTH_HEADER_PREFIX, self.www_authenticate_realm + ) diff --git a/common/middleware/get_company.py b/common/middleware/get_company.py index b37339a..28c546d 100644 --- a/common/middleware/get_company.py +++ b/common/middleware/get_company.py @@ -10,8 +10,8 @@ def __call__(self, request): return response def process_view(self, request, view_func, view_args, view_kwargs): - if request.headers.get('company'): - subdomain = request.headers.get('company') + if request.headers.get("company"): + subdomain = request.headers.get("company") company = Company.objects.filter(sub_domain=subdomain).first() if company: request.company = company diff --git a/common/migrations/0001_initial.py b/common/migrations/0001_initial.py index 13e5d78..1777dc0 100644 --- a/common/migrations/0001_initial.py +++ b/common/migrations/0001_initial.py @@ -71,8 +71,12 @@ class Migration(migrations.Migration): ), ), ], - options={"abstract": False,}, - managers=[("objects", django.contrib.auth.models.UserManager()),], + options={ + "abstract": False, + }, + managers=[ + ("objects", django.contrib.auth.models.UserManager()), + ], ), migrations.CreateModel( name="Address", diff --git a/common/migrations/0005_auto_20190204_1400.py b/common/migrations/0005_auto_20190204_1400.py index 03fb6d4..a2023c7 100644 --- a/common/migrations/0005_auto_20190204_1400.py +++ b/common/migrations/0005_auto_20190204_1400.py @@ -18,7 +18,8 @@ class Migration(migrations.Migration): operations = [ migrations.AlterModelOptions( - name="user", options={"ordering": ["-is_active"]}, + name="user", + options={"ordering": ["-is_active"]}, ), migrations.AddField( model_name="document", diff --git a/common/migrations/0007_auto_20190212_1334.py b/common/migrations/0007_auto_20190212_1334.py index 00a78f3..0fd6256 100644 --- a/common/migrations/0007_auto_20190212_1334.py +++ b/common/migrations/0007_auto_20190212_1334.py @@ -18,7 +18,10 @@ class Migration(migrations.Migration): ] operations = [ - migrations.RemoveField(model_name="team", name="members",), + migrations.RemoveField( + model_name="team", + name="members", + ), migrations.AlterField( model_name="attachments", name="created_by", @@ -39,5 +42,7 @@ class Migration(migrations.Migration): to=settings.AUTH_USER_MODEL, ), ), - migrations.DeleteModel(name="Team",), + migrations.DeleteModel( + name="Team", + ), ] diff --git a/common/migrations/0017_auto_20190722_1443.py b/common/migrations/0017_auto_20190722_1443.py index c12797d..e905674 100644 --- a/common/migrations/0017_auto_20190722_1443.py +++ b/common/migrations/0017_auto_20190722_1443.py @@ -13,10 +13,12 @@ class Migration(migrations.Migration): operations = [ migrations.AlterModelOptions( - name="apisettings", options={"ordering": ("-created_on",)}, + name="apisettings", + options={"ordering": ("-created_on",)}, ), migrations.AlterModelOptions( - name="document", options={"ordering": ("-created_on",)}, + name="document", + options={"ordering": ("-created_on",)}, ), migrations.CreateModel( name="Profile", diff --git a/common/serializer.py b/common/serializer.py index 30af7ca..91dc635 100644 --- a/common/serializer.py +++ b/common/serializer.py @@ -1,29 +1,20 @@ from rest_framework import serializers -from common.models import User, Company, Comment, Address, Attachments +from common.models import User, Company, Comment, Address, Attachments, Document from django.utils.http import urlsafe_base64_decode from django.contrib.auth.tokens import default_token_generator class CompanySerializer(serializers.ModelSerializer): - class Meta: model = Company - fields = ( - 'id', - "name", - "address", - "sub_domain", - "user_limit", - "country" - ) + fields = ("id", "name", "address", "sub_domain", "user_limit", "country") class UserSerializer(serializers.ModelSerializer): - class Meta: model = User fields = ( - 'id', + "id", "file_prepend", "username", "first_name", @@ -39,12 +30,10 @@ class Meta: "has_marketing_access", "company", "get_app_name", - ) class CommentSerializer(serializers.ModelSerializer): - class Meta: model = Comment fields = "__all__" @@ -64,7 +53,7 @@ class Meta: "profile_pic", "has_sales_access", "has_marketing_access", - "password" + "password", ) def __init__(self, *args, **kwargs): @@ -74,9 +63,9 @@ def __init__(self, *args, **kwargs): if not self.instance: self.fields["password"].required = True else: - self.fields['password'].required = False - self.fields['email'].required = False - self.fields['role'].required = False + self.fields["password"].required = False + self.fields["email"].required = False + self.fields["role"].required = False def validate_password(self, password): if password: @@ -94,10 +83,10 @@ def validate_has_sales_access(self, has_sales_access): is_admin = False if self.request_user.role == "ADMIN" or self.request_user.is_superuser: if not is_admin: - marketing = self.initial_data.get("has_marketing_access", False) + marketing = self.initial_data.get( + "has_marketing_access", False) if not has_sales_access and not marketing: - raise serializers.ValidationError( - "Select atleast one option.") + raise serializers.ValidationError("Select atleast one option.") if self.request_user.role == "USER": has_sales_access = self.instance.has_sales_access return has_sales_access @@ -110,9 +99,7 @@ def validate_has_marketing_access(self, marketing): def validate_email(self, email): if self.instance: if self.instance.email != email: - if not User.objects.filter( - email=email - ).exists(): + if not User.objects.filter(email=email).exists(): return email raise serializers.ValidationError("Email already exists") else: @@ -120,15 +107,14 @@ def validate_email(self, email): else: if not User.objects.filter(email=email).exists(): return email - raise serializers.ValidationError( - "User already exists with this email") + raise serializers.ValidationError("User already exists with this email") class ForgotPasswordSerializer(serializers.Serializer): email = serializers.CharField(max_length=200) def validate(self, data): - email = data.get('email') + email = data.get("email") user = User.objects.filter(email__iexact=email).last() if not user: raise serializers.ValidationError( @@ -138,11 +124,11 @@ def validate(self, data): class CheckTokenSerializer(serializers.Serializer): - uidb64_regex = r'[0-9A-Za-z_\-]+' - token_regex = r'[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20}' + uidb64_regex = r"[0-9A-Za-z_\-]+" + token_regex = r"[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20}" uidb64 = serializers.RegexField(uidb64_regex) token = serializers.RegexField(token_regex) - error_message = {'__all__': ('Invalid password reset token')} + error_message = {"__all__": ("Invalid password reset token")} def get_user(self, uidb64): try: @@ -158,34 +144,31 @@ class ResetPasswordSerailizer(CheckTokenSerializer): new_password2 = serializers.CharField() def validate(self, data): - self.user = self.get_user(data.get('uidb64')) + self.user = self.get_user(data.get("uidb64")) if not self.user: raise serializers.ValidationError(self.error_message) is_valid_token = default_token_generator.check_token( - self.user, data.get('token')) + self.user, data.get("token") + ) if not is_valid_token: raise serializers.ValidationError(self.error_message) - new_password2 = data.get('new_password2') - new_password1 = data.get('new_password1') + new_password2 = data.get("new_password2") + new_password1 = data.get("new_password1") if new_password1 != new_password2: - raise serializers.ValidationError( - "The two password fields didn't match.") + raise serializers.ValidationError("The two password fields didn't match.") return new_password2 class AttachmentsSerializer(serializers.ModelSerializer): - class Meta: model = Attachments - fields = ['created_by', 'file_name', 'created_on'] + fields = ["created_by", "file_name", "created_on"] class BillingAddressSerializer(serializers.ModelSerializer): - class Meta: model = Address - fields = ("address_line", "street", "city", - "state", "postcode", "country") + fields = ("address_line", "street", "city", "state", "postcode", "country") def __init__(self, *args, **kwargs): account_view = kwargs.pop("account", False) @@ -199,3 +182,15 @@ def __init__(self, *args, **kwargs): self.fields["state"].required = True self.fields["postcode"].required = True self.fields["country"].required = True + + +class DocumentSerializer(serializers.ModelSerializer): + shared_to = UserSerializer(read_only=True, many=True) + teams = serializers.SerializerMethodField() + + def get_teams(self, obj): + return obj.teams.all().values() + + class Meta: + model = Document + fields = "__all__" diff --git a/common/swagger_params.py b/common/swagger_params.py index a33eba9..4747a16 100644 --- a/common/swagger_params.py +++ b/common/swagger_params.py @@ -1,95 +1,153 @@ from drf_yasg import openapi company_params_in_header = openapi.Parameter( - 'company', openapi.IN_HEADER, required=True, type=openapi.TYPE_STRING) + "company", openapi.IN_HEADER, required=True, type=openapi.TYPE_STRING +) login_page_params = [ company_params_in_header, - openapi.Parameter('email', openapi.IN_QUERY, - required=True, type=openapi.TYPE_STRING), - openapi.Parameter('password', openapi.IN_QUERY, - format='password', required=True, type=openapi.TYPE_STRING) + openapi.Parameter( + "email", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "password", + openapi.IN_QUERY, + format="password", + required=True, + type=openapi.TYPE_STRING, + ), ] change_password_params = [ company_params_in_header, - openapi.Parameter('old_password', openapi.IN_QUERY, - format='password', required=True, type=openapi.TYPE_STRING), - openapi.Parameter('new_password', openapi.IN_QUERY, - format='password', required=True, type=openapi.TYPE_STRING), - openapi.Parameter('retype_password', openapi.IN_QUERY, - format='password', required=True, type=openapi.TYPE_STRING), + openapi.Parameter( + "old_password", + openapi.IN_QUERY, + format="password", + required=True, + type=openapi.TYPE_STRING, + ), + openapi.Parameter( + "new_password", + openapi.IN_QUERY, + format="password", + required=True, + type=openapi.TYPE_STRING, + ), + openapi.Parameter( + "retype_password", + openapi.IN_QUERY, + format="password", + required=True, + type=openapi.TYPE_STRING, + ), ] -dashboard_params = [ - company_params_in_header -] +dashboard_params = [company_params_in_header] user_update_params = [ company_params_in_header, - openapi.Parameter('username', openapi.IN_QUERY, type=openapi.TYPE_STRING, required=True), - openapi.Parameter('first_name', openapi.IN_QUERY, type=openapi.TYPE_STRING, required=True), - openapi.Parameter('last_name', openapi.IN_QUERY, type=openapi.TYPE_STRING), - openapi.Parameter('profile_pic', openapi.IN_QUERY, type=openapi.TYPE_FILE), - openapi.Parameter('has_sales_access', openapi.IN_QUERY, type=openapi.TYPE_BOOLEAN), - openapi.Parameter('has_marketing_access', openapi.IN_QUERY, type=openapi.TYPE_BOOLEAN), - openapi.Parameter('teams', openapi.IN_QUERY, type=openapi.TYPE_STRING) + openapi.Parameter( + "username", openapi.IN_QUERY, type=openapi.TYPE_STRING, required=True + ), + openapi.Parameter( + "first_name", openapi.IN_QUERY, type=openapi.TYPE_STRING, required=True + ), + openapi.Parameter("last_name", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter("profile_pic", openapi.IN_QUERY, type=openapi.TYPE_FILE), + openapi.Parameter("has_sales_access", openapi.IN_QUERY, type=openapi.TYPE_BOOLEAN), + openapi.Parameter( + "has_marketing_access", openapi.IN_QUERY, type=openapi.TYPE_BOOLEAN + ), + openapi.Parameter("teams", openapi.IN_QUERY, type=openapi.TYPE_STRING), ] user_delete_params = [ company_params_in_header, - openapi.Parameter('user_id', openapi.IN_QUERY, required=True, type=openapi.TYPE_NUMBER), + openapi.Parameter( + "user_id", openapi.IN_QUERY, required=True, type=openapi.TYPE_NUMBER + ), ] check_sub_domain_params = [ - openapi.Parameter('sub_domain', openapi.IN_QUERY, - required=True, type=openapi.TYPE_STRING), + openapi.Parameter( + "sub_domain", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), ] registration_page_params = [ - openapi.Parameter('sub_domain', openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING), - openapi.Parameter('username', openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING), - openapi.Parameter('email', openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING), - openapi.Parameter('password', openapi.IN_QUERY, format='password', required=True, type=openapi.TYPE_STRING) + openapi.Parameter( + "sub_domain", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "username", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "email", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "password", + openapi.IN_QUERY, + format="password", + required=True, + type=openapi.TYPE_STRING, + ), ] forgot_password_params = [ - openapi.Parameter('email', openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING), + openapi.Parameter( + "email", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), ] reset_password_params = [ - openapi.Parameter('uidb64', openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING), - openapi.Parameter('token', openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING), - openapi.Parameter('new_password1', openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING), - openapi.Parameter('new_password2', openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING), - + openapi.Parameter( + "uidb64", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "token", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "new_password1", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "new_password2", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), ] user_list_params = [ company_params_in_header, - openapi.Parameter('username', openapi.IN_QUERY, type=openapi.TYPE_STRING), - openapi.Parameter('email', openapi.IN_QUERY, type=openapi.TYPE_STRING), - openapi.Parameter('role', openapi.IN_QUERY, type=openapi.TYPE_STRING), - openapi.Parameter('status', openapi.IN_QUERY, type=openapi.TYPE_STRING) + openapi.Parameter("username", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter("email", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter("role", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter("status", openapi.IN_QUERY, type=openapi.TYPE_STRING), ] user_create_params = [ company_params_in_header, - openapi.Parameter('username', openapi.IN_QUERY, type=openapi.TYPE_STRING), - openapi.Parameter('email', openapi.IN_QUERY, type=openapi.TYPE_STRING), - openapi.Parameter('role', openapi.IN_QUERY, type=openapi.TYPE_STRING), - openapi.Parameter('password', openapi.IN_QUERY, format='password', required=True, type=openapi.TYPE_STRING), - openapi.Parameter('first_name', openapi.IN_QUERY, type=openapi.TYPE_STRING), - openapi.Parameter('last_name', openapi.IN_QUERY, type=openapi.TYPE_STRING), - openapi.Parameter('profile_pic', openapi.IN_QUERY, type=openapi.TYPE_FILE), - openapi.Parameter('has_sales_access', openapi.IN_QUERY, type=openapi.TYPE_BOOLEAN), - openapi.Parameter('has_marketing_access', openapi.IN_QUERY, type=openapi.TYPE_BOOLEAN), - openapi.Parameter('status', openapi.IN_QUERY, type=openapi.TYPE_STRING) + openapi.Parameter("username", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter("email", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter("role", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter( + "password", + openapi.IN_QUERY, + format="password", + required=True, + type=openapi.TYPE_STRING, + ), + openapi.Parameter("first_name", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter("last_name", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter("profile_pic", openapi.IN_QUERY, type=openapi.TYPE_FILE), + openapi.Parameter("has_sales_access", openapi.IN_QUERY, type=openapi.TYPE_BOOLEAN), + openapi.Parameter( + "has_marketing_access", openapi.IN_QUERY, type=openapi.TYPE_BOOLEAN + ), + openapi.Parameter("status", openapi.IN_QUERY, type=openapi.TYPE_STRING), ] document_create_params = [ company_params_in_header, - openapi.Parameter('title', openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter('title', openapi.IN_QUERY, type=openapi.TYPE_STRING, required=True), openapi.Parameter('status', openapi.IN_QUERY, type=openapi.TYPE_STRING), openapi.Parameter('shared_to', openapi.IN_QUERY, type=openapi.TYPE_STRING), - openapi.Parameter('document_file', openapi.IN_QUERY, type=openapi.TYPE_FILE), -] \ No newline at end of file + openapi.Parameter('document_file', openapi.IN_QUERY, type=openapi.TYPE_FILE, required=True), +] diff --git a/common/tasks.py b/common/tasks.py index 1bb8adb..6561386 100644 --- a/common/tasks.py +++ b/common/tasks.py @@ -109,8 +109,7 @@ def send_email_user_mentions( protocol + "://" + domain - + reverse("opportunity:opp_view", - args=(comment.opportunity.id,)) + + reverse("opportunity:opp_view", args=(comment.opportunity.id,)) ) subject = "New comment on Opportunity. " elif called_from == "cases": @@ -134,8 +133,7 @@ def send_email_user_mentions( protocol + "://" + domain - + reverse("invoices:invoice_details", - args=(comment.invoice.id,)) + + reverse("invoices:invoice_details", args=(comment.invoice.id,)) ) subject = "New comment on Invoice. " elif called_from == "events": @@ -149,8 +147,7 @@ def send_email_user_mentions( else: context["url"] = "" # subject = 'Django CRM : comment ' - blocked_domains = BlockedDomain.objects.values_list( - "domain", flat=True) + blocked_domains = BlockedDomain.objects.values_list("domain", flat=True) blocked_emails = BlockedEmail.objects.values_list("email", flat=True) if recipients: for recipient in recipients: @@ -224,8 +221,7 @@ def send_email_user_delete( recipients = [] recipients.append(user_email) subject = "CRM : Your account is Deleted. " - html_content = render_to_string( - "user_delete_email.html", context=context) + html_content = render_to_string("user_delete_email.html", context=context) if recipients: msg = EmailMessage(subject, html_content, to=recipients) msg.content_subtype = "html" @@ -282,8 +278,11 @@ def send_email_to_reset_password( context["uid"] = (urlsafe_base64_encode(force_bytes(user.pk)),) context["token"] = default_token_generator.make_token(user) context["token"] = context["token"] - context["complete_url"] = context["url"] + '/api-common/reset-password/{uidb64}/{token}/'.format( - uidb64=context["uid"], token=context["token"]) + context["complete_url"] = context[ + "url" + ] + "/api-common/reset-password/{uidb64}/{token}/".format( + uidb64=context["uid"], token=context["token"] + ) recipients = [] recipients.append(user_email) subject = "Password Reset" @@ -291,4 +290,4 @@ def send_email_to_reset_password( if recipients: msg = EmailMessage(subject, html_content, to=recipients) msg.content_subtype = "html" - msg.send() \ No newline at end of file + msg.send() diff --git a/common/tests.py b/common/tests.py index 7f3f387..de0dff9 100644 --- a/common/tests.py +++ b/common/tests.py @@ -1308,13 +1308,15 @@ def test_get_complete_address(self): postcode="postcode", country="IN", ) - Address_obj_street_city_address_line_state_postcode_country = Address.objects.create( - street="street", - city="city", - address_line="address_line", - state="state", - postcode="postcode", - country="IN", + Address_obj_street_city_address_line_state_postcode_country = ( + Address.objects.create( + street="street", + city="city", + address_line="address_line", + state="state", + postcode="postcode", + country="IN", + ) ) self.assertEqual(Address_obj_street.get_complete_address(), "street") @@ -1673,7 +1675,9 @@ def test_user_create_with_team(self): "username": "john@developer.com", "password": "password", "role": "USER", - "teams": [self.team_dev.id,], + "teams": [ + self.team_dev.id, + ], "has_sales_access": "on", }, HTTP_X_REQUESTED_WITH="XMLHttpRequest", @@ -1709,7 +1713,9 @@ def test_user_create_with_team(self): "username": "john@developer.com", "password": "password", "role": "USER", - "teams": [self.team_test.id,], + "teams": [ + self.team_test.id, + ], "has_sales_access": "on", }, HTTP_X_REQUESTED_WITH="XMLHttpRequest", @@ -1744,8 +1750,12 @@ def test_doc_create(self): data = { "title": "new doc", "document_file": SimpleUploadedFile(upload_file.name, upload_file.read()), - "teams": [self.team_test.id,], - "shared_to": [shared_user.id,], + "teams": [ + self.team_test.id, + ], + "shared_to": [ + shared_user.id, + ], } response = self.client.post( reverse("common:create_doc"), data, HTTP_X_REQUESTED_WITH="XMLHttpRequest" @@ -1756,8 +1766,12 @@ def test_doc_create(self): data = { "title": "another new doc", "document_file": SimpleUploadedFile(upload_file.name, upload_file.read()), - "teams": [self.team_test.id,], - "shared_to": [shared_user.id,], + "teams": [ + self.team_test.id, + ], + "shared_to": [ + shared_user.id, + ], } response = self.client.post( reverse("common:edit_doc", args=(self.document.id,)), diff --git a/common/tests_celery_tasks.py b/common/tests_celery_tasks.py index bb119b8..6d5a074 100644 --- a/common/tests_celery_tasks.py +++ b/common/tests_celery_tasks.py @@ -29,10 +29,20 @@ class TestCeleryTasks(ObjectsCreation, TestCase): BROKER_BACKEND="memory", ) def test_celery_tasks(self): - task = send_email_to_new_user.apply((self.user1.email, self.user.email,),) + task = send_email_to_new_user.apply( + ( + self.user1.email, + self.user.email, + ), + ) self.assertEqual("SUCCESS", task.state) - task = send_email_user_status.apply((self.user1.id, self.user.id,),) + task = send_email_user_status.apply( + ( + self.user1.id, + self.user.id, + ), + ) self.assertEqual("SUCCESS", task.state) self.user1.is_active = False @@ -40,7 +50,9 @@ def test_celery_tasks(self): self.user1.has_marketing_access = True self.user1.save() - task = send_email_user_status.apply((self.user1.id,),) + task = send_email_user_status.apply( + (self.user1.id,), + ) self.assertEqual("SUCCESS", task.state) self.user1.is_active = True @@ -48,16 +60,24 @@ def test_celery_tasks(self): self.user1.has_marketing_access = False self.user1.save() - task = send_email_user_status.apply((self.user1.id,),) + task = send_email_user_status.apply( + (self.user1.id,), + ) self.assertEqual("SUCCESS", task.state) - task = send_email_user_delete.apply((self.user1.email,),) + task = send_email_user_delete.apply( + (self.user1.email,), + ) self.assertEqual("SUCCESS", task.state) - task = resend_activation_link_to_user.apply((self.user1.email,),) + task = resend_activation_link_to_user.apply( + (self.user1.email,), + ) self.assertEqual("SUCCESS", task.state) - task = resend_activation_link_to_user.apply((self.user1.email,),) + task = resend_activation_link_to_user.apply( + (self.user1.email,), + ) self.assertEqual("SUCCESS", task.state) @@ -85,7 +105,12 @@ def test_user_mentions_for_account_comment(self): self.comment.account = self.account self.comment.save() - task = send_email_user_mentions.apply((self.comment.id, "accounts",),) + task = send_email_user_mentions.apply( + ( + self.comment.id, + "accounts", + ), + ) self.assertEqual("SUCCESS", task.state) @@ -113,7 +138,12 @@ def test_user_mentions_for_contacts_comments(self): self.comment.contact = self.contact self.comment.save() - task = send_email_user_mentions.apply((self.comment.id, "contacts",),) + task = send_email_user_mentions.apply( + ( + self.comment.id, + "contacts", + ), + ) self.assertEqual("SUCCESS", task.state) @@ -141,7 +171,12 @@ def test_user_mentions_for_leads_comments(self): self.comment.lead = self.lead self.comment.save() - task = send_email_user_mentions.apply((self.comment.id, "leads",),) + task = send_email_user_mentions.apply( + ( + self.comment.id, + "leads", + ), + ) self.assertEqual("SUCCESS", task.state) @@ -169,7 +204,12 @@ def test_user_mentions_for_opportunity_comments(self): self.comment.opportunity = self.opportunity self.comment.save() - task = send_email_user_mentions.apply((self.comment.id, "opportunity",),) + task = send_email_user_mentions.apply( + ( + self.comment.id, + "opportunity", + ), + ) self.assertEqual("SUCCESS", task.state) @@ -197,7 +237,12 @@ def test_user_mentions_for_cases_comments(self): self.comment.case = self.case self.comment.save() - task = send_email_user_mentions.apply((self.comment.id, "cases",),) + task = send_email_user_mentions.apply( + ( + self.comment.id, + "cases", + ), + ) self.assertEqual("SUCCESS", task.state) @@ -225,7 +270,12 @@ def test_user_mentions_for_tasks_comments(self): self.comment.task = self.task self.comment.save() - task = send_email_user_mentions.apply((self.comment.id, "tasks",),) + task = send_email_user_mentions.apply( + ( + self.comment.id, + "tasks", + ), + ) self.assertEqual("SUCCESS", task.state) @@ -253,7 +303,12 @@ def test_user_mentions_for_invoice_comments(self): self.comment.invoice = self.invoice self.comment.save() - task = send_email_user_mentions.apply((self.comment.id, "invoices",),) + task = send_email_user_mentions.apply( + ( + self.comment.id, + "invoices", + ), + ) self.assertEqual("SUCCESS", task.state) @@ -281,5 +336,10 @@ def test_user_mentions_for_events_comments(self): self.comment.event = self.event self.comment.save() - task = send_email_user_mentions.apply((self.comment.id, "events",),) + task = send_email_user_mentions.apply( + ( + self.comment.id, + "events", + ), + ) self.assertEqual("SUCCESS", task.state) diff --git a/common/utils.py b/common/utils.py index 4f8ba98..4288dcb 100644 --- a/common/utils.py +++ b/common/utils.py @@ -10,27 +10,27 @@ def jwt_payload_handler(user): - """ Custom payload handler + """Custom payload handler Token encrypts the dictionary returned by this function, and can be decoded by rest_framework_jwt.utils.jwt_decode_handler """ return { - 'id': user.pk, - # 'name': user.name, - 'email': user.email, - 'company': user.company.id, - "role": user.role, - "has_sales_access": user.has_sales_access, - "has_marketing_access": user.has_marketing_access, - "file_prepend": user.file_prepend, - "username": user.username, - "first_name": user.first_name, - "last_name": user.last_name, - "is_active": user.is_active, - "is_admin": user.is_admin, - "is_staff": user.is_staff, - # "date_joined" -} + "id": user.pk, + # 'name': user.name, + "email": user.email, + "company": user.company.id, + "role": user.role, + "has_sales_access": user.has_sales_access, + "has_marketing_access": user.has_marketing_access, + "file_prepend": user.file_prepend, + "username": user.username, + "first_name": user.first_name, + "last_name": user.last_name, + "is_active": user.is_active, + "is_admin": user.is_admin, + "is_staff": user.is_staff, + # "date_joined" + } INDCHOICES = ( diff --git a/common/views.py b/common/views.py index 6ac8f66..6768236 100644 --- a/common/views.py +++ b/common/views.py @@ -104,7 +104,9 @@ def check_sub_domain(request): sub_domain = request.POST.get("sub_domain", "") if sub_domain == "": return render( - request, "check_subdomain.html", {"error": "Please mention a sub_domain"} + request, + "check_subdomain.html", + {"error": "Please mention a sub_domain"}, ) company = Company.objects.filter(sub_domain=sub_domain).first() if company: @@ -156,8 +158,9 @@ def get_context_data(self, **kwargs): context = super(HomeView, self).get_context_data(**kwargs) accounts = Account.objects.filter(status="open", company=self.request.company) contacts = Contact.objects.filter(company=self.request.company) - leads = Lead.objects.filter(company=self.request.company).exclude(Q(status="converted") | - Q(status="closed")) + leads = Lead.objects.filter(company=self.request.company).exclude( + Q(status="converted") | Q(status="closed") + ) opportunities = Opportunity.objects.filter(company=self.request.company) if self.request.user.role == "ADMIN" or self.request.user.is_superuser: pass @@ -403,7 +406,11 @@ def post(self, request, *args, **kwargs): request.company = company request.session["company"] = company.id else: - return render(request, "check_subdomain.html", {"error": "Please mention a sub_domain"}) + return render( + request, + "check_subdomain.html", + {"error": "Please mention a sub_domain"}, + ) form = CompanyLoginForm(request.POST, request=request) if form.is_valid(): email = form.cleaned_data.get("email", "") @@ -881,7 +888,10 @@ def get_context_data(self, **kwargs): context = super(DocumentDetailView, self).get_context_data(**kwargs) # documents = Document.objects.all() context.update( - {"file_type_code": self.object.file_type()[1], "doc_obj": self.object,} + { + "file_type_code": self.object.file_type()[1], + "doc_obj": self.object, + } ) return context @@ -1022,7 +1032,10 @@ def edit_comment(request, pk): comment_obj.comment = form.cleaned_data.get("comment") comment_obj.save(update_fields=["comment"]) return JsonResponse( - {"comment_id": comment_obj.id, "comment": comment_obj.comment,} + { + "comment_id": comment_obj.id, + "comment": comment_obj.comment, + } ) return JsonResponse({"error": form["comment"].errors}) data = {"error": "You don't have permission to edit this comment."} @@ -1358,7 +1371,10 @@ def create_lead_from_site(request): # pragma: no cover ] # add origin_domain = request.get_host() in the post body if ( - request.get_host() in ["sales.micropyramid.com",] + request.get_host() + in [ + "sales.micropyramid.com", + ] and request.POST.get("origin_domain") in allowed_domains ): if request.method == "POST": @@ -1414,8 +1430,10 @@ def activate_user(request, uidb64, token, activation_key): # pragma: no cover resend_url = reverse( "common:resend_activation_link", args=(profile.user.id,) ) - link_content = 'Click Here to resend the activation link.'.format( - resend_url + link_content = ( + 'Click Here to resend the activation link.'.format( + resend_url + ) ) message_content = "Your activation link has expired, {}".format( link_content diff --git a/contacts/api_urls.py b/contacts/api_urls.py index 1b64022..619943e 100644 --- a/contacts/api_urls.py +++ b/contacts/api_urls.py @@ -1,12 +1,9 @@ from django.urls import path from contacts import api_views -app_name = 'api_contacts' +app_name = "api_contacts" urlpatterns = [ - path("contacts-list/", api_views.ContactsListView.as_view()), - path("create/", api_views.CreateContactView.as_view(), name="add_contact"), - path("/view/", api_views.ContactDetailView.as_view(), name="view_contact"), - path("/edit/", api_views.UpdateContactView.as_view(), name="edit_contact"), - path("/delete/", api_views.RemoveContactView.as_view(), name="remove_contact"), + path("", api_views.ContactsListView.as_view()), + path("/", api_views.ContactDetailView.as_view(), name="view_contact"), ] diff --git a/contacts/api_views.py b/contacts/api_views.py index c88d56f..291d63c 100644 --- a/contacts/api_views.py +++ b/contacts/api_views.py @@ -24,7 +24,7 @@ class ContactsListView(APIView): permission_classes = (IsAuthenticated,) model = Contact - def get_queryset(self): + def get_queryset(self, params): queryset = self.model.objects.filter( company=self.request.company).order_by("-created_on") if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: @@ -34,7 +34,7 @@ def get_queryset(self): ) request_post = params - if request_post: + if request_post and params.get('is_filter'): if request_post.get("first_name"): queryset = queryset.filter( first_name__icontains=request_post.get("first_name") @@ -56,9 +56,24 @@ def get_queryset(self): return queryset.distinct() def get_context_data(self, **kwargs): + params = self.request.query_params if len( + self.request.data) == 0 else self.request.data context = {} + if self.request.user.role == "ADMIN" or self.request.user.is_superuser: + self.users = User.objects.filter( + is_active=True, company=self.request.company).order_by("email") + else: + self.users = User.objects.filter( + role="ADMIN", company=self.request.company).order_by("email") + context["users"] = UserSerializer(self.users, many=True).data + context["countries"] = COUNTRIES + context["assignedto_list"] = [ + int(i) for i in params.getlist("assigned_to", []) if i + ] + context["teams"] = TeamsSerializer(Teams.objects.filter( + company=self.request.company), many=True).data context["contact_obj_list"] = ContactSerializer( - self.get_queryset(), many=True).data + self.get_queryset(params), many=True).data context["per_page"] = params.get("per_page") context["users"] = UserSerializer( User.objects.filter(is_active=True).order_by("username"), many=True).data @@ -82,20 +97,8 @@ def get(self, request, *args, **kwargs): context = self.get_context_data(**kwargs) return Response(context) - @swagger_auto_schema(tags=["contacts"], manual_parameters=swagger_params.contact_list_post_params) - def post(self, request, *args, **kwargs): - context = self.get_context_data(**kwargs) - return Response(context) - - -class CreateContactView(APIView): - authentication_classes = (JSONWebTokenAuthentication,) - permission_classes = (IsAuthenticated,) - model = Contact - @swagger_auto_schema(tags=["contacts"], manual_parameters=swagger_params.contact_create_post_params) def post(self, request, *args, **kwargs): - self.object = None params = request.query_params if len( request.data) == 0 else request.data contact_serializer = CreateContctForm(data=params) @@ -159,31 +162,7 @@ def post(self, request, *args, **kwargs): attachment.attachment = request.FILES.get("contact_attachment") attachment.save() - return Response({'error': False}) - - def get_context_data(self, **kwargs): - params = self.request.query_params if len( - self.request.data) == 0 else request.data - context = {} - if self.request.user.role == "ADMIN" or self.request.user.is_superuser: - self.users = User.objects.filter( - is_active=True, company=self.request.company).order_by("email") - else: - self.users = User.objects.filter( - role="ADMIN", company=self.request.company).order_by("email") - context["users"] = UserSerializer(self.users, many=True).data - context["countries"] = COUNTRIES - context["assignedto_list"] = [ - int(i) for i in params.getlist("assigned_to", []) if i - ] - context["teams"] = TeamsSerializer(Teams.objects.filter( - company=self.request.company), many=True).data - return context - - @swagger_auto_schema(tags=["contacts"], manual_parameters=swagger_params.contact_list_get_params) - def get(self, request, *args, **kwargs): - context = self.get_context_data(**kwargs) - return Response(context) + return Response({'error': False, 'message': 'Contact created Successfuly'}) class ContactDetailView(APIView): @@ -191,81 +170,17 @@ class ContactDetailView(APIView): permission_classes = (IsAuthenticated,) model = Contact - def get_context_data(self, **kwargs): - context = {} - contact_obj = get_object_or_404(Contact, pk=kwargs['pk']) - context["contact_obj"] = ContactSerializer(contact_obj).data - user_assgn_list = [ - assigned_to.id for assigned_to in contact_obj.assigned_to.all() - ] - user_assigned_accounts = set( - self.request.user.account_assigned_users.values_list( - "id", flat=True) - ) - contact_accounts = set( - contact_obj.account_contacts.values_list("id", flat=True) - ) - if user_assigned_accounts.intersection(contact_accounts): - user_assgn_list.append(self.request.user.id) - if self.request.user == contact_obj.created_by: - user_assgn_list.append(self.request.user.id) - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - if self.request.user.id not in user_assgn_list: - raise PermissionDenied - assigned_data = [] - for each in contact_obj.assigned_to.all(): - assigned_dict = {} - assigned_dict["id"] = each.id - assigned_dict["name"] = each.email - assigned_data.append(assigned_dict) - - if self.request.user.is_superuser or self.request.user.role == "ADMIN": - users_mention = list( - User.objects.filter( - is_active=True, company=self.request.company - ).values("username") - ) - elif self.request.user != contact_obj.created_by: - users_mention = [ - {"username": contact_obj.created_by.username}] - else: - users_mention = list( - contact_obj.assigned_to.all().values("username")) - - context.update( - { - "comments": CommentSerializer(contact_obj.contact_comments.all(), many=True).data, - "attachments": AttachmentsSerializer(contact_obj.contact_attachment.all(), many=True).data, - "assigned_data": assigned_data, - "tasks": TaskSerializer(contact_obj.contacts_tasks.all(), many=True).data, - "users_mention": users_mention, - } - ) - return context - - @swagger_auto_schema(tags=["contacts"], manual_parameters=swagger_params.contact_detail_get_params) - def get(self, request, *args, **kwargs): - context = self.get_context_data(**kwargs) - return Response(context) - - -class UpdateContactView(APIView): - authentication_classes = (JSONWebTokenAuthentication,) - permission_classes = (IsAuthenticated,) - model = Contact - - def dispatch(self, request, *args, **kwargs): - self.contact = get_object_or_404(Contact, pk=kwargs.get('pk')) - return super(UpdateContactView, self).dispatch(request, *args, **kwargs) + def get_object(self, pk): + return get_object_or_404(Contact, pk=pk) @swagger_auto_schema(tags=["contacts"], manual_parameters=swagger_params.contact_create_post_params) - def post(self, request, *args, **kwargs): + def put(self, request, pk, format=None): params = request.query_params if len( request.data) == 0 else request.data - self.object = get_object_or_404(Contact, pk=kwargs.get('pk')) - address_obj = self.contact.address + self.object = self.get_object(pk) + address_obj = self.object.address contact_serializer = CreateContctForm( - data=params, instance=self.contact) + data=params, instance=self.object) address_serializer = BillingAddressSerializer( data=params, instance=address_obj) data = {} @@ -333,50 +248,80 @@ def post(self, request, *args, **kwargs): attachment.save() return Response({'error': False}) - def get_context_data(self, **kwargs): - params = self.request.query_params if len( - self.request.data) == 0 else request.data + @swagger_auto_schema(tags=["contacts"], manual_parameters=swagger_params.contact_detail_get_params) + def get(self, request, pk, format=None): context = {} - context["contact_obj"] = ContactSerializer(self.contact).data + contact_obj = self.get_object(pk) + context["contact_obj"] = ContactSerializer(contact_obj).data user_assgn_list = [ - assigned_to.id for assigned_to in self.contact.assigned_to.all() + assigned_to.id for assigned_to in contact_obj.assigned_to.all() ] + user_assigned_accounts = set( + self.request.user.account_assigned_users.values_list( + "id", flat=True) + ) + contact_accounts = set( + contact_obj.account_contacts.values_list("id", flat=True) + ) + if user_assigned_accounts.intersection(contact_accounts): + user_assgn_list.append(self.request.user.id) + if self.request.user == contact_obj.created_by: + user_assgn_list.append(self.request.user.id) + if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: + if self.request.user.id not in user_assgn_list: + raise PermissionDenied + assigned_data = [] + for each in contact_obj.assigned_to.all(): + assigned_dict = {} + assigned_dict["id"] = each.id + assigned_dict["name"] = each.email + assigned_data.append(assigned_dict) + + if self.request.user.is_superuser or self.request.user.role == "ADMIN": + users_mention = list( + User.objects.filter( + is_active=True, company=self.request.company + ).values("username") + ) + elif self.request.user != contact_obj.created_by: + users_mention = [ + {"username": contact_obj.created_by.username}] + else: + users_mention = list( + contact_obj.assigned_to.all().values("username")) + if self.request.user.role == "ADMIN" or self.request.user.is_superuser: self.users = User.objects.filter( is_active=True, company=self.request.company).order_by("email") else: self.users = User.objects.filter( role="ADMIN", company=self.request.company).order_by("email") - if self.request.user == self.contact.created_by: + if request.user == contact_obj.created_by: user_assgn_list.append(self.request.user.id) - if self.request.user.role != "ADMIN" and not self.request.user.is_superuser: - if self.request.user.id not in user_assgn_list: - raise PermissionDenied + context["address_obj"] = BillingAddressSerializer( - self.contact.address).data + contact_obj.address).data context["users"] = UserSerializer(self.users, many=True).data context["countries"] = COUNTRIES context["teams"] = TeamsSerializer( - Teams.objects.filter(company=self.request.company), many=True).data - context["assignedto_list"] = [ - int(i) for i in params.getlist("assigned_to", []) if i - ] - return context - - @swagger_auto_schema(tags=["contacts"], manual_parameters=swagger_params.contact_list_get_params) - def get(self, request, *args, **kwargs): - context = self.get_context_data(**kwargs) + Teams.objects.filter(company=request.company), many=True).data + context.update( + { + "comments": CommentSerializer( + contact_obj.contact_comments.all(), many=True).data, + "attachments": AttachmentsSerializer( + contact_obj.contact_attachment.all(), many=True).data, + "assigned_data": assigned_data, + "tasks": TaskSerializer( + contact_obj.contacts_tasks.all(), many=True).data, + "users_mention": users_mention, + } + ) return Response(context) - -class RemoveContactView(APIView): - authentication_classes = (JSONWebTokenAuthentication,) - permission_classes = (IsAuthenticated,) - @swagger_auto_schema(tags=["contacts"], manual_parameters=swagger_params.contact_delete_get_params) - def get(self, request, *args, **kwargs): - contact_id = kwargs.get("pk") - self.object = get_object_or_404(Contact, id=contact_id) + def delete(self, request, pk, format=None): + self.object = self.get_object(pk) if ( self.request.user.role != "ADMIN" and not self.request.user.is_superuser @@ -387,4 +332,4 @@ def get(self, request, *args, **kwargs): if self.object.address_id: self.object.address.delete() self.object.delete() - return Response({"error": False}) + return Response({"error": False}) diff --git a/contacts/forms.py b/contacts/forms.py index 913f3f2..d95ce7f 100644 --- a/contacts/forms.py +++ b/contacts/forms.py @@ -20,7 +20,7 @@ def __init__(self, *args, **kwargs): for key, value in self.fields.items(): if key == "phone": - pass + pass else: value.widget.attrs["placeholder"] = value.label self.fields["teams"].choices = [ diff --git a/contacts/migrations/0002_auto_20190210_1810.py b/contacts/migrations/0002_auto_20190210_1810.py index 436dca3..a67b9c0 100644 --- a/contacts/migrations/0002_auto_20190210_1810.py +++ b/contacts/migrations/0002_auto_20190210_1810.py @@ -11,6 +11,7 @@ class Migration(migrations.Migration): operations = [ migrations.AlterModelOptions( - name="contact", options={"ordering": ["-created_on"]}, + name="contact", + options={"ordering": ["-created_on"]}, ), ] diff --git a/contacts/migrations/0002_auto_20190212_1334.py b/contacts/migrations/0002_auto_20190212_1334.py index ba5242f..65f3c62 100644 --- a/contacts/migrations/0002_auto_20190212_1334.py +++ b/contacts/migrations/0002_auto_20190212_1334.py @@ -13,10 +13,17 @@ class Migration(migrations.Migration): operations = [ migrations.AlterModelOptions( - name="contact", options={"ordering": ["-created_on"]}, + name="contact", + options={"ordering": ["-created_on"]}, + ), + migrations.RemoveField( + model_name="contact", + name="account", + ), + migrations.RemoveField( + model_name="contact", + name="teams", ), - migrations.RemoveField(model_name="contact", name="account",), - migrations.RemoveField(model_name="contact", name="teams",), migrations.AlterField( model_name="contact", name="created_by", diff --git a/contacts/serializer.py b/contacts/serializer.py index ab696c3..aafdbb2 100644 --- a/contacts/serializer.py +++ b/contacts/serializer.py @@ -1,6 +1,10 @@ from rest_framework import serializers from contacts.models import Contact -from common.serializer import UserSerializer, CompanySerializer, BillingAddressSerializer +from common.serializer import ( + UserSerializer, + CompanySerializer, + BillingAddressSerializer, +) from teams.serializer import TeamsSerializer @@ -17,7 +21,7 @@ class ContactSerializer(serializers.ModelSerializer): class Meta: model = Contact fields = ( - 'id', + "id", "first_name", "last_name", "email", @@ -38,7 +42,6 @@ class Meta: class CreateContctForm(serializers.ModelSerializer): - class Meta: model = Contact fields = ( diff --git a/contacts/swagger_params.py b/contacts/swagger_params.py index 5b3c18e..b10b1c7 100644 --- a/contacts/swagger_params.py +++ b/contacts/swagger_params.py @@ -1,7 +1,8 @@ from drf_yasg import openapi company_params_in_header = openapi.Parameter( - 'company', openapi.IN_HEADER, required=True, type=openapi.TYPE_STRING) + "company", openapi.IN_HEADER, required=True, type=openapi.TYPE_STRING +) contact_list_get_params = [company_params_in_header] @@ -14,18 +15,26 @@ contact_create_post_params = [ company_params_in_header, - openapi.Parameter('first_name', openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING), - openapi.Parameter('last_name', openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING), - openapi.Parameter('phone', openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING), - openapi.Parameter('email', openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING), - openapi.Parameter('teams', openapi.IN_QUERY, type=openapi.TYPE_INTEGER), - openapi.Parameter('contact_attachment', openapi.IN_QUERY, type=openapi.TYPE_FILE), - openapi.Parameter('description', openapi.IN_QUERY, type=openapi.TYPE_STRING), - openapi.Parameter('address_line', openapi.IN_QUERY, type=openapi.TYPE_STRING), - openapi.Parameter('street', openapi.IN_QUERY, type=openapi.TYPE_STRING), - openapi.Parameter('city', openapi.IN_QUERY, type=openapi.TYPE_STRING), - openapi.Parameter('state', openapi.IN_QUERY, type=openapi.TYPE_STRING), - openapi.Parameter('postcode', openapi.IN_QUERY, type=openapi.TYPE_STRING), - openapi.Parameter('country', openapi.IN_QUERY, type=openapi.TYPE_STRING), - openapi.Parameter('assigned_to', openapi.IN_QUERY, type=openapi.TYPE_INTEGER), + openapi.Parameter( + "first_name", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "last_name", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "phone", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter( + "email", openapi.IN_QUERY, required=True, type=openapi.TYPE_STRING + ), + openapi.Parameter("teams", openapi.IN_QUERY, type=openapi.TYPE_INTEGER), + openapi.Parameter("contact_attachment", openapi.IN_QUERY, type=openapi.TYPE_FILE), + openapi.Parameter("description", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter("address_line", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter("street", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter("city", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter("state", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter("postcode", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter("country", openapi.IN_QUERY, type=openapi.TYPE_STRING), + openapi.Parameter("assigned_to", openapi.IN_QUERY, type=openapi.TYPE_INTEGER), ] diff --git a/contacts/tests.py b/contacts/tests.py index 477dd5b..b5ea69b 100644 --- a/contacts/tests.py +++ b/contacts/tests.py @@ -496,7 +496,9 @@ def test_create_contact(self): "last_name": "last name", "phone": "+91-123-456-7854", "email": "example@user.com", - "teams": [self.teams_contacts.id,], + "teams": [ + self.teams_contacts.id, + ], } response = self.client.post( reverse("contacts:add_contact") @@ -510,7 +512,9 @@ def test_create_contact(self): "last_name": "last name", "phone": "+91-123-456-7858", "email": "example@mail.com", - "teams": [self.teams_contacts.id,], + "teams": [ + self.teams_contacts.id, + ], } response = self.client.post( reverse("contacts:add_contact") @@ -525,7 +529,9 @@ def test_create_contact(self): "last_name": "last name", "phone": "+91-123-456-7854", "email": "example@user", - "teams": [self.teams_contacts.id,], + "teams": [ + self.teams_contacts.id, + ], } response = self.client.post( reverse("contacts:add_contact") @@ -544,7 +550,9 @@ def test_create_contact(self): "last_name": "contact@example.com", "phone": "+91-123-456-7856", "email": "contact@example.com", - "teams": [self.teams_contacts.id,], + "teams": [ + self.teams_contacts.id, + ], }, ) self.assertEqual(302, response.status_code) @@ -582,7 +590,9 @@ def test_create_contact(self): "last_name": "contact", "phone": "+91-123-456-7852", "email": "contact@example.com", - "teams": [self.teams_contacts.id,], + "teams": [ + self.teams_contacts.id, + ], } response = self.client.post( reverse("contacts:edit_contact", args=(self.contact.id,)) @@ -604,7 +614,9 @@ def test_create_contact(self): "last_name": "contact", "phone": "+91-123-456", "email": "contact@example", - "teams": [self.teams_contacts.id,], + "teams": [ + self.teams_contacts.id, + ], } response = self.client.post( reverse("contacts:edit_contact", args=(self.contact.id,)) diff --git a/contacts/tests_celery_tasks.py b/contacts/tests_celery_tasks.py index 2c4f470..c9c3459 100644 --- a/contacts/tests_celery_tasks.py +++ b/contacts/tests_celery_tasks.py @@ -15,6 +15,12 @@ class TestCeleryTasks(ContactObjectsCreation, TestCase): ) def test_celery_tasks(self): task = send_email_to_assigned_user.apply( - ([self.user.id, self.user_contacts_mp.id,], self.contact.id,), + ( + [ + self.user.id, + self.user_contacts_mp.id, + ], + self.contact.id, + ), ) self.assertEqual("SUCCESS", task.state) diff --git a/contacts/views.py b/contacts/views.py index f97739e..6fedf17 100644 --- a/contacts/views.py +++ b/contacts/views.py @@ -107,15 +107,21 @@ class CreateContactView(SalesAccessRequiredMixin, LoginRequiredMixin, CreateView def dispatch(self, request, *args, **kwargs): if self.request.user.role == "ADMIN" or self.request.user.is_superuser: - self.users = User.objects.filter(is_active=True, company=self.request.company).order_by("email") + self.users = User.objects.filter( + is_active=True, company=self.request.company + ).order_by("email") else: - self.users = User.objects.filter(role="ADMIN", company=self.request.company).order_by("email") + self.users = User.objects.filter( + role="ADMIN", company=self.request.company + ).order_by("email") return super(CreateContactView, self).dispatch(request, *args, **kwargs) def get_form_kwargs(self): kwargs = super(CreateContactView, self).get_form_kwargs() if self.request.user.role == "ADMIN" or self.request.user.is_superuser: - self.users = User.objects.filter(is_active=True, company=self.request.company).order_by("email") + self.users = User.objects.filter( + is_active=True, company=self.request.company + ).order_by("email") kwargs.update({"assigned_to": self.users}) return kwargs @@ -306,15 +312,21 @@ def dispatch(self, request, *args, **kwargs): raise PermissionDenied if self.request.user.role == "ADMIN" or self.request.user.is_superuser: - self.users = User.objects.filter(is_active=True, company=self.request.company).order_by("email") + self.users = User.objects.filter( + is_active=True, company=self.request.company + ).order_by("email") else: - self.users = User.objects.filter(role="ADMIN", company=self.request.company).order_by("email") + self.users = User.objects.filter( + role="ADMIN", company=self.request.company + ).order_by("email") return super(UpdateContactView, self).dispatch(request, *args, **kwargs) def get_form_kwargs(self): kwargs = super(UpdateContactView, self).get_form_kwargs() if self.request.user.role == "ADMIN" or self.request.user.is_superuser: - self.users = User.objects.filter(is_active=True, company=self.request.company).order_by("email") + self.users = User.objects.filter( + is_active=True, company=self.request.company + ).order_by("email") kwargs.update({"assigned_to": self.users}) return kwargs @@ -560,7 +572,10 @@ def form_valid(self, form): protocol=self.request.scheme, ) return JsonResponse( - {"commentid": self.comment_obj.id, "comment": self.comment_obj.comment,} + { + "commentid": self.comment_obj.id, + "comment": self.comment_obj.comment, + } ) def form_invalid(self, form): diff --git a/crm/helper.py b/crm/helper.py index 895a4ab..8f52b8e 100644 --- a/crm/helper.py +++ b/crm/helper.py @@ -27,7 +27,12 @@ def send_mail(mto, mfrom, msubject, mbody, user_active): response = requests.post( settings.MGUN_API_URL, auth=("api", settings.MGUN_API_KEY), - data={"from": mfrom, "to": mto, "subject": msubject, "html": mbody,}, + data={ + "from": mfrom, + "to": mto, + "subject": msubject, + "html": mbody, + }, ) elif mail_sender == "SENDGRID": sg = sendgrid.SendGridClient(settings.SG_USER, settings.SG_PWD) diff --git a/crm/server_settings.py b/crm/server_settings.py index 28f599d..27772c0 100644 --- a/crm/server_settings.py +++ b/crm/server_settings.py @@ -45,16 +45,15 @@ SESSION_COOKIE_DOMAIN = ".bottlecrm.com" ELASTIC_APM = { - 'SERVICE_NAME': os.getenv("ELASTIC_APM_SERVICE_NAME"), - 'SECRET_TOKEN': os.getenv("ELASTIC_APM_SECRET_TOKEN"), - 'SERVER_URL': os.getenv("ELASTIC_APM_SERVER_URL"), + "SERVICE_NAME": os.getenv("ELASTIC_APM_SERVICE_NAME"), + "SECRET_TOKEN": os.getenv("ELASTIC_APM_SECRET_TOKEN"), + "SERVER_URL": os.getenv("ELASTIC_APM_SERVER_URL"), } sentry_sdk.init( dsn=os.getenv("SENTRY_DSN"), integrations=[DjangoIntegration()], - # If you wish to associate users to errors (assuming you are using # django.contrib.auth) you may enable sending PII data. - send_default_pii=True + send_default_pii=True, ) diff --git a/crm/settings.py b/crm/settings.py index f7eb73f..e1a7d2d 100644 --- a/crm/settings.py +++ b/crm/settings.py @@ -7,7 +7,7 @@ # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -env_path = Path('.') / '.env' +env_path = Path(".") / ".env" load_dotenv(dotenv_path=env_path) # SECURITY WARNING: keep the secret key used in production secret! @@ -65,7 +65,6 @@ "django.middleware.clickjacking.XFrameOptionsMiddleware", "common.middleware.get_company.GetCompany", "corsheaders.middleware.CorsMiddleware", - ] ROOT_URLCONF = "crm.urls" @@ -73,7 +72,9 @@ TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", - "DIRS": [os.path.join(BASE_DIR, "templates"), ], + "DIRS": [ + os.path.join(BASE_DIR, "templates"), + ], "APP_DIRS": True, "OPTIONS": { "context_processors": [ @@ -117,9 +118,15 @@ { "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", }, - {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", }, - {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", }, - {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", }, + { + "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", + }, + { + "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", + }, ] # Internationalization @@ -177,11 +184,11 @@ elif ENV_TYPE == "live": INSTALLED_APPS = INSTALLED_APPS + [ - 'elasticapm.contrib.django', + "elasticapm.contrib.django", ] MIDDLEWARE = MIDDLEWARE + [ - 'elasticapm.contrib.django.middleware.TracingMiddleware', + "elasticapm.contrib.django.middleware.TracingMiddleware", ] from .server_settings import * @@ -297,8 +304,12 @@ "version": 1, "disable_existing_loggers": False, "filters": { - "require_debug_false": {"()": "django.utils.log.RequireDebugFalse", }, - "require_debug_true": {"()": "django.utils.log.RequireDebugTrue", }, + "require_debug_false": { + "()": "django.utils.log.RequireDebugFalse", + }, + "require_debug_true": { + "()": "django.utils.log.RequireDebugTrue", + }, }, "formatters": { "django.server": { @@ -327,11 +338,18 @@ "filters": ["require_debug_false"], "class": "django.utils.log.AdminEmailHandler", }, - "logfile": {"class": "logging.FileHandler", "filename": "server.log", }, + "logfile": { + "class": "logging.FileHandler", + "filename": "server.log", + }, }, "loggers": { "django": { - "handlers": ["console", "console_debug_false", "logfile", ], + "handlers": [ + "console", + "console_debug_false", + "logfile", + ], "level": "INFO", }, "django.server": { @@ -400,63 +418,46 @@ } - SETTINGS_EXPORT = ["APPLICATION_NAME"] REST_FRAMEWORK = { - 'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler', - 'DEFAULT_AUTHENTICATION_CLASSES': ( - 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', - 'rest_framework.authentication.SessionAuthentication', - 'rest_framework.authentication.BasicAuthentication', + "EXCEPTION_HANDLER": "rest_framework.views.exception_handler", + "DEFAULT_AUTHENTICATION_CLASSES": ( + "rest_framework_jwt.authentication.JSONWebTokenAuthentication", + "rest_framework.authentication.SessionAuthentication", + "rest_framework.authentication.BasicAuthentication", ), } SWAGGER_SETTINGS = { - 'DEFAULT_INFO': "crm.urls.info", - 'SECURITY_DEFINITIONS': { - "api_key": { - "type": "apiKey", - "name": "Authorization", - "in": "header" - }, + "DEFAULT_INFO": "crm.urls.info", + "SECURITY_DEFINITIONS": { + "api_key": {"type": "apiKey", "name": "Authorization", "in": "header"}, }, } -TOKEN_SECRET_KEY = 'mk%l3jsghg-u*!luyer@tew$xn!ksb(k$&2rj4h4@%tmy76z' +TOKEN_SECRET_KEY = "mk%l3jsghg-u*!luyer@tew$xn!ksb(k$&2rj4h4@%tmy76z" JWT_AUTH = { - 'JWT_ENCODE_HANDLER': - 'rest_framework_jwt.utils.jwt_encode_handler', - - 'JWT_DECODE_HANDLER': - 'rest_framework_jwt.utils.jwt_decode_handler', - - 'JWT_PAYLOAD_HANDLER': - 'common.utils.jwt_payload_handler', - - 'JWT_RESPONSE_PAYLOAD_HANDLER': - 'rest_framework_jwt.utils.jwt_response_payload_handler', - - 'JWT_SECRET_KEY': TOKEN_SECRET_KEY, - 'JWT_GET_USER_SECRET_KEY': None, - 'JWT_PUBLIC_KEY': None, - 'JWT_PRIVATE_KEY': None, - 'JWT_ALGORITHM': 'HS256', - 'JWT_VERIFY': True, - 'JWT_VERIFY_EXPIRATION': True, - 'JWT_LEEWAY': 0, - 'JWT_AUDIENCE': None, - 'JWT_ISSUER': None, - 'JWT_ALLOW_REFRESH': True, - - 'JWT_AUTH_HEADER_PREFIX': 'JWT', - 'JWT_AUTH_COOKIE': None, - + "JWT_ENCODE_HANDLER": "rest_framework_jwt.utils.jwt_encode_handler", + "JWT_DECODE_HANDLER": "rest_framework_jwt.utils.jwt_decode_handler", + "JWT_PAYLOAD_HANDLER": "common.utils.jwt_payload_handler", + "JWT_RESPONSE_PAYLOAD_HANDLER": "rest_framework_jwt.utils.jwt_response_payload_handler", + "JWT_SECRET_KEY": TOKEN_SECRET_KEY, + "JWT_GET_USER_SECRET_KEY": None, + "JWT_PUBLIC_KEY": None, + "JWT_PRIVATE_KEY": None, + "JWT_ALGORITHM": "HS256", + "JWT_VERIFY": True, + "JWT_VERIFY_EXPIRATION": True, + "JWT_LEEWAY": 0, + "JWT_AUDIENCE": None, + "JWT_ISSUER": None, + "JWT_ALLOW_REFRESH": True, + "JWT_AUTH_HEADER_PREFIX": "JWT", + "JWT_AUTH_COOKIE": None, } -CORS_ALLOW_HEADERS = default_headers + ( - 'company', -) +CORS_ALLOW_HEADERS = default_headers + ("company",) CORS_ORIGIN_ALLOW_ALL = True diff --git a/crm/urls.py b/crm/urls.py index 38b12fb..17a6a3e 100644 --- a/crm/urls.py +++ b/crm/urls.py @@ -11,7 +11,7 @@ openapi_info = openapi.Info( title="Crm API", - default_version='v1', + default_version="v1", ) schema_view = get_schema_view( @@ -24,12 +24,19 @@ app_name = "crm" urlpatterns = [ - url(r'^swagger(?P\.json|\.yaml)$', - schema_view.without_ui(cache_timeout=0), name='schema-json'), - url(r'^swagger/$', schema_view.with_ui('swagger', - cache_timeout=0), name='schema-swagger-ui'), - url(r'^redoc/$', schema_view.with_ui('redoc', - cache_timeout=0), name='schema-redoc'), + url( + r"^swagger(?P\.json|\.yaml)$", + schema_view.without_ui(cache_timeout=0), + name="schema-json", + ), + url( + r"^swagger/$", + schema_view.with_ui("swagger", cache_timeout=0), + name="schema-swagger-ui", + ), + url( + r"^redoc/$", schema_view.with_ui("redoc", cache_timeout=0), name="schema-redoc" + ), path("", include("common.urls", namespace="common")), path("api/", include("common.app_urls", namespace="common_urls")), path("", include("django.contrib.auth.urls")), diff --git a/emails/migrations/0001_initial.py b/emails/migrations/0001_initial.py index f710f13..4d95510 100644 --- a/emails/migrations/0001_initial.py +++ b/emails/migrations/0001_initial.py @@ -31,6 +31,8 @@ class Migration(migrations.Migration): ("status", models.CharField(default="sent", max_length=200)), ("important", models.BooleanField(default=False, max_length=10)), ], - options={"ordering": ["-id"],}, + options={ + "ordering": ["-id"], + }, ), ] diff --git a/events/views.py b/events/views.py index b159ae1..9b0fe93 100644 --- a/events/views.py +++ b/events/views.py @@ -217,7 +217,12 @@ def event_create(request): {"error": False, "success_url": reverse("events:events_list")} ) else: - return JsonResponse({"error": True, "errors": form.errors,}) + return JsonResponse( + { + "error": True, + "errors": form.errors, + } + ) @login_required @@ -376,7 +381,12 @@ def event_update(request, event_id): {"error": False, "success_url": reverse("events:events_list")} ) else: - return JsonResponse({"error": True, "errors": form.errors,}) + return JsonResponse( + { + "error": True, + "errors": form.errors, + } + ) @login_required @@ -472,7 +482,10 @@ def form_valid(self, form): protocol=self.request.scheme, ) return JsonResponse( - {"comment_id": self.comment_obj.id, "comment": self.comment_obj.comment,} + { + "comment_id": self.comment_obj.id, + "comment": self.comment_obj.comment, + } ) def form_invalid(self, form): diff --git a/invoices/forms.py b/invoices/forms.py index 663ff5e..0409c58 100644 --- a/invoices/forms.py +++ b/invoices/forms.py @@ -41,7 +41,8 @@ def __init__(self, *args, **kwargs): role="ADMIN", company=request_obj.company ) self.fields["accounts"].queryset = Account.objects.filter( - status="open", company=request_obj.company, + status="open", + company=request_obj.company, ).filter(Q(created_by=request_user) | Q(assigned_to=request_user)) else: pass @@ -81,7 +82,7 @@ class Meta: "details", "due_date", "accounts", - "tax" + "tax", ) diff --git a/invoices/migrations/0001_initial.py b/invoices/migrations/0001_initial.py index 9785b62..ea2005b 100644 --- a/invoices/migrations/0001_initial.py +++ b/invoices/migrations/0001_initial.py @@ -284,6 +284,9 @@ class Migration(migrations.Migration): ), ), ], - options={"verbose_name": "Invoice", "verbose_name_plural": "Invoices",}, + options={ + "verbose_name": "Invoice", + "verbose_name_plural": "Invoices", + }, ), ] diff --git a/invoices/migrations/0007_auto_20190909_1621.py b/invoices/migrations/0007_auto_20190909_1621.py index 112d03a..55bd1c8 100644 --- a/invoices/migrations/0007_auto_20190909_1621.py +++ b/invoices/migrations/0007_auto_20190909_1621.py @@ -11,6 +11,7 @@ class Migration(migrations.Migration): operations = [ migrations.AlterModelOptions( - name="invoicehistory", options={"ordering": ("created_on",)}, + name="invoicehistory", + options={"ordering": ("created_on",)}, ), ] diff --git a/invoices/migrations/0010_invoice_tax.py b/invoices/migrations/0010_invoice_tax.py index 6df8cc0..17d5872 100644 --- a/invoices/migrations/0010_invoice_tax.py +++ b/invoices/migrations/0010_invoice_tax.py @@ -6,13 +6,15 @@ class Migration(migrations.Migration): dependencies = [ - ('invoices', '0009_invoice_company'), + ("invoices", "0009_invoice_company"), ] operations = [ migrations.AddField( - model_name='invoice', - name='tax', - field=models.DecimalField(blank=True, decimal_places=2, max_digits=12, null=True), + model_name="invoice", + name="tax", + field=models.DecimalField( + blank=True, decimal_places=2, max_digits=12, null=True + ), ), ] diff --git a/invoices/models.py b/invoices/models.py index e1d73e8..19aff35 100644 --- a/invoices/models.py +++ b/invoices/models.py @@ -42,9 +42,7 @@ class Invoice(models.Model): total_amount = models.DecimalField( blank=True, null=True, max_digits=12, decimal_places=2 ) - tax = models.DecimalField( - blank=True, null=True, max_digits=12, decimal_places=2 - ) + tax = models.DecimalField(blank=True, null=True, max_digits=12, decimal_places=2) currency = models.CharField( max_length=3, choices=CURRENCY_CODES, blank=True, null=True ) @@ -70,9 +68,7 @@ class Invoice(models.Model): company = models.ForeignKey( Company, on_delete=models.SET_NULL, null=True, blank=True ) - tax = models.DecimalField( - blank=True, null=True, max_digits=12, decimal_places=2 - ) + tax = models.DecimalField(blank=True, null=True, max_digits=12, decimal_places=2) class Meta: """Meta definition for Invoice.""" @@ -88,14 +84,16 @@ def invoice_id_generator(self, prev_invoice_number=None): if prev_invoice_number: prev_invoice_number += 1 return prev_invoice_number - date = datetime.datetime.now().strftime('%d%m%Y') + date = datetime.datetime.now().strftime("%d%m%Y") return int(date + "0001") def save(self, *args, **kwargs): if not self.invoice_number: self.invoice_number = self.invoice_id_generator() while Invoice.objects.filter(invoice_number=self.invoice_number).exists(): - self.invoice_number = self.invoice_id_generator(prev_invoice_number=self.invoice_number) + self.invoice_number = self.invoice_id_generator( + prev_invoice_number=self.invoice_number + ) super(Invoice, self).save(*args, **kwargs) def formatted_total_amount(self): diff --git a/invoices/tasks.py b/invoices/tasks.py index 1e31753..22e97ff 100644 --- a/invoices/tasks.py +++ b/invoices/tasks.py @@ -63,7 +63,11 @@ def send_email(invoice_id, recipients, domain="demo.django-crm.io", protocol="ht "assigned_to_email_template.html", context=context ) msg = EmailMessage( - subject=subject, body=html_content, to=[recipient.email,] + subject=subject, + body=html_content, + to=[ + recipient.email, + ], ) msg.content_subtype = "html" msg.send() diff --git a/invoices/tests.py b/invoices/tests.py index 3b3c194..78b221c 100644 --- a/invoices/tests.py +++ b/invoices/tests.py @@ -13,7 +13,10 @@ class InvoiceCreateTest(object): def setUp(self): self.company, _ = Company.objects.get_or_create( - name="test company", address="IN", sub_domain="test", country="IN", + name="test company", + address="IN", + sub_domain="test", + country="IN", ) self.user = User.objects.create( first_name="johnInvoice", @@ -524,6 +527,8 @@ def test_invoices_delete(self): self.assertEqual(self.invoice.is_paid_or_cancelled(), True) response = self.client.get( reverse("invoices:invoice_delete", args=(self.invoice.id,)) - + "?view_account={}".format(self.account.id,) + + "?view_account={}".format( + self.account.id, + ) ) self.assertEqual(response.status_code, 302) diff --git a/invoices/views.py b/invoices/views.py index 578e0ce..67cfbcc 100644 --- a/invoices/views.py +++ b/invoices/views.py @@ -587,7 +587,10 @@ def form_valid(self, form): protocol=self.request.scheme, ) return JsonResponse( - {"comment_id": self.comment_obj.id, "comment": self.comment_obj.comment,} + { + "comment_id": self.comment_obj.id, + "comment": self.comment_obj.comment, + } ) def form_invalid(self, form): diff --git a/leads/forms.py b/leads/forms.py index 331b8b4..ab28eb7 100644 --- a/leads/forms.py +++ b/leads/forms.py @@ -77,20 +77,20 @@ def __init__(self, *args, **kwargs): self.fields["source"]._set_choices(prev_choices) self.company = request_obj.company - def clean_account_name(self): account_name = self.cleaned_data.get("account_name") if self.instance.id: if self.instance.account_name != account_name: if not Account.objects.filter( name__iexact=self.cleaned_data.get("account_name"), - company=self.company + company=self.company, ).exists(): return self.cleaned_data.get("account_name") - raise forms.ValidationError( - "Account already exists with this name") + raise forms.ValidationError("Account already exists with this name") return self.cleaned_data.get("account_name") - if not Account.objects.filter(name__iexact=self.cleaned_data.get("account_name"), company=self.company).exists(): + if not Account.objects.filter( + name__iexact=self.cleaned_data.get("account_name"), company=self.company + ).exists(): return self.cleaned_data.get("account_name") raise forms.ValidationError("Account already exists with this name") @@ -206,12 +206,16 @@ class LeadListForm(forms.Form): def __init__(self, *args, **kwargs): super(LeadListForm, self).__init__(*args, **kwargs) self.fields["leads_file"].widget.attrs.update( - {"accept": ".csv",} + { + "accept": ".csv", + } ) self.fields["leads_file"].required = True if self.data.get("leads_file"): self.fields["leads_file"].widget.attrs.update( - {"accept": ".csv",} + { + "accept": ".csv", + } ) def clean_leads_file(self): diff --git a/leads/migrations/0001_initial.py b/leads/migrations/0001_initial.py index 556f764..1686a88 100644 --- a/leads/migrations/0001_initial.py +++ b/leads/migrations/0001_initial.py @@ -150,6 +150,8 @@ class Migration(migrations.Migration): ), ("teams", models.ManyToManyField(to="common.Team")), ], - options={"ordering": ["-created_on"],}, + options={ + "ordering": ["-created_on"], + }, ), ] diff --git a/leads/migrations/0004_auto_20190212_1334.py b/leads/migrations/0004_auto_20190212_1334.py index f8f164b..290f938 100644 --- a/leads/migrations/0004_auto_20190212_1334.py +++ b/leads/migrations/0004_auto_20190212_1334.py @@ -13,8 +13,14 @@ class Migration(migrations.Migration): ] operations = [ - migrations.RemoveField(model_name="lead", name="account",), - migrations.RemoveField(model_name="lead", name="teams",), + migrations.RemoveField( + model_name="lead", + name="account", + ), + migrations.RemoveField( + model_name="lead", + name="teams", + ), migrations.AddField( model_name="lead", name="contacts", diff --git a/leads/migrations/0005_auto_20190212_1708.py b/leads/migrations/0005_auto_20190212_1708.py index 7780de0..f8665ae 100644 --- a/leads/migrations/0005_auto_20190212_1708.py +++ b/leads/migrations/0005_auto_20190212_1708.py @@ -10,7 +10,10 @@ class Migration(migrations.Migration): ] operations = [ - migrations.RemoveField(model_name="lead", name="address",), + migrations.RemoveField( + model_name="lead", + name="address", + ), migrations.AddField( model_name="lead", name="address_line", diff --git a/leads/serializer.py b/leads/serializer.py index f901d6e..992e7ba 100644 --- a/leads/serializer.py +++ b/leads/serializer.py @@ -8,10 +8,7 @@ class TagsSerailizer(serializers.ModelSerializer): class Meta: model = Tags - fields = ( - "name", - "slug" - ) + fields = ("name", "slug") class LeadSerializer(serializers.ModelSerializer): @@ -25,7 +22,7 @@ class Meta: model = Lead # fields = ‘__all__’ fields = ( - 'id', + "id", "title", "first_name", "last_name", diff --git a/leads/tasks.py b/leads/tasks.py index 3dea3bf..e2fd92c 100644 --- a/leads/tasks.py +++ b/leads/tasks.py @@ -152,7 +152,10 @@ def update_leads_cache(): Lead.objects.all() .exclude(status="converted") .select_related("created_by") - .prefetch_related("tags", "assigned_to",) + .prefetch_related( + "tags", + "assigned_to", + ) ) open_leads = queryset.exclude(status="closed") close_leads = queryset.filter(status="closed") diff --git a/leads/tests.py b/leads/tests.py index e6ae30f..0b90545 100644 --- a/leads/tests.py +++ b/leads/tests.py @@ -734,7 +734,9 @@ def test_file_upload_for_leads(self): reverse("leads:add_lead"), { "title": "new lead title", - "teams": [self.teams_leads.id,], + "teams": [ + self.teams_leads.id, + ], "savenewform": "true", }, ) @@ -781,7 +783,9 @@ def test_file_upload_for_leads(self): self.teams_leads.users.add(self.user3) data = { "title": self.lead_1.title, - "teams": [self.teams_leads.id,], + "teams": [ + self.teams_leads.id, + ], "status": "converted", "account_name": "lead_conversion", "email": "account@lead.com", diff --git a/leads/tests_celery_tasks.py b/leads/tests_celery_tasks.py index 89cb48e..ade0e3a 100644 --- a/leads/tests_celery_tasks.py +++ b/leads/tests_celery_tasks.py @@ -18,29 +18,52 @@ class TestCeleryTasks(TestLeadModel, TestCase): ) def test_celery_tasks(self): task = send_email_to_assigned_user.apply( - ([self.user.id, self.user1.id,], self.lead.id,), + ( + [ + self.user.id, + self.user1.id, + ], + self.lead.id, + ), ) self.assertEqual("SUCCESS", task.state) task = send_lead_assigned_emails.apply( ( self.lead.id, - [self.user.id, self.user1.id, self.user2.id,], + [ + self.user.id, + self.user1.id, + self.user2.id, + ], "https://www.example.com", ), ) self.assertEqual("SUCCESS", task.state) task = send_email.apply( - ("mail subject", "html content",), - {"recipients": [self.user.id, self.user1.id, self.user2.id,],}, + ( + "mail subject", + "html content", + ), + { + "recipients": [ + self.user.id, + self.user1.id, + self.user2.id, + ], + }, ) self.assertEqual("SUCCESS", task.state) task = send_lead_assigned_emails.apply( ( self.lead1.id, - [self.user.id, self.user1.id, self.user2.id,], + [ + self.user.id, + self.user1.id, + self.user2.id, + ], "https://www.example.com", ), ) diff --git a/leads/views.py b/leads/views.py index 9b0dc15..c2ab17d 100644 --- a/leads/views.py +++ b/leads/views.py @@ -63,7 +63,10 @@ def lead_list_view(request): Lead.objects.filter(company=request.company) .exclude(status="converted") .select_related("created_by") - .prefetch_related("tags", "assigned_to",) + .prefetch_related( + "tags", + "assigned_to", + ) ) if request.user.role == "ADMIN" or request.user.is_superuser: queryset = queryset @@ -92,7 +95,14 @@ def lead_list_view(request): .values("id", "username") ) - tag_ids = list(set(queryset.values_list("tags", flat=True,))) + tag_ids = list( + set( + queryset.values_list( + "tags", + flat=True, + ) + ) + ) context["tags"] = Tags.objects.filter(id__in=tag_ids) return render(request, "leads.html", context) @@ -154,7 +164,14 @@ def lead_list_view(request): .order_by("email") .values("id", "email") ) - tag_ids = list(set(queryset.values_list("tags", flat=True,))) + tag_ids = list( + set( + queryset.values_list( + "tags", + flat=True, + ) + ) + ) context["tags"] = Tags.objects.filter(id__in=tag_ids) context["assignedto_list"] = [ @@ -180,7 +197,10 @@ def get_queryset(self): self.model.objects.all() .exclude(status="converted") .select_related("created_by") - .prefetch_related("tags", "assigned_to",) + .prefetch_related( + "tags", + "assigned_to", + ) ) # .defer('first_name', 'last_name', 'email', # 'phone', 'address_line', 'street', 'city', 'postcode', 'website', 'description', # 'account_name', 'opportunity_amount', 'enquery_type', 'created_from_site', @@ -275,7 +295,14 @@ def get_context_data(self, **kwargs): context["search"] = search - tag_ids = list(set(self.get_queryset().values_list("tags", flat=True,))) + tag_ids = list( + set( + self.get_queryset().values_list( + "tags", + flat=True, + ) + ) + ) context["tags"] = Tags.objects.filter(id__in=tag_ids) tab_status = "Open" @@ -545,7 +572,10 @@ def update_lead(request, pk): initial.update({"status": status, "lead": lead_record.id}) error = "" form = LeadForm( - instance=lead_record, initial=initial, assigned_to=users, request_obj=request, + instance=lead_record, + initial=initial, + assigned_to=users, + request_obj=request, ) if request.POST: @@ -665,7 +695,7 @@ def update_lead(request, pk): description=request.POST.get("description"), website=request.POST.get("website"), lead=lead_obj, - company=request.company + company=request.company, ) account_object.billing_address_line = lead_obj.address_line account_object.billing_street = lead_obj.street @@ -886,7 +916,10 @@ def form_valid(self, form): protocol=self.request.scheme, ) return JsonResponse( - {"commentid": self.comment_obj.id, "comment": self.comment_obj.comment,} + { + "commentid": self.comment_obj.id, + "comment": self.comment_obj.comment, + } ) def form_invalid(self, form): diff --git a/marketing/forms.py b/marketing/forms.py index cf13483..a6a881c 100644 --- a/marketing/forms.py +++ b/marketing/forms.py @@ -257,7 +257,9 @@ class Meta: def __init__(self, *args, **kwargs): super(ContactListForm, self).__init__(*args, **kwargs) self.fields["contacts_file"].widget.attrs.update( - {"accept": ".csv,.xls,.xlsx,.xlsm,.xlsb,.xml",} + { + "accept": ".csv,.xls,.xlsx,.xlsm,.xlsb,.xml", + } ) if self.instance.id is None: self.fields["contacts_file"].required = True @@ -265,7 +267,9 @@ def __init__(self, *args, **kwargs): self.fields["contacts_file"].required = False if self.data.get("contacts_file"): self.fields["contacts_file"].widget.attrs.update( - {"accept": ".csv,.xls,.xlsx,.xlsm,.xlsb,.xml",} + { + "accept": ".csv,.xls,.xlsx,.xlsm,.xlsb,.xml", + } ) def clean_name(self): diff --git a/marketing/migrations/0008_auto_20190612_1905.py b/marketing/migrations/0008_auto_20190612_1905.py index 1a918eb..1ab2ed7 100644 --- a/marketing/migrations/0008_auto_20190612_1905.py +++ b/marketing/migrations/0008_auto_20190612_1905.py @@ -12,14 +12,20 @@ class Migration(migrations.Migration): operations = [ migrations.AlterModelOptions( - name="campaign", options={"ordering": ("created_on",)}, + name="campaign", + options={"ordering": ("created_on",)}, + ), + migrations.AlterModelOptions( + name="contact", + options={"ordering": ["id"]}, ), - migrations.AlterModelOptions(name="contact", options={"ordering": ["id"]},), migrations.AlterModelOptions( - name="contactlist", options={"ordering": ("id",)}, + name="contactlist", + options={"ordering": ("id",)}, ), migrations.AlterModelOptions( - name="emailtemplate", options={"ordering": ["id"]}, + name="emailtemplate", + options={"ordering": ["id"]}, ), migrations.AddField( model_name="campaign", diff --git a/marketing/migrations/0009_auto_20190618_1144.py b/marketing/migrations/0009_auto_20190618_1144.py index ebb2074..d8cd39e 100644 --- a/marketing/migrations/0009_auto_20190618_1144.py +++ b/marketing/migrations/0009_auto_20190618_1144.py @@ -28,7 +28,8 @@ class Migration(migrations.Migration): ], ), migrations.AlterModelOptions( - name="campaign", options={"ordering": ("-created_on",)}, + name="campaign", + options={"ordering": ("-created_on",)}, ), migrations.AddField( model_name="contactunsubscribedcampaign", diff --git a/marketing/migrations/0010_auto_20190805_1038.py b/marketing/migrations/0010_auto_20190805_1038.py index f98a6d6..e91cf13 100644 --- a/marketing/migrations/0010_auto_20190805_1038.py +++ b/marketing/migrations/0010_auto_20190805_1038.py @@ -14,9 +14,13 @@ class Migration(migrations.Migration): operations = [ migrations.AlterModelOptions( - name="contactlist", options={"ordering": ("-created_on",)}, + name="contactlist", + options={"ordering": ("-created_on",)}, + ), + migrations.AlterModelOptions( + name="link", + options={"ordering": ("id",)}, ), - migrations.AlterModelOptions(name="link", options={"ordering": ("id",)},), migrations.AlterField( model_name="campaignlinkclick", name="campaign", diff --git a/marketing/migrations/0011_auto_20190904_1143.py b/marketing/migrations/0011_auto_20190904_1143.py index d7f7b29..c70a87d 100644 --- a/marketing/migrations/0011_auto_20190904_1143.py +++ b/marketing/migrations/0011_auto_20190904_1143.py @@ -12,7 +12,8 @@ class Migration(migrations.Migration): operations = [ migrations.AlterModelOptions( - name="contactemailcampaign", options={"ordering": ("created_on",)}, + name="contactemailcampaign", + options={"ordering": ("created_on",)}, ), migrations.CreateModel( name="DuplicateContacts", diff --git a/marketing/migrations/0012_auto_20190909_1621.py b/marketing/migrations/0012_auto_20190909_1621.py index 05f0365..447f3d3 100644 --- a/marketing/migrations/0012_auto_20190909_1621.py +++ b/marketing/migrations/0012_auto_20190909_1621.py @@ -11,6 +11,7 @@ class Migration(migrations.Migration): operations = [ migrations.AlterModelOptions( - name="duplicatecontacts", options={"ordering": ("id",)}, + name="duplicatecontacts", + options={"ordering": ("id",)}, ), ] diff --git a/marketing/migrations/0013_blockeddomain_blockedemail.py b/marketing/migrations/0013_blockeddomain_blockedemail.py index 765172c..abdc740 100644 --- a/marketing/migrations/0013_blockeddomain_blockedemail.py +++ b/marketing/migrations/0013_blockeddomain_blockedemail.py @@ -37,7 +37,9 @@ class Migration(migrations.Migration): ), ), ], - options={"ordering": ("created_on",),}, + options={ + "ordering": ("created_on",), + }, ), migrations.CreateModel( name="BlockedDomain", @@ -63,6 +65,8 @@ class Migration(migrations.Migration): ), ), ], - options={"ordering": ("created_on",),}, + options={ + "ordering": ("created_on",), + }, ), ] diff --git a/marketing/migrations/0014_emailtemplate_company.py b/marketing/migrations/0014_emailtemplate_company.py index 7fb4ab0..1353597 100644 --- a/marketing/migrations/0014_emailtemplate_company.py +++ b/marketing/migrations/0014_emailtemplate_company.py @@ -7,14 +7,19 @@ class Migration(migrations.Migration): dependencies = [ - ('common', '0022_auto_20200609_1203'), - ('marketing', '0013_blockeddomain_blockedemail'), + ("common", "0022_auto_20200609_1203"), + ("marketing", "0013_blockeddomain_blockedemail"), ] operations = [ migrations.AddField( - model_name='emailtemplate', - name='company', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='marketing_emailtemplates_company', to='common.company'), + model_name="emailtemplate", + name="company", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="marketing_emailtemplates_company", + to="common.company", + ), ), ] diff --git a/marketing/migrations/0015_auto_20200912_0301.py b/marketing/migrations/0015_auto_20200912_0301.py index 8e54556..f28ed23 100644 --- a/marketing/migrations/0015_auto_20200912_0301.py +++ b/marketing/migrations/0015_auto_20200912_0301.py @@ -7,49 +7,86 @@ class Migration(migrations.Migration): dependencies = [ - ('common', '0022_auto_20200609_1203'), - ('marketing', '0014_emailtemplate_company'), + ("common", "0022_auto_20200609_1203"), + ("marketing", "0014_emailtemplate_company"), ] operations = [ migrations.AddField( - model_name='blockeddomain', - name='company', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='common.company'), + model_name="blockeddomain", + name="company", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="common.company", + ), ), migrations.AddField( - model_name='blockedemail', - name='company', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='common.company'), + model_name="blockedemail", + name="company", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="common.company", + ), ), migrations.AddField( - model_name='campaign', - name='company', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='marketing_campaigns_company', to='common.company'), + model_name="campaign", + name="company", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="marketing_campaigns_company", + to="common.company", + ), ), migrations.AddField( - model_name='contact', - name='company', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='marketing_contacts_company', to='common.company'), + model_name="contact", + name="company", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="marketing_contacts_company", + to="common.company", + ), ), migrations.AddField( - model_name='contactemailcampaign', - name='company', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='marketing_contacts_emails_campaign_company', to='common.company'), + model_name="contactemailcampaign", + name="company", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="marketing_contacts_emails_campaign_company", + to="common.company", + ), ), migrations.AddField( - model_name='contactlist', - name='company', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='marketing_contactlist_company', to='common.company'), + model_name="contactlist", + name="company", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="marketing_contactlist_company", + to="common.company", + ), ), migrations.AddField( - model_name='failedcontact', - name='company', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='marketing_failed_contacts_company', to='common.company'), + model_name="failedcontact", + name="company", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="marketing_failed_contacts_company", + to="common.company", + ), ), migrations.AddField( - model_name='tag', - name='company', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='common.company'), + model_name="tag", + name="company", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="common.company", + ), ), ] diff --git a/marketing/models.py b/marketing/models.py index 0b0845c..2c78daf 100644 --- a/marketing/models.py +++ b/marketing/models.py @@ -20,12 +20,11 @@ class Tag(models.Model): ) created_on = models.DateTimeField(auto_now_add=True) company = models.ForeignKey( - Company, - on_delete=models.CASCADE, - null=True, + Company, + on_delete=models.CASCADE, + null=True, ) - @property def created_by_user(self): return self.created_by if self.created_by else None @@ -44,10 +43,10 @@ class EmailTemplate(models.Model): subject = models.CharField(max_length=5000) html = models.TextField() company = models.ForeignKey( - Company, + Company, related_name="marketing_emailtemplates_company", - on_delete=models.CASCADE, - null=True, + on_delete=models.CASCADE, + null=True, ) class Meta: @@ -75,10 +74,10 @@ class ContactList(models.Model): # is_public = models.BooleanField(default=False) visible_to = models.ManyToManyField(User, related_name="contact_lists_visible_to") company = models.ForeignKey( - Company, + Company, related_name="marketing_contactlist_company", - on_delete=models.CASCADE, - null=True, + on_delete=models.CASCADE, + null=True, ) class Meta: @@ -167,10 +166,10 @@ class Contact(models.Model): state = models.CharField(max_length=500, null=True, blank=True) contry = models.CharField(max_length=500, null=True, blank=True) company = models.ForeignKey( - Company, + Company, related_name="marketing_contacts_company", - on_delete=models.CASCADE, - null=True, + on_delete=models.CASCADE, + null=True, ) def __str__(self): @@ -211,10 +210,10 @@ class FailedContact(models.Model): state = models.CharField(max_length=500, null=True, blank=True) contry = models.CharField(max_length=500, null=True, blank=True) company = models.ForeignKey( - Company, + Company, related_name="marketing_failed_contacts_company", - on_delete=models.CASCADE, - null=True, + on_delete=models.CASCADE, + null=True, ) def __str__(self): @@ -274,10 +273,10 @@ class Campaign(models.Model): max_length=1000, upload_to=get_campaign_attachment_path, blank=True, null=True ) company = models.ForeignKey( - Company, + Company, related_name="marketing_campaigns_company", - on_delete=models.CASCADE, - null=True, + on_delete=models.CASCADE, + null=True, ) class Meta: @@ -443,8 +442,8 @@ class CampaignOpen(models.Model): class CampaignCompleted(models.Model): - """ This Model Is Used To Check If The Scheduled Later Emails Have Been Sent - related name : campaign_is_completed + """This Model Is Used To Check If The Scheduled Later Emails Have Been Sent + related name : campaign_is_completed """ campaign = models.OneToOneField( @@ -454,8 +453,8 @@ class CampaignCompleted(models.Model): class ContactUnsubscribedCampaign(models.Model): - """ This Model Is Used To Check If The Contact has Unsubscribed To a Particular Campaign - related name : contact_is_unsubscribed + """This Model Is Used To Check If The Contact has Unsubscribed To a Particular Campaign + related name : contact_is_unsubscribed """ campaigns = models.ForeignKey( @@ -483,10 +482,10 @@ class ContactEmailCampaign(models.Model): ) created_on = models.DateTimeField(auto_now_add=True) company = models.ForeignKey( - Company, + Company, related_name="marketing_contacts_emails_campaign_company", - on_delete=models.CASCADE, - null=True, + on_delete=models.CASCADE, + null=True, ) def created_on_arrow(self): @@ -517,7 +516,7 @@ class Meta: class BlockedDomain(models.Model): """ - this model is used to block the domain + this model is used to block the domain """ domain = models.CharField(max_length=200) @@ -526,9 +525,9 @@ class BlockedDomain(models.Model): User, on_delete=models.SET_NULL, null=True, blank=True ) company = models.ForeignKey( - Company, - on_delete=models.CASCADE, - null=True, + Company, + on_delete=models.CASCADE, + null=True, ) def __str__(self): @@ -543,7 +542,7 @@ class Meta: class BlockedEmail(models.Model): """ - this model is used to block the email + this model is used to block the email """ email = models.EmailField() @@ -552,12 +551,11 @@ class BlockedEmail(models.Model): User, on_delete=models.SET_NULL, null=True, blank=True ) company = models.ForeignKey( - Company, - on_delete=models.CASCADE, - null=True, + Company, + on_delete=models.CASCADE, + null=True, ) - def __str__(self): return self.email diff --git a/marketing/tasks.py b/marketing/tasks.py index 9e8994a..ac43df4 100644 --- a/marketing/tasks.py +++ b/marketing/tasks.py @@ -92,7 +92,14 @@ def upload_csv_file(data, invalid_data, user, contact_lists): def send_campaign_mail( subject, content, from_email, to_email, bcc, reply_to, attachments ): - msg = EmailMessage(subject, content, from_email, to_email, bcc, reply_to=reply_to,) + msg = EmailMessage( + subject, + content, + from_email, + to_email, + bcc, + reply_to=reply_to, + ) for attachment in attachments: msg.attach(*attachment) msg.content_subtype = "html" @@ -181,8 +188,10 @@ def run_campaign(campaign, domain="demo.django-crm.io", protocol="https"): "campaign_id": campaign.id, }, ) - unsubscribe_from_campaign_html = "

Unsubscribe".format( - domain_url + unsubscribe_from_campaign_url + unsubscribe_from_campaign_html = ( + "

Unsubscribe".format( + domain_url + unsubscribe_from_campaign_url + ) ) names_dict = { "company_name": each_contact.company_name diff --git a/marketing/tests.py b/marketing/tests.py index 29fd21f..d4387ba 100644 --- a/marketing/tests.py +++ b/marketing/tests.py @@ -152,7 +152,8 @@ def setUp(self): self.campaign.tags.add(self.tag_marketing.id) self.link = Link.objects.create( - campaign=self.campaign, original="https://example.com", + campaign=self.campaign, + original="https://example.com", ) self.campaign_link_click = CampaignLinkClick.objects.create( @@ -494,7 +495,9 @@ def test_edit_contact(self): response = self.client.post( reverse("marketing:edit_contact", args=(self.contact.id,)) - + "?from_url={}".format(self.contact_list.id,), + + "?from_url={}".format( + self.contact_list.id, + ), data, ) self.assertEqual(response.status_code, 200) @@ -1513,7 +1516,10 @@ def test_campaign_link_click(self): response = self.client.get( reverse( "marketing:campaign_link_click", - kwargs={"link_id": self.link.id, "email_id": self.contact_1.id,}, + kwargs={ + "link_id": self.link.id, + "email_id": self.contact_1.id, + }, ) ) self.assertEqual(response.status_code, 302) @@ -1521,7 +1527,10 @@ def test_campaign_link_click(self): response = self.client.get( reverse( "marketing:campaign_link_click", - kwargs={"link_id": self.link.id, "email_id": self.contact_1.id,}, + kwargs={ + "link_id": self.link.id, + "email_id": self.contact_1.id, + }, ) ) self.assertEqual(response.status_code, 302) diff --git a/marketing/tests_celery_tasks.py b/marketing/tests_celery_tasks.py index 1b6c7d2..b6a9ea5 100644 --- a/marketing/tests_celery_tasks.py +++ b/marketing/tests_celery_tasks.py @@ -22,13 +22,17 @@ class TestCeleryTasks(TestMarketingModel, TestCase): BROKER_BACKEND="memory", ) def test_celery_tasks(self): - task = run_campaign.apply((self.campaign.id,),) + task = run_campaign.apply( + (self.campaign.id,), + ) self.assertEqual("SUCCESS", task.state) self.campaign.reply_to_email = None self.campaign.save() - task = run_campaign.apply((self.campaign.id,),) + task = run_campaign.apply( + (self.campaign.id,), + ) self.assertEqual("SUCCESS", task.state) self.campaign.schedule_date_time = datetime.now() @@ -43,10 +47,14 @@ def test_celery_tasks(self): task = send_scheduled_campaigns.apply() self.assertEqual("SUCCESS", task.state) - task = delete_multiple_contacts_tasks.apply((self.contact_list.id,),) + task = delete_multiple_contacts_tasks.apply( + (self.contact_list.id,), + ) self.assertEqual("SUCCESS", task.state) - task = send_campaign_email_to_admin_contact.apply((self.campaign.id,),) + task = send_campaign_email_to_admin_contact.apply( + (self.campaign.id,), + ) self.assertEqual("SUCCESS", task.state) valid_rows = [ @@ -103,6 +111,13 @@ def test_celery_tasks(self): }, ] task = upload_csv_file.apply( - (valid_rows, invalid_rows, self.user.id, [self.contact_list.id,],), + ( + valid_rows, + invalid_rows, + self.user.id, + [ + self.contact_list.id, + ], + ), ) self.assertEqual("SUCCESS", task.state) diff --git a/marketing/views.py b/marketing/views.py index 3094feb..7b50f91 100644 --- a/marketing/views.py +++ b/marketing/views.py @@ -125,7 +125,9 @@ def dashboard(request): def contact_lists(request): tags = Tag.objects.all() if request.user.role == "ADMIN": - queryset = ContactList.objects.filter(company=request.company).order_by("-created_on") + queryset = ContactList.objects.filter(company=request.company).order_by( + "-created_on" + ) else: queryset = ContactList.objects.filter( Q(created_by=request.user) | Q(visible_to=request.user) @@ -405,7 +407,12 @@ def edit_contact(request, pk): {"error": False, "success_url": reverse("marketing:contacts_list")} ) else: - return JsonResponse({"error": True, "errors": form.errors,}) + return JsonResponse( + { + "error": True, + "errors": form.errors, + } + ) @login_required(login_url="/login") @@ -563,7 +570,9 @@ def failed_contact_list_download_delete(request, pk): def email_template_list(request): # users = User.objects.all() if request.user.role == "ADMIN" or request.user.is_superuser: - queryset = EmailTemplate.objects.filter(company=request.company).order_by("-created_on") + queryset = EmailTemplate.objects.filter(company=request.company).order_by( + "-created_on" + ) else: queryset = EmailTemplate.objects.filter(created_by=request.user).order_by( "-created_on" @@ -1606,7 +1615,9 @@ def contacts_list_elastic_search(request): # contacts = SearchQuerySet().filter(is_bounced='false').models(Contact) # bounced_contacts = SearchQuerySet().filter(is_bounced='true').models(Contact) # failed_contacts = SearchQuerySet().models(FailedContact).filter() - bounced_contacts = Contact.objects.filter(is_bounced=True, company=request.company) + bounced_contacts = Contact.objects.filter( + is_bounced=True, company=request.company + ) failed_contacts = FailedContact.objects.filter(company=request.company) contact_lists = ContactList.objects.filter(company=request.company) else: diff --git a/opportunity/migrations/0001_initial.py b/opportunity/migrations/0001_initial.py index ee556c5..4cc6bf9 100644 --- a/opportunity/migrations/0001_initial.py +++ b/opportunity/migrations/0001_initial.py @@ -289,6 +289,8 @@ class Migration(migrations.Migration): ), ("teams", models.ManyToManyField(to="common.Team")), ], - options={"ordering": ["-created_on"],}, + options={ + "ordering": ["-created_on"], + }, ), ] diff --git a/opportunity/migrations/0003_auto_20190212_1334.py b/opportunity/migrations/0003_auto_20190212_1334.py index 30496c2..133764a 100644 --- a/opportunity/migrations/0003_auto_20190212_1334.py +++ b/opportunity/migrations/0003_auto_20190212_1334.py @@ -12,7 +12,10 @@ class Migration(migrations.Migration): ] operations = [ - migrations.RemoveField(model_name="opportunity", name="teams",), + migrations.RemoveField( + model_name="opportunity", + name="teams", + ), migrations.AlterField( model_name="opportunity", name="closed_by", diff --git a/opportunity/serializer.py b/opportunity/serializer.py index 318936f..2fae0b3 100644 --- a/opportunity/serializer.py +++ b/opportunity/serializer.py @@ -13,7 +13,7 @@ class Meta: model = Opportunity # fields = ‘__all__’ fields = ( - 'id', + "id", "name", "account", "stage", diff --git a/opportunity/tests.py b/opportunity/tests.py index 010ad42..60eebf3 100644 --- a/opportunity/tests.py +++ b/opportunity/tests.py @@ -650,7 +650,9 @@ def test_attachment_add(self): response = self.client.post( reverse("opportunity:list") + "?tag={}".format(self.tag_1.id), - {"tag": self.tag_1.id,}, + { + "tag": self.tag_1.id, + }, ) self.assertEqual(200, response.status_code) @@ -722,7 +724,9 @@ def test_attachment_add(self): self.client.login(email="janeOpp@example.com", password="password") response = self.client.get( reverse("opportunity:opp_remove", args=(self.opportunity_1.id,)), - {"pk": self.opportunity_1.id,}, + { + "pk": self.opportunity_1.id, + }, HTTP_X_REQUESTED_WITH="XMLHttpRequest", ) diff --git a/opportunity/tests_celery_tasks.py b/opportunity/tests_celery_tasks.py index a28ed40..c01c6d0 100644 --- a/opportunity/tests_celery_tasks.py +++ b/opportunity/tests_celery_tasks.py @@ -13,6 +13,12 @@ class TestCeleryTasks(OpportunityModel, TestCase): ) def test_celery_tasks(self): task = send_email_to_assigned_user.apply( - ([self.user.id, self.user1.id,], self.opportunity.id,), + ( + [ + self.user.id, + self.user1.id, + ], + self.opportunity.id, + ), ) self.assertEqual("SUCCESS", task.state) diff --git a/opportunity/views.py b/opportunity/views.py index 40153e6..b1a77cc 100644 --- a/opportunity/views.py +++ b/opportunity/views.py @@ -606,7 +606,10 @@ def form_valid(self, form): protocol=self.request.scheme, ) return JsonResponse( - {"commentid": self.comment_obj.id, "comment": self.comment_obj.comment,} + { + "commentid": self.comment_obj.id, + "comment": self.comment_obj.comment, + } ) def form_invalid(self, form): diff --git a/planner/migrations/0002_auto_20190212_1334.py b/planner/migrations/0002_auto_20190212_1334.py index 75b268e..3344425 100644 --- a/planner/migrations/0002_auto_20190212_1334.py +++ b/planner/migrations/0002_auto_20190212_1334.py @@ -12,7 +12,10 @@ class Migration(migrations.Migration): ] operations = [ - migrations.RemoveField(model_name="event", name="teams",), + migrations.RemoveField( + model_name="event", + name="teams", + ), migrations.AlterField( model_name="event", name="created_by", diff --git a/requirements.txt b/requirements.txt index 544afa1..365c6df 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,74 +1,58 @@ -amqp==2.6.0 +appdirs==1.4.3 arrow==0.14.5 -atomicwrites==1.3.0 -attrs==19.3.0 -Babel==2.8.0 -billiard==3.6.3.0 boto==2.49.0 -boto3==1.13.20 -botocore==1.16.20 +CacheControl==0.12.6 celery==4.3.0 -certifi==2020.4.5.1 chardet==3.0.4 codacy-coverage==1.3.11 +colorama==0.4.3 +contextlib2==0.6.0 coverage==5.1 cssselect==1.1.0 -Django==3.1.0 -django-appconf==1.0.4 -django-compressor==2.4 +distlib==0.3.0 +distro==1.4.0 +django==3.1 +django-cors-headers==3.4.0 django-haystack==2.8.1 django-libsass==0.8 django-phonenumber-field==4.0.0 +django-ses==1.0.2 django-settings-export==1.2.1 django-simple-pagination==1.3 django-storages==1.9.1 -django-ses==1.0.2 -docutils==0.15.2 -elasticsearch==7.7.1 +djangorestframework-jwt==1.11.0 +drf-yasg==1.17.1 elastic-apm==5.8.1 -et-xmlfile==1.0.1 +elasticsearch==7.7.1 +html5lib==1.0.1 idna==2.9 importlib-metadata==1.6.0 -jdcal==1.4.1 -jmespath==0.10.0 -kombu==4.6.9 -libsass==0.20.0 +ipaddr==2.2.0 +lockfile==0.12.2 lxml==4.4.1 -more-itertools==8.2.0 +msgpack==0.6.2 openpyxl==2.6.3 -packaging==20.3 pdfkit==0.6.1 +pep517==0.8.2 phonenumbers==8.10.4 Pillow==7.1.2 -pluggy==0.13.1 +pkg-resources==0.0.0 +progress==1.5 psycopg2-binary==2.8.3 -py==1.8.1 pyparsing==2.4.7 -pytest==5.1.1 pytest-django==3.5.1 -python-dateutil==2.8.1 python-dotenv==0.13.0 python-memcached==1.59 -pytz==2020.1 +pytoml==0.1.21 raven==6.10.0 -rcssmin==1.0.6 redis==3.3.8 -requests==2.22.0 -rjsmin==1.1.0 -s3transfer==0.3.3 -six==1.14.0 +retrying==1.3.3 +sentry-sdk==0.14.4 +setuptools==44.0.0 sorl-thumbnail==12.6.3 -sqlparse==0.3.1 -urllib3==1.25.9 uWSGI==2.0.18 -vine==1.3.0 -wcwidth==0.1.9 +webencodings==0.5.1 +wheel==0.34.2 whitenoise==5.1.0 xlrd==1.2.0 xlwt==1.3.0 -zipp==3.1.0 -drf-yasg==1.17.1 -djangorestframework==3.11.0 -django-cors-headers==3.4.0 -djangorestframework-jwt==1.11.0 -sentry-sdk==0.14.4 diff --git a/tasks/migrations/0001_initial.py b/tasks/migrations/0001_initial.py index fa040d1..9302e0e 100644 --- a/tasks/migrations/0001_initial.py +++ b/tasks/migrations/0001_initial.py @@ -77,6 +77,8 @@ class Migration(migrations.Migration): ), ), ], - options={"ordering": ["-due_date"],}, + options={ + "ordering": ["-due_date"], + }, ), ] diff --git a/tasks/serializer.py b/tasks/serializer.py index df0bf69..c1cc659 100644 --- a/tasks/serializer.py +++ b/tasks/serializer.py @@ -2,9 +2,7 @@ from tasks.models import Task - class TaskSerializer(serializers.ModelSerializer): - class Meta: model = Task - fields = "__all__" \ No newline at end of file + fields = "__all__" diff --git a/tasks/tests_celery_tasks.py b/tasks/tests_celery_tasks.py index 4b0a4c0..4529b98 100644 --- a/tasks/tests_celery_tasks.py +++ b/tasks/tests_celery_tasks.py @@ -12,5 +12,13 @@ class TestEventCeleryTasks(TaskCreateTest, TestCase): BROKER_BACKEND="memory", ) def test_event_celery_tasks(self): - task = send_email.apply((self.task.id, [self.user.id, self.user1.id,])) + task = send_email.apply( + ( + self.task.id, + [ + self.user.id, + self.user1.id, + ], + ) + ) self.assertEqual("SUCCESS", task.state) diff --git a/tasks/views.py b/tasks/views.py index 2397bde..e7b39a3 100644 --- a/tasks/views.py +++ b/tasks/views.py @@ -426,7 +426,10 @@ def form_valid(self, form): protocol=self.request.scheme, ) return JsonResponse( - {"comment_id": self.comment_obj.id, "comment": self.comment_obj.comment,} + { + "comment_id": self.comment_obj.id, + "comment": self.comment_obj.comment, + } ) def form_invalid(self, form): diff --git a/teams/migrations/0003_auto_20190909_1621.py b/teams/migrations/0003_auto_20190909_1621.py index 20668cc..39f07e4 100644 --- a/teams/migrations/0003_auto_20190909_1621.py +++ b/teams/migrations/0003_auto_20190909_1621.py @@ -10,5 +10,8 @@ class Migration(migrations.Migration): ] operations = [ - migrations.AlterModelOptions(name="teams", options={"ordering": ("id",)},), + migrations.AlterModelOptions( + name="teams", + options={"ordering": ("id",)}, + ), ] diff --git a/teams/serializer.py b/teams/serializer.py index 568d0c3..bbcb038 100644 --- a/teams/serializer.py +++ b/teams/serializer.py @@ -18,5 +18,5 @@ class Meta: "created_on", "created_by", "company", - "created_on_arrow" + "created_on_arrow", )