diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index d799dc254b..04cb82a8da 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,2 +1,2 @@ -* @coronasafe/care-developers -*.yml @tomahawk-pilot @mathew-alex +* @ohcnetwork/care-developers +*.yml @tomahawk-pilot diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 0d6891c378..4fabb5306f 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -19,4 +19,4 @@ _*Only PR's with test cases included and passing lint and test pipelines will be reviewed*_ -@coronasafe/care-backend-maintainers @coronasafe/care-backend-admins +@ohcnetwork/care-backend-maintainers @ohcnetwork/care-backend-admins diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 6299ccbeb6..11ed3918b4 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -15,7 +15,7 @@ on: jobs: build-docs: - if: github.repository == 'coronasafe/care' + if: github.repository == 'ohcnetwork/care' name: Build docs runs-on: ubuntu-latest steps: @@ -44,7 +44,7 @@ jobs: retention-days: 30 deploy-docs: - if: github.repository == 'coronasafe/care' && github.ref == 'refs/heads/develop' + if: github.repository == 'ohcnetwork/care' && github.ref == 'refs/heads/develop' name: Deploy docs runs-on: ubuntu-latest needs: build-docs diff --git a/.github/workflows/issue-automation.yml b/.github/workflows/issue-automation.yml index b3fa119796..5b6ba19d4d 100644 --- a/.github/workflows/issue-automation.yml +++ b/.github/workflows/issue-automation.yml @@ -9,26 +9,26 @@ jobs: issue_opened_and_reopened: name: issue_opened_and_reopened runs-on: ubuntu-latest - if: github.repository == 'coronasafe/care' && github.event_name == 'issues' && github.event.action == 'opened' || github.event.action == 'reopened' + if: github.repository == 'ohcnetwork/care' && github.event_name == 'issues' && github.event.action == 'opened' || github.event.action == 'reopened' steps: - name: 'Move issue to "Triage"' uses: leonsteinhaeuser/project-beta-automations@v1.0.1 with: gh_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} - organization: coronasafe + organization: ohcnetwork project_id: 4 resource_node_id: ${{ github.event.issue.node_id }} status_value: "Triage" issue_closed: name: issue_closed runs-on: ubuntu-latest - if: github.repository == 'coronasafe/care' && github.event_name == 'issues' && github.event.action == 'closed' + if: github.repository == 'ohcnetwork/care' && github.event_name == 'issues' && github.event.action == 'closed' steps: - name: 'Moved issue to "Done"' uses: leonsteinhaeuser/project-beta-automations@v1.0.1 with: gh_token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} - organization: coronasafe + organization: ohcnetwork project_id: 4 resource_node_id: ${{ github.event.issue.node_id }} status_value: "Done" diff --git a/.gitignore b/.gitignore index b4a2f6477d..b6fcb392f8 100644 --- a/.gitignore +++ b/.gitignore @@ -347,16 +347,8 @@ test_db celerybeat-schedule secrets.sh -/.idea/inspectionProfiles/profiles_settings.xml -/.idea/.gitignore -/.idea/aws.xml -/.idea/backend.iml -/.idea/git_toolbox_prj.xml -/.idea/misc.xml -/.idea/modules.xml -/.idea/vcs.xml -/.idea/ruff.xml +/.idea/* # Redis *.rdb diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cd950287fc..e32e20002a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,7 +5,7 @@ Any support is welcome. You could help by writing documentation, pull-requests, ### Getting Started -An issue wih the [good first](https://github.com/coronasafe/care/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22) or [help wanted](https://github.com/coronasafe/care/issues?q=is%3Aissue+sort%3Aupdated-desc+label%3A%22help+wanted%22+is%3Aopen) label might be a good place to start with. +An issue wih the [good first](https://github.com/ohcnetwork/care/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22good+first+issue%22) or [help wanted](https://github.com/ohcnetwork/care/issues?q=is%3Aissue+sort%3Aupdated-desc+label%3A%22help+wanted%22+is%3Aopen) label might be a good place to start with. ### Setting up the development environment diff --git a/Makefile b/Makefile index 37bae1c950..549d86d8b7 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: build, re-build, up, down, list, logs, test, makemigrations +.PHONY: build, re-build, up, down, list, logs, test, makemigrations, reset_db DOCKER_VERSION := $(shell docker --version 2>/dev/null) @@ -47,3 +47,10 @@ test-coverage: docker compose exec backend bash -c "coverage run manage.py test --settings=config.settings.test --keepdb --parallel --shuffle" docker compose exec backend bash -c "coverage combine || true; coverage xml" docker compose cp backend:/app/coverage.xml coverage.xml + +reset_db: + docker compose exec backend bash -c "python manage.py reset_db --noinput" + docker compose exec backend bash -c "python manage.py migrate" + +%: + docker compose exec backend bash -c "python manage.py $*" diff --git a/Pipfile b/Pipfile index 76b1ed4222..6beddc1590 100644 --- a/Pipfile +++ b/Pipfile @@ -5,14 +5,13 @@ name = "pypi" [packages] argon2-cffi = "==23.1.0" -authlib = "==1.3.0" -boto3 = "==1.34.117" +authlib = "==1.3.1" +boto3 = "==1.35.0" celery = "==5.4.0" -django = "==4.2.10" +django = "==4.2.15" django-environ = "==0.11.2" django-cors-headers = "==4.3.1" django-filter = "==24.2" -django-hardcopy = "==0.1.4" django-maintenance-mode = "==0.21.1" django-model-utils = "==4.5.1" django-multiselectfield = "==0.1.12" @@ -22,7 +21,7 @@ django-redis = "==5.4.0" django-rest-passwordreset = "==1.4.1" django-simple-history = "==3.7.0" djangoql = "==0.18.1" -djangorestframework = "==3.15.1" +djangorestframework = "==3.15.2" djangorestframework-simplejwt = "==5.3.1" dry-rest-permissions = "==0.1.10" drf-nested-routers = "==0.94.1" @@ -32,23 +31,23 @@ gunicorn = "==22.0.0" healthy-django = "==0.1.0" jsonschema = "==4.22.0" jwcrypto = "==1.5.6" -newrelic = "==9.10.0" +newrelic = "==9.13.0" pillow = "==10.3.0" psycopg = { extras = ["c"], version = "==3.1.19" } pycryptodome = "==3.20.0" pydantic = "==1.10.15" # fix for fhir.resources < 7.0.2 pyjwt = "==2.8.0" python-slugify = "==8.0.4" -pywebpush = "==1.14.0" +pywebpush = "==2.0.0" redis = { extras = ["hiredis"], version = "==5.0.5" } # constraint for redis-om redis-om = "==0.3.1" requests = "==2.32.3" -sentry-sdk = "==2.5.1" +sentry-sdk = "==2.13.0" whitenoise = "==6.6.0" [dev-packages] black = "==24.4.2" -boto3-stubs = { extras = ["s3", "boto3"], version = "==1.34.117" } +boto3-stubs = { extras = ["s3", "boto3"], version = "==1.35.0" } coverage = "==7.5.3" debugpy = "==1.8.1" django-coverage-plugin = "==3.1.0" @@ -58,7 +57,7 @@ django-silk = "==5.1.0" django-stubs = "==5.0.2" djangorestframework-stubs = "==3.15.0" factory-boy = "==3.3.0" -flake8 = "==7.0.0" +flake8 = "==7.1.1" freezegun = "==1.5.1" ipython = "==8.25.0" isort = "==5.13.2" diff --git a/Pipfile.lock b/Pipfile.lock index 297ac479b9..6cfb4f13d5 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "7d926299b4a6a70b52ff723433da0406c26cf2a6faeee3ec7432368be663f120" + "sha256": "0f478643ec74971469522c09c3e635a7ca9346c16a687ae7c14c7f638335cb1e" }, "pipfile-spec": 6, "requires": { @@ -16,6 +16,119 @@ ] }, "default": { + "aiohappyeyeballs": { + "hashes": [ + "sha256:55a1714f084e63d49639800f95716da97a1f173d46a16dfcfda0016abb93b6b2", + "sha256:7ce92076e249169a13c2f49320d1967425eaf1f407522d707d59cac7628d62bd" + ], + "markers": "python_version >= '3.8'", + "version": "==2.4.0" + }, + "aiohttp": { + "hashes": [ + "sha256:02594361128f780eecc2a29939d9dfc870e17b45178a867bf61a11b2a4367277", + "sha256:03f2645adbe17f274444953bdea69f8327e9d278d961d85657cb0d06864814c1", + "sha256:074d1bff0163e107e97bd48cad9f928fa5a3eb4b9d33366137ffce08a63e37fe", + "sha256:0912b8a8fadeb32ff67a3ed44249448c20148397c1ed905d5dac185b4ca547bb", + "sha256:0d277cfb304118079e7044aad0b76685d30ecb86f83a0711fc5fb257ffe832ca", + "sha256:0d93400c18596b7dc4794d48a63fb361b01a0d8eb39f28800dc900c8fbdaca91", + "sha256:123dd5b16b75b2962d0fff566effb7a065e33cd4538c1692fb31c3bda2bfb972", + "sha256:17e997105bd1a260850272bfb50e2a328e029c941c2708170d9d978d5a30ad9a", + "sha256:18a01eba2574fb9edd5f6e5fb25f66e6ce061da5dab5db75e13fe1558142e0a3", + "sha256:1923a5c44061bffd5eebeef58cecf68096e35003907d8201a4d0d6f6e387ccaa", + "sha256:1942244f00baaacaa8155eca94dbd9e8cc7017deb69b75ef67c78e89fdad3c77", + "sha256:1b2c16a919d936ca87a3c5f0e43af12a89a3ce7ccbce59a2d6784caba945b68b", + "sha256:1c19de68896747a2aa6257ae4cf6ef59d73917a36a35ee9d0a6f48cff0f94db8", + "sha256:1e72589da4c90337837fdfe2026ae1952c0f4a6e793adbbfbdd40efed7c63599", + "sha256:22c0a23a3b3138a6bf76fc553789cb1a703836da86b0f306b6f0dc1617398abc", + "sha256:2c634a3207a5445be65536d38c13791904fda0748b9eabf908d3fe86a52941cf", + "sha256:2d21ac12dc943c68135ff858c3a989f2194a709e6e10b4c8977d7fcd67dfd511", + "sha256:2f1f1c75c395991ce9c94d3e4aa96e5c59c8356a15b1c9231e783865e2772699", + "sha256:305be5ff2081fa1d283a76113b8df7a14c10d75602a38d9f012935df20731487", + "sha256:33e6bc4bab477c772a541f76cd91e11ccb6d2efa2b8d7d7883591dfb523e5987", + "sha256:349ef8a73a7c5665cca65c88ab24abe75447e28aa3bc4c93ea5093474dfdf0ff", + "sha256:380f926b51b92d02a34119d072f178d80bbda334d1a7e10fa22d467a66e494db", + "sha256:38172a70005252b6893088c0f5e8a47d173df7cc2b2bd88650957eb84fcf5022", + "sha256:391cc3a9c1527e424c6865e087897e766a917f15dddb360174a70467572ac6ce", + "sha256:3a1c32a19ee6bbde02f1cb189e13a71b321256cc1d431196a9f824050b160d5a", + "sha256:4120d7fefa1e2d8fb6f650b11489710091788de554e2b6f8347c7a20ceb003f5", + "sha256:424ae21498790e12eb759040bbb504e5e280cab64693d14775c54269fd1d2bb7", + "sha256:44b324a6b8376a23e6ba25d368726ee3bc281e6ab306db80b5819999c737d820", + "sha256:4790f0e15f00058f7599dab2b206d3049d7ac464dc2e5eae0e93fa18aee9e7bf", + "sha256:4aff049b5e629ef9b3e9e617fa6e2dfeda1bf87e01bcfecaf3949af9e210105e", + "sha256:4b38b1570242fbab8d86a84128fb5b5234a2f70c2e32f3070143a6d94bc854cf", + "sha256:4d46c7b4173415d8e583045fbc4daa48b40e31b19ce595b8d92cf639396c15d5", + "sha256:4f1c9866ccf48a6df2b06823e6ae80573529f2af3a0992ec4fe75b1a510df8a6", + "sha256:4f7acae3cf1a2a2361ec4c8e787eaaa86a94171d2417aae53c0cca6ca3118ff6", + "sha256:54d9ddea424cd19d3ff6128601a4a4d23d54a421f9b4c0fff740505813739a91", + "sha256:58718e181c56a3c02d25b09d4115eb02aafe1a732ce5714ab70326d9776457c3", + "sha256:5ede29d91a40ba22ac1b922ef510aab871652f6c88ef60b9dcdf773c6d32ad7a", + "sha256:61645818edd40cc6f455b851277a21bf420ce347baa0b86eaa41d51ef58ba23d", + "sha256:66bf9234e08fe561dccd62083bf67400bdbf1c67ba9efdc3dac03650e97c6088", + "sha256:673f988370f5954df96cc31fd99c7312a3af0a97f09e407399f61583f30da9bc", + "sha256:676f94c5480d8eefd97c0c7e3953315e4d8c2b71f3b49539beb2aa676c58272f", + "sha256:6c225286f2b13bab5987425558baa5cbdb2bc925b2998038fa028245ef421e75", + "sha256:7384d0b87d4635ec38db9263e6a3f1eb609e2e06087f0aa7f63b76833737b471", + "sha256:7e2fe37ac654032db1f3499fe56e77190282534810e2a8e833141a021faaab0e", + "sha256:7f2bfc0032a00405d4af2ba27f3c429e851d04fad1e5ceee4080a1c570476697", + "sha256:7f6b639c36734eaa80a6c152a238242bedcee9b953f23bb887e9102976343092", + "sha256:814375093edae5f1cb31e3407997cf3eacefb9010f96df10d64829362ae2df69", + "sha256:8224f98be68a84b19f48e0bdc14224b5a71339aff3a27df69989fa47d01296f3", + "sha256:898715cf566ec2869d5cb4d5fb4be408964704c46c96b4be267442d265390f32", + "sha256:8989f46f3d7ef79585e98fa991e6ded55d2f48ae56d2c9fa5e491a6e4effb589", + "sha256:8ba01ebc6175e1e6b7275c907a3a36be48a2d487549b656aa90c8a910d9f3178", + "sha256:8c5c6fa16412b35999320f5c9690c0f554392dc222c04e559217e0f9ae244b92", + "sha256:8c6a4e5e40156d72a40241a25cc226051c0a8d816610097a8e8f517aeacd59a2", + "sha256:8eaf44ccbc4e35762683078b72bf293f476561d8b68ec8a64f98cf32811c323e", + "sha256:8fb4fc029e135859f533025bc82047334e24b0d489e75513144f25408ecaf058", + "sha256:9093a81e18c45227eebe4c16124ebf3e0d893830c6aca7cc310bfca8fe59d857", + "sha256:94c4381ffba9cc508b37d2e536b418d5ea9cfdc2848b9a7fea6aebad4ec6aac1", + "sha256:94fac7c6e77ccb1ca91e9eb4cb0ac0270b9fb9b289738654120ba8cebb1189c6", + "sha256:95c4dc6f61d610bc0ee1edc6f29d993f10febfe5b76bb470b486d90bbece6b22", + "sha256:975218eee0e6d24eb336d0328c768ebc5d617609affaca5dbbd6dd1984f16ed0", + "sha256:ad146dae5977c4dd435eb31373b3fe9b0b1bf26858c6fc452bf6af394067e10b", + "sha256:afe16a84498441d05e9189a15900640a2d2b5e76cf4efe8cbb088ab4f112ee57", + "sha256:b1c43eb1ab7cbf411b8e387dc169acb31f0ca0d8c09ba63f9eac67829585b44f", + "sha256:b90078989ef3fc45cf9221d3859acd1108af7560c52397ff4ace8ad7052a132e", + "sha256:b98e698dc34966e5976e10bbca6d26d6724e6bdea853c7c10162a3235aba6e16", + "sha256:ba5a8b74c2a8af7d862399cdedce1533642fa727def0b8c3e3e02fcb52dca1b1", + "sha256:c31ad0c0c507894e3eaa843415841995bf8de4d6b2d24c6e33099f4bc9fc0d4f", + "sha256:c3b9162bab7e42f21243effc822652dc5bb5e8ff42a4eb62fe7782bcbcdfacf6", + "sha256:c58c6837a2c2a7cf3133983e64173aec11f9c2cd8e87ec2fdc16ce727bcf1a04", + "sha256:c83f7a107abb89a227d6c454c613e7606c12a42b9a4ca9c5d7dad25d47c776ae", + "sha256:cde98f323d6bf161041e7627a5fd763f9fd829bcfcd089804a5fdce7bb6e1b7d", + "sha256:ce91db90dbf37bb6fa0997f26574107e1b9d5ff939315247b7e615baa8ec313b", + "sha256:d00f3c5e0d764a5c9aa5a62d99728c56d455310bcc288a79cab10157b3af426f", + "sha256:d17920f18e6ee090bdd3d0bfffd769d9f2cb4c8ffde3eb203777a3895c128862", + "sha256:d55f011da0a843c3d3df2c2cf4e537b8070a419f891c930245f05d329c4b0689", + "sha256:d742c36ed44f2798c8d3f4bc511f479b9ceef2b93f348671184139e7d708042c", + "sha256:d9a487ef090aea982d748b1b0d74fe7c3950b109df967630a20584f9a99c0683", + "sha256:d9ef084e3dc690ad50137cc05831c52b6ca428096e6deb3c43e95827f531d5ef", + "sha256:da452c2c322e9ce0cfef392e469a26d63d42860f829026a63374fde6b5c5876f", + "sha256:dc4826823121783dccc0871e3f405417ac116055bf184ac04c36f98b75aacd12", + "sha256:de7a5299827253023c55ea549444e058c0eb496931fa05d693b95140a947cb73", + "sha256:e04a1f2a65ad2f93aa20f9ff9f1b672bf912413e5547f60749fa2ef8a644e061", + "sha256:e1ca1ef5ba129718a8fc827b0867f6aa4e893c56eb00003b7367f8a733a9b072", + "sha256:ee40b40aa753d844162dcc80d0fe256b87cba48ca0054f64e68000453caead11", + "sha256:f071854b47d39591ce9a17981c46790acb30518e2f83dfca8db2dfa091178691", + "sha256:f29930bc2921cef955ba39a3ff87d2c4398a0394ae217f41cb02d5c26c8b1b77", + "sha256:f489a2c9e6455d87eabf907ac0b7d230a9786be43fbe884ad184ddf9e9c1e385", + "sha256:f5bf3ead3cb66ab990ee2561373b009db5bc0e857549b6c9ba84b20bc462e172", + "sha256:f6f18898ace4bcd2d41a122916475344a87f1dfdec626ecde9ee802a711bc569", + "sha256:f8112fb501b1e0567a1251a2fd0747baae60a4ab325a871e975b7bb67e59221f", + "sha256:fd31f176429cecbc1ba499d4aba31aaccfea488f418d60376b911269d3b883c5" + ], + "markers": "python_version >= '3.8'", + "version": "==3.10.5" + }, + "aiosignal": { + "hashes": [ + "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc", + "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.1" + }, "amqp": { "hashes": [ "sha256:827cb12fb0baa892aad844fd95258143bce4027fdac4fccddbc43330fd281637", @@ -70,20 +183,20 @@ }, "attrs": { "hashes": [ - "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30", - "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1" + "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346", + "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2" ], "markers": "python_version >= '3.7'", - "version": "==23.2.0" + "version": "==24.2.0" }, "authlib": { "hashes": [ - "sha256:959ea62a5b7b5123c5059758296122b57cd2585ae2ed1c0622c21b371ffdae06", - "sha256:9637e4de1fb498310a56900b3e2043a206b03cb11c05422014b0302cbc814be3" + "sha256:7ae843f03c06c5c0debd63c9db91f9fda64fa62a42a77419fa15fbb7e7a58917", + "sha256:d35800b973099bbadc49b42b256ecb80041ad56b7fe1216a362c7943c088f377" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==1.3.0" + "version": "==1.3.1" }, "billiard": { "hashes": [ @@ -95,20 +208,20 @@ }, "boto3": { "hashes": [ - "sha256:1506589e30566bbb2f4997b60968ff7d4ef8a998836c31eedd36437ac3b7408a", - "sha256:c8a383b904d6faaf7eed0c06e31b423db128e4c09ce7bd2afc39d1cd07030a51" + "sha256:ada32dab854c46a877cf967b8a55ab1a7d356c3c87f1c8bd556d446ff03dfd95", + "sha256:bdc242e3ea81decc6ea551b04b2c122f088c29269d8e093b55862946aa0fcfc6" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==1.34.117" + "version": "==1.35.0" }, "botocore": { "hashes": [ - "sha256:26a431997f882bcdd1e835f44c24b2a1752b1c4e5183c2ce62999ce95d518d6c", - "sha256:4637ca42e6c51aebc4d9a2d92f97bf4bdb042e3f7985ff31a659a11e4c170e73" + "sha256:10195e5ca764745f02b9a51df048b996ddbdc1899a44a2caf35dfb225dfea489", + "sha256:4cc51a6a486915aedc140f9d027b7e156646b7a0f7b33b1000762c81aff9a12f" ], "markers": "python_version >= '3.8'", - "version": "==1.34.117" + "version": "==1.35.4" }, "celery": { "hashes": [ @@ -121,69 +234,84 @@ }, "certifi": { "hashes": [ - "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516", - "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56" + "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b", + "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90" ], "markers": "python_version >= '3.6'", - "version": "==2024.6.2" + "version": "==2024.7.4" }, "cffi": { "hashes": [ - "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc", - "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a", - "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417", - "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab", - "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520", - "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36", - "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743", - "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8", - "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed", - "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684", - "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56", - "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324", - "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d", - "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235", - "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e", - "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088", - "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000", - "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7", - "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e", - "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673", - "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c", - "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe", - "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2", - "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098", - "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8", - "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a", - "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0", - "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b", - "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896", - "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e", - "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9", - "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2", - "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b", - "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6", - "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404", - "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f", - "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0", - "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4", - "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc", - "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936", - "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba", - "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872", - "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb", - "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614", - "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1", - "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d", - "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969", - "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b", - "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4", - "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627", - "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956", - "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357" + "sha256:011aff3524d578a9412c8b3cfaa50f2c0bd78e03eb7af7aa5e0df59b158efb2f", + "sha256:0a048d4f6630113e54bb4b77e315e1ba32a5a31512c31a273807d0027a7e69ab", + "sha256:0bb15e7acf8ab35ca8b24b90af52c8b391690ef5c4aec3d31f38f0d37d2cc499", + "sha256:0d46ee4764b88b91f16661a8befc6bfb24806d885e27436fdc292ed7e6f6d058", + "sha256:0e60821d312f99d3e1569202518dddf10ae547e799d75aef3bca3a2d9e8ee693", + "sha256:0fdacad9e0d9fc23e519efd5ea24a70348305e8d7d85ecbb1a5fa66dc834e7fb", + "sha256:14b9cbc8f7ac98a739558eb86fabc283d4d564dafed50216e7f7ee62d0d25377", + "sha256:17c6d6d3260c7f2d94f657e6872591fe8733872a86ed1345bda872cfc8c74885", + "sha256:1a2ddbac59dc3716bc79f27906c010406155031a1c801410f1bafff17ea304d2", + "sha256:2404f3de742f47cb62d023f0ba7c5a916c9c653d5b368cc966382ae4e57da401", + "sha256:24658baf6224d8f280e827f0a50c46ad819ec8ba380a42448e24459daf809cf4", + "sha256:24aa705a5f5bd3a8bcfa4d123f03413de5d86e497435693b638cbffb7d5d8a1b", + "sha256:2770bb0d5e3cc0e31e7318db06efcbcdb7b31bcb1a70086d3177692a02256f59", + "sha256:331ad15c39c9fe9186ceaf87203a9ecf5ae0ba2538c9e898e3a6967e8ad3db6f", + "sha256:3aa9d43b02a0c681f0bfbc12d476d47b2b2b6a3f9287f11ee42989a268a1833c", + "sha256:41f4915e09218744d8bae14759f983e466ab69b178de38066f7579892ff2a555", + "sha256:4304d4416ff032ed50ad6bb87416d802e67139e31c0bde4628f36a47a3164bfa", + "sha256:435a22d00ec7d7ea533db494da8581b05977f9c37338c80bc86314bec2619424", + "sha256:45f7cd36186db767d803b1473b3c659d57a23b5fa491ad83c6d40f2af58e4dbb", + "sha256:48b389b1fd5144603d61d752afd7167dfd205973a43151ae5045b35793232aa2", + "sha256:4e67d26532bfd8b7f7c05d5a766d6f437b362c1bf203a3a5ce3593a645e870b8", + "sha256:516a405f174fd3b88829eabfe4bb296ac602d6a0f68e0d64d5ac9456194a5b7e", + "sha256:5ba5c243f4004c750836f81606a9fcb7841f8874ad8f3bf204ff5e56332b72b9", + "sha256:5bdc0f1f610d067c70aa3737ed06e2726fd9d6f7bfee4a351f4c40b6831f4e82", + "sha256:6107e445faf057c118d5050560695e46d272e5301feffda3c41849641222a828", + "sha256:6327b572f5770293fc062a7ec04160e89741e8552bf1c358d1a23eba68166759", + "sha256:669b29a9eca6146465cc574659058ed949748f0809a2582d1f1a324eb91054dc", + "sha256:6ce01337d23884b21c03869d2f68c5523d43174d4fc405490eb0091057943118", + "sha256:6d872186c1617d143969defeadac5a904e6e374183e07977eedef9c07c8953bf", + "sha256:6f76a90c345796c01d85e6332e81cab6d70de83b829cf1d9762d0a3da59c7932", + "sha256:70d2aa9fb00cf52034feac4b913181a6e10356019b18ef89bc7c12a283bf5f5a", + "sha256:7cbc78dc018596315d4e7841c8c3a7ae31cc4d638c9b627f87d52e8abaaf2d29", + "sha256:856bf0924d24e7f93b8aee12a3a1095c34085600aa805693fb7f5d1962393206", + "sha256:8a98748ed1a1df4ee1d6f927e151ed6c1a09d5ec21684de879c7ea6aa96f58f2", + "sha256:93a7350f6706b31f457c1457d3a3259ff9071a66f312ae64dc024f049055f72c", + "sha256:964823b2fc77b55355999ade496c54dde161c621cb1f6eac61dc30ed1b63cd4c", + "sha256:a003ac9edc22d99ae1286b0875c460351f4e101f8c9d9d2576e78d7e048f64e0", + "sha256:a0ce71725cacc9ebf839630772b07eeec220cbb5f03be1399e0457a1464f8e1a", + "sha256:a47eef975d2b8b721775a0fa286f50eab535b9d56c70a6e62842134cf7841195", + "sha256:a8b5b9712783415695663bd463990e2f00c6750562e6ad1d28e072a611c5f2a6", + "sha256:a9015f5b8af1bb6837a3fcb0cdf3b874fe3385ff6274e8b7925d81ccaec3c5c9", + "sha256:aec510255ce690d240f7cb23d7114f6b351c733a74c279a84def763660a2c3bc", + "sha256:b00e7bcd71caa0282cbe3c90966f738e2db91e64092a877c3ff7f19a1628fdcb", + "sha256:b50aaac7d05c2c26dfd50c3321199f019ba76bb650e346a6ef3616306eed67b0", + "sha256:b7b6ea9e36d32582cda3465f54c4b454f62f23cb083ebc7a94e2ca6ef011c3a7", + "sha256:bb9333f58fc3a2296fb1d54576138d4cf5d496a2cc118422bd77835e6ae0b9cb", + "sha256:c1c13185b90bbd3f8b5963cd8ce7ad4ff441924c31e23c975cb150e27c2bf67a", + "sha256:c3b8bd3133cd50f6b637bb4322822c94c5ce4bf0d724ed5ae70afce62187c492", + "sha256:c5d97162c196ce54af6700949ddf9409e9833ef1003b4741c2b39ef46f1d9720", + "sha256:c815270206f983309915a6844fe994b2fa47e5d05c4c4cef267c3b30e34dbe42", + "sha256:cab2eba3830bf4f6d91e2d6718e0e1c14a2f5ad1af68a89d24ace0c6b17cced7", + "sha256:d1df34588123fcc88c872f5acb6f74ae59e9d182a2707097f9e28275ec26a12d", + "sha256:d6bdcd415ba87846fd317bee0774e412e8792832e7805938987e4ede1d13046d", + "sha256:db9a30ec064129d605d0f1aedc93e00894b9334ec74ba9c6bdd08147434b33eb", + "sha256:dbc183e7bef690c9abe5ea67b7b60fdbca81aa8da43468287dae7b5c046107d4", + "sha256:dca802c8db0720ce1c49cce1149ff7b06e91ba15fa84b1d59144fef1a1bc7ac2", + "sha256:dec6b307ce928e8e112a6bb9921a1cb00a0e14979bf28b98e084a4b8a742bd9b", + "sha256:df8bb0010fdd0a743b7542589223a2816bdde4d94bb5ad67884348fa2c1c67e8", + "sha256:e4094c7b464cf0a858e75cd14b03509e84789abf7b79f8537e6a72152109c76e", + "sha256:e4760a68cab57bfaa628938e9c2971137e05ce48e762a9cb53b76c9b569f1204", + "sha256:eb09b82377233b902d4c3fbeeb7ad731cdab579c6c6fda1f763cd779139e47c3", + "sha256:eb862356ee9391dc5a0b3cbc00f416b48c1b9a52d252d898e5b7696a5f9fe150", + "sha256:ef9528915df81b8f4c7612b19b8628214c65c9b7f74db2e34a646a0a2a0da2d4", + "sha256:f3157624b7558b914cb039fd1af735e5e8049a87c817cc215109ad1c8779df76", + "sha256:f3e0992f23bbb0be00a921eae5363329253c3b86287db27092461c887b791e5e", + "sha256:f9338cc05451f1942d0d8203ec2c346c830f8e86469903d5126c1f0a13a2bcbb", + "sha256:ffef8fd58a36fb5f1196919638f73dd3ae0db1a878982b27a9a5a176ede4ba91" ], "markers": "platform_python_implementation != 'PyPy'", - "version": "==1.16.0" + "version": "==1.17.0" }, "charset-normalizer": { "hashes": [ @@ -314,50 +442,45 @@ }, "cryptography": { "hashes": [ - "sha256:02c0eee2d7133bdbbc5e24441258d5d2244beb31da5ed19fbb80315f4bbbff55", - "sha256:0d563795db98b4cd57742a78a288cdbdc9daedac29f2239793071fe114f13785", - "sha256:16268d46086bb8ad5bf0a2b5544d8a9ed87a0e33f5e77dd3c3301e63d941a83b", - "sha256:1a58839984d9cb34c855197043eaae2c187d930ca6d644612843b4fe8513c886", - "sha256:2954fccea107026512b15afb4aa664a5640cd0af630e2ee3962f2602693f0c82", - "sha256:2e47577f9b18723fa294b0ea9a17d5e53a227867a0a4904a1a076d1646d45ca1", - "sha256:31adb7d06fe4383226c3e963471f6837742889b3c4caa55aac20ad951bc8ffda", - "sha256:3577d029bc3f4827dd5bf8bf7710cac13527b470bbf1820a3f394adb38ed7d5f", - "sha256:36017400817987670037fbb0324d71489b6ead6231c9604f8fc1f7d008087c68", - "sha256:362e7197754c231797ec45ee081f3088a27a47c6c01eff2ac83f60f85a50fe60", - "sha256:3de9a45d3b2b7d8088c3fbf1ed4395dfeff79d07842217b38df14ef09ce1d8d7", - "sha256:4f698edacf9c9e0371112792558d2f705b5645076cc0aaae02f816a0171770fd", - "sha256:5482e789294854c28237bba77c4c83be698be740e31a3ae5e879ee5444166582", - "sha256:5e44507bf8d14b36b8389b226665d597bc0f18ea035d75b4e53c7b1ea84583cc", - "sha256:779245e13b9a6638df14641d029add5dc17edbef6ec915688f3acb9e720a5858", - "sha256:789caea816c6704f63f6241a519bfa347f72fbd67ba28d04636b7c6b7da94b0b", - "sha256:7f8b25fa616d8b846aef64b15c606bb0828dbc35faf90566eb139aa9cff67af2", - "sha256:8cb8ce7c3347fcf9446f201dc30e2d5a3c898d009126010cbd1f443f28b52678", - "sha256:93a3209f6bb2b33e725ed08ee0991b92976dfdcf4e8b38646540674fc7508e13", - "sha256:a3a5ac8b56fe37f3125e5b72b61dcde43283e5370827f5233893d461b7360cd4", - "sha256:a47787a5e3649008a1102d3df55424e86606c9bae6fb77ac59afe06d234605f8", - "sha256:a79165431551042cc9d1d90e6145d5d0d3ab0f2d66326c201d9b0e7f5bf43604", - "sha256:a987f840718078212fdf4504d0fd4c6effe34a7e4740378e59d47696e8dfb477", - "sha256:a9bc127cdc4ecf87a5ea22a2556cab6c7eda2923f84e4f3cc588e8470ce4e42e", - "sha256:bd13b5e9b543532453de08bcdc3cc7cebec6f9883e886fd20a92f26940fd3e7a", - "sha256:c65f96dad14f8528a447414125e1fc8feb2ad5a272b8f68477abbcc1ea7d94b9", - "sha256:d8e3098721b84392ee45af2dd554c947c32cc52f862b6a3ae982dbb90f577f14", - "sha256:e6b79d0adb01aae87e8a44c2b64bc3f3fe59515280e00fb6d57a7267a2583cda", - "sha256:e6b8f1881dac458c34778d0a424ae5769de30544fc678eac51c1c8bb2183e9da", - "sha256:e9b2a6309f14c0497f348d08a065d52f3020656f675819fc405fb63bbcd26562", - "sha256:ecbfbc00bf55888edda9868a4cf927205de8499e7fabe6c050322298382953f2", - "sha256:efd0bf5205240182e0f13bcaea41be4fdf5c22c5129fc7ced4a0282ac86998c9" + "sha256:0663585d02f76929792470451a5ba64424acc3cd5227b03921dab0e2f27b1709", + "sha256:08a24a7070b2b6804c1940ff0f910ff728932a9d0e80e7814234269f9d46d069", + "sha256:232ce02943a579095a339ac4b390fbbe97f5b5d5d107f8a08260ea2768be8cc2", + "sha256:2905ccf93a8a2a416f3ec01b1a7911c3fe4073ef35640e7ee5296754e30b762b", + "sha256:299d3da8e00b7e2b54bb02ef58d73cd5f55fb31f33ebbf33bd00d9aa6807df7e", + "sha256:2c6d112bf61c5ef44042c253e4859b3cbbb50df2f78fa8fae6747a7814484a70", + "sha256:31e44a986ceccec3d0498e16f3d27b2ee5fdf69ce2ab89b52eaad1d2f33d8778", + "sha256:3d9a1eca329405219b605fac09ecfc09ac09e595d6def650a437523fcd08dd22", + "sha256:3dcdedae5c7710b9f97ac6bba7e1052b95c7083c9d0e9df96e02a1932e777895", + "sha256:47ca71115e545954e6c1d207dd13461ab81f4eccfcb1345eac874828b5e3eaaf", + "sha256:4a997df8c1c2aae1e1e5ac49c2e4f610ad037fc5a3aadc7b64e39dea42249431", + "sha256:51956cf8730665e2bdf8ddb8da0056f699c1a5715648c1b0144670c1ba00b48f", + "sha256:5bcb8a5620008a8034d39bce21dc3e23735dfdb6a33a06974739bfa04f853947", + "sha256:64c3f16e2a4fc51c0d06af28441881f98c5d91009b8caaff40cf3548089e9c74", + "sha256:6e2b11c55d260d03a8cf29ac9b5e0608d35f08077d8c087be96287f43af3ccdc", + "sha256:7b3f5fe74a5ca32d4d0f302ffe6680fcc5c28f8ef0dc0ae8f40c0f3a1b4fca66", + "sha256:844b6d608374e7d08f4f6e6f9f7b951f9256db41421917dfb2d003dde4cd6b66", + "sha256:9a8d6802e0825767476f62aafed40532bd435e8a5f7d23bd8b4f5fd04cc80ecf", + "sha256:aae4d918f6b180a8ab8bf6511a419473d107df4dbb4225c7b48c5c9602c38c7f", + "sha256:ac1955ce000cb29ab40def14fd1bbfa7af2017cca696ee696925615cafd0dce5", + "sha256:b88075ada2d51aa9f18283532c9f60e72170041bba88d7f37e49cbb10275299e", + "sha256:cb013933d4c127349b3948aa8aaf2f12c0353ad0eccd715ca789c8a0f671646f", + "sha256:cc70b4b581f28d0a254d006f26949245e3657d40d8857066c2ae22a61222ef55", + "sha256:e9c5266c432a1e23738d178e51c2c7a5e2ddf790f248be939448c0ba2021f9d1", + "sha256:ea9e57f8ea880eeea38ab5abf9fbe39f923544d7884228ec67d666abd60f5a47", + "sha256:ee0c405832ade84d4de74b9029bedb7b31200600fa524d218fc29bfa371e97f5", + "sha256:fdcb265de28585de5b859ae13e3846a8e805268a823a12a4da2597f1f5afc9f0" ], "markers": "python_version >= '3.7'", - "version": "==42.0.7" + "version": "==43.0.0" }, "django": { "hashes": [ - "sha256:a2d4c4d4ea0b6f0895acde632071aff6400bfc331228fc978b05452a0ff3e9f1", - "sha256:b1260ed381b10a11753c73444408e19869f3241fc45c985cd55a30177c789d13" + "sha256:61ee4a130efb8c451ef3467c67ca99fdce400fedd768634efc86a68c18d80d30", + "sha256:c77f926b81129493961e19c0e02188f8d07c112a1162df69bfab178ae447f94a" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==4.2.10" + "version": "==4.2.15" }, "django-cors-headers": { "hashes": [ @@ -386,14 +509,6 @@ "markers": "python_version >= '3.8'", "version": "==24.2" }, - "django-hardcopy": { - "hashes": [ - "sha256:1ceda5fb262c9787fbd2554b4b92db9c8feebdd6da4ef6c1746e1aa8c8e55377", - "sha256:8bf962245d95918bd5c4b4e1b809a3d029b19d4f331e1c7c5f65768fb8366ed8" - ], - "index": "pypi", - "version": "==0.1.4" - }, "django-maintenance-mode": { "hashes": [ "sha256:b79afddb671c59972ae542e4fafbc99117d2d37991843eaaa837e328eed12b1b", @@ -470,12 +585,12 @@ }, "djangorestframework": { "hashes": [ - "sha256:3ccc0475bce968608cf30d07fb17d8e52d1d7fc8bfe779c905463200750cbca6", - "sha256:f88fad74183dfc7144b2756d0d2ac716ea5b4c7c9840995ac3bfd8ec034333c1" + "sha256:2b8871b062ba1aefc2de01f773875441a961fefbf79f5eed1e32b2f096944b20", + "sha256:36fe88cd2d6c6bec23dca9804bab2ba5517a8bb9d8f47ebc68981b56840107ad" ], "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==3.15.1" + "markers": "python_version >= '3.8'", + "version": "==3.15.2" }, "djangorestframework-simplejwt": { "hashes": [ @@ -522,10 +637,10 @@ }, "email-validator": { "hashes": [ - "sha256:200a70680ba08904be6d1eef729205cc0d687634399a5924d842533efb824b84", - "sha256:97d882d174e2a65732fb43bfce81a3a834cbc1bde8bf419e30ef5ea976370a05" + "sha256:561977c2d73ce3611850a06fa56b414621e0c8faa9d66f2611407d87465da631", + "sha256:cb690f344c617a714f22e66ae771445a1ceb46821152df8e165c5f9a364582b7" ], - "version": "==2.1.1" + "version": "==2.2.0" }, "fhir.resources": { "hashes": [ @@ -535,6 +650,89 @@ "markers": "python_version >= '3.6'", "version": "==6.5.0" }, + "frozenlist": { + "hashes": [ + "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7", + "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98", + "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad", + "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5", + "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae", + "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e", + "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a", + "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701", + "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d", + "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6", + "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6", + "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106", + "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75", + "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868", + "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a", + "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0", + "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1", + "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826", + "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec", + "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6", + "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950", + "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19", + "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0", + "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8", + "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a", + "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09", + "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86", + "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c", + "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5", + "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b", + "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b", + "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d", + "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0", + "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea", + "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776", + "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a", + "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897", + "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7", + "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09", + "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9", + "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe", + "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd", + "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742", + "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09", + "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0", + "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932", + "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1", + "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a", + "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49", + "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d", + "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7", + "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480", + "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89", + "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e", + "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b", + "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82", + "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb", + "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068", + "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8", + "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b", + "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb", + "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2", + "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11", + "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b", + "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc", + "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0", + "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497", + "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17", + "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0", + "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2", + "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439", + "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5", + "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac", + "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825", + "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887", + "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced", + "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74" + ], + "markers": "python_version >= '3.8'", + "version": "==1.4.1" + }, "gunicorn": { "hashes": [ "sha256:350679f91b24062c86e386e198a15438d53a7a8207235a78ba1b53df4c4378d9", @@ -554,124 +752,109 @@ }, "hiredis": { "hashes": [ - "sha256:01b6c24c0840ac7afafbc4db236fd55f56a9a0919a215c25a238f051781f4772", - "sha256:02fc71c8333586871602db4774d3a3e403b4ccf6446dc4603ec12df563127cee", - "sha256:0c0773266e1c38a06e7593bd08870ac1503f5f0ce0f5c63f2b4134b090b5d6a4", - "sha256:0c5f6972d2bdee3cd301d5c5438e31195cf1cabf6fd9274491674d4ceb46914d", - "sha256:0da56915bda1e0a49157191b54d3e27689b70960f0685fdd5c415dacdee2fbed", - "sha256:14c7b43205e515f538a9defb4e411e0f0576caaeeda76bb9993ed505486f7562", - "sha256:16b01d9ceae265d4ab9547be0cd628ecaff14b3360357a9d30c029e5ae8b7e7f", - "sha256:1979334ccab21a49c544cd1b8d784ffb2747f99a51cb0bd0976eebb517628382", - "sha256:1c4c0bcf786f0eac9593367b6279e9b89534e008edbf116dcd0de956524702c8", - "sha256:1d63318ca189fddc7e75f6a4af8eae9c0545863619fb38cfba5f43e81280b286", - "sha256:27e9619847e9dc70b14b1ad2d0fb4889e7ca18996585c3463cff6c951fd6b10b", - "sha256:28adecb308293e705e44087a1c2d557a816f032430d8a2a9bb7873902a1c6d48", - "sha256:28bd184b33e0dd6d65816c16521a4ba1ffbe9ff07d66873c42ea4049a62fed83", - "sha256:322c668ee1c12d6c5750a4b1057e6b4feee2a75b3d25d630922a463cfe5e7478", - "sha256:333b5e04866758b11bda5f5315b4e671d15755fc6ed3b7969721bc6311d0ee36", - "sha256:33d5ebc93c39aed4b5bc769f8ce0819bc50e74bb95d57a35f838f1c4378978e0", - "sha256:380e029bb4b1d34cf560fcc8950bf6b57c2ef0c9c8b7c7ac20b7c524a730fadd", - "sha256:387f655444d912a963ab68abf64bf6e178a13c8e4aa945cb27388fd01a02e6f1", - "sha256:3dd63d0bbbe75797b743f35d37a4cca7ca7ba35423a0de742ae2985752f20c6d", - "sha256:419780f8583ddb544ffa86f9d44a7fcc183cd826101af4e5ffe535b6765f5f6b", - "sha256:4852f4bf88f0e2d9bdf91279892f5740ed22ae368335a37a52b92a5c88691140", - "sha256:49532d7939cc51f8e99efc326090c54acf5437ed88b9c904cc8015b3c4eda9c9", - "sha256:4baf4b579b108062e91bd2a991dc98b9dc3dc06e6288db2d98895eea8acbac22", - "sha256:4d59f88c4daa36b8c38e59ac7bffed6f5d7f68eaccad471484bf587b28ccc478", - "sha256:4fc242e9da4af48714199216eb535b61e8f8d66552c8819e33fc7806bd465a09", - "sha256:532a84a82156a82529ec401d1c25d677c6543c791e54a263aa139541c363995f", - "sha256:5341ce3d01ef3c7418a72e370bf028c7aeb16895e79e115fe4c954fff990489e", - "sha256:53d0f2c59bce399b8010a21bc779b4f8c32d0f582b2284ac8c98dc7578b27bc4", - "sha256:55ce31bf4711da879b96d511208efb65a6165da4ba91cb3a96d86d5a8d9d23e6", - "sha256:56e9b7d6051688ca94e68c0c8a54a243f8db841911b683cedf89a29d4de91509", - "sha256:57c0d0c7e308ed5280a4900d4468bbfec51f0e1b4cde1deae7d4e639bc6b7766", - "sha256:5986fb5f380169270a0293bebebd95466a1c85010b4f1afc2727e4d17c452512", - "sha256:5bd42d0d45ea47a2f96babd82a659fbc60612ab9423a68e4a8191e538b85542a", - "sha256:5c614552c6bd1d0d907f448f75550f6b24fb56cbfce80c094908b7990cad9702", - "sha256:63a090761ddc3c1f7db5e67aa4e247b4b3bb9890080bdcdadd1b5200b8b89ac4", - "sha256:63b99b5ea9fe4f21469fb06a16ca5244307678636f11917359e3223aaeca0b67", - "sha256:66ab949424ac6504d823cba45c4c4854af5c59306a1531edb43b4dd22e17c102", - "sha256:684840b014ce83541a087fcf2d48227196576f56ae3e944d4dfe14c0a3e0ccb7", - "sha256:6871306d8b98a15e53a5f289ec1106a3a1d43e7ab6f4d785f95fcef9a7bd9504", - "sha256:6b4edee59dc089bc3948f4f6fba309f51aa2ccce63902364900aa0a553a85e97", - "sha256:6d7302b4b17fcc1cc727ce84ded7f6be4655701e8d58744f73b09cb9ed2b13df", - "sha256:6dbfe1887ffa5cf3030451a56a8f965a9da2fa82b7149357752b67a335a05fc6", - "sha256:70d226ab0306a5b8d408235cabe51d4bf3554c9e8a72d53ce0b3c5c84cf78881", - "sha256:7298562a49d95570ab1c7fc4051e72824c6a80e907993a21a41ba204223e7334", - "sha256:733e2456b68f3f126ddaf2cd500a33b25146c3676b97ea843665717bda0c5d43", - "sha256:742093f33d374098aa21c1696ac6e4874b52658c870513a297a89265a4d08fe5", - "sha256:7bac7e02915b970c3723a7a7c5df4ba7a11a3426d2a3f181e041aa506a1ff028", - "sha256:7e8bf4444b09419b77ce671088db9f875b26720b5872d97778e2545cd87dba4a", - "sha256:7f39f28ffc65de577c3bc0c7615f149e35bc927802a0f56e612db9b530f316f9", - "sha256:80441b55edbef868e2563842f5030982b04349408396e5ac2b32025fb06b5212", - "sha256:80b02d27864ebaf9b153d4b99015342382eeaed651f5591ce6f07e840307c56d", - "sha256:88cb0b35b63717ef1e41d62f4f8717166f7c6245064957907cfe177cc144357c", - "sha256:8c490191fa1218851f8a80c5a21a05a6f680ac5aebc2e688b71cbfe592f8fec6", - "sha256:8e3f8b1733078ac663dad57e20060e16389a60ab542f18a97931f3a2a2dd64a4", - "sha256:8f34801b251ca43ad70691fb08b606a2e55f06b9c9fb1fc18fd9402b19d70f7b", - "sha256:8fc7197ff33047ce43a67851ccf190acb5b05c52fd4a001bb55766358f04da68", - "sha256:92830c16885f29163e1c2da1f3c1edb226df1210ec7e8711aaabba3dd0d5470a", - "sha256:9412a06b8a8e09abd6313d96864b6d7713c6003a365995a5c70cfb9209df1570", - "sha256:948d9f2ca7841794dd9b204644963a4bcd69ced4e959b0d4ecf1b8ce994a6daa", - "sha256:9a0026cfbf29f07649b0e34509091a2a6016ff8844b127de150efce1c3aff60b", - "sha256:9c431431abf55b64347ddc8df68b3ef840269cb0aa5bc2d26ad9506eb4b1b866", - "sha256:9e14fb70ca4f7efa924f508975199353bf653f452e4ef0a1e47549e208f943d7", - "sha256:a45857e87e9d2b005e81ddac9d815a33efd26ec67032c366629f023fe64fb415", - "sha256:a50c8af811b35b8a43b1590cf890b61ff2233225257a3cad32f43b3ec7ff1b9f", - "sha256:a6481c3b7673a86276220140456c2a6fbfe8d1fb5c613b4728293c8634134824", - "sha256:a6b54dabfaa5dbaa92f796f0c32819b4636e66aa8e9106c3d421624bd2a2d676", - "sha256:a797d8c7df9944314d309b0d9e1b354e2fa4430a05bb7604da13b6ad291bf959", - "sha256:a91a14dd95e24dc078204b18b0199226ee44644974c645dc54ee7b00c3157330", - "sha256:adfbf2e9c38b77d0db2fb32c3bdaea638fa76b4e75847283cd707521ad2475ef", - "sha256:ba3dc0af0def8c21ce7d903c59ea1e8ec4cb073f25ece9edaec7f92a286cd219", - "sha256:bb777a38797c8c7df0444533119570be18d1a4ce5478dffc00c875684df7bfcb", - "sha256:bcbe47da0aebc00a7cfe3ebdcff0373b86ce2b1856251c003e3d69c9db44b5a7", - "sha256:bd1cee053416183adcc8e6134704c46c60c3f66b8faaf9e65bf76191ca59a2f7", - "sha256:bd40d2e2f82a483de0d0a6dfd8c3895a02e55e5c9949610ecbded18188fd0a56", - "sha256:bfa73e3f163c6e8b2ec26f22285d717a5f77ab2120c97a2605d8f48b26950dac", - "sha256:c1f567489f422d40c21e53212a73bef4638d9f21043848150f8544ef1f3a6ad1", - "sha256:c3dde4ca00fe9eee3b76209711f1941bb86db42b8a75d7f2249ff9dfc026ab0e", - "sha256:c8937f1100435698c18e4da086968c4b5d70e86ea718376f833475ab3277c9aa", - "sha256:ca33c175c1cf60222d9c6d01c38fc17ec3a484f32294af781de30226b003e00f", - "sha256:ce42649e2676ad783186264d5ffc788a7612ecd7f9effb62d51c30d413a3eefe", - "sha256:cfa67afe2269b2d203cd1389c00c5bc35a287cd57860441fb0e53b371ea6a029", - "sha256:d47c915897a99d0d34a39fad4be97b4b709ab3d0d3b779ebccf2b6024a8c681e", - "sha256:d4dd676107a1d3c724a56a9d9db38166ad4cf44f924ee701414751bd18a784a0", - "sha256:d711c107e83117129b7f8bd08e9820c43ceec6204fff072a001fd82f6d13db9f", - "sha256:dc1c3fd49930494a67dcec37d0558d99d84eca8eb3f03b17198424538f2608d7", - "sha256:de3a32b4b76d46f1eb42b24a918d51d8ca52411a381748196241d59a895f7c5c", - "sha256:dfa904045d7cebfb0f01dad51352551cce1d873d7c3f80c7ded7d42f8cac8f89", - "sha256:e138d141ec5a6ec800b6d01ddc3e5561ce1c940215e0eb9960876bfde7186aae", - "sha256:e15a408f71a6c8c87b364f1f15a6cd9c1baca12bbc47a326ac8ab99ec7ad3c64", - "sha256:e1d86b75de787481b04d112067a4033e1ecfda2a060e50318a74e4e1c9b2948c", - "sha256:e2674a5a3168349435b08fa0b82998ed2536eb9acccf7087efe26e4cd088a525", - "sha256:e58494f282215fc461b06709e9a195a24c12ba09570f25bdf9efb036acc05101", - "sha256:e627d8ef5e100556e09fb44c9571a432b10e11596d3c4043500080ca9944a91a", - "sha256:e741ffe4e2db78a1b9dd6e5d29678ce37fbaaf65dfe132e5b82a794413302ef1", - "sha256:e81aa4e9a1fcf604c8c4b51aa5d258e195a6ba81efe1da82dea3204443eba01c", - "sha256:e96cd35df012a17c87ae276196ea8f215e77d6eeca90709eb03999e2d5e3fd8a", - "sha256:ea002656a8d974daaf6089863ab0a306962c8b715db6b10879f98b781a2a5bf5", - "sha256:eae62ed60d53b3561148bcd8c2383e430af38c0deab9f2dd15f8874888ffd26f", - "sha256:eb8797b528c1ff81eef06713623562b36db3dafa106b59f83a6468df788ff0d1", - "sha256:eb98038ccd368e0d88bd92ee575c58cfaf33e77f788c36b2a89a84ee1936dc6b", - "sha256:ec444ab8f27562a363672d6a7372bc0700a1bdc9764563c57c5f9efa0e592b5f", - "sha256:ed63e8b75c193c5e5a8288d9d7b011da076cc314fafc3bfd59ec1d8a750d48c8", - "sha256:f2c9c0d910dd3f7df92f0638e7f65d8edd7f442203caf89c62fc79f11b0b73f8", - "sha256:f3020b60e3fc96d08c2a9b011f1c2e2a6bdcc09cb55df93c509b88be5cb791df", - "sha256:f47775e27388b58ce52f4f972f80e45b13c65113e9e6b6bf60148f893871dc9b", - "sha256:f70481213373d44614148f0f2e38e7905be3f021902ae5167289413196de4ba4", - "sha256:f9de7586522e5da6bee83c9cf0dcccac0857a43249cb4d721a2e312d98a684d1", - "sha256:f9f606e810858207d4b4287b4ef0dc622c2aa469548bf02b59dcc616f134f811", - "sha256:fa45f7d771094b8145af10db74704ab0f698adb682fbf3721d8090f90e42cc49" - ], - "markers": "python_version >= '3.7'", - "version": "==2.3.2" + "sha256:06815c3b9bf7225c4dcc9dd9dfb5a9fa91b4f680104443ef3fcd78410d7eb027", + "sha256:070a0198401bc567709b9edff7f01e94c136dcca69d0ded4747b116bb0b8b577", + "sha256:082ba6a3189d59f44bf75ca2c0467cdbc67c860eacd4bf564b9a927471888603", + "sha256:0a87a249124666db2b795a0eb77cea5b8af8b148566616a681304826b4405869", + "sha256:1537d13eefe4f48cb979362264851ee90d2bb7a221c8c350e9ceeda9f0392228", + "sha256:168de1672bd73f7f3cdf0097084b4a71651ac35f7d99d0229ea8f223358d3a79", + "sha256:1bfa50491d3222e3c2297b52c14e835ac52702ac8a91ec3fc1ff5201912623bb", + "sha256:1c0e706e0c3d1ec54d8243410e0fd5974b1c7b69db5c54cd9ae6a3a4b64fae33", + "sha256:1d16f5023c1d9971f284231eb7036a25d4d123138a5adc4512c92a73d83b9a77", + "sha256:2a21e2740c33347740dceb106b64b8a384e91da49aac7e8b3f2a25a9b33714b9", + "sha256:2b76a5600047387c73c1b3d950e4ae3feffaefd442b20ba2f5fea773881d9bcd", + "sha256:2b90d9861673b0ba04651ade62e0fe568df71bbff8468657406848e9abf3650a", + "sha256:2d7715598c9034369cf739475ccc2db53a8ca895ff398fef6b9c597c30960ea8", + "sha256:339f29542be968153afd6c6495c1222681c4b66b9a5a5573c11512378b7167c9", + "sha256:38dd931f1124bd9781d3027a0cd6fb6f5a75b5c4ba4fe5540584105239b1f901", + "sha256:39e1c7212dea1bbed0b075574808bc7c3192b324f54ea5d9ee522f6c35014ce7", + "sha256:3abc0936c1efc59b510c7eab3799119a6ce8da94cea1f891854a6c3678d711f0", + "sha256:3ced14fbec28fbabda7cb9f9094f2578c154c14f1a820a91c30fc8ee0bea1a0d", + "sha256:400a42b8d16206e45c8223cdaf5acc35839e10c35383b3fba3f43e7eb315c213", + "sha256:468efdcbad7349a44aace693aed8324a01de180fcd4ef5513199eedb9b4341c8", + "sha256:469c1a85017abf11d854fb16eca9a4093ebe1f2dacf777fed869d726f02b1389", + "sha256:48baae8fbebf3b11660db6e51a55ff51516ed32edcd44a57f51ea9b373aca330", + "sha256:4bf4b8513cea6e04ddee1b578ab306fb8bfa84b2f7e92ee3dbaf65652abb07d1", + "sha256:4da6d881033a1bcb31bba152ea0925344127f0a98f86a6cf2ceb01cf6ecd29e2", + "sha256:52d92df0eb5bba7f31f302a08174d628956d7216453da9d96498da9341179288", + "sha256:54409fbefebe26274170c1c54e1852d310d84b85e405258aea6a78bec03b3eba", + "sha256:5598afad9e2f8e4fc9a456d281a9cc80315b0e18f5064437223dbfe67f49bded", + "sha256:5b0b2463906cc4119187dfaad493c48a7b2e17120946feb3eb7c2328c8cb4bca", + "sha256:5bdb223e7c3b9470f126bb77879ee2593fd79b28e1e8b11ad9edd3f866556109", + "sha256:5cc3c59dd0cd67d0aa0481a43392848a60f1a81d12b38ce8d56d6a5d6c190de8", + "sha256:5e45171fd046bbed2ce6ac485071cd0575d18ae98b5bbcf6533356e443ec47ea", + "sha256:6033cc6caaf056969af9ce372282a6ef2838559f2eadffe7ddb73bf65dcb27d6", + "sha256:605fe35ebb482b7c8d5daadcf3d264dc5edd205a352d89ee3a983861ef73cda8", + "sha256:6494120d0a0f46a1d7dfc7def55782782856bdd5acb2f6039fb1eafecea2c2c0", + "sha256:668b02556d12046e7ce94ded5bfe0ad9989d26e6977ecc55941b9a1a4a49d7d5", + "sha256:68e39d2c0beed53e5361caacd0de98f864b3532344edb79e27e62efba2262de5", + "sha256:6c3f8e0c3a0744d843e3044ea76db8aa996a6cc7541693111acc2c9c30a05182", + "sha256:6ceaf7c6b593bf62e0567fd16547727f502ed704352392708a57c65bfd2feb73", + "sha256:6dac8a5be01d92707409feec61b98721b7b5c3e77fe7e9e5c7cfb9fdd28385af", + "sha256:6e38f66dd7fd07a9306ed37d6d02bc584b67e5945f2ddc98e5c78420cc66dbac", + "sha256:7236b26828e005435fb3013894eed6a40c6f9b1b11a48391a904eee693ded204", + "sha256:737585b122fca03273bbf1f4e98909254dba6f8cd85f1cb566d6c890d0389277", + "sha256:764032f2222d70a130445fd332cf45d46d8226f4b3a7bf8abc314aa93d5a8212", + "sha256:76503a0edaf3d1557518127511e69e5d9fa37b6ff15598b0d9d9c2db18b08a41", + "sha256:83538638a788b7b4a0b02de0eedcf0e71ae27474b031276e4c8ca88285281a2e", + "sha256:8767cae1474f8102ec3d362976f80c8dd4eafd4109c6072adee0a15e37ba919c", + "sha256:87a8ece3e893f45354395c6b9dc0479744c1c8c6ee4471b60945d96c9b5ce6c2", + "sha256:8b88390a5e31572e05e8eab476ed3176cc3d2f9622ccc059398ffdb02aaefec4", + "sha256:90d7af678056c7889d86821344d79fec3932a6a1480ebba3d644cb29a3135348", + "sha256:98148ecaa7836f76ed33429e84a23253ac00acbad90c62b8b4ad0f61de31da2b", + "sha256:9aabc6098ef00e158598489db5a8b9e12d57a55ea5a4ec35ba3b527dfb88d16e", + "sha256:9ae4b19cab270fae77d7f944d56bbb308c9886d9577891b347a8deea75563995", + "sha256:9b4039cd40335f66e55a8bee314b6a795f169fb02d70215d482023ec74613371", + "sha256:9fc1a6c78197eff8b4d125bb98410b661e732f3ec563c03264d2d7378cf9e613", + "sha256:a40f1d985047fe4654a1afb4702cbe0daeacde3868d52be9e4652615d387e05b", + "sha256:a459b7ff3d802792254d6fc6a622e53ca9cf9f002ed79db7e4dee536b2e20e5d", + "sha256:a4f733882b67407d4b667eafd61fce86e8e204b158258cc1d0cb0843f6bb4708", + "sha256:a56a35e2e0b7eda39957ccd33059b79bb2fc57f54c501a917d1092c895f56d08", + "sha256:a5c3a32af789b0ec413a606c99b55579abbcb6c86220610a5c5041da8688e7ca", + "sha256:a5d2776c7cd6a338cd9338fb50f2a38a7ca3e16250b40ab2d0c41eb1697ebc12", + "sha256:a816f732f695261798a8a0fc1e0232a3638933b8ddfc574c00f9ef70d9f34cb8", + "sha256:a9d559775a95aee0ff06c0aaac638691619d6342b7cde85c62ad228804f82829", + "sha256:ac9d91b4d9c306e66a1abd224524fada07684a57f7da72a675e4b8bee9302b38", + "sha256:ae340c41024b9be566f600f364c8d286217f2975fd765fb3fb4dd6dfbdbec825", + "sha256:aeb60452d5b6150075974bc36e1cc74a46bd4b125cd5e72a86a04f4d6abf4e67", + "sha256:aee6c4e8f670ea685345ce4ca01c574a52e0a4318af2b8cdd563de9567731056", + "sha256:b027b53adb1df11923753d85587e3ab611fe70bc69596e9eb3269acab809c376", + "sha256:b0adbe8f33f57f2b6bfa8a2ea18f3e4ed91676503673f70f796bfbd06a1a2214", + "sha256:b30dcfbc5ab2fc932a723a39c2cb52d4f5c8b1705aa05a0bae23f28f70e06982", + "sha256:b385fc7fc7b0811c3fcac4b0a35e5606eca693efba0d1446623ef0158a078034", + "sha256:b4e5e9d1f84bbc01bf6a32a4704920c72e37d9090b3e0e29bd1574d06b3249f1", + "sha256:b50ad622d8a71c8b72582dc84a990f3f079775edc1bcf0f43ed59bb2277fca2f", + "sha256:b544a1a78e0812134572cc13f5ee330bfb6bfe6dda58d2e26c20557bb0e0cec9", + "sha256:b8472151e6f7ae90d7fd231a1ac16d2e628b93ce20d0f8063da25bd8bfdeb9e5", + "sha256:b868b7fc24dd8ab4762b59a533bdbd096ebba7eabc853c7f78af8edce46d1390", + "sha256:b8eee5d25efee64e172ed0d60ebcf6bca92b0b26a7fd048bb946b32fb90dbdc0", + "sha256:bae7f07731c6c285b87111c7d5c5efa65f8b48016a98bcc57eebc24a3c7d854d", + "sha256:beb0f7f8371d933072e9bdc00c6df7eb5fdf76b93f08bfe73094f60c3f011f57", + "sha256:c2676e2a934e046200faf0dc26ffa48c4989c3561c9bb97832e79969a41b2afe", + "sha256:c77113fbdbd7ca5de72dd3b7d113856609a1b878f6164de09dd95d12e6a51de2", + "sha256:c85110f536e59fe19ea4b002d04228f57f55462add1630a0785cd6ec62e70415", + "sha256:c9f8827cd7a84f5344779754ebb633bca71c470e028f92ecc959e666ef5c5e3c", + "sha256:cb62c82a2518b8446be1cc5eb4319e282776bf96fdb2964e81ff2c15d632248b", + "sha256:d5c711c8ca8d5767ed8ecd5fb5602c12eaf8fb256a5f4308ae36f2dc79e6f853", + "sha256:d851b7ff732ebc9d823de3c7cc95a5ed4261a0226acd46861a18369ac9568f36", + "sha256:e2a917ab420cd88b040ec85b5abc1244ab82b34d56461e2ffff58e0c7d018bae", + "sha256:e3215b43632a23b5b99165097949ce51dd093ab33d410bcf8aa901cdbc64d9cd", + "sha256:e71386f89dc2db805b4c9518dee6d81abddb8e79e4d9313cecdb702c924b8187", + "sha256:f34b39057956305935c71f51a0860709b6124c92281dc03841587dd45a86322c", + "sha256:f44715d6a3313d614ff7550e52ecff67a283776909d960f338701b57e6013542", + "sha256:f74bfa9f1b91718d6664d4708d092f7d44e2f0f825a5fab82819d43d41e0302d", + "sha256:f76fcf2867d19259b53680c08314435b46f632d20a4d7b9f0ccbb5dd3e925e79", + "sha256:fa4842977924209ae653e856238a30b1c68e579ecde5cf1c16c4de471b35cec7", + "sha256:fc8d3edbc9f32da930da6ea33d43ce0c3239e6b2018a77907fbf4e9836bd6def" + ], + "markers": "python_version >= '3.8'", + "version": "==2.4.0" }, "http-ece": { "hashes": [ - "sha256:b5920f8efb8e1b5fb025713e3b36fda54336262010634b26dc1f98f85d1eb3de" + "sha256:8c6ab23116bbf6affda894acfd5f2ca0fb8facbcbb72121c11c75c33e7ce8cff" ], - "version": "==1.2.0" + "version": "==1.2.1" }, "idna": { "hashes": [ @@ -725,63 +908,159 @@ }, "kombu": { "hashes": [ - "sha256:011c4cd9a355c14a1de8d35d257314a1d2456d52b7140388561acac3cf1a97bf", - "sha256:5634c511926309c7f9789f1433e9ed402616b56836ef9878f01bd59267b4c7a9" + "sha256:ad200a8dbdaaa2bbc5f26d2ee7d707d9a1fded353a0f4bd751ce8c7d9f449c60", + "sha256:c8dd99820467610b4febbc7a9e8a0d3d7da2d35116b67184418b51cc520ea6b6" ], "markers": "python_version >= '3.8'", - "version": "==5.3.7" + "version": "==5.4.0" }, "more-itertools": { "hashes": [ - "sha256:686b06abe565edfab151cb8fd385a05651e1fdf8f0a14191e4439283421f8684", - "sha256:8fccb480c43d3e99a00087634c06dd02b0d50fbf088b380de5a41a015ec239e1" + "sha256:0f7d9f83a0a8dcfa8a2694a770590d98a67ea943e3d9f5298309a484758c4e27", + "sha256:fe0e63c4ab068eac62410ab05cccca2dc71ec44ba8ef29916a0090df061cf923" + ], + "markers": "python_version >= '3.8'", + "version": "==10.4.0" + }, + "multidict": { + "hashes": [ + "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556", + "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c", + "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29", + "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b", + "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8", + "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7", + "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd", + "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40", + "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6", + "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3", + "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c", + "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9", + "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5", + "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae", + "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442", + "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9", + "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc", + "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c", + "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea", + "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5", + "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50", + "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182", + "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453", + "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e", + "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600", + "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733", + "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda", + "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241", + "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461", + "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e", + "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e", + "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b", + "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e", + "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7", + "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386", + "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd", + "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9", + "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf", + "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee", + "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5", + "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a", + "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271", + "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54", + "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4", + "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496", + "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb", + "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319", + "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3", + "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f", + "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527", + "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed", + "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604", + "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef", + "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8", + "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5", + "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5", + "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626", + "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c", + "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d", + "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c", + "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc", + "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc", + "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b", + "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38", + "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450", + "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1", + "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f", + "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3", + "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755", + "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226", + "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a", + "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046", + "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf", + "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479", + "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e", + "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1", + "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a", + "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83", + "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929", + "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93", + "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a", + "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c", + "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44", + "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89", + "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba", + "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e", + "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da", + "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24", + "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423", + "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef" ], - "markers": "python_version >= '3.8'", - "version": "==10.2.0" + "markers": "python_version >= '3.7'", + "version": "==6.0.5" }, "newrelic": { "hashes": [ - "sha256:02db25b0fd2fc835efe4a7f1c92dbc5bbb95125341aba07152041aa6a5666cda", - "sha256:09912303e04bee6aa1fe1c671e87b4e8e55461081a96210895828798f5ba8c3f", - "sha256:1cc3ddb26c0615ba4e18f87453bca57f0688a43d2fcdd50e2771a77515cfc3ba", - "sha256:1f11d9c17b50982fcc39de71f6592a61920ec5e5c29b9105edc9f8fb7f2480b9", - "sha256:2236f70b8c6aa79635f2175e7315d032f3a80dfd65ad9c9ed12a921f5df4c655", - "sha256:40368dca0d423efe40b210686d7018787d4365a24ee1deca136b3b7c9d850325", - "sha256:4404c649b5e6165dcdd59091092c19b292a43cc96520d5ffd718b628fb866096", - "sha256:4d68fc707d896dc7da8d6939bcc1f995bf9e463c2b911fc63250a10e1502a234", - "sha256:4e573d49c1543a488d6567906a9b2cb0c748cdbf80724c322b06874f8e47c789", - "sha256:524ed5bfa09d330746b45e0087765da994ca34802cce032063041e404e58414c", - "sha256:56f4c309a07a2c66243b12d18056c32aa704735469741495642c31be4a1c77fa", - "sha256:5d18236bf4a80fca4eb1db03448ed72bf8e16b84b3a4ed5fcc29bb91c2d05d54", - "sha256:667722cf1f4ed9f6cd99f4fbe247fc2bdb941935528e14a93659ba2c651dc889", - "sha256:6ed4bc2c9a44dfe59958eeecf1f327f0a0fb6324b5e609515bc511944d12db74", - "sha256:744c815f15ec06e441c11a6c57042d2eca8c41401c11de6f47b3e105d952b9bd", - "sha256:77537a020ce84033f39210e46cc43bb3927cec3fb4b34b5c4df802e96fddaedf", - "sha256:7cd462804a6ede617fb3b4b126e9083b3ee8b4ed1250f7cc12299ebacb785432", - "sha256:8ad9cd5459b8c620ab7a876bd5d920c3ef2943948d1262a42289d4f8d16dadab", - "sha256:a4d4e5670082225ca7ef0ee986ef8e6588f4e530a05d43d66f9368459c0b1f18", - "sha256:acf5cdcafd2971933ad2f9e836284957f4a3eababe88f063cf53b1b1f67f1a16", - "sha256:ae0515f7ab19f1a5dd14e31506420d1b86014c5e1340c2a210833248bc765dae", - "sha256:ae84bacfdc60792bd04e681027cc5c58e6737a04c652e9be2eda84abe21f57f5", - "sha256:b8201a33caf7632b2e55e3f9687584ad6956aaf5751485cdb2bad7c428a9b400", - "sha256:bf6757d422954e61082715dbba4208cae17bf3720006bc337c3f87f19ede2876", - "sha256:ceef4fef2a5cffb69e9e1742bd18a35625ca62c3856c7016c22be68ec876753d", - "sha256:d0c18210648889416da3de61aa282248e012cb507ba9841511407f922fff9a52", - "sha256:d3be6c97d007ceb142f908f5ab2444807b44dc600a0b7f3254dc685b5b03fd10", - "sha256:e2576bbec0b640d9b76454dcfd5b2f03078e0bb062a7ea3952a8db7b9972c352", - "sha256:f4605bc4feb114235e242dfe260b75ec85d0894f5400aa7f30e75fbbc0423b3f" + "sha256:07743279225f860444283c4dcaa7ccd02944e61ce95d666b6ab00188bb1f7f99", + "sha256:0bd29b99dce7402635922df984c338358fbe159f0df9b153d1e913bed77210d3", + "sha256:0e1e40fe4b953925f86590a74a7de2488fa37f1ba9c9f5ebcc3f765b9ba3bd1b", + "sha256:0f5e404d46d6e24c920dfb0ad441e88fde633ced747f9894c1654263c9ed2c59", + "sha256:14894911effd29f7bca70126ff991d4291198c6b1d9a29c9aa10d9743a685c27", + "sha256:273c30db450d2ae3fa0c2bce583e7d64a4cdb2b957c94bf4202bcfb30bfee411", + "sha256:348c298232d6323b31d65d95dc97ac55d9b0117feb713a8f1c6baa056e7f6204", + "sha256:3c5cc86c88302623375e282ec17a1c55da739f2ab58ca48607f85c48a43cba33", + "sha256:3eba2b1a0c1b31d42f5ea1a80f60e57483898faf86bb24474dbd7d0a7fad41b0", + "sha256:49cabe8222da2515d1e6a113f9fccd8a9d41ca3678dec9592e87a01ea0005056", + "sha256:52c801bd2147acfec8cbbf92adba8cab3d8d19982eceaa08409a3938d6f8524a", + "sha256:632435a5f5170dd9a72012b6c21ca62ec2e9e4b24e7d52fc4d895a359dbba652", + "sha256:63636e34ab52a303ad21afd5d7f5c6418e814fcb8d3430266db4a3cfc7e19aef", + "sha256:6ee7edcd5d364c6d2d97922aa436f5d27788a7ab9e8aa845ecaf59ddf7c66457", + "sha256:7405bfc65d6d983a738e756044956f06c366a234fdde0ccf7cf0d52fedfd72e4", + "sha256:743b5ff8a2ad02989ea87334391506dbcb578436a4d8cc49e819421ca2e5f743", + "sha256:75c73cd71005e1467a76b9108dbd355fc256e12b822b2fdc28810bde991cc92e", + "sha256:7ebbef59d94d5feaae5eab56a44df5a677b90ac75e437d48eb6b71ae7d8e6f9d", + "sha256:aa8addb08bf7595eeb65ada2b33d9272541b6e872e519382be28690a920f4785", + "sha256:abc7487cff166de747da8b05b108150a6f7f2c855b3d2547cfb1f53b9330e7dd", + "sha256:b70eed56613147a96a5ae4c559c42f54ea00d4d52e5679ac9b9d93c4d6e572a4", + "sha256:bd417c5873b45c8154cca92d81ab159f6c5058138ff848cba4c9e02f10ad5c61", + "sha256:c59adb97aaa4d111a33e3f936bf85d990f8837cabe51cebb1c6128778006563f", + "sha256:d5fe36aae1154610d2d03cd8cdfc52b6ea3f63a0b672b14185e4e1532016f826", + "sha256:d720f97c844a015cd54d69e052f0956e93e45fcd33b829e8cc20356af6a0b0c4", + "sha256:db3cc230970902c2548e5d747ce96d38bc009d087cf49bef4ce8679cdedc57c1", + "sha256:dbfe4a0f2d34d8d9ef31cee7c73a49d3fe2b9a92129d70819058f1df736cdd38", + "sha256:ec37f7bd9df294b17948fcfa761e0fe06301c7eaea4bbd97f4afe04dc2acbbac", + "sha256:f9ab59b30729532bab64497910c1051665269814366be8ee3fde2391032dd9f6" ], "index": "pypi", "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", - "version": "==9.10.0" + "version": "==9.13.0" }, "packaging": { "hashes": [ - "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5", - "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9" + "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002", + "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124" ], - "markers": "python_version >= '3.7'", - "version": "==24.0" + "markers": "python_version >= '3.8'", + "version": "==24.1" }, "pillow": { "hashes": [ @@ -868,11 +1147,11 @@ }, "prompt-toolkit": { "hashes": [ - "sha256:07c60ee4ab7b7e90824b61afa840c8f5aad2d46b3e2e10acc33d8ecc94a49089", - "sha256:a29b89160e494e3ea8622b09fa5897610b437884dcdcd054fdc1308883326c2a" + "sha256:0d7bfa67001d5e39d02c224b663abc33687405033a8c422d0d675a5a13361d10", + "sha256:1e1b29cb58080b1e69f207c893a1a7bf16d127a5c30c9d17a25a5d77792e5360" ], "markers": "python_full_version >= '3.7.0'", - "version": "==3.0.45" + "version": "==3.0.47" }, "psycopg": { "extras": [ @@ -1033,67 +1312,69 @@ }, "pywebpush": { "hashes": [ - "sha256:6c36e1679268219e693ba940db2bf254c240ca02664de102b7269afc3c545731" + "sha256:03ccc3e975b60374b7634c495595616be523bf2c7da0d976e84fda9ac8c63301" ], "index": "pypi", - "version": "==1.14.0" + "version": "==2.0.0" }, "pyyaml": { "hashes": [ - "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5", - "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc", - "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df", - "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741", - "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206", - "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27", - "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595", - "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62", - "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98", - "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696", - "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290", - "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9", - "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d", - "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6", - "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867", - "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47", - "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486", - "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6", - "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3", - "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007", - "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938", - "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0", - "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c", - "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735", - "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d", - "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28", - "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4", - "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba", - "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8", - "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef", - "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5", - "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd", - "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3", - "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0", - "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515", - "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c", - "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c", - "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924", - "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34", - "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43", - "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859", - "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673", - "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54", - "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a", - "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b", - "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab", - "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa", - "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c", - "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585", - "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d", - "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f" - ], - "markers": "python_version >= '3.6'", - "version": "==6.0.1" + "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff", + "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", + "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", + "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e", + "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", + "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", + "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", + "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", + "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", + "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", + "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a", + "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", + "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", + "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8", + "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", + "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19", + "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", + "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a", + "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", + "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", + "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", + "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631", + "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d", + "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", + "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", + "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", + "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", + "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", + "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", + "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706", + "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", + "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", + "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", + "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083", + "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", + "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", + "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", + "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f", + "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725", + "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", + "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", + "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", + "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", + "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", + "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5", + "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d", + "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290", + "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", + "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", + "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", + "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", + "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12", + "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4" + ], + "markers": "python_version >= '3.8'", + "version": "==6.0.2" }, "redis": { "extras": [ @@ -1103,7 +1384,6 @@ "sha256:30b47d4ebb6b7a0b9b40c1275a19b87bb6f46b3bed82a89012cf56dea4024ada", "sha256:3417688621acf6ee368dec4a04dd95881be24efd34c79f00d31f62bb528800ae" ], - "index": "pypi", "markers": "python_version >= '3.7'", "version": "==5.0.5" }, @@ -1135,125 +1415,129 @@ }, "rpds-py": { "hashes": [ - "sha256:05f3d615099bd9b13ecf2fc9cf2d839ad3f20239c678f461c753e93755d629ee", - "sha256:06d218939e1bf2ca50e6b0ec700ffe755e5216a8230ab3e87c059ebb4ea06afc", - "sha256:07f2139741e5deb2c5154a7b9629bc5aa48c766b643c1a6750d16f865a82c5fc", - "sha256:08d74b184f9ab6289b87b19fe6a6d1a97fbfea84b8a3e745e87a5de3029bf944", - "sha256:0abeee75434e2ee2d142d650d1e54ac1f8b01e6e6abdde8ffd6eeac6e9c38e20", - "sha256:154bf5c93d79558b44e5b50cc354aa0459e518e83677791e6adb0b039b7aa6a7", - "sha256:17c6d2155e2423f7e79e3bb18151c686d40db42d8645e7977442170c360194d4", - "sha256:1805d5901779662d599d0e2e4159d8a82c0b05faa86ef9222bf974572286b2b6", - "sha256:19ba472b9606c36716062c023afa2484d1e4220548751bda14f725a7de17b4f6", - "sha256:19e515b78c3fc1039dd7da0a33c28c3154458f947f4dc198d3c72db2b6b5dc93", - "sha256:1d54f74f40b1f7aaa595a02ff42ef38ca654b1469bef7d52867da474243cc633", - "sha256:207c82978115baa1fd8d706d720b4a4d2b0913df1c78c85ba73fe6c5804505f0", - "sha256:2625f03b105328729f9450c8badda34d5243231eef6535f80064d57035738360", - "sha256:27bba383e8c5231cd559affe169ca0b96ec78d39909ffd817f28b166d7ddd4d8", - "sha256:2c3caec4ec5cd1d18e5dd6ae5194d24ed12785212a90b37f5f7f06b8bedd7139", - "sha256:2cc7c1a47f3a63282ab0f422d90ddac4aa3034e39fc66a559ab93041e6505da7", - "sha256:2fc24a329a717f9e2448f8cd1f960f9dac4e45b6224d60734edeb67499bab03a", - "sha256:312fe69b4fe1ffbe76520a7676b1e5ac06ddf7826d764cc10265c3b53f96dbe9", - "sha256:32b7daaa3e9389db3695964ce8e566e3413b0c43e3394c05e4b243a4cd7bef26", - "sha256:338dee44b0cef8b70fd2ef54b4e09bb1b97fc6c3a58fea5db6cc083fd9fc2724", - "sha256:352a88dc7892f1da66b6027af06a2e7e5d53fe05924cc2cfc56495b586a10b72", - "sha256:35b2b771b13eee8729a5049c976197ff58a27a3829c018a04341bcf1ae409b2b", - "sha256:38e14fb4e370885c4ecd734f093a2225ee52dc384b86fa55fe3f74638b2cfb09", - "sha256:3c20f05e8e3d4fc76875fc9cb8cf24b90a63f5a1b4c5b9273f0e8225e169b100", - "sha256:3dd3cd86e1db5aadd334e011eba4e29d37a104b403e8ca24dcd6703c68ca55b3", - "sha256:489bdfe1abd0406eba6b3bb4fdc87c7fa40f1031de073d0cfb744634cc8fa261", - "sha256:48c2faaa8adfacefcbfdb5f2e2e7bdad081e5ace8d182e5f4ade971f128e6bb3", - "sha256:4a98a1f0552b5f227a3d6422dbd61bc6f30db170939bd87ed14f3c339aa6c7c9", - "sha256:4adec039b8e2928983f885c53b7cc4cda8965b62b6596501a0308d2703f8af1b", - "sha256:4e0ee01ad8260184db21468a6e1c37afa0529acc12c3a697ee498d3c2c4dcaf3", - "sha256:51584acc5916212e1bf45edd17f3a6b05fe0cbb40482d25e619f824dccb679de", - "sha256:531796fb842b53f2695e94dc338929e9f9dbf473b64710c28af5a160b2a8927d", - "sha256:5463c47c08630007dc0fe99fb480ea4f34a89712410592380425a9b4e1611d8e", - "sha256:5c45a639e93a0c5d4b788b2613bd637468edd62f8f95ebc6fcc303d58ab3f0a8", - "sha256:6031b25fb1b06327b43d841f33842b383beba399884f8228a6bb3df3088485ff", - "sha256:607345bd5912aacc0c5a63d45a1f73fef29e697884f7e861094e443187c02be5", - "sha256:618916f5535784960f3ecf8111581f4ad31d347c3de66d02e728de460a46303c", - "sha256:636a15acc588f70fda1661234761f9ed9ad79ebed3f2125d44be0862708b666e", - "sha256:673fdbbf668dd958eff750e500495ef3f611e2ecc209464f661bc82e9838991e", - "sha256:6afd80f6c79893cfc0574956f78a0add8c76e3696f2d6a15bca2c66c415cf2d4", - "sha256:6b5ff7e1d63a8281654b5e2896d7f08799378e594f09cf3674e832ecaf396ce8", - "sha256:6c4c4c3f878df21faf5fac86eda32671c27889e13570645a9eea0a1abdd50922", - "sha256:6cd8098517c64a85e790657e7b1e509b9fe07487fd358e19431cb120f7d96338", - "sha256:6d1e42d2735d437e7e80bab4d78eb2e459af48c0a46e686ea35f690b93db792d", - "sha256:6e30ac5e329098903262dc5bdd7e2086e0256aa762cc8b744f9e7bf2a427d3f8", - "sha256:70a838f7754483bcdc830444952fd89645569e7452e3226de4a613a4c1793fb2", - "sha256:720edcb916df872d80f80a1cc5ea9058300b97721efda8651efcd938a9c70a72", - "sha256:732672fbc449bab754e0b15356c077cc31566df874964d4801ab14f71951ea80", - "sha256:740884bc62a5e2bbb31e584f5d23b32320fd75d79f916f15a788d527a5e83644", - "sha256:7700936ef9d006b7ef605dc53aa364da2de5a3aa65516a1f3ce73bf82ecfc7ae", - "sha256:7732770412bab81c5a9f6d20aeb60ae943a9b36dcd990d876a773526468e7163", - "sha256:7750569d9526199c5b97e5a9f8d96a13300950d910cf04a861d96f4273d5b104", - "sha256:7f1944ce16401aad1e3f7d312247b3d5de7981f634dc9dfe90da72b87d37887d", - "sha256:81c5196a790032e0fc2464c0b4ab95f8610f96f1f2fa3d4deacce6a79852da60", - "sha256:8352f48d511de5f973e4f2f9412736d7dea76c69faa6d36bcf885b50c758ab9a", - "sha256:8927638a4d4137a289e41d0fd631551e89fa346d6dbcfc31ad627557d03ceb6d", - "sha256:8c7672e9fba7425f79019db9945b16e308ed8bc89348c23d955c8c0540da0a07", - "sha256:8d2e182c9ee01135e11e9676e9a62dfad791a7a467738f06726872374a83db49", - "sha256:910e71711d1055b2768181efa0a17537b2622afeb0424116619817007f8a2b10", - "sha256:942695a206a58d2575033ff1e42b12b2aece98d6003c6bc739fbf33d1773b12f", - "sha256:9437ca26784120a279f3137ee080b0e717012c42921eb07861b412340f85bae2", - "sha256:967342e045564cef76dfcf1edb700b1e20838d83b1aa02ab313e6a497cf923b8", - "sha256:998125738de0158f088aef3cb264a34251908dd2e5d9966774fdab7402edfab7", - "sha256:9e6934d70dc50f9f8ea47081ceafdec09245fd9f6032669c3b45705dea096b88", - "sha256:a3d456ff2a6a4d2adcdf3c1c960a36f4fd2fec6e3b4902a42a384d17cf4e7a65", - "sha256:a7b28c5b066bca9a4eb4e2f2663012debe680f097979d880657f00e1c30875a0", - "sha256:a888e8bdb45916234b99da2d859566f1e8a1d2275a801bb8e4a9644e3c7e7909", - "sha256:aa3679e751408d75a0b4d8d26d6647b6d9326f5e35c00a7ccd82b78ef64f65f8", - "sha256:aaa71ee43a703c321906813bb252f69524f02aa05bf4eec85f0c41d5d62d0f4c", - "sha256:b646bf655b135ccf4522ed43d6902af37d3f5dbcf0da66c769a2b3938b9d8184", - "sha256:b906b5f58892813e5ba5c6056d6a5ad08f358ba49f046d910ad992196ea61397", - "sha256:b9bb1f182a97880f6078283b3505a707057c42bf55d8fca604f70dedfdc0772a", - "sha256:bd1105b50ede37461c1d51b9698c4f4be6e13e69a908ab7751e3807985fc0346", - "sha256:bf18932d0003c8c4d51a39f244231986ab23ee057d235a12b2684ea26a353590", - "sha256:c273e795e7a0f1fddd46e1e3cb8be15634c29ae8ff31c196debb620e1edb9333", - "sha256:c69882964516dc143083d3795cb508e806b09fc3800fd0d4cddc1df6c36e76bb", - "sha256:c827576e2fa017a081346dce87d532a5310241648eb3700af9a571a6e9fc7e74", - "sha256:cbfbea39ba64f5e53ae2915de36f130588bba71245b418060ec3330ebf85678e", - "sha256:ce0bb20e3a11bd04461324a6a798af34d503f8d6f1aa3d2aa8901ceaf039176d", - "sha256:d0cee71bc618cd93716f3c1bf56653740d2d13ddbd47673efa8bf41435a60daa", - "sha256:d21be4770ff4e08698e1e8e0bce06edb6ea0626e7c8f560bc08222880aca6a6f", - "sha256:d31dea506d718693b6b2cffc0648a8929bdc51c70a311b2770f09611caa10d53", - "sha256:d44607f98caa2961bab4fa3c4309724b185b464cdc3ba6f3d7340bac3ec97cc1", - "sha256:d58ad6317d188c43750cb76e9deacf6051d0f884d87dc6518e0280438648a9ac", - "sha256:d70129cef4a8d979caa37e7fe957202e7eee8ea02c5e16455bc9808a59c6b2f0", - "sha256:d85164315bd68c0806768dc6bb0429c6f95c354f87485ee3593c4f6b14def2bd", - "sha256:d960de62227635d2e61068f42a6cb6aae91a7fe00fca0e3aeed17667c8a34611", - "sha256:dc48b479d540770c811fbd1eb9ba2bb66951863e448efec2e2c102625328e92f", - "sha256:e1735502458621921cee039c47318cb90b51d532c2766593be6207eec53e5c4c", - "sha256:e2be6e9dd4111d5b31ba3b74d17da54a8319d8168890fbaea4b9e5c3de630ae5", - "sha256:e4c39ad2f512b4041343ea3c7894339e4ca7839ac38ca83d68a832fc8b3748ab", - "sha256:ed402d6153c5d519a0faf1bb69898e97fb31613b49da27a84a13935ea9164dfc", - "sha256:ee17cd26b97d537af8f33635ef38be873073d516fd425e80559f4585a7b90c43", - "sha256:f3027be483868c99b4985fda802a57a67fdf30c5d9a50338d9db646d590198da", - "sha256:f5bab211605d91db0e2995a17b5c6ee5edec1270e46223e513eaa20da20076ac", - "sha256:f6f8e3fecca256fefc91bb6765a693d96692459d7d4c644660a9fff32e517843", - "sha256:f7afbfee1157e0f9376c00bb232e80a60e59ed716e3211a80cb8506550671e6e", - "sha256:fa242ac1ff583e4ec7771141606aafc92b361cd90a05c30d93e343a0c2d82a89", - "sha256:fab6ce90574645a0d6c58890e9bcaac8d94dff54fb51c69e5522a7358b80ab64" - ], - "markers": "python_version >= '3.8'", - "version": "==0.18.1" + "sha256:06db23d43f26478303e954c34c75182356ca9aa7797d22c5345b16871ab9c45c", + "sha256:0e13e6952ef264c40587d510ad676a988df19adea20444c2b295e536457bc585", + "sha256:11ef6ce74616342888b69878d45e9f779b95d4bd48b382a229fe624a409b72c5", + "sha256:1259c7b3705ac0a0bd38197565a5d603218591d3f6cee6e614e380b6ba61c6f6", + "sha256:18d7585c463087bddcfa74c2ba267339f14f2515158ac4db30b1f9cbdb62c8ef", + "sha256:1e0f80b739e5a8f54837be5d5c924483996b603d5502bfff79bf33da06164ee2", + "sha256:1e5f3cd7397c8f86c8cc72d5a791071431c108edd79872cdd96e00abd8497d29", + "sha256:220002c1b846db9afd83371d08d239fdc865e8f8c5795bbaec20916a76db3318", + "sha256:22e6c9976e38f4d8c4a63bd8a8edac5307dffd3ee7e6026d97f3cc3a2dc02a0b", + "sha256:238a2d5b1cad28cdc6ed15faf93a998336eb041c4e440dd7f902528b8891b399", + "sha256:2580b0c34583b85efec8c5c5ec9edf2dfe817330cc882ee972ae650e7b5ef739", + "sha256:28527c685f237c05445efec62426d285e47a58fb05ba0090a4340b73ecda6dee", + "sha256:2cf126d33a91ee6eedc7f3197b53e87a2acdac63602c0f03a02dd69e4b138174", + "sha256:338ca4539aad4ce70a656e5187a3a31c5204f261aef9f6ab50e50bcdffaf050a", + "sha256:39ed0d010457a78f54090fafb5d108501b5aa5604cc22408fc1c0c77eac14344", + "sha256:3ad0fda1635f8439cde85c700f964b23ed5fc2d28016b32b9ee5fe30da5c84e2", + "sha256:3d2b1ad682a3dfda2a4e8ad8572f3100f95fad98cb99faf37ff0ddfe9cbf9d03", + "sha256:3d61339e9f84a3f0767b1995adfb171a0d00a1185192718a17af6e124728e0f5", + "sha256:3fde368e9140312b6e8b6c09fb9f8c8c2f00999d1823403ae90cc00480221b22", + "sha256:40ce74fc86ee4645d0a225498d091d8bc61f39b709ebef8204cb8b5a464d3c0e", + "sha256:49a8063ea4296b3a7e81a5dfb8f7b2d73f0b1c20c2af401fb0cdf22e14711a96", + "sha256:4a1f1d51eccb7e6c32ae89243cb352389228ea62f89cd80823ea7dd1b98e0b91", + "sha256:4b16aa0107ecb512b568244ef461f27697164d9a68d8b35090e9b0c1c8b27752", + "sha256:4f1ed4749a08379555cebf4650453f14452eaa9c43d0a95c49db50c18b7da075", + "sha256:4fe84294c7019456e56d93e8ababdad5a329cd25975be749c3f5f558abb48253", + "sha256:50eccbf054e62a7b2209b28dc7a22d6254860209d6753e6b78cfaeb0075d7bee", + "sha256:514b3293b64187172bc77c8fb0cdae26981618021053b30d8371c3a902d4d5ad", + "sha256:54b43a2b07db18314669092bb2de584524d1ef414588780261e31e85846c26a5", + "sha256:55fea87029cded5df854ca7e192ec7bdb7ecd1d9a3f63d5c4eb09148acf4a7ce", + "sha256:569b3ea770c2717b730b61998b6c54996adee3cef69fc28d444f3e7920313cf7", + "sha256:56e27147a5a4c2c21633ff8475d185734c0e4befd1c989b5b95a5d0db699b21b", + "sha256:57eb94a8c16ab08fef6404301c38318e2c5a32216bf5de453e2714c964c125c8", + "sha256:5a35df9f5548fd79cb2f52d27182108c3e6641a4feb0f39067911bf2adaa3e57", + "sha256:5a8c94dad2e45324fc74dce25e1645d4d14df9a4e54a30fa0ae8bad9a63928e3", + "sha256:5b4f105deeffa28bbcdff6c49b34e74903139afa690e35d2d9e3c2c2fba18cec", + "sha256:5c1dc0f53856b9cc9a0ccca0a7cc61d3d20a7088201c0937f3f4048c1718a209", + "sha256:614fdafe9f5f19c63ea02817fa4861c606a59a604a77c8cdef5aa01d28b97921", + "sha256:617c7357272c67696fd052811e352ac54ed1d9b49ab370261a80d3b6ce385045", + "sha256:65794e4048ee837494aea3c21a28ad5fc080994dfba5b036cf84de37f7ad5074", + "sha256:6632f2d04f15d1bd6fe0eedd3b86d9061b836ddca4c03d5cf5c7e9e6b7c14580", + "sha256:6c8ef2ebf76df43f5750b46851ed1cdf8f109d7787ca40035fe19fbdc1acc5a7", + "sha256:758406267907b3781beee0f0edfe4a179fbd97c0be2e9b1154d7f0a1279cf8e5", + "sha256:7e60cb630f674a31f0368ed32b2a6b4331b8350d67de53c0359992444b116dd3", + "sha256:89c19a494bf3ad08c1da49445cc5d13d8fefc265f48ee7e7556839acdacf69d0", + "sha256:8a86a9b96070674fc88b6f9f71a97d2c1d3e5165574615d1f9168ecba4cecb24", + "sha256:8bc7690f7caee50b04a79bf017a8d020c1f48c2a1077ffe172abec59870f1139", + "sha256:8d7919548df3f25374a1f5d01fbcd38dacab338ef5f33e044744b5c36729c8db", + "sha256:9426133526f69fcaba6e42146b4e12d6bc6c839b8b555097020e2b78ce908dcc", + "sha256:9824fb430c9cf9af743cf7aaf6707bf14323fb51ee74425c380f4c846ea70789", + "sha256:9bb4a0d90fdb03437c109a17eade42dfbf6190408f29b2744114d11586611d6f", + "sha256:9bc2d153989e3216b0559251b0c260cfd168ec78b1fac33dd485750a228db5a2", + "sha256:9d35cef91e59ebbeaa45214861874bc6f19eb35de96db73e467a8358d701a96c", + "sha256:a1862d2d7ce1674cffa6d186d53ca95c6e17ed2b06b3f4c476173565c862d232", + "sha256:a84ab91cbe7aab97f7446652d0ed37d35b68a465aeef8fc41932a9d7eee2c1a6", + "sha256:aa7f429242aae2947246587d2964fad750b79e8c233a2367f71b554e9447949c", + "sha256:aa9a0521aeca7d4941499a73ad7d4f8ffa3d1affc50b9ea11d992cd7eff18a29", + "sha256:ac2f4f7a98934c2ed6505aead07b979e6f999389f16b714448fb39bbaa86a489", + "sha256:ae94bd0b2f02c28e199e9bc51485d0c5601f58780636185660f86bf80c89af94", + "sha256:af0fc424a5842a11e28956e69395fbbeab2c97c42253169d87e90aac2886d751", + "sha256:b2a5db5397d82fa847e4c624b0c98fe59d2d9b7cf0ce6de09e4d2e80f8f5b3f2", + "sha256:b4c29cbbba378759ac5786730d1c3cb4ec6f8ababf5c42a9ce303dc4b3d08cda", + "sha256:b74b25f024b421d5859d156750ea9a65651793d51b76a2e9238c05c9d5f203a9", + "sha256:b7f19250ceef892adf27f0399b9e5afad019288e9be756d6919cb58892129f51", + "sha256:b80d4a7900cf6b66bb9cee5c352b2d708e29e5a37fe9bf784fa97fc11504bf6c", + "sha256:b8c00a3b1e70c1d3891f0db1b05292747f0dbcfb49c43f9244d04c70fbc40eb8", + "sha256:bb273176be34a746bdac0b0d7e4e2c467323d13640b736c4c477881a3220a989", + "sha256:c3c20f0ddeb6e29126d45f89206b8291352b8c5b44384e78a6499d68b52ae511", + "sha256:c3e130fd0ec56cb76eb49ef52faead8ff09d13f4527e9b0c400307ff72b408e1", + "sha256:c52d3f2f82b763a24ef52f5d24358553e8403ce05f893b5347098014f2d9eff2", + "sha256:c6377e647bbfd0a0b159fe557f2c6c602c159fc752fa316572f012fc0bf67150", + "sha256:c638144ce971df84650d3ed0096e2ae7af8e62ecbbb7b201c8935c370df00a2c", + "sha256:ce9845054c13696f7af7f2b353e6b4f676dab1b4b215d7fe5e05c6f8bb06f965", + "sha256:cf258ede5bc22a45c8e726b29835b9303c285ab46fc7c3a4cc770736b5304c9f", + "sha256:d0a26ffe9d4dd35e4dfdd1e71f46401cff0181c75ac174711ccff0459135fa58", + "sha256:d0b67d87bb45ed1cd020e8fbf2307d449b68abc45402fe1a4ac9e46c3c8b192b", + "sha256:d20277fd62e1b992a50c43f13fbe13277a31f8c9f70d59759c88f644d66c619f", + "sha256:d454b8749b4bd70dd0a79f428731ee263fa6995f83ccb8bada706e8d1d3ff89d", + "sha256:d4c7d1a051eeb39f5c9547e82ea27cbcc28338482242e3e0b7768033cb083821", + "sha256:d72278a30111e5b5525c1dd96120d9e958464316f55adb030433ea905866f4de", + "sha256:d72a210824facfdaf8768cf2d7ca25a042c30320b3020de2fa04640920d4e121", + "sha256:d807dc2051abe041b6649681dce568f8e10668e3c1c6543ebae58f2d7e617855", + "sha256:dbe982f38565bb50cb7fb061ebf762c2f254ca3d8c20d4006878766e84266272", + "sha256:dcedf0b42bcb4cfff4101d7771a10532415a6106062f005ab97d1d0ab5681c60", + "sha256:deb62214c42a261cb3eb04d474f7155279c1a8a8c30ac89b7dcb1721d92c3c02", + "sha256:def7400461c3a3f26e49078302e1c1b38f6752342c77e3cf72ce91ca69fb1bc1", + "sha256:df3de6b7726b52966edf29663e57306b23ef775faf0ac01a3e9f4012a24a4140", + "sha256:e1940dae14e715e2e02dfd5b0f64a52e8374a517a1e531ad9412319dc3ac7879", + "sha256:e4df1e3b3bec320790f699890d41c59d250f6beda159ea3c44c3f5bac1976940", + "sha256:e6900ecdd50ce0facf703f7a00df12374b74bbc8ad9fe0f6559947fb20f82364", + "sha256:ea438162a9fcbee3ecf36c23e6c68237479f89f962f82dae83dc15feeceb37e4", + "sha256:eb851b7df9dda52dc1415ebee12362047ce771fc36914586b2e9fcbd7d293b3e", + "sha256:ec31a99ca63bf3cd7f1a5ac9fe95c5e2d060d3c768a09bc1d16e235840861420", + "sha256:f0475242f447cc6cb8a9dd486d68b2ef7fbee84427124c232bff5f63b1fe11e5", + "sha256:f2fbf7db2012d4876fb0d66b5b9ba6591197b0f165db8d99371d976546472a24", + "sha256:f60012a73aa396be721558caa3a6fd49b3dd0033d1675c6d59c4502e870fcf0c", + "sha256:f8e604fe73ba048c06085beaf51147eaec7df856824bfe7b98657cf436623daf", + "sha256:f90a4cd061914a60bd51c68bcb4357086991bd0bb93d8aa66a6da7701370708f", + "sha256:f918a1a130a6dfe1d7fe0f105064141342e7dd1611f2e6a21cd2f5c8cb1cfb3e", + "sha256:fa518bcd7600c584bf42e6617ee8132869e877db2f76bcdc281ec6a4113a53ab", + "sha256:faefcc78f53a88f3076b7f8be0a8f8d35133a3ecf7f3770895c25f8813460f08", + "sha256:fcaeb7b57f1a1e071ebd748984359fef83ecb026325b9d4ca847c95bc7311c92", + "sha256:fd2d84f40633bc475ef2d5490b9c19543fbf18596dcb1b291e3a12ea5d722f7a", + "sha256:fdfc3a892927458d98f3d55428ae46b921d1f7543b89382fdb483f5640daaec8" + ], + "markers": "python_version >= '3.8'", + "version": "==0.20.0" }, "s3transfer": { "hashes": [ - "sha256:5683916b4c724f799e600f41dd9e10a9ff19871bf87623cc8f491cb4f5fa0a19", - "sha256:ceb252b11bcf87080fb7850a224fb6e05c8a776bab8f2b64b7f25b969464839d" + "sha256:0711534e9356d3cc692fdde846b4a1e4b0cb6519971860796e6bc4c7aea00ef6", + "sha256:eca1c20de70a39daee580aef4986996620f365c4e0fda6a86100231d62f1bf69" ], "markers": "python_version >= '3.8'", - "version": "==0.10.1" + "version": "==0.10.2" }, "sentry-sdk": { "hashes": [ - "sha256:1f87acdce4a43a523ae5aa21a3fc37522d73ebd9ec04b1dbf01aa3d173852def", - "sha256:fbc40a78a8a9c6675133031116144f0d0940376fa6e4e1acd5624c90b0aaf58b" + "sha256:6beede8fc2ab4043da7f69d95534e320944690680dd9a963178a49de71d726c6", + "sha256:8d4a576f7a98eb2fdb40e13106e41f330e5c79d72a68be1316e7852cf4995260" ], "index": "pypi", "markers": "python_version >= '3.6'", - "version": "==2.5.1" + "version": "==2.13.0" }, "six": { "hashes": [ @@ -1265,11 +1549,11 @@ }, "sqlparse": { "hashes": [ - "sha256:714d0a4932c059d16189f58ef5411ec2287a4360f17cdd0edd2d09d4c5087c93", - "sha256:c204494cd97479d0e39f28c93d46c0b2d5959c7b9ab904762ea6c7af211c8663" + "sha256:773dcbf9a5ab44a090f3441e2180efe2560220203dc2f8c0b0fa141e18b505e4", + "sha256:bb6b4df465655ef332548e24f08e205afc81b9ab86cb1c45657a7ff173a3a00e" ], "markers": "python_version >= '3.8'", - "version": "==0.5.0" + "version": "==0.5.1" }, "text-unidecode": { "hashes": [ @@ -1288,35 +1572,35 @@ }, "types-pyopenssl": { "hashes": [ - "sha256:0a7e82626c1983dc8dc59292bf20654a51c3c3881bcbb9b337c1da6e32f0204e", - "sha256:f51a156835555dd2a1f025621e8c4fbe7493470331afeef96884d1d29bf3a473" + "sha256:47913b4678a01d879f503a12044468221ed8576263c1540dcb0484ca21b08c39", + "sha256:6a7a5d2ec042537934cfb4c9d4deb0e16c4c6250b09358df1f083682fe6fda54" ], "markers": "python_version >= '3.8'", - "version": "==24.1.0.20240425" + "version": "==24.1.0.20240722" }, "types-redis": { "hashes": [ - "sha256:9402a10ee931d241fdfcc04592ebf7a661d7bb92a8dea631279f0d8acbcf3a22", - "sha256:ac5bc19e8f5997b9e76ad5d9cf15d0392d9f28cf5fc7746ea4a64b989c45c6a8" + "sha256:08f51f550ad41d0152bd98d77ac9d6d8f761369121710a213642f6036b9a7183", + "sha256:86db9af6f0033154e12bc22c77236cef0907b995fda8c9f0f0eacd59943ed2fc" ], "markers": "python_version >= '3.8'", - "version": "==4.6.0.20240425" + "version": "==4.6.0.20240819" }, "types-setuptools": { "hashes": [ - "sha256:8f5379b9948682d72a9ab531fbe52932e84c4f38deda570255f9bae3edd766bc", - "sha256:e31fee7b9d15ef53980526579ac6089b3ae51a005a281acf97178e90ac71aff6" + "sha256:3a060681098eb3fbc2fea0a86f7f6af6aa1ca71906039d88d891ea2cecdd4dbf", + "sha256:b9eba9b68546031317a0fa506d4973641d987d74f79e7dd8369ad4f7a93dea17" ], "markers": "python_version >= '3.8'", - "version": "==70.0.0.20240524" + "version": "==73.0.0.20240822" }, "typing-extensions": { "hashes": [ - "sha256:6024b58b69089e5a89c347397254e35f1bf02a907728ec7fee9bf0fe837d203a", - "sha256:915f5e35ff76f56588223f15fdd5938f9a1cf9195c0de25130c627e4d597f6d1" + "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", + "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8" ], "markers": "python_version >= '3.8'", - "version": "==4.12.1" + "version": "==4.12.2" }, "tzdata": { "hashes": [ @@ -1342,11 +1626,11 @@ }, "urllib3": { "hashes": [ - "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d", - "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19" + "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472", + "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168" ], "markers": "python_version >= '3.8'", - "version": "==2.2.1" + "version": "==2.2.2" }, "vine": { "hashes": [ @@ -1371,6 +1655,102 @@ "index": "pypi", "markers": "python_version >= '3.8'", "version": "==6.6.0" + }, + "yarl": { + "hashes": [ + "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51", + "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce", + "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559", + "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0", + "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81", + "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc", + "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4", + "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c", + "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130", + "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136", + "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e", + "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec", + "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7", + "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1", + "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455", + "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099", + "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129", + "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10", + "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142", + "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98", + "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa", + "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7", + "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525", + "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c", + "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9", + "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c", + "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8", + "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b", + "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf", + "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23", + "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd", + "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27", + "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f", + "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece", + "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434", + "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec", + "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff", + "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78", + "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d", + "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863", + "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53", + "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31", + "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15", + "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5", + "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b", + "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57", + "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3", + "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1", + "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f", + "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad", + "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c", + "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7", + "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2", + "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b", + "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2", + "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b", + "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9", + "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be", + "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e", + "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984", + "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4", + "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074", + "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2", + "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392", + "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91", + "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541", + "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf", + "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572", + "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66", + "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575", + "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14", + "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5", + "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1", + "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e", + "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551", + "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17", + "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead", + "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0", + "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe", + "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234", + "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0", + "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7", + "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34", + "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42", + "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385", + "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78", + "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be", + "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958", + "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749", + "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec" + ], + "markers": "python_version >= '3.7'", + "version": "==1.9.4" } }, "develop": { @@ -1391,11 +1771,11 @@ }, "autopep8": { "hashes": [ - "sha256:05418a981f038969d8bdcd5636bf15948db7555ae944b9f79b5a34b35f1370d4", - "sha256:d306a0581163ac29908280ad557773a95a9bede072c0fafed6f141f5311f43c1" + "sha256:8d6c87eba648fdcfc83e29b788910b8643171c395d9c4bcf115ece035b9c9dda", + "sha256:a203fe0fcad7939987422140ab17a930f684763bf7335bdb6709991dd7ef6c2d" ], "markers": "python_version >= '3.8'", - "version": "==2.2.0" + "version": "==2.3.1" }, "black": { "hashes": [ @@ -1428,12 +1808,12 @@ }, "boto3": { "hashes": [ - "sha256:1506589e30566bbb2f4997b60968ff7d4ef8a998836c31eedd36437ac3b7408a", - "sha256:c8a383b904d6faaf7eed0c06e31b423db128e4c09ce7bd2afc39d1cd07030a51" + "sha256:ada32dab854c46a877cf967b8a55ab1a7d356c3c87f1c8bd556d446ff03dfd95", + "sha256:bdc242e3ea81decc6ea551b04b2c122f088c29269d8e093b55862946aa0fcfc6" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==1.34.117" + "version": "==1.35.0" }, "boto3-stubs": { "extras": [ @@ -1441,35 +1821,35 @@ "s3" ], "hashes": [ - "sha256:d9ac034dd943d545d1f067ad7976cdbc729c689d16c961b8bc26ec595838beac", - "sha256:f2cf09536486d08dd6e132b742de17df16ab635f7bdc8106a56abce55583a62a" + "sha256:786d93ec9df8bfdb7ee21e4e4ecadcf0be4e67cbe09d16148ceba26f1706d9e1", + "sha256:80cf941607a0d9c756e13c9c19533aec29f63bdead3dbaa97ef2a501f7159fd8" ], "markers": "python_version >= '3.8'", - "version": "==1.34.117" + "version": "==1.35.0" }, "botocore": { "hashes": [ - "sha256:26a431997f882bcdd1e835f44c24b2a1752b1c4e5183c2ce62999ce95d518d6c", - "sha256:4637ca42e6c51aebc4d9a2d92f97bf4bdb042e3f7985ff31a659a11e4c170e73" + "sha256:10195e5ca764745f02b9a51df048b996ddbdc1899a44a2caf35dfb225dfea489", + "sha256:4cc51a6a486915aedc140f9d027b7e156646b7a0f7b33b1000762c81aff9a12f" ], "markers": "python_version >= '3.8'", - "version": "==1.34.117" + "version": "==1.35.4" }, "botocore-stubs": { "hashes": [ - "sha256:64d80a3467e3b19939e9c2750af33328b3087f8f524998dbdf7ed168227f507d", - "sha256:b0345f55babd8b901c53804fc5c326a4a0bd2e23e3b71f9ea5d9f7663466e6ba" + "sha256:2a0a2a1c058d4b2f3070ba68e17dbcaae8b8699e81879c5de4058c0580d26368", + "sha256:ad89ec214ffa29894db9515aa69a3b44256edd30f1ba78f89bb24d146e2048fa" ], "markers": "python_version >= '3.8' and python_version < '4.0'", - "version": "==1.34.94" + "version": "==1.35.4" }, "certifi": { "hashes": [ - "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516", - "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56" + "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b", + "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90" ], "markers": "python_version >= '3.6'", - "version": "==2024.6.2" + "version": "==2024.7.4" }, "cfgv": { "hashes": [ @@ -1688,12 +2068,12 @@ }, "django": { "hashes": [ - "sha256:a2d4c4d4ea0b6f0895acde632071aff6400bfc331228fc978b05452a0ff3e9f1", - "sha256:b1260ed381b10a11753c73444408e19869f3241fc45c985cd55a30177c789d13" + "sha256:61ee4a130efb8c451ef3467c67ca99fdce400fedd768634efc86a68c18d80d30", + "sha256:c77f926b81129493961e19c0e02188f8d07c112a1162df69bfab178ae447f94a" ], "index": "pypi", "markers": "python_version >= '3.8'", - "version": "==4.2.10" + "version": "==4.2.15" }, "django-coverage-plugin": { "hashes": [ @@ -1741,11 +2121,11 @@ }, "django-stubs-ext": { "hashes": [ - "sha256:409c62585d7f996cef5c760e6e27ea3ff29f961c943747e67519c837422cad32", - "sha256:8d8efec5a86241266bec94a528fe21258ad90d78c67307f3ae5f36e81de97f12" + "sha256:85da065224204774208be29c7d02b4482d5a69218a728465c2fbe41725fdc819", + "sha256:910cbaff3d1e8e806a5c27d5ddd4088535aae8371ea921b7fd680fdfa5f14e30" ], "markers": "python_version >= '3.8'", - "version": "==5.0.2" + "version": "==5.0.4" }, "djangorestframework-stubs": { "hashes": [ @@ -1775,28 +2155,28 @@ }, "faker": { "hashes": [ - "sha256:0158d47e955b6ec22134c0a74ebb7ed34fe600896208bafbf1008db831b17f04", - "sha256:bcbe31eee5ef4bbf87ce36c4eba53c01e2a1d912fde2a4d3528b430d2beb784f" + "sha256:1c44d4bdcad7237516c9a829b6a0bcb031c6a4cb0506207c480c79f74d8922bf", + "sha256:4ce108fc96053bbba3abf848e3a2885f05faa938deb987f97e4420deaec541c4" ], "markers": "python_version >= '3.8'", - "version": "==25.3.0" + "version": "==27.4.0" }, "filelock": { "hashes": [ - "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f", - "sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a" + "sha256:2207938cbc1844345cb01a5a95524dae30f0ce089eba5b00378295a17e3e90cb", + "sha256:6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7" ], "markers": "python_version >= '3.8'", - "version": "==3.14.0" + "version": "==3.15.4" }, "flake8": { "hashes": [ - "sha256:33f96621059e65eec474169085dc92bf26e7b2d47366b70be2f67ab80dc25132", - "sha256:a6dfbb75e03252917f2473ea9653f7cd799c3064e54d4c8140044c5c065f53c3" + "sha256:049d058491e228e03e67b390f311bbf88fce2dbaa8fa673e7aea87b7198b8d38", + "sha256:597477df7860daa5aa0fdd84bf5208a043ab96b8e96ab708770ae0364dd03213" ], "index": "pypi", "markers": "python_full_version >= '3.8.1'", - "version": "==7.0.0" + "version": "==7.1.1" }, "freezegun": { "hashes": [ @@ -1809,19 +2189,19 @@ }, "gprof2dot": { "hashes": [ - "sha256:45b4d298bd36608fccf9511c3fd88a773f7a1abc04d6cd39445b11ba43133ec5", - "sha256:f165b3851d3c52ee4915eb1bd6cca571e5759823c2cd0f71a79bda93c2dc85d6" + "sha256:45b14ad7ce64e299c8f526881007b9eb2c6b75505d5613e96e66ee4d5ab33696", + "sha256:fa1420c60025a9eb7734f65225b4da02a10fc6dd741b37fa129bc6b41951e5ab" ], - "markers": "python_version >= '2.7'", - "version": "==2022.7.29" + "markers": "python_version >= '3.8'", + "version": "==2024.6.6" }, "identify": { "hashes": [ - "sha256:37d93f380f4de590500d9dba7db359d0d3da95ffe7f9de1753faa159e71e7dfa", - "sha256:e5e00f54165f9047fbebeb4a560f9acfb8af4c88232be60a488e9b68d122745d" + "sha256:cb171c685bdc31bcc4c1734698736a7d5b6c8bf2e0c15117f4d469c8640ae5cf", + "sha256:e79ae4406387a9d300332b5fd366d8994f1525e8414984e1a59e058b2eda2dd0" ], "markers": "python_version >= '3.8'", - "version": "==2.5.36" + "version": "==2.6.0" }, "idna": { "hashes": [ @@ -1983,10 +2363,10 @@ }, "mypy-boto3-s3": { "hashes": [ - "sha256:95fbc6bcba2bb03c20a97cc5cf60ff66c6842c8c4fc4183c49bfa35905d5a1ee", - "sha256:a137bca9bbe86c0fe35bbf36a2d44ab62526f41bb683550dd6cfbb5a10ede832" + "sha256:74d8f3492eeff768ff6f69ac6d40bf68b40aa6e54ebe10a8d098fc3d24a54abf", + "sha256:f7300b559dee5435872625448becf159abe36b19cd7006dd78e0d51610312183" ], - "version": "==1.34.105" + "version": "==1.35.2" }, "mypy-extensions": { "hashes": [ @@ -1998,19 +2378,19 @@ }, "nodeenv": { "hashes": [ - "sha256:07f144e90dae547bf0d4ee8da0ee42664a42a04e02ed68e06324348dafe4bdb1", - "sha256:508ecec98f9f3330b636d4448c0f1a56fc68017c68f1e7857ebc52acf0eb879a" + "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", + "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", - "version": "==1.9.0" + "version": "==1.9.1" }, "packaging": { "hashes": [ - "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5", - "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9" + "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002", + "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124" ], - "markers": "python_version >= '3.7'", - "version": "==24.0" + "markers": "python_version >= '3.8'", + "version": "==24.1" }, "parso": { "hashes": [ @@ -2055,11 +2435,11 @@ }, "prompt-toolkit": { "hashes": [ - "sha256:07c60ee4ab7b7e90824b61afa840c8f5aad2d46b3e2e10acc33d8ecc94a49089", - "sha256:a29b89160e494e3ea8622b09fa5897610b437884dcdcd054fdc1308883326c2a" + "sha256:0d7bfa67001d5e39d02c224b663abc33687405033a8c422d0d675a5a13361d10", + "sha256:1e1b29cb58080b1e69f207c893a1a7bf16d127a5c30c9d17a25a5d77792e5360" ], "markers": "python_full_version >= '3.7.0'", - "version": "==3.0.45" + "version": "==3.0.47" }, "ptyprocess": { "hashes": [ @@ -2070,18 +2450,18 @@ }, "pure-eval": { "hashes": [ - "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350", - "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3" + "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", + "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42" ], - "version": "==0.2.2" + "version": "==0.2.3" }, "pycodestyle": { "hashes": [ - "sha256:41ba0e7afc9752dfb53ced5489e89f8186be00e599e712660695b7a75ff2663f", - "sha256:44fe31000b2d866f2e41841b18528a505fbd7fef9017b04eff4e2648a0fadc67" + "sha256:46f0fb92069a7c28ab7bb558f05bfc0110dac69a0cd23c61ea0040283a9d78b3", + "sha256:6838eae08bbce4f6accd5d5572075c63626a15ee3e6f842df996bf62f6d73521" ], "markers": "python_version >= '3.8'", - "version": "==2.11.1" + "version": "==2.12.1" }, "pyflakes": { "hashes": [ @@ -2109,60 +2489,62 @@ }, "pyyaml": { "hashes": [ - "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5", - "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc", - "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df", - "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741", - "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206", - "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27", - "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595", - "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62", - "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98", - "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696", - "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290", - "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9", - "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d", - "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6", - "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867", - "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47", - "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486", - "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6", - "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3", - "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007", - "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938", - "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0", - "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c", - "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735", - "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d", - "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28", - "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4", - "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba", - "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8", - "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef", - "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5", - "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd", - "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3", - "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0", - "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515", - "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c", - "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c", - "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924", - "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34", - "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43", - "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859", - "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673", - "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54", - "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a", - "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b", - "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab", - "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa", - "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c", - "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585", - "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d", - "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f" - ], - "markers": "python_version >= '3.6'", - "version": "==6.0.1" + "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff", + "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", + "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", + "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e", + "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", + "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", + "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", + "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", + "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", + "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", + "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a", + "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", + "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", + "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8", + "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", + "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19", + "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", + "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a", + "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", + "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", + "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", + "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631", + "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d", + "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", + "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", + "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", + "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", + "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", + "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", + "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706", + "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", + "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", + "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", + "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083", + "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", + "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", + "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", + "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f", + "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725", + "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", + "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", + "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", + "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", + "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", + "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5", + "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d", + "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290", + "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", + "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", + "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", + "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", + "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12", + "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4" + ], + "markers": "python_version >= '3.8'", + "version": "==6.0.2" }, "requests": { "hashes": [ @@ -2184,11 +2566,11 @@ }, "s3transfer": { "hashes": [ - "sha256:5683916b4c724f799e600f41dd9e10a9ff19871bf87623cc8f491cb4f5fa0a19", - "sha256:ceb252b11bcf87080fb7850a224fb6e05c8a776bab8f2b64b7f25b969464839d" + "sha256:0711534e9356d3cc692fdde846b4a1e4b0cb6519971860796e6bc4c7aea00ef6", + "sha256:eca1c20de70a39daee580aef4986996620f365c4e0fda6a86100231d62f1bf69" ], "markers": "python_version >= '3.8'", - "version": "==0.10.1" + "version": "==0.10.2" }, "six": { "hashes": [ @@ -2200,11 +2582,11 @@ }, "sqlparse": { "hashes": [ - "sha256:714d0a4932c059d16189f58ef5411ec2287a4360f17cdd0edd2d09d4c5087c93", - "sha256:c204494cd97479d0e39f28c93d46c0b2d5959c7b9ab904762ea6c7af211c8663" + "sha256:773dcbf9a5ab44a090f3441e2180efe2560220203dc2f8c0b0fa141e18b505e4", + "sha256:bb6b4df465655ef332548e24f08e205afc81b9ab86cb1c45657a7ff173a3a00e" ], "markers": "python_version >= '3.8'", - "version": "==0.5.0" + "version": "==0.5.1" }, "stack-data": { "hashes": [ @@ -2232,27 +2614,27 @@ }, "types-awscrt": { "hashes": [ - "sha256:3ae374b553e7228ba41a528cf42bd0b2ad7303d806c73eff4aaaac1515e3ea4e", - "sha256:64898a2f4a2468f66233cb8c29c5f66de907cf80ba1ef5bb1359aef2f81bb521" + "sha256:0839fe12f0f914d8f7d63ed777c728cb4eccc2d5d79a26e377d12b0604e7bf0e", + "sha256:84a9f4f422ec525c314fdf54c23a1e73edfbcec968560943ca2d41cfae623b38" ], "markers": "python_version >= '3.7' and python_version < '4.0'", - "version": "==0.20.9" + "version": "==0.21.2" }, "types-pyyaml": { "hashes": [ - "sha256:a9e0f0f88dc835739b0c1ca51ee90d04ca2a897a71af79de9aec5f38cb0a5342", - "sha256:b845b06a1c7e54b8e5b4c683043de0d9caf205e7434b3edc678ff2411979b8f6" + "sha256:b8f76ddbd7f65440a8bda5526a9607e4c7a322dc2f8e1a8c405644f9a6f4b9af", + "sha256:deda34c5c655265fc517b546c902aa6eed2ef8d3e921e4765fe606fe2afe8d35" ], "markers": "python_version >= '3.8'", - "version": "==6.0.12.20240311" + "version": "==6.0.12.20240808" }, "types-requests": { "hashes": [ - "sha256:3f98d7bbd0dd94ebd10ff43a7fbe20c3b8528acace6d8efafef0b6a184793f06", - "sha256:ed3946063ea9fbc6b5fc0c44fa279188bae42d582cb63760be6cb4b9d06c3de8" + "sha256:90c079ff05e549f6bf50e02e910210b98b8ff1ebdd18e19c873cd237737c1358", + "sha256:f754283e152c752e46e70942fa2a146b5bc70393522257bb85bd1ef7e019dcc3" ], "markers": "python_version >= '3.8'", - "version": "==2.32.0.20240602" + "version": "==2.32.0.20240712" }, "types-s3transfer": { "hashes": [ @@ -2264,27 +2646,27 @@ }, "typing-extensions": { "hashes": [ - "sha256:6024b58b69089e5a89c347397254e35f1bf02a907728ec7fee9bf0fe837d203a", - "sha256:915f5e35ff76f56588223f15fdd5938f9a1cf9195c0de25130c627e4d597f6d1" + "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", + "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8" ], "markers": "python_version >= '3.8'", - "version": "==4.12.1" + "version": "==4.12.2" }, "urllib3": { "hashes": [ - "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d", - "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19" + "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472", + "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168" ], "markers": "python_version >= '3.8'", - "version": "==2.2.1" + "version": "==2.2.2" }, "virtualenv": { "hashes": [ - "sha256:82bf0f4eebbb78d36ddaee0283d43fe5736b53880b8a8cdcd37390a07ac3741c", - "sha256:a624db5e94f01ad993d476b9ee5346fdf7b9de43ccaee0e0197012dc838a0e9b" + "sha256:4c43a2a236279d9ea36a0d76f98d84bd6ca94ac4e0f4a3b9d46d05e10fea542a", + "sha256:8cc4a31139e796e9a7de2cd5cf2489de1217193116a8fd42328f1bd65f434589" ], "markers": "python_version >= '3.7'", - "version": "==20.26.2" + "version": "==20.26.3" }, "watchdog": { "hashes": [ @@ -2353,11 +2735,11 @@ }, "babel": { "hashes": [ - "sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb", - "sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413" + "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b", + "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316" ], "markers": "python_version >= '3.8'", - "version": "==2.15.0" + "version": "==2.16.0" }, "beautifulsoup4": { "hashes": [ @@ -2369,11 +2751,11 @@ }, "certifi": { "hashes": [ - "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516", - "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56" + "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b", + "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90" ], "markers": "python_version >= '3.6'", - "version": "==2024.6.2" + "version": "==2024.7.4" }, "charset-normalizer": { "hashes": [ @@ -2613,11 +2995,11 @@ }, "packaging": { "hashes": [ - "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5", - "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9" + "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002", + "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124" ], - "markers": "python_version >= '3.7'", - "version": "==24.0" + "markers": "python_version >= '3.8'", + "version": "==24.1" }, "pygments": { "hashes": [ @@ -2629,60 +3011,62 @@ }, "pyyaml": { "hashes": [ - "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5", - "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc", - "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df", - "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741", - "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206", - "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27", - "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595", - "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62", - "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98", - "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696", - "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290", - "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9", - "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d", - "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6", - "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867", - "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47", - "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486", - "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6", - "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3", - "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007", - "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938", - "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0", - "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c", - "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735", - "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d", - "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28", - "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4", - "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba", - "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8", - "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef", - "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5", - "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd", - "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3", - "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0", - "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515", - "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c", - "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c", - "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924", - "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34", - "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43", - "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859", - "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673", - "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54", - "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a", - "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b", - "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab", - "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa", - "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c", - "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585", - "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d", - "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f" - ], - "markers": "python_version >= '3.6'", - "version": "==6.0.1" + "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff", + "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", + "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", + "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e", + "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", + "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", + "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", + "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", + "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", + "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", + "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a", + "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", + "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", + "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8", + "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", + "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19", + "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", + "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a", + "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", + "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", + "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", + "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631", + "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d", + "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", + "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", + "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", + "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", + "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", + "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", + "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706", + "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", + "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", + "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", + "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083", + "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", + "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", + "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", + "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f", + "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725", + "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", + "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", + "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", + "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", + "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", + "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5", + "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d", + "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290", + "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", + "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", + "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", + "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", + "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12", + "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4" + ], + "markers": "python_version >= '3.8'", + "version": "==6.0.2" }, "requests": { "hashes": [ @@ -2702,11 +3086,11 @@ }, "soupsieve": { "hashes": [ - "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690", - "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7" + "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb", + "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9" ], "markers": "python_version >= '3.8'", - "version": "==2.5" + "version": "==2.6" }, "sphinx": { "hashes": [ @@ -2727,27 +3111,27 @@ }, "sphinxcontrib-applehelp": { "hashes": [ - "sha256:c40a4f96f3776c4393d933412053962fac2b84f4c99a7982ba42e09576a70619", - "sha256:cb61eb0ec1b61f349e5cc36b2028e9e7ca765be05e49641c97241274753067b4" + "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1", + "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5" ], "markers": "python_version >= '3.9'", - "version": "==1.0.8" + "version": "==2.0.0" }, "sphinxcontrib-devhelp": { "hashes": [ - "sha256:6485d09629944511c893fa11355bda18b742b83a2b181f9a009f7e500595c90f", - "sha256:9893fd3f90506bc4b97bdb977ceb8fbd823989f4316b28c3841ec128544372d3" + "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad", + "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2" ], "markers": "python_version >= '3.9'", - "version": "==1.0.6" + "version": "==2.0.0" }, "sphinxcontrib-htmlhelp": { "hashes": [ - "sha256:0dc87637d5de53dd5eec3a6a01753b1ccf99494bd756aafecd74b4fa9e729015", - "sha256:393f04f112b4d2f53d93448d4bce35842f62b307ccdc549ec1585e950bc35e04" + "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8", + "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9" ], "markers": "python_version >= '3.9'", - "version": "==2.0.5" + "version": "==2.1.0" }, "sphinxcontrib-jsmath": { "hashes": [ @@ -2759,27 +3143,27 @@ }, "sphinxcontrib-qthelp": { "hashes": [ - "sha256:053dedc38823a80a7209a80860b16b722e9e0209e32fea98c90e4e6624588ed6", - "sha256:e2ae3b5c492d58fcbd73281fbd27e34b8393ec34a073c792642cd8e529288182" + "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab", + "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb" ], "markers": "python_version >= '3.9'", - "version": "==1.0.7" + "version": "==2.0.0" }, "sphinxcontrib-serializinghtml": { "hashes": [ - "sha256:326369b8df80a7d2d8d7f99aa5ac577f51ea51556ed974e7716cfd4fca3f6cb7", - "sha256:93f3f5dc458b91b192fe10c397e324f262cf163d79f3282c158e8436a2c4511f" + "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", + "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d" ], "markers": "python_version >= '3.9'", - "version": "==1.1.10" + "version": "==2.0.0" }, "urllib3": { "hashes": [ - "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d", - "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19" + "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472", + "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168" ], "markers": "python_version >= '3.8'", - "version": "==2.2.1" + "version": "==2.2.2" } } } diff --git a/README.md b/README.md index c4ac20362f..38d0df9fb0 100644 --- a/README.md +++ b/README.md @@ -9,12 +9,12 @@

-[![Deploy Care](https://github.com/coronasafe/care/actions/workflows/deployment.yaml/badge.svg)](https://github.com/coronasafe/care/actions/workflows/deployment.yaml) +[![Deploy Care](https://github.com/ohcnetwork/care/actions/workflows/deployment.yaml/badge.svg)](https://github.com/ohcnetwork/care/actions/workflows/deployment.yaml) [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT) [![Cookiecutter Django](https://img.shields.io/badge/built%20with-Cookiecutter%20Django-ff69b4.svg)](https://github.com/pydanny/cookiecutter-django/) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) -[![Chat](https://img.shields.io/badge/-Join%20us%20on%20slack-7b1c7d?logo=slack)](https://slack.coronasafe.in/) -[![Open in Dev Containers](https://img.shields.io/static/v1?label=&message=Open%20in%20Dev%20Containers&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/coronasafe/care) +[![Chat](https://img.shields.io/badge/-Join%20us%20on%20slack-7b1c7d?logo=slack)](https://slack.ohc.network/) +[![Open in Dev Containers](https://img.shields.io/static/v1?label=&message=Open%20in%20Dev%20Containers&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/ohcnetwork/care) This is the backend for care. an open source platform for managing patients, health workers, and hospitals. @@ -70,7 +70,7 @@ make load-dummy-data #### Docker Prebuilt docker images for server deployments are available -on [ghcr](https://github.com/coronasafe/care/pkgs/container/care) +on [ghcr](https://github.com/ohcnetwork/care/pkgs/container/care) ## Contributing diff --git a/aws/backend.json b/aws/backend.json index 3d419d67c7..48a28f3fbd 100644 --- a/aws/backend.json +++ b/aws/backend.json @@ -35,7 +35,7 @@ }, { "name": "CORS_ALLOWED_ORIGINS", - "value": "[\"https://care.coronasafe.in\", \"https://careapi.coronasafe.in\", \"https://care.ohc.network\", \"https://careapi.ohc.network\", \"https://status.10bedicu.org\"]" + "value": "[\"https://care.coronasafe.in\", \"https://careapi.coronasafe.in\", \"https://care.ohc.network\", \"https://careapi.ohc.network\", \"https://status.10bedicu.org\", \"http://localhost:4000\"]" }, { "name": "CURRENT_DOMAIN", @@ -286,6 +286,10 @@ { "valueFrom": "/care/backend/PLAUSIBLE_AUTH_TOKEN", "name": "PLAUSIBLE_AUTH_TOKEN" + }, + { + "valueFrom": "/care/backend/JWKS_BASE64", + "name": "JWKS_BASE64" } ], "name": "care-backend" diff --git a/aws/celery.json b/aws/celery.json index 524a548144..0c4e574bd4 100644 --- a/aws/celery.json +++ b/aws/celery.json @@ -275,6 +275,10 @@ { "valueFrom": "/care/backend/ABDM_CLIENT_SECRET", "name": "ABDM_CLIENT_SECRET" + }, + { + "valueFrom": "/care/backend/JWKS_BASE64", + "name": "JWKS_BASE64" } ], "name": "care-celery-beat" @@ -548,6 +552,10 @@ { "valueFrom": "/care/backend/ABDM_CLIENT_SECRET", "name": "ABDM_CLIENT_SECRET" + }, + { + "valueFrom": "/care/backend/JWKS_BASE64", + "name": "JWKS_BASE64" } ], "name": "care-celery-worker" diff --git a/care/facility/api/serializers/patient_consultation.py b/care/facility/api/serializers/patient_consultation.py index c3437cf99a..0e92854bd5 100644 --- a/care/facility/api/serializers/patient_consultation.py +++ b/care/facility/api/serializers/patient_consultation.py @@ -204,15 +204,11 @@ class Meta: "created_by", "kasp_enabled_date", "is_readmission", - "deprecated_diagnosis", "deprecated_verified_by", ) exclude = ( "deleted", "external_id", - "deprecated_icd11_provisional_diagnoses", - "deprecated_icd11_diagnoses", - "deprecated_icd11_principal_diagnosis", ) def validate_bed_number(self, bed_number): @@ -613,11 +609,12 @@ def validate(self, attrs): {"patient_no": "This field is required for admission."} ) - if ( - "suggestion" in validated - and validated["suggestion"] != SuggestionChoices.DD - ): - if "treating_physician" not in validated: + if "suggestion" in validated and validated["suggestion"] not in [ + SuggestionChoices.DD, + SuggestionChoices.DC, + ]: + treating_physician = validated.get("treating_physician") + if not treating_physician: raise ValidationError( { "treating_physician": [ @@ -625,10 +622,7 @@ def validate(self, attrs): ] } ) - if ( - not validated["treating_physician"].user_type - == User.TYPE_VALUE_MAP["Doctor"] - ): + if not treating_physician.user_type == User.TYPE_VALUE_MAP["Doctor"]: raise ValidationError("Only Doctors can verify a Consultation") facility = ( @@ -636,9 +630,15 @@ def validate(self, attrs): and self.instance.facility or validated["patient"].facility ) + # Check if the Doctor is associated with the Facility (.facilities) + if not treating_physician.facilities.filter(id=facility.id).exists(): + raise ValidationError( + "The treating doctor is no longer linked to this facility. Please update the respective field in the form before proceeding." + ) + if ( - validated["treating_physician"].home_facility - and validated["treating_physician"].home_facility != facility + treating_physician.home_facility + and treating_physician.home_facility != facility ): raise ValidationError( "Home Facility of the Doctor must be the same as the Consultation Facility" diff --git a/care/facility/api/serializers/shifting.py b/care/facility/api/serializers/shifting.py index fbdb615fdc..ec4d416a8c 100644 --- a/care/facility/api/serializers/shifting.py +++ b/care/facility/api/serializers/shifting.py @@ -24,8 +24,13 @@ ) from care.facility.models.bed import ConsultationBed from care.facility.models.notification import Notification -from care.facility.models.patient_base import NewDischargeReasonEnum +from care.facility.models.patient_base import ( + DISEASE_STATUS_CHOICES, + DiseaseStatusEnum, + NewDischargeReasonEnum, +) from care.facility.models.patient_consultation import PatientConsultation +from care.users.api.serializers.lsg import StateSerializer from care.users.api.serializers.user import UserBaseMinimumSerializer from care.utils.notification_handler import NotificationGenerator from care.utils.serializer.external_id_field import ExternalIdSerializerField @@ -344,6 +349,7 @@ def update(self, instance, validated_data): if ( "status" in validated_data + and new_instance.shifting_approving_facility is not None and validated_data["status"] != old_status and validated_data["status"] == 40 ): @@ -435,7 +441,122 @@ class Meta: read_only_fields = TIMESTAMP_FIELDS -class ShiftingRequestCommentSerializer(serializers.ModelSerializer): +class FacilityShiftingBareMinimumSerializer(serializers.ModelSerializer): + class Meta: + model = Facility + fields = ["id", "name"] + + +class PatientShiftingBareMinimumSerializer(serializers.ModelSerializer): + id = serializers.CharField(source="external_id", read_only=True) + facility = serializers.UUIDField( + source="facility.external_id", allow_null=True, read_only=True + ) + facility_object = FacilityShiftingBareMinimumSerializer( + source="facility", read_only=True + ) + state_object = StateSerializer(source="state", read_only=True) + disease_status = ChoiceField( + choices=DISEASE_STATUS_CHOICES, default=DiseaseStatusEnum.SUSPECTED.value + ) + age = serializers.SerializerMethodField() + + def get_age(self, obj): + return obj.get_age() + + class Meta: + model = PatientRegistration + fields = [ + "id", + "name", + "allow_transfer", + "age", + "phone_number", + "address", + "disease_status", + "facility", + "facility_object", + "state_object", + ] + read_only = TIMESTAMP_FIELDS + + +class ShiftingListSerializer(serializers.ModelSerializer): + id = serializers.UUIDField(source="external_id", read_only=True) + + patient = ExternalIdSerializerField( + queryset=PatientRegistration.objects.all(), + allow_null=False, + required=True, + ) + patient_object = PatientShiftingBareMinimumSerializer( + source="patient", read_only=True + ) + + status = ChoiceField(choices=SHIFTING_STATUS_CHOICES) + origin_facility_object = FacilityShiftingBareMinimumSerializer( + source="origin_facility", read_only=True + ) + shifting_approving_facility_object = FacilityShiftingBareMinimumSerializer( + source="shifting_approving_facility", read_only=True + ) + + assigned_facility = ExternalIdSerializerField( + queryset=Facility.objects.all(), allow_null=True, required=False + ) + assigned_facility_external = serializers.CharField( + required=False, allow_null=True, allow_blank=True + ) + assigned_facility_object = FacilityShiftingBareMinimumSerializer( + source="assigned_facility", read_only=True + ) + + class Meta: + model = ShiftingRequest + exclude = [ + "created_by", + "last_edited_by", + "assigned_to", + "shifting_approving_facility", + "origin_facility", + "ambulance_number", + "ambulance_phone_number", + "ambulance_driver_name", + "is_assigned_to_user", + "is_kasp", + "refering_facility_contact_number", + "refering_facility_contact_name", + "comments", + "preferred_vehicle_choice", + "vehicle_preference", + "reason", + "is_up_shift", + "assigned_facility_type", + "deleted", + "breathlessness_level", + ] + read_only_fields = TIMESTAMP_FIELDS + + +class ShiftingUserBareMinimumSerializer(serializers.ModelSerializer): + class Meta: + model = User + fields = ["id", "first_name", "last_name"] + + +class ShiftingRequestCommentListSerializer(serializers.ModelSerializer): + id = serializers.UUIDField(source="external_id", read_only=True) + comment = serializers.CharField(required=True) + created_by_object = ShiftingUserBareMinimumSerializer( + source="created_by", read_only=True + ) + + class Meta: + model = ShiftingRequestComment + fields = ["id", "comment", "modified_date", "created_by_object"] + + +class ShiftingRequestCommentDetailSerializer(ShiftingRequestCommentListSerializer): id = serializers.UUIDField(source="external_id", read_only=True) created_by_object = UserBaseMinimumSerializer(source="created_by", read_only=True) diff --git a/care/facility/api/viewsets/asset.py b/care/facility/api/viewsets/asset.py index 42323de545..4f33bc6225 100644 --- a/care/facility/api/viewsets/asset.py +++ b/care/facility/api/viewsets/asset.py @@ -389,6 +389,7 @@ def operate_assets(self, request, *args, **kwargs): asset_class: BaseAssetIntegration = AssetClasses[asset.asset_class].value( { **asset.meta, + "id": asset.external_id, "middleware_hostname": middleware_hostname, } ) diff --git a/care/facility/api/viewsets/patient_consultation.py b/care/facility/api/viewsets/patient_consultation.py index 95aa138331..b166971dc9 100644 --- a/care/facility/api/viewsets/patient_consultation.py +++ b/care/facility/api/viewsets/patient_consultation.py @@ -1,7 +1,11 @@ +import tempfile + from django.db import transaction from django.db.models import Prefetch from django.db.models.query_utils import Q -from django.shortcuts import get_object_or_404, render +from django.http import HttpResponse +from django.shortcuts import get_object_or_404 +from django.utils import timezone from django_filters import rest_framework as filters from drf_spectacular.utils import extend_schema from dry_rest_permissions.generics import DRYPermissions @@ -296,7 +300,18 @@ def dev_preview_discharge_summary(request, consultation_id): if not consultation: raise NotFound({"detail": "Consultation not found"}) data = discharge_summary.get_discharge_summary_data(consultation) - return render(request, "reports/patient_discharge_summary_pdf.html", data) + data["date"] = timezone.now() + + with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp_file: + discharge_summary.generate_discharge_summary_pdf(data, tmp_file) + + with open(tmp_file.name, "rb") as pdf_file: + pdf_content = pdf_file.read() + + response = HttpResponse(pdf_content, content_type="application/pdf") + response["Content-Disposition"] = 'inline; filename="discharge_summary.pdf"' + + return response class PatientConsentViewSet( diff --git a/care/facility/api/viewsets/shifting.py b/care/facility/api/viewsets/shifting.py index 3d87f822fd..3111e70c30 100644 --- a/care/facility/api/viewsets/shifting.py +++ b/care/facility/api/viewsets/shifting.py @@ -1,4 +1,5 @@ from django.conf import settings +from django.db.models.query import QuerySet from django.db.models.query_utils import Q from django.utils.timezone import localtime, now from django_filters import rest_framework as filters @@ -15,7 +16,9 @@ from care.facility.api.serializers.shifting import ( ShiftingDetailSerializer, - ShiftingRequestCommentSerializer, + ShiftingListSerializer, + ShiftingRequestCommentDetailSerializer, + ShiftingRequestCommentListSerializer, ShiftingSerializer, has_facility_permission, ) @@ -93,36 +96,7 @@ class ShiftingViewSet( ): serializer_class = ShiftingSerializer lookup_field = "external_id" - queryset = ShiftingRequest.objects.all().select_related( - "origin_facility", - "origin_facility__ward", - "origin_facility__local_body", - "origin_facility__district", - "origin_facility__state", - "shifting_approving_facility", - "shifting_approving_facility__ward", - "shifting_approving_facility__local_body", - "shifting_approving_facility__district", - "shifting_approving_facility__state", - "assigned_facility", - "assigned_facility__ward", - "assigned_facility__local_body", - "assigned_facility__district", - "assigned_facility__state", - "patient", - "patient__ward", - "patient__local_body", - "patient__district", - "patient__state", - "patient__facility", - "patient__facility__ward", - "patient__facility__local_body", - "patient__facility__district", - "patient__facility__state", - "assigned_to", - "created_by", - "last_edited_by", - ) + queryset = ShiftingRequest.objects.all() ordering_fields = ["id", "created_date", "modified_date", "emergency"] permission_classes = (IsAuthenticated, DRYPermissions) @@ -133,8 +107,52 @@ class ShiftingViewSet( ) filterset_class = ShiftingFilterSet + def get_queryset(self) -> QuerySet: + if self.action == "list": + self.queryset = self.queryset.select_related( + "origin_facility", + "shifting_approving_facility", + "assigned_facility", + "patient", + ) + + else: + self.queryset = self.queryset.select_related( + "origin_facility", + "origin_facility__ward", + "origin_facility__local_body", + "origin_facility__district", + "origin_facility__state", + "shifting_approving_facility", + "shifting_approving_facility__ward", + "shifting_approving_facility__local_body", + "shifting_approving_facility__district", + "shifting_approving_facility__state", + "assigned_facility", + "assigned_facility__ward", + "assigned_facility__local_body", + "assigned_facility__district", + "assigned_facility__state", + "patient", + "patient__ward", + "patient__local_body", + "patient__district", + "patient__state", + "patient__facility", + "patient__facility__ward", + "patient__facility__local_body", + "patient__facility__district", + "patient__facility__state", + "assigned_to", + "created_by", + "last_edited_by", + ) + return self.queryset + def get_serializer_class(self): serializer_class = self.serializer_class + if self.action == "list": + return ShiftingListSerializer if self.action == "retrieve": serializer_class = ShiftingDetailSerializer return serializer_class @@ -186,7 +204,8 @@ def list(self, request, *args, **kwargs): field_header_map=ShiftingRequest.CSV_MAPPING, field_serializer_map=ShiftingRequest.CSV_MAKE_PRETTY, ) - return super(ShiftingViewSet, self).list(request, *args, **kwargs) + response = super().list(request, *args, **kwargs) + return response class ShifitngRequestCommentViewSet( @@ -195,7 +214,7 @@ class ShifitngRequestCommentViewSet( mixins.RetrieveModelMixin, GenericViewSet, ): - serializer_class = ShiftingRequestCommentSerializer + serializer_class = ShiftingRequestCommentDetailSerializer lookup_field = "external_id" queryset = ShiftingRequestComment.objects.all().order_by("-created_date") @@ -243,3 +262,8 @@ def get_request(self): def perform_create(self, serializer): serializer.save(request=self.get_request()) + + def get_serializer_class(self): + if self.action == "list": + return ShiftingRequestCommentListSerializer + return ShiftingRequestCommentDetailSerializer diff --git a/care/facility/migrations/0446_alter_hospitaldoctors_area.py b/care/facility/migrations/0446_alter_hospitaldoctors_area.py new file mode 100644 index 0000000000..3f2ad707df --- /dev/null +++ b/care/facility/migrations/0446_alter_hospitaldoctors_area.py @@ -0,0 +1,85 @@ +# Generated by Django 4.2.10 on 2024-07-17 17:43 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("facility", "0445_merge_20240715_0301"), + ] + + operations = [ + migrations.AlterField( + model_name="hospitaldoctors", + name="area", + field=models.IntegerField( + choices=[ + (1, "General Medicine"), + (2, "Pulmonology"), + (3, "Intensivist"), + (4, "Pediatrician"), + (5, "Others"), + (6, "Anesthesiologist"), + (7, "Cardiac Surgeon"), + (8, "Cardiologist"), + (9, "Dentist"), + (10, "Dermatologist"), + (11, "Diabetologist"), + (12, "Emergency Medicine Physician"), + (13, "Endocrinologist"), + (14, "Family Physician"), + (15, "Gastroenterologist"), + (16, "General Surgeon"), + (17, "Geriatrician"), + (18, "Hematologist"), + (29, "Immunologist"), + (20, "Infectious Disease Specialist"), + (21, "MBBS doctor"), + (22, "Medical Officer"), + (23, "Nephrologist"), + (24, "Neuro Surgeon"), + (25, "Neurologist"), + (26, "Obstetrician/Gynecologist (OB/GYN)"), + (27, "Oncologist"), + (28, "Oncology Surgeon"), + (29, "Ophthalmologist"), + (30, "Oral and Maxillofacial Surgeon"), + (31, "Orthopedic"), + (32, "Orthopedic Surgeon"), + (33, "Otolaryngologist (ENT)"), + (34, "Palliative care Physician"), + (35, "Pathologist"), + (36, "Pediatric Surgeon"), + (37, "Physician"), + (38, "Plastic Surgeon"), + (39, "Psychiatrist"), + (40, "Pulmonologist"), + (41, "Radio technician"), + (42, "Radiologist"), + (43, "Rheumatologist"), + (44, "Sports Medicine Specialist"), + (45, "Thoraco-Vascular Surgeon"), + (46, "Transfusion Medicine Specialist"), + (47, "Urologist"), + (48, "Nurse"), + (49, "Allergist/Immunologist"), + (50, "Cardiothoracic Surgeon"), + (51, "Gynecologic Oncologist"), + (52, "Hepatologist"), + (53, "Internist"), + (54, "Neonatologist"), + (55, "Pain Management Specialist"), + (56, "Physiatrist (Physical Medicine and Rehabilitation)"), + (57, "Podiatrist"), + (58, "Preventive Medicine Specialist"), + (59, "Radiation Oncologist"), + (60, "Sleep Medicine Specialist"), + (61, "Transplant Surgeon"), + (62, "Trauma Surgeon"), + (63, "Vascular Surgeon"), + (64, "Critical Care Physician"), + ] + ), + ), + ] diff --git a/care/facility/migrations/0447_alter_dailyround_patient_category_and_more.py b/care/facility/migrations/0447_alter_dailyround_patient_category_and_more.py new file mode 100644 index 0000000000..46a11a7dd7 --- /dev/null +++ b/care/facility/migrations/0447_alter_dailyround_patient_category_and_more.py @@ -0,0 +1,43 @@ +# Generated by Django 4.2.10 on 2024-07-24 10:16 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("facility", "0446_alter_notification_event"), + ] + + operations = [ + migrations.AlterField( + model_name="dailyround", + name="patient_category", + field=models.CharField( + choices=[ + ("Comfort", "Comfort Care"), + ("Stable", "Mild"), + ("Moderate", "Moderate"), + ("Critical", "Critical"), + ("ActivelyDying", "Actively Dying"), + ], + max_length=13, + null=True, + ), + ), + migrations.AlterField( + model_name="patientconsultation", + name="category", + field=models.CharField( + choices=[ + ("Comfort", "Comfort Care"), + ("Stable", "Mild"), + ("Moderate", "Moderate"), + ("Critical", "Critical"), + ("ActivelyDying", "Actively Dying"), + ], + max_length=13, + null=True, + ), + ), + ] diff --git a/care/facility/migrations/0450_corrections_for_io_balance_fields.py b/care/facility/migrations/0450_corrections_for_io_balance_fields.py new file mode 100644 index 0000000000..24c8a00d3b --- /dev/null +++ b/care/facility/migrations/0450_corrections_for_io_balance_fields.py @@ -0,0 +1,60 @@ +# Generated by Django 4.2.10 on 2024-08-20 12:38 + +from django.core.paginator import Paginator +from django.db import migrations + + +class Migration(migrations.Migration): + """ + Migration to correct the entries with spelling mistake for "Rules Tube Aspiration" + to "Ryles Tube Aspiration" in both DailyRound's output JSONField. + """ + + dependencies = [ + ("facility", "0449_merge_20240822_1343"), + ] + + def forward_rename_dailyround_entries(apps, schema_editor): + DailyRound = apps.get_model("facility", "DailyRound") + + paginator = Paginator( + DailyRound.objects.filter( + output__contains=[{"name": "Rules Tube Aspiration"}] + ).order_by("id"), + 1000, + ) + + for page_number in paginator.page_range: + bulk = [] + for instance in paginator.page(page_number).object_list: + for entry in instance.output: + if entry["name"] == "Rules Tube Aspiration": + entry["name"] = "Ryles Tube Aspiration" + bulk.append(instance) + DailyRound.objects.bulk_update(bulk, ["output"]) + + def reverse_rename_dailyround_entries(apps, schema_editor): + DailyRound = apps.get_model("facility", "DailyRound") + + paginator = Paginator( + DailyRound.objects.filter( + output__contains=[{"name": "Ryles Tube Aspiration"}] + ).order_by("id"), + 1000, + ) + + for page_number in paginator.page_range: + bulk = [] + for instance in paginator.page(page_number).object_list: + for entry in instance.output: + if entry["name"] == "Ryles Tube Aspiration": + entry["name"] = "Rules Tube Aspiration" + bulk.append(instance) + DailyRound.objects.bulk_update(bulk, ["output"]) + + operations = [ + migrations.RunPython( + forward_rename_dailyround_entries, + reverse_code=reverse_rename_dailyround_entries, + ), + ] diff --git a/care/facility/migrations/0450_merge_20240823_1617.py b/care/facility/migrations/0450_merge_20240823_1617.py new file mode 100644 index 0000000000..00bee19cc2 --- /dev/null +++ b/care/facility/migrations/0450_merge_20240823_1617.py @@ -0,0 +1,13 @@ +# Generated by Django 4.2.10 on 2024-08-23 10:47 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("facility", "0446_alter_hospitaldoctors_area"), + ("facility", "0449_merge_20240822_1343"), + ] + + operations = [] diff --git a/care/facility/migrations/0451_merge_20240823_1642.py b/care/facility/migrations/0451_merge_20240823_1642.py new file mode 100644 index 0000000000..f9f6c74805 --- /dev/null +++ b/care/facility/migrations/0451_merge_20240823_1642.py @@ -0,0 +1,13 @@ +# Generated by Django 4.2.10 on 2024-08-23 11:12 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("facility", "0447_alter_dailyround_patient_category_and_more"), + ("facility", "0450_merge_20240823_1617"), + ] + + operations = [] diff --git a/care/facility/migrations/0452_remove_patientconsultation_deprecated_diagnosis_and_more.py b/care/facility/migrations/0452_remove_patientconsultation_deprecated_diagnosis_and_more.py new file mode 100644 index 0000000000..30e0d372d5 --- /dev/null +++ b/care/facility/migrations/0452_remove_patientconsultation_deprecated_diagnosis_and_more.py @@ -0,0 +1,64 @@ +# Generated by Django 4.2.10 on 2024-08-23 10:57 + +from django.db import migrations + + +class Migration(migrations.Migration): + dependencies = [ + ("facility", "0451_merge_20240823_1642"), + ] + + operations = [ + migrations.RemoveField( + model_name="patientconsultation", + name="deprecated_diagnosis", + ), + migrations.RemoveField( + model_name="patientconsultation", + name="deprecated_icd11_diagnoses", + ), + migrations.RemoveField( + model_name="patientconsultation", + name="deprecated_icd11_principal_diagnosis", + ), + migrations.RemoveField( + model_name="patientconsultation", + name="deprecated_icd11_provisional_diagnoses", + ), + migrations.RemoveField( + model_name="patientconsultation", + name="discharge_advice", + ), + migrations.RemoveField( + model_name="patientconsultation", + name="discharge_prescription", + ), + migrations.RemoveField( + model_name="patientconsultation", + name="discharge_prn_prescription", + ), + migrations.RemoveField( + model_name="patientconsultation", + name="prn_prescription", + ), + migrations.RemoveField( + model_name="dailyround", + name="deprecated_additional_symptoms", + ), + migrations.RemoveField( + model_name="dailyround", + name="deprecated_other_symptoms", + ), + migrations.RemoveField( + model_name="patientconsultation", + name="deprecated_other_symptoms", + ), + migrations.RemoveField( + model_name="patientconsultation", + name="deprecated_symptoms", + ), + migrations.RemoveField( + model_name="patientconsultation", + name="deprecated_symptoms_onset_date", + ), + ] diff --git a/care/facility/migrations/0453_merge_20240824_2040.py b/care/facility/migrations/0453_merge_20240824_2040.py new file mode 100644 index 0000000000..0a0d11202f --- /dev/null +++ b/care/facility/migrations/0453_merge_20240824_2040.py @@ -0,0 +1,13 @@ +# Generated by Django 4.2.10 on 2024-08-24 15:10 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("facility", "0450_corrections_for_io_balance_fields"), + ("facility", "0452_remove_patientconsultation_deprecated_diagnosis_and_more"), + ] + + operations = [] diff --git a/care/facility/models/daily_round.py b/care/facility/models/daily_round.py index 9f12dc25a3..078709d9c9 100644 --- a/care/facility/models/daily_round.py +++ b/care/facility/models/daily_round.py @@ -4,8 +4,6 @@ from django.db import models from django.db.models import JSONField from django.shortcuts import get_object_or_404 -from multiselectfield import MultiSelectField -from multiselectfield.utils import get_max_length from care.facility.models import ( CATEGORY_CHOICES, @@ -25,7 +23,6 @@ PAIN_SCALE_ENHANCED, PRESSURE_SORE, ) -from care.facility.models.patient_base import SYMPTOM_CHOICES from care.facility.models.patient_consultation import PatientConsultation from care.users.models import User from care.utils.models.validators import JSONFieldSchemaValidator @@ -141,14 +138,6 @@ class InsulinIntakeFrequencyType(enum.Enum): max_digits=4, decimal_places=2, blank=True, null=True, default=None ) physical_examination_info = models.TextField(null=True, blank=True) - deprecated_additional_symptoms = MultiSelectField( - choices=SYMPTOM_CHOICES, - default=1, - null=True, - blank=True, - max_length=get_max_length(SYMPTOM_CHOICES, None), - ) # Deprecated - deprecated_other_symptoms = models.TextField(default="", blank=True) # Deprecated deprecated_covid_category = models.CharField( choices=COVID_CATEGORY_CHOICES, max_length=8, @@ -157,7 +146,7 @@ class InsulinIntakeFrequencyType(enum.Enum): null=True, ) # Deprecated patient_category = models.CharField( - choices=CATEGORY_CHOICES, max_length=8, blank=False, null=True + choices=CATEGORY_CHOICES, max_length=13, blank=False, null=True ) other_details = models.TextField(null=True, blank=True) medication_given = JSONField(default=dict) # To be Used Later on diff --git a/care/facility/models/facility.py b/care/facility/models/facility.py index 6d2f25ac3e..53bcac81ea 100644 --- a/care/facility/models/facility.py +++ b/care/facility/models/facility.py @@ -137,7 +137,7 @@ class FacilityFeature(models.IntegerChoices): (23, "Nephrologist"), (24, "Neuro Surgeon"), (25, "Neurologist"), - (26, "Obstetrician and Gynecologist"), + (26, "Obstetrician/Gynecologist (OB/GYN)"), (27, "Oncologist"), (28, "Oncology Surgeon"), (29, "Ophthalmologist"), @@ -160,6 +160,22 @@ class FacilityFeature(models.IntegerChoices): (46, "Transfusion Medicine Specialist"), (47, "Urologist"), (48, "Nurse"), + (49, "Allergist/Immunologist"), + (50, "Cardiothoracic Surgeon"), + (51, "Gynecologic Oncologist"), + (52, "Hepatologist"), + (53, "Internist"), + (54, "Neonatologist"), + (55, "Pain Management Specialist"), + (56, "Physiatrist (Physical Medicine and Rehabilitation)"), + (57, "Podiatrist"), + (58, "Preventive Medicine Specialist"), + (59, "Radiation Oncologist"), + (60, "Sleep Medicine Specialist"), + (61, "Transplant Surgeon"), + (62, "Trauma Surgeon"), + (63, "Vascular Surgeon"), + (64, "Critical Care Physician"), ] REVERSE_DOCTOR_TYPES = reverse_choices(DOCTOR_TYPES) diff --git a/care/facility/models/patient.py b/care/facility/models/patient.py index b3d42bef01..8a5aeb6e4c 100644 --- a/care/facility/models/patient.py +++ b/care/facility/models/patient.py @@ -1,4 +1,5 @@ import enum +from datetime import date from dateutil.relativedelta import relativedelta from django.contrib.postgres.aggregates import ArrayAgg @@ -6,6 +7,7 @@ from django.db import models from django.db.models import Case, F, Func, JSONField, Value, When from django.db.models.functions import Coalesce, Now +from django.template.defaultfilters import pluralize from django.utils import timezone from django.utils.translation import gettext_lazy as _ from simple_history.models import HistoricalRecords @@ -481,10 +483,29 @@ def save(self, *args, **kwargs) -> None: self._alias_recovery_to_recovered() super().save(*args, **kwargs) - def get_age(self) -> int: - start = self.date_of_birth or timezone.datetime(self.year_of_birth, 1, 1).date() + def get_age(self) -> str: + start = self.date_of_birth or date(self.year_of_birth, 1, 1) end = (self.death_datetime or timezone.now()).date() - return relativedelta(end, start).years + + delta = relativedelta(end, start) + + if delta.years > 0: + year_str = f"{delta.years} year{pluralize(delta.years)}" + return f"{year_str}" + + elif delta.months > 0: + month_str = f"{delta.months} month{pluralize(delta.months)}" + day_str = ( + f" {delta.days} day{pluralize(delta.days)}" if delta.days > 0 else "" + ) + return f"{month_str}{day_str}" + + elif delta.days > 0: + day_str = f"{delta.days} day{pluralize(delta.days)}" + return day_str + + else: + return "0 days" def annotate_diagnosis_ids(*args, **kwargs): return ArrayAgg( diff --git a/care/facility/models/patient_base.py b/care/facility/models/patient_base.py index 976b38d320..5ce0b2106f 100644 --- a/care/facility/models/patient_base.py +++ b/care/facility/models/patient_base.py @@ -73,6 +73,7 @@ def reverse_choices(choices): ("Stable", "Mild"), ("Moderate", "Moderate"), ("Critical", "Critical"), + ("ActivelyDying", "Actively Dying"), ] DISCHARGE_REASON_CHOICES = [ diff --git a/care/facility/models/patient_consultation.py b/care/facility/models/patient_consultation.py index fa092905ea..24e027f608 100644 --- a/care/facility/models/patient_consultation.py +++ b/care/facility/models/patient_consultation.py @@ -3,8 +3,6 @@ from django.db import models from django.db.models import JSONField from django.utils import timezone -from multiselectfield import MultiSelectField -from multiselectfield.utils import get_max_length from care.facility.models import ( CATEGORY_CHOICES, @@ -20,7 +18,6 @@ NEW_DISCHARGE_REASON_CHOICES, REVERSE_CATEGORY_CHOICES, REVERSE_COVID_CATEGORY_CHOICES, - SYMPTOM_CHOICES, RouteToFacility, SuggestionChoices, reverse_choices, @@ -68,29 +65,6 @@ class PatientConsultation(PatientBaseModel, ConsultationRelatedPermissionMixin): facility = models.ForeignKey( "Facility", on_delete=models.CASCADE, related_name="consultations" ) - deprecated_diagnosis = models.TextField( - default="", null=True, blank=True - ) # Deprecated - deprecated_icd11_provisional_diagnoses = ArrayField( - models.CharField(max_length=100), default=list, blank=True, null=True - ) # Deprecated in favour of ConsultationDiagnosis M2M model - deprecated_icd11_diagnoses = ArrayField( - models.CharField(max_length=100), default=list, blank=True, null=True - ) # Deprecated in favour of ConsultationDiagnosis M2M model - deprecated_icd11_principal_diagnosis = models.CharField( - max_length=100, default="", blank=True, null=True - ) # Deprecated in favour of ConsultationDiagnosis M2M model - deprecated_symptoms = MultiSelectField( - choices=SYMPTOM_CHOICES, - default=1, - null=True, - blank=True, - max_length=get_max_length(SYMPTOM_CHOICES, None), - ) # Deprecated - deprecated_other_symptoms = models.TextField(default="", blank=True) # Deprecated - deprecated_symptoms_onset_date = models.DateTimeField( - null=True, blank=True - ) # Deprecated deprecated_covid_category = models.CharField( choices=COVID_CATEGORY_CHOICES, max_length=8, @@ -99,7 +73,7 @@ class PatientConsultation(PatientBaseModel, ConsultationRelatedPermissionMixin): null=True, ) # Deprecated category = models.CharField( - choices=CATEGORY_CHOICES, max_length=8, blank=False, null=True + choices=CATEGORY_CHOICES, max_length=13, blank=False, null=True ) examination_details = models.TextField(null=True, blank=True) history_of_present_illness = models.TextField(null=True, blank=True) @@ -163,12 +137,6 @@ class PatientConsultation(PatientBaseModel, ConsultationRelatedPermissionMixin): null=True, ) discharge_notes = models.TextField(default="", null=True, blank=True) - discharge_prescription = JSONField( - default=dict, null=True, blank=True - ) # Deprecated - discharge_prn_prescription = JSONField( - default=dict, null=True, blank=True - ) # Deprecated death_datetime = models.DateTimeField(null=True, blank=True) death_confirmed_doctor = models.TextField(default="", null=True, blank=True) bed_number = models.CharField(max_length=100, null=True, blank=True) # Deprecated @@ -251,11 +219,6 @@ class PatientConsultation(PatientBaseModel, ConsultationRelatedPermissionMixin): intubation_history = JSONField(default=list) - # Deprecated Fields - - prn_prescription = JSONField(default=dict) - discharge_advice = JSONField(default=dict) - has_consents = ArrayField( models.IntegerField(choices=ConsentType.choices), default=list, diff --git a/care/facility/tasks/asset_monitor.py b/care/facility/tasks/asset_monitor.py index df302b399e..f3b50a87c6 100644 --- a/care/facility/tasks/asset_monitor.py +++ b/care/facility/tasks/asset_monitor.py @@ -4,6 +4,7 @@ from celery import shared_task from django.contrib.contenttypes.models import ContentType +from django.db.models import Q from django.utils import timezone from care.facility.models.asset import Asset, AvailabilityRecord, AvailabilityStatus @@ -17,12 +18,25 @@ def check_asset_status(): logger.info(f"Checking Asset Status: {timezone.now()}") - assets = Asset.objects.all() + assets = ( + Asset.objects.exclude(Q(asset_class=None) | Q(asset_class="")) + .select_related( + "current_location", + "current_location__facility", + ) + .only( + "external_id", + "meta", + "asset_class", + "current_location__middleware_address", + "current_location__facility__middleware_address", + ) + ) asset_content_type = ContentType.objects.get_for_model(Asset) for asset in assets: - # Skipping if asset class or local IP address is not present - if not asset.asset_class or not asset.meta.get("local_ip_address", None): + # Skipping if local IP address is not present + if not asset.meta.get("local_ip_address", None): continue try: # Fetching middleware hostname @@ -49,24 +63,31 @@ def check_asset_status(): ].value( { **asset.meta, + "id": asset.external_id, "middleware_hostname": resolved_middleware, } ) # Fetching the status of the device if asset.asset_class == "ONVIF": - asset_config = asset.meta["camera_access_key"].split(":") - assets_config = [ - { - "hostname": asset.meta.get("local_ip_address"), - "port": 80, - "username": asset_config[0], - "password": asset_config[1], - } - ] - - result = asset_class.api_post( - asset_class.get_url("cameras/status"), data=assets_config - ) + try: + # TODO: Remove this block after all assets are migrated to the new middleware + asset_config = asset.meta["camera_access_key"].split(":") + assets_config = [ + { + "hostname": asset.meta.get("local_ip_address"), + "port": 80, + "username": asset_config[0], + "password": asset_config[1], + } + ] + + result = asset_class.api_post( + asset_class.get_url("cameras/status"), data=assets_config + ) + except Exception: + result = asset_class.api_get( + asset_class.get_url("cameras/status") + ) else: result = asset_class.api_get(asset_class.get_url("devices/status")) except Exception as e: diff --git a/care/facility/templatetags/data_formatting_tags.py b/care/facility/templatetags/data_formatting_tags.py new file mode 100644 index 0000000000..18cc43c545 --- /dev/null +++ b/care/facility/templatetags/data_formatting_tags.py @@ -0,0 +1,35 @@ +from django import template + +register = template.Library() + + +@register.filter(name="format_empty_data") +def format_empty_data(data): + if data is None or data == "" or data == 0.0 or data == []: + return "N/A" + + return data + + +@register.filter(name="format_to_sentence_case") +def format_to_sentence_case(data): + if data is None: + return + + def convert_to_sentence_case(s): + if s == "ICU": + return "ICU" + s = s.lower() + s = s.replace("_", " ") + return s.capitalize() + + if isinstance(data, str): + items = data.split(", ") + converted_items = [convert_to_sentence_case(item) for item in items] + return ", ".join(converted_items) + + elif isinstance(data, (list, tuple)): + converted_items = [convert_to_sentence_case(item) for item in data] + return ", ".join(converted_items) + + return data diff --git a/care/facility/templatetags/prescription_tags.py b/care/facility/templatetags/prescription_tags.py new file mode 100644 index 0000000000..2f1b2ecee8 --- /dev/null +++ b/care/facility/templatetags/prescription_tags.py @@ -0,0 +1,13 @@ +from django import template + +register = template.Library() + + +@register.filter(name="format_prescription") +def format_prescription(prescription): + if prescription.dosage_type == "TITRATED": + return f"{prescription.medicine_name}, titration from {prescription.base_dosage} to {prescription.target_dosage}, {prescription.route}, {prescription.frequency} for {prescription.days} days." + if prescription.dosage_type == "PRN": + return f"{prescription.medicine_name}, {prescription.base_dosage}, {prescription.route}" + else: + return f"{prescription.medicine_name}, {prescription.base_dosage}, {prescription.route}, {prescription.frequency} for {prescription.days} days." diff --git a/care/facility/tests/sample_reports/sample1.png b/care/facility/tests/sample_reports/sample1.png new file mode 100644 index 0000000000..7cb6ce14b9 Binary files /dev/null and b/care/facility/tests/sample_reports/sample1.png differ diff --git a/care/facility/tests/sample_reports/sample2.png b/care/facility/tests/sample_reports/sample2.png new file mode 100644 index 0000000000..e46ee40001 Binary files /dev/null and b/care/facility/tests/sample_reports/sample2.png differ diff --git a/care/facility/tests/test_facility_shifting_api.py b/care/facility/tests/test_facility_shifting_api.py new file mode 100644 index 0000000000..2a849e3f4e --- /dev/null +++ b/care/facility/tests/test_facility_shifting_api.py @@ -0,0 +1,222 @@ +from enum import Enum + +from rest_framework import status +from rest_framework.test import APITestCase +from rest_framework_simplejwt.tokens import RefreshToken + +from care.utils.tests.test_utils import TestUtils + + +class ExpectedShiftListKeys(Enum): + id = "id" + patient = "patient" + patient_object = "patient_object" + status = "status" + origin_facility_object = "origin_facility_object" + shifting_approving_facility_object = "shifting_approving_facility_object" + assigned_facility = "assigned_facility" + assigned_facility_external = "assigned_facility_external" + assigned_facility_object = "assigned_facility_object" + external_id = "external_id" + created_date = "created_date" + modified_date = "modified_date" + emergency = "emergency" + + +class PatientObjectKeys(Enum): + id = "id" + name = "name" + allow_transfer = "allow_transfer" + age = "age" + phone_number = "phone_number" + address = "address" + disease_status = "disease_status" + facility = "facility" + facility_object = "facility_object" + state_object = "state_object" + + +class FacilityKeys(Enum): + id = "id" + name = "name" + + +class StateKeys(Enum): + id = "id" + name = "name" + + +class ExpectedShiftRetrieveKeys(Enum): + ID = "id" + PATIENT = "patient" + PATIENT_OBJECT = "patient_object" + STATUS = "status" + BREATHLESSNESS_LEVEL = "breathlessness_level" + ORIGIN_FACILITY = "origin_facility" + ORIGIN_FACILITY_OBJECT = "origin_facility_object" + SHIFTING_APPROVING_FACILITY = "shifting_approving_facility" + SHIFTING_APPROVING_FACILITY_OBJECT = "shifting_approving_facility_object" + ASSIGNED_FACILITY = "assigned_facility" + ASSIGNED_FACILITY_EXTERNAL = "assigned_facility_external" + ASSIGNED_FACILITY_OBJECT = "assigned_facility_object" + ASSIGNED_FACILITY_TYPE = "assigned_facility_type" + PREFERRED_VEHICLE_CHOICE = "preferred_vehicle_choice" + ASSIGNED_TO_OBJECT = "assigned_to_object" + CREATED_BY_OBJECT = "created_by_object" + LAST_EDITED_BY_OBJECT = "last_edited_by_object" + AMBULANCE_DRIVER_NAME = "ambulance_driver_name" + AMBULANCE_NUMBER = "ambulance_number" + EXTERNAL_ID = "external_id" + CREATED_DATE = "created_date" + MODIFIED_DATE = "modified_date" + EMERGENCY = "emergency" + IS_UP_SHIFT = "is_up_shift" + REASON = "reason" + VEHICLE_PREFERENCE = "vehicle_preference" + COMMENTS = "comments" + REFERING_FACILITY_CONTACT_NAME = "refering_facility_contact_name" + REFERING_FACILITY_CONTACT_NUMBER = "refering_facility_contact_number" + IS_KASP = "is_kasp" + IS_ASSIGNED_TO_USER = "is_assigned_to_user" + AMBULANCE_PHONE_NUMBER = "ambulance_phone_number" + ASSIGNED_TO = "assigned_to" + CREATED_BY = "created_by" + LAST_EDITED_BY = "last_edited_by" + + +class ExpectedShiftCommentListCreatedByKeys(Enum): + ID = "id" + FIRST_NAME = "first_name" + LAST_NAME = "last_name" + + +class ExpectedShiftCommentListKeys(Enum): + ID = "id" + COMMENT = "comment" + MODIFIED_DATE = "modified_date" + CREATED_BY_OBJECT = "created_by_object" + + +class ExpectedShiftCommentRetrieveCreatedByKeys(Enum): + ID = "id" + FIRST_NAME = "first_name" + LAST_NAME = "last_name" + USERNAME = "username" + EMAIL = "email" + USER_TYPE = "user_type" + LAST_LOGIN = "last_login" + + +class ExpectedShiftCommentRetrieveKeys(Enum): + ID = "id" + COMMENT = "comment" + CREATED_BY_OBJECT = "created_by_object" + EXTERNAL_ID = "external_id" + CREATED_DATE = "created_date" + MODIFIED_DATE = "modified_date" + CREATED_BY = "created_by" + + +class ShiftingViewSetTestCase(TestUtils, APITestCase): + @classmethod + def setUpTestData(cls): + cls.state = cls.create_state() + cls.district = cls.create_district(cls.state) + cls.local_body = cls.create_local_body(cls.district) + cls.user = cls.create_user( + username="test_user", district=cls.district, local_body=cls.local_body + ) + cls.facility = cls.create_facility( + user=cls.user, district=cls.district, local_body=cls.local_body + ) + cls.patient = cls.create_patient(cls.district, cls.facility) + cls.patient_shift = cls.create_patient_shift( + facility=cls.facility, user=cls.user, patient=cls.patient + ) + + def setUp(self) -> None: + refresh_token = RefreshToken.for_user(self.user) + self.client.credentials( + HTTP_AUTHORIZATION=f"Bearer {refresh_token.access_token}" + ) + + def test_list_shift(self): + response = self.client.get("/api/v1/shift/") + + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertIsInstance(response.json()["results"], list) + + expected_keys = [key.value for key in ExpectedShiftListKeys] + data = response.json()["results"][0] + self.assertCountEqual(data.keys(), expected_keys) + + def test_retrieve_shift(self): + response = self.client.get(f"/api/v1/shift/{self.patient_shift.external_id}/") + + self.assertEqual(response.status_code, status.HTTP_200_OK) + expected_keys = [key.value for key in ExpectedShiftRetrieveKeys] + data = response.json() + self.assertCountEqual(data.keys(), expected_keys) + + +class ShifitngRequestCommentViewSetTestCase(TestUtils, APITestCase): + @classmethod + def setUpTestData(cls) -> None: + cls.state = cls.create_state() + cls.district = cls.create_district(cls.state) + cls.local_body = cls.create_local_body(cls.district) + cls.user = cls.create_user( + username="test_user", district=cls.district, local_body=cls.local_body + ) + cls.facility = cls.create_facility( + user=cls.user, district=cls.district, local_body=cls.local_body + ) + cls.patient = cls.create_patient(cls.district, cls.facility) + cls.patient_shift = cls.create_patient_shift( + facility=cls.facility, user=cls.user, patient=cls.patient + ) + cls.patient_shift_comment = cls.create_patient_shift_comment( + resource=cls.patient_shift + ) + + def setUp(self) -> None: + refresh_token = RefreshToken.for_user(self.user) + self.client.credentials( + HTTP_AUTHORIZATION=f"Bearer {refresh_token.access_token}" + ) + + def test_list_shift_request_comment(self): + response = self.client.get( + f"/api/v1/shift/{self.patient_shift.external_id}/comment/" + ) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertIsInstance(response.json()["results"], list) + + expected_keys = [key.value for key in ExpectedShiftCommentListKeys] + data = response.json()["results"][0] + self.assertCountEqual(data.keys(), expected_keys) + + expected_created_by_keys = [ + key.value for key in ExpectedShiftCommentListCreatedByKeys + ] + data = response.json()["results"][0]["created_by_object"] + if data: + self.assertCountEqual(data.keys(), expected_created_by_keys) + + def test_retrieve_shift_request_comment(self): + response = self.client.get( + f"/api/v1/shift/{self.patient_shift.external_id}/comment/{self.patient_shift_comment.external_id}/" + ) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + expected_keys = [key.value for key in ExpectedShiftCommentRetrieveKeys] + data = response.json() + self.assertCountEqual(data.keys(), expected_keys) + + expected_created_by_keys = [ + key.value for key in ExpectedShiftCommentRetrieveCreatedByKeys + ] + data = response.json()["created_by_object"] + if data: + self.assertCountEqual(data.keys(), expected_created_by_keys) diff --git a/care/facility/tests/test_patient_consultation_api.py b/care/facility/tests/test_patient_consultation_api.py index 8fd901e274..0bea4b9847 100644 --- a/care/facility/tests/test_patient_consultation_api.py +++ b/care/facility/tests/test_patient_consultation_api.py @@ -87,7 +87,7 @@ def create_route_to_facility_consultation( data.update(kwargs) return self.client.post(self.get_url(), data, format="json") - def create_admission_consultation(self, patient=None, **kwargs): + def call_create_admission_consultation_api(self, patient=None, **kwargs): patient = patient or self.create_patient(self.district, self.facility) data = self.get_default_data().copy() kwargs.update( @@ -97,7 +97,10 @@ def create_admission_consultation(self, patient=None, **kwargs): } ) data.update(kwargs) - res = self.client.post(self.get_url(), data, format="json") + return self.client.post(self.get_url(), data, format="json") + + def create_admission_consultation(self, patient=None, **kwargs): + res = self.call_create_admission_consultation_api(patient, **kwargs) return PatientConsultation.objects.get(external_id=res.data["id"]) def update_consultation(self, consultation, **kwargs): @@ -132,6 +135,12 @@ def test_encounter_date_less_than_minimum(self): res = self.client.post(self.get_url(), data, format="json") self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) + def test_create_admission_consultation_without_treating_physician(self): + res = self.call_create_admission_consultation_api( + suggestion="A", treating_physician=None + ) + self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) + def test_create_consultation_treating_physician_invalid_user(self): consultation = self.create_admission_consultation(suggestion="A") res = self.update_consultation( diff --git a/care/facility/tests/test_pdf_generation.py b/care/facility/tests/test_pdf_generation.py new file mode 100644 index 0000000000..6754c0c43a --- /dev/null +++ b/care/facility/tests/test_pdf_generation.py @@ -0,0 +1,230 @@ +import os +import subprocess +import tempfile +from datetime import date +from pathlib import Path + +from django.conf import settings +from django.template.loader import render_to_string +from django.test import TestCase +from PIL import Image +from rest_framework.test import APIClient + +from care.facility.models import ( + ConditionVerificationStatus, + ICD11Diagnosis, + PrescriptionDosageType, + PrescriptionType, +) +from care.facility.utils.reports import discharge_summary +from care.facility.utils.reports.discharge_summary import compile_typ +from care.utils.tests.test_utils import TestUtils + + +def compare_pngs(png_path1, png_path2): + with Image.open(png_path1) as img1, Image.open(png_path2) as img2: + if img1.mode != img2.mode: + return False + + if img1.size != img2.size: + return False + + img1_data = list(img1.getdata()) + img2_data = list(img2.getdata()) + + if img1_data == img2_data: + return True + else: + return False + + +def test_compile_typ(data): + sample_file_path = os.path.join( + os.getcwd(), "care", "facility", "tests", "sample_reports", "sample{n}.png" + ) + test_output_file_path = os.path.join( + os.getcwd(), "care", "facility", "tests", "sample_reports", "test_output{n}.png" + ) + try: + logo_path = ( + Path(settings.BASE_DIR) + / "staticfiles" + / "images" + / "logos" + / "black-logo.svg" + ) + data["logo_path"] = str(logo_path) + content = render_to_string( + "reports/patient_discharge_summary_pdf_template.typ", context=data + ) + subprocess.run( + ["typst", "compile", "-", test_output_file_path, "--format", "png"], + input=content.encode("utf-8"), + capture_output=True, + check=True, + cwd="/", + ) + + number_of_pngs_generated = 2 + # To be updated only if the number of sample png increase in future + + for i in range(1, number_of_pngs_generated + 1): + current_sample_file_path = sample_file_path + current_sample_file_path = str(current_sample_file_path).replace( + "{n}", str(i) + ) + + current_test_output_file_path = test_output_file_path + current_test_output_file_path = str(current_test_output_file_path).replace( + "{n}", str(i) + ) + + if not compare_pngs( + Path(current_sample_file_path), Path(current_test_output_file_path) + ): + return False + return True + except Exception: + return False + finally: + count = 1 + while True: + current_test_output_file_path = test_output_file_path + current_test_output_file_path = current_test_output_file_path.replace( + "{n}", str(count) + ) + if Path(current_test_output_file_path).exists(): + os.remove(Path(current_test_output_file_path)) + else: + break + count += 1 + + +class TestTypstInstallation(TestCase): + def test_typst_installed(self): + try: + subprocess.run(["typst", "--version"], check=True) + typst_installed = True + except subprocess.CalledProcessError: + typst_installed = False + + self.assertTrue(typst_installed, "Typst is not installed or not accessible") + + +class TestGenerateDischargeSummaryPDF(TestCase, TestUtils): + @classmethod + def setUpTestData(cls) -> None: + cls.state = cls.create_state(name="sample_state") + cls.district = cls.create_district(cls.state, name="sample_district") + cls.local_body = cls.create_local_body(cls.district, name="sample_local_body") + cls.super_user = cls.create_super_user("su", cls.district) + cls.facility = cls.create_facility( + cls.super_user, cls.district, cls.local_body, name="_Sample_Facility" + ) + cls.user = cls.create_user("staff1", cls.district, home_facility=cls.facility) + cls.treating_physician = cls.create_user( + "test Doctor", + cls.district, + home_facility=cls.facility, + first_name="Doctor", + last_name="Tester", + user_type=15, + ) + cls.patient = cls.create_patient( + cls.district, cls.facility, local_body=cls.local_body + ) + cls.consultation = cls.create_consultation( + cls.patient, + cls.facility, + patient_no="123456", + doctor=cls.treating_physician, + height=178, + weight=80, + suggestion="A", + ) + cls.create_patient_sample(cls.patient, cls.consultation, cls.facility, cls.user) + cls.create_policy(patient=cls.patient, user=cls.user) + cls.create_encounter_symptom(cls.consultation, cls.user) + cls.patient_investigation_group = cls.create_patient_investigation_group() + cls.patient_investigation = cls.create_patient_investigation( + cls.patient_investigation_group + ) + cls.patient_investigation_session = cls.create_patient_investigation_session( + cls.user + ) + cls.create_investigation_value( + cls.patient_investigation, + cls.consultation, + cls.patient_investigation_session, + cls.patient_investigation_group, + ) + cls.create_disease(cls.patient) + cls.create_prescription(cls.consultation, cls.user) + cls.create_prescription( + cls.consultation, cls.user, dosage_type=PrescriptionDosageType.TITRATED + ) + cls.create_prescription( + cls.consultation, cls.user, dosage_type=PrescriptionDosageType.PRN + ) + cls.create_prescription( + cls.consultation, cls.user, prescription_type=PrescriptionType.DISCHARGE + ) + cls.create_prescription( + cls.consultation, + cls.user, + prescription_type=PrescriptionType.DISCHARGE, + dosage_type=PrescriptionDosageType.TITRATED, + ) + cls.create_prescription( + cls.consultation, + cls.user, + prescription_type=PrescriptionType.DISCHARGE, + dosage_type=PrescriptionDosageType.PRN, + ) + cls.create_consultation_diagnosis( + cls.consultation, + ICD11Diagnosis.objects.filter( + label="SG31 Conception vessel pattern (TM1)" + ).first(), + verification_status=ConditionVerificationStatus.CONFIRMED, + ) + cls.create_consultation_diagnosis( + cls.consultation, + ICD11Diagnosis.objects.filter( + label="SG2B Liver meridian pattern (TM1)" + ).first(), + verification_status=ConditionVerificationStatus.DIFFERENTIAL, + ) + cls.create_consultation_diagnosis( + cls.consultation, + ICD11Diagnosis.objects.filter( + label="SG29 Triple energizer meridian pattern (TM1)" + ).first(), + verification_status=ConditionVerificationStatus.PROVISIONAL, + ) + cls.create_consultation_diagnosis( + cls.consultation, + ICD11Diagnosis.objects.filter( + label="SG60 Early yang stage pattern (TM1)" + ).first(), + verification_status=ConditionVerificationStatus.UNCONFIRMED, + ) + + def setUp(self) -> None: + self.client = APIClient() + + def test_pdf_generation_success(self): + test_data = {"consultation": self.consultation} + + with tempfile.NamedTemporaryFile(suffix=".pdf", delete=False) as file: + compile_typ(file.name, test_data) + + self.assertTrue(os.path.exists(file.name)) + self.assertGreater(os.path.getsize(file.name), 0) + + def test_pdf_generation(self): + data = discharge_summary.get_discharge_summary_data(self.consultation) + data["date"] = date(2020, 1, 1) + + # This sorting is test's specific and done in order to keep the values in order + self.assertTrue(test_compile_typ(data)) diff --git a/care/facility/utils/reports/discharge_summary.py b/care/facility/utils/reports/discharge_summary.py index acec25ea20..b9fb47d077 100644 --- a/care/facility/utils/reports/discharge_summary.py +++ b/care/facility/utils/reports/discharge_summary.py @@ -1,18 +1,20 @@ import logging +import subprocess import tempfile from collections.abc import Iterable +from pathlib import Path from uuid import uuid4 from django.conf import settings from django.core.cache import cache from django.core.mail import EmailMessage -from django.db.models import Q +from django.db.models import Case, IntegerField, Q, Value, When from django.template.loader import render_to_string from django.utils import timezone -from hardcopy import bytestring_to_pdf from care.facility.models import ( - DailyRound, + BedType, + ConsultationBed, Disease, EncounterSymptom, InvestigationValue, @@ -28,7 +30,7 @@ ACTIVE_CONDITION_VERIFICATION_STATUSES, ConditionVerificationStatus, ) -from care.facility.static_data.icd11 import get_icd11_diagnoses_objects_by_ids +from care.facility.static_data.icd11 import get_icd11_diagnosis_object_by_id from care.hcx.models.policy import Policy logger = logging.getLogger(__name__) @@ -65,13 +67,19 @@ def get_diagnoses_data(consultation: PatientConsultation): ) ) - # retrieve diagnosis objects from in-memory table - diagnoses = get_icd11_diagnoses_objects_by_ids([entry[0] for entry in entries]) - + # retrieve diagnosis objects + diagnoses = [] + for entry in entries: + diagnose = get_icd11_diagnosis_object_by_id(entry[0]) + if diagnose: + diagnoses.append(diagnose) principal, unconfirmed, provisional, differential, confirmed = [], [], [], [], [] for diagnosis, record in zip(diagnoses, entries): _, verification_status, is_principal = record + + diagnosis.verification_status = verification_status + if is_principal: principal.append(diagnosis) if verification_status == ConditionVerificationStatus.UNCONFIRMED: @@ -92,40 +100,61 @@ def get_diagnoses_data(consultation: PatientConsultation): } +def format_duration(duration): + if not duration: + return "" + + days = duration.days + if days > 0: + return f"{days} days" + hours, remainder = divmod(duration.seconds, 3600) + minutes, _ = divmod(remainder, 60) + return f"{hours:02}:{minutes:02}" + + def get_discharge_summary_data(consultation: PatientConsultation): logger.info(f"fetching discharge summary data for {consultation.external_id}") samples = PatientSample.objects.filter( patient=consultation.patient, consultation=consultation ) hcx = Policy.objects.filter(patient=consultation.patient) - daily_rounds = DailyRound.objects.filter(consultation=consultation) - symptoms = EncounterSymptom.objects.filter(consultation=consultation).exclude( - clinical_impression_status=ClinicalImpressionStatus.ENTERED_IN_ERROR - ) + symptoms = EncounterSymptom.objects.filter( + consultation=consultation, onset_date__lt=consultation.encounter_date + ).exclude(clinical_impression_status=ClinicalImpressionStatus.ENTERED_IN_ERROR) diagnoses = get_diagnoses_data(consultation) investigations = InvestigationValue.objects.filter( Q(consultation=consultation.id) & (Q(value__isnull=False) | Q(notes__isnull=False)) ) medical_history = Disease.objects.filter(patient=consultation.patient) - prescriptions = Prescription.objects.filter( - consultation=consultation, - prescription_type=PrescriptionType.REGULAR.value, - ).exclude(dosage_type=PrescriptionDosageType.PRN.value) - prn_prescriptions = Prescription.objects.filter( - consultation=consultation, - prescription_type=PrescriptionType.REGULAR.value, - dosage_type=PrescriptionDosageType.PRN.value, + prescriptions = ( + Prescription.objects.filter( + consultation=consultation, prescription_type=PrescriptionType.REGULAR.value + ) + .annotate( + order_priority=Case( + When(dosage_type=PrescriptionDosageType.PRN.value, then=Value(2)), + When(dosage_type=PrescriptionDosageType.TITRATED.value, then=Value(1)), + default=Value(0), + output_field=IntegerField(), + ) + ) + .order_by("order_priority", "id") ) - discharge_prescriptions = Prescription.objects.filter( - consultation=consultation, - prescription_type=PrescriptionType.DISCHARGE.value, - ).exclude(dosage_type=PrescriptionDosageType.PRN.value) - - discharge_prn_prescriptions = Prescription.objects.filter( - consultation=consultation, - prescription_type=PrescriptionType.DISCHARGE.value, - dosage_type=PrescriptionDosageType.PRN.value, + discharge_prescriptions = ( + Prescription.objects.filter( + consultation=consultation, + prescription_type=PrescriptionType.DISCHARGE.value, + ) + .annotate( + order_priority=Case( + When(dosage_type=PrescriptionDosageType.PRN.value, then=Value(2)), + When(dosage_type=PrescriptionDosageType.TITRATED.value, then=Value(1)), + default=Value(0), + output_field=IntegerField(), + ) + ) + .order_by("order_priority", "id") ) files = FileUpload.objects.filter( associating_id=consultation.id, @@ -133,47 +162,91 @@ def get_discharge_summary_data(consultation: PatientConsultation): upload_completed=True, is_archived=False, ) + admitted_to = set() + if ConsultationBed.objects.filter(consultation=consultation).exists(): + for bed in ConsultationBed.objects.filter(consultation=consultation).order_by( + "-created_date" + ): + admitted_to.add(BedType(bed.bed.bed_type).name) + admitted_to = list(admitted_to) + if not admitted_to: + admitted_to = None + + admission_duration = ( + format_duration(consultation.discharge_date - consultation.encounter_date) + if consultation.discharge_date + else None + ) return { "patient": consultation.patient, "samples": samples, "hcx": hcx, "symptoms": symptoms, - "principal_diagnoses": diagnoses["principal"], - "unconfirmed_diagnoses": diagnoses["unconfirmed"], - "provisional_diagnoses": diagnoses["provisional"], - "differential_diagnoses": diagnoses["differential"], - "confirmed_diagnoses": diagnoses["confirmed"], + "admitted_to": admitted_to, + "admission_duration": admission_duration, + "diagnoses": diagnoses["confirmed"] + + diagnoses["provisional"] + + diagnoses["unconfirmed"] + + diagnoses["differential"], + "primary_diagnoses": diagnoses["principal"], "consultation": consultation, "prescriptions": prescriptions, - "prn_prescriptions": prn_prescriptions, "discharge_prescriptions": discharge_prescriptions, - "discharge_prn_prescriptions": discharge_prn_prescriptions, - "dailyrounds": daily_rounds, "medical_history": medical_history, "investigations": investigations, "files": files, } -def generate_discharge_summary_pdf(data, file): - logger.info( - f"Generating Discharge Summary html for {data['consultation'].external_id}" - ) - html_string = render_to_string("reports/patient_discharge_summary_pdf.html", data) +def compile_typ(output_file, data): + try: + logo_path = ( + Path(settings.BASE_DIR) + / "staticfiles" + / "images" + / "logos" + / "black-logo.svg" + ) + + data["logo_path"] = str(logo_path) + + content = render_to_string( + "reports/patient_discharge_summary_pdf_template.typ", context=data + ) + + subprocess.run( + [ + "typst", + "compile", + "-", + str(output_file), + ], + input=content.encode("utf-8"), + capture_output=True, + check=True, + cwd="/", + ) + logging.info( + f"Successfully Compiled Summary pdf for {data['consultation'].external_id}" + ) + return True + + except subprocess.CalledProcessError as e: + logging.error( + f"Error compiling summary pdf for {data['consultation'].external_id}: {e.stderr.decode('utf-8')}" + ) + return False + + +def generate_discharge_summary_pdf(data, file): logger.info( f"Generating Discharge Summary pdf for {data['consultation'].external_id}" ) - bytestring_to_pdf( - html_string.encode(), - file, - **{ - "no-margins": None, - "disable-gpu": None, - "disable-dev-shm-usage": False, - "window-size": "2480,3508", - }, + compile_typ(output_file=file.name, data=data) + logger.info( + f"Successfully Generated Discharge Summary pdf for {data['consultation'].external_id}" ) diff --git a/care/templates/base.html b/care/templates/base.html index 53b13042d1..a2d766b9ec 100644 --- a/care/templates/base.html +++ b/care/templates/base.html @@ -103,11 +103,11 @@ src="{% static 'images/logos/dpg-logo.svg' %}" alt="Digital Public Goods logo" /> - + Open Healthcare Network is an open-source digital public good designed by a multi-disciplinary team of innovators and volunteers who are working on a model to support Government efforts.  - (Github) + (Github)

diff --git a/care/templates/pages/home.html b/care/templates/pages/home.html index d3ead4016d..7e4326f675 100644 --- a/care/templates/pages/home.html +++ b/care/templates/pages/home.html @@ -5,8 +5,8 @@
-

Corona Safe Network

-

Our Goal is to defend the Healthcare system of Kerala from overloading beyond capacity. +

{% translate "Open Healthcare Network" %}

+

{% blocktranslate %}Our Goal is to defend the Healthcare system of Kerala from overloading beyond capacity.{% endblocktranslate %}

diff --git a/care/templates/reports/daily_report.html b/care/templates/reports/daily_report.html deleted file mode 100644 index c8ceea3ccd..0000000000 --- a/care/templates/reports/daily_report.html +++ /dev/null @@ -1,436 +0,0 @@ - - - - - - - - - - -
-
- -
-
-
- {{object_type}} : {{object_name}} -
-
-
-

- Daily Summary -

-

- Generated for {{current_date}} -

-
- -
-
-
-
-
- Active Patients -
-
- {{patients_summary.current_active}} -
-
-
-
- Patient Registered Today -
-
- {{patients_summary.created_today}} -
-
-
-
- Patient Discharged Today -
-
- {{patients_summary.discharged_today}} -
-
-
-
-

- Patients Registered By Age Group -

-
-
-
-
-
- - - - - - - - - {% for patients_age_group in patients_age %} - - - - - {% endfor %} - -
- Age Group - - Count -
- {{patients_age_group.title}} - - {{patients_age_group.total_count}} -
-
-
-
-
-
-

- Patients Registered By Category -

-
-
-
-
-
- - - - - - - - - {% for patients_category in patients_categories %} - - - - - {% endfor %} - -
- Category - - Count -
- {{patients_category.title}} - - {{patients_category.total_count}} -
-
-
-
-
-
-
-

Shifting

-
-
-
- Total -
-
- {{shifting_summary.total_count}} -
-
-
-
- Up Shift -
-
- {{shifting_summary.total_up}} -
-
-
-
- Down Shift -
-
- {{shifting_summary.total_down}} -
-
-
-
-

- Shifting Summary -

-
-
-
-
-
- - - - - - - - - - {% for shifting in shifting_status %} - - - - - - {% endfor %} - -
- Status - - Total Count - - Emergency Count -
- {{shifting.status}} - - {{shifting.total_count}} - - {{shifting.emergency_count}} -
-
-
-
-
-
- - diff --git a/care/templates/reports/patient_discharge_summary_pdf.html b/care/templates/reports/patient_discharge_summary_pdf.html deleted file mode 100644 index 2a2125c788..0000000000 --- a/care/templates/reports/patient_discharge_summary_pdf.html +++ /dev/null @@ -1,1065 +0,0 @@ -{% load filters static %} - - - - - - - - - - - - -
-
-
- {{patient.facility.name}} -
-
-
-

- Patient Discharge Summary -

-

- Created on {{date}} -

-
- -
-
-
-

- Full name: {{patient.name}} -

-

- Gender: {{patient.get_gender_display}} -

-

- Age: {{patient.get_age}} -

- {% if patient.date_of_birth %} -

- Date of Birth: {{patient.date_of_birth}} -

- {% else %} -

- Year of Birth: {{patient.year_of_birth}} -

- {% endif %} -

- Blood Group: {{patient.blood_group}} -

-

- Phone Number: {{patient.phone_number}} -

-

- Address: {{patient.address}} -

-

- Ration Card Category: {{patient.get_ration_card_category_display}} -

-
-
- -
-

- Admission Details -

-
-
-
-

- Route to Facility: - {{consultation.get_route_to_facility_display|field_name_to_label}} -

-

- Decision after consultation: - {{consultation.get_suggestion_display|field_name_to_label}} -

- {% if consultation.icu_admission_date %} -

- ICU Admission Date & Time: - {{consultation.icu_admission_date}} -

- {% endif %} - {% if consultation.suggestion == 'A' %} -

- Date of addmission: - {{consultation.encounter_date}} -

- {% elif consultation.suggestion == 'R' %} -

- Referred to: - {{consultation.referred_to.name}} -

- {% elif consultation.suggestion == 'DD' %} -

- Cause of death: - {{consultation.discharge_notes}} -

-

- Date and time of death: - {{consultation.death_datetime}} -

-

- Death Confirmed by: - {{consultation.death_confirmed_by}} -

- {% endif %} -
-

- - {% if consultation.suggestion == 'A' %} - IP No: - {% else %} - OP No: - {% endif %} - {{consultation.patient_no}} -

-

- Weight: - {{consultation.weight}} kg -

-

- Height: - {{consultation.height}} cm -

-
-
- - {% if hcx %} -

- Health insurance details: -

- -
- - - - - - - - - - - {% for policy in hcx %} - - - - - - - {% endfor %} - -
- Insurer Name - - Issuer ID - - Member ID - - Policy ID -
- {{policy.insurer_name}} - - {{policy.insurer_id}} - - {{policy.subscriber_id}} - - {{policy.policy_id}} -
-
- {% endif %} - - {% if symptoms %} -

- Symptoms: -

-
- - - - - - - - - - {% for symptom in symptoms %} - - - - - - {% endfor %} - -
- Name - - Onset Date - - Cure Date -
- {% if symptom.symptom == 9 %} - {{symptom.other_symptom}} - {% else %} - {{symptom.get_symptom_display}} - {% endif %} - - {{symptom.onset_date.date}} - - {{symptom.cure_date.date}} -
-
- {% endif %} - - {% if principal_diagnosis %} -

- Principal Diagnosis (as per ICD-11 recommended by WHO): -

-
- - - - - - - - - {% for disease in principal_diagnosis %} - - - - - {% endfor %} - -
- ID - - Name -
- {{disease.id}} - - {{disease.label}} -
-
- {% endif %} - - {% if unconfirmed_diagnoses %} -

- Unconfirmed Diagnoses (as per ICD-11 recommended by WHO): -

-
- - - - - - - - - {% for disease in unconfirmed_diagnoses %} - - - - - {% endfor %} - -
- ID - - Name -
- {{disease.id}} - - {{disease.label}} -
-
- {% endif %} - - {% if provisional_diagnoses %} -

- Provisional Diagnosis (as per ICD-11 recommended by WHO): -

-
- - - - - - - - - {% for disease in provisional_diagnoses %} - - - - - {% endfor %} - -
- ID - - Name -
- {{disease.id}} - - {{disease.label}} -
-
- {% endif %} - - {% if differential_diagnoses %} -

- Differential Diagnoses (as per ICD-11 recommended by WHO): -

-
- - - - - - - - - {% for disease in differential_diagnoses %} - - - - - {% endfor %} - -
- ID - - Name -
- {{disease.id}} - - {{disease.label}} -
-
- {% endif %} - - {% if confirmed_diagnoses %} -

- Confirmed Diagnoses (as per ICD-11 recommended by WHO): -

-
- - - - - - - - - {% for disease in confirmed_diagnoses %} - - - - - {% endfor %} - -
- ID - - Name -
- {{disease.id}} - - {{disease.label}} -
-
- {% endif %} - - - {% if medical_history %} -

- Medication History: -

-
- - - - - - - - - {% for disease in medical_history %} - - - - - {% endfor %} - -
- Comorbidity - - Details -
- {{disease.get_disease_display}} - - {{disease.details}} -
-
- {% endif %} - -
-

- Health status at admission: -

-

- Present health condition: - {{patient.present_health}} -

-

- Ongoing Medication: - {{patient.ongoing_medication}} -

- {% if consultation.route_to_facility %} -

- History of present illness: - {{consultation.history_of_present_illness}} -

- {% endif %} -

- Examination details and Clinical conditions: - {{consultation.examination_details}} -

-

- Allergies: - {{patient.allergies}} -

-
-
- - {% if consultation.suggestion != 'DD' %} -
-

- Treatment Summary -

-
-
- {% if patient.disease_status == 2 %} -
-

- COVID Disease Status: - Positive -

- {% if patient.date_of_result %} -

- Test Result Date: - {{patient.date_of_result.date}} -

- {% endif %} -

- Vaccinated against COVID: - {% if patient.is_vaccinated %} - Yes - {% else %} - No - {% endif %} -

-
- {% endif %} - - {% if prescriptions %} -

- Prescription Medication: -

-
- - - - - - - - - - - - - {% for prescription in prescriptions %} - - - - - - - - - {% endfor %} - -
- Medicine - - Dosage - - Route - - Frequency - - Days - - Notes -
- {{ prescription.medicine_name }} - - {{ prescription.base_dosage }} - {% if prescription.dosage_type == 'TITRATED' %} - to {{ prescription.target_dosage }} -

Instruction on titration: {{ prescription.instruction_on_titration }}

- {% endif %} -
- {{ prescription.route }} - - {{ prescription.frequency }} - - {{ prescription.days }} - - {{ prescription.notes }} -
-
- {% endif %} - - {% if prn_prescriptions %} -

- PRN Prescription: -

-
- - - - - - - - - - - - - {% for prescription in prn_prescriptions %} - - - - - - - - - {% endfor %} - -
- Medicine - - Dosage - - Max Dosage - - Min Time btwn. 2 doses - - Route - - Indicator -
- {{ prescription.medicine_name }} - - {{ prescription.base_dosage }} - - {{ prescription.max_dosage }} - - {{ prescription.min_hours_between_doses }} Hrs. - - {{ prescription.route }} - - {{ prescription.indicator }} -
-
- {% endif %} - - {% if consultation.investigation %} -

- Investigations Suggestions: -

-
- - - - - - - - - - {% for investigation in consultation.investigation %} - - - - - - {% endfor %} - -
- Type - - Time - - Notes -
- {{investigation.type|join:", "}} - - {% if investigation.repetitive %} - every {{investigation.frequency}} - {% else %} - {{investigation.time|parse_datetime}} - {% endif %} - - {{investigation.notes}} -
-
- {% endif %} - - {% if consultation.procedure %} -

- Procedures: -

-
- - - - - - - - - - {% for procedure in consultation.procedure %} - - - - - - {% endfor %} - -
- Procedure - - Time - - Notes -
- {{procedure.procedure}} - - {% if procedure.repetitive %} - every {{procedure.frequency}} - {% else %} - {{procedure.time|parse_datetime}} - {% endif %} - - {{procedure.notes}} -
-
- {% endif %} - - {% if consultation.treatment_plan %} -

- Prescribed medication: -

-

- {{ consultation.treatment_plan }} -

- {% endif %} - - {% if consultation.consultation_notes %} -

- General Instructions (Advice): -

-

- {{consultation.consultation_notes}} -

- {% endif %} - - {% if consultation.special_instruction %} -

- Special Instructions: -

-

- {{consultation.special_instruction}} -

- {% endif %} - - - {% if samples %} -

- Lab Reports: -

-
- - - - - - - - - - - {% for sample in samples %} - - - - - - - {% endfor %} - -
- Requested on - - Sample type - - Label - - Result -
- {{sample.created_date}} - - {{sample.get_sample_type_display}} - - {{sample.icmr_label}} - - {{sample.get_result_display}} -
-
- {% endif %} - - {% if dailyrounds %} -

- Daily Rounds: -

- {% for daily_round in dailyrounds %} -
-
-

- {{daily_round.created_date}} -

-
-
-
-
- Category -
-
- {{daily_round.get_patient_category_display}} -
-
-
-
-
- Physical Examination Details -
-
- {{daily_round.physical_examination_info}} -
-
-
-
- Other Details -
-
- {{daily_round.other_details}} -
-
-
-
-
- {% endfor %} - {% endif %} - - {% if investigations %} -
-

- Investigation History -

-
-
- - - - - - - - - - - - {% for investigation in investigations %} - - - - - - - - {% endfor %} - -
- Group - - Name - - Result - - Range - - Date -
- {{investigation.investigation.groups.first}} - - {{investigation.investigation.name}} - - {% if investigation.value%} - {{investigation.value}} - {% else %} - {{investigation.notes}} - {% endif %} - - {% if investigation.investigation.min_value and investigation.investigation.max_value%} - {{investigation.investigation.min_value}} - {{investigation.investigation.max_value}} - {% else %} - - - {% endif %} - {% if investigation.investigation.unit %} - {{investigation.investigation.unit}} - {% endif %} - - {{investigation.created_date}} -
-
- {% endif %} -
- {% endif %} - -
-

- Discharge Summary -

-
-
-
-

- Discharge Date: {{consultation.discharge_date}} -

-

- Discharge Reason: {{consultation.get_discharge_reason_display}} -

-
- {% if consultation.new_discharge_reason == 1 %} - {% if discharge_prescriptions %} -

- Discharge Prescription Medication: -

-
- - - - - - - - - - - - - {% for prescription in discharge_prescriptions %} - - - - - - - - - {% endfor %} - -
- Medicine - - Dosage - - Route - - Frequency - - Days - - Notes -
- {{ prescription.medicine_name }} - - {{ prescription.base_dosage }} - - {{ prescription.route }} - - {{ prescription.frequency }} - - {{ prescription.days }} - - {{ prescription.notes }} -
-
- {% endif %} - - {% if discharge_prn_prescriptions %} -

- Discharge PRN Prescription: -

-
- - - - - - - - - - - - - {% for prescription in discharge_prn_prescriptions %} - - - - - - - - - {% endfor %} - -
- Medicine - - Dosage - - Max Dosage - - Min Time btwn. 2 doses - - Route - - Indicator -
- {{ prescription.medicine_name }} - - {{ prescription.base_dosage }} - - {{ prescription.max_dosage }} - - {{ prescription.min_hours_between_doses }} Hrs. - - {{ prescription.route }} - - {{ prescription.indicator }} -
-
- {% endif %} - {% elif consultation.new_discharge_reason == 2 %} - {% elif consultation.new_discharge_reason == 3 %} - {% elif consultation.new_discharge_reason == 4 %} - {% endif %} - -

- Discharge Notes: {{consultation.discharge_notes}} -

-
- - {% if files %} -
-

- Annexes -

-
-
-

- Uploaded Files: -

-
- - - - - - - - - {% for file in files %} - - - - - {% endfor %} - -
- Uploaded at - - Name -
- {{file.modified_date}} - - {{file.name}} -
-
-
- {% endif %} - -
-
- Treating Physician -
-
- {% if consultation.treating_physician %} - {{ consultation.treating_physician.first_name }} {{ consultation.treating_physician.last_name }} - {% else %} - - - {% endif %} -
-
- - - diff --git a/care/templates/reports/patient_discharge_summary_pdf_template.typ b/care/templates/reports/patient_discharge_summary_pdf_template.typ new file mode 100644 index 0000000000..b24c8402e4 --- /dev/null +++ b/care/templates/reports/patient_discharge_summary_pdf_template.typ @@ -0,0 +1,419 @@ +{% load static %} +{% load filters static %} +{% load prescription_tags %} +{% load data_formatting_tags %} + +#set page("a4",margin: 40pt) +#set text(font: "DejaVu Sans",size: 10pt,hyphenate: true) +#let mygray = luma(100) + +#let frame(stroke) = (x, y) => ( + left: if x > 0 { 0pt } else { stroke }, + right: stroke, + top: if y < 2 { stroke } else { 0pt }, + bottom: stroke, +) + +#set table( + fill: (_, y) => if calc.odd(y) { rgb("EAF2F5") }, + stroke: frame(rgb("21222C")), +) + +#let facility_name="{{patient.facility.name}}" + +#align(center, text(24pt,weight: "bold")[= #facility_name]) + +#line(length: 100%, stroke: mygray) + +#grid( + columns: (auto, 1fr), + row-gutter: 1em, + align: (left, right), + {% if consultation.suggestion == "A" %} + text(size: 15pt)[= Patient Discharge Summary], + {% else %} + text(size: 15pt)[= Patient Summary], + {% endif %} + grid.cell(align: right, rowspan: 2)[#scale(x:90%, y:90%, reflow: true)[#image("{{ logo_path }}")]], + [#text(fill: mygray, weight: 500)[*Created on {{date}}*]] +) + +#line(length: 100%, stroke: mygray) + +#show grid.cell.where(x: 0): set text(fill: mygray,weight: "bold") +#show grid.cell.where(x: 2): set text(fill: mygray,weight: "bold") + +#grid( + columns: (1fr, 1fr, 1fr, 1fr), + row-gutter: 1.5em, + [Full name:], "{{patient.name}}", + [Gender:], "{{patient.get_gender_display }}", + [Age:], "{{patient.get_age }}", + [Blood Group:], "{{patient.blood_group }}", + [Phone Number:], "{{patient.phone_number }}", + [Ration Card Category:], "{{patient.get_ration_card_category_display|format_empty_data }}", + [Address:], grid.cell(colspan: 3, "{{patient.address }}"), +) + +#line(length: 100%, stroke: mygray) + +{% if consultation.suggestion == "A" %} +#align(left, text(18pt)[== Admission Details]) +{% else %} +#align(left, text(18pt)[== Patient Details]) +{% endif %} +#text("") +#grid( + columns: (1.1fr, 2fr), + row-gutter: 1.2em, + align: (left), + [Route to Facility:], "{{ consultation.get_route_to_facility_display | field_name_to_label }}", + {% if consultation.suggestion == "A" %} + [Admitted To:], "{{ admitted_to|format_to_sentence_case|format_empty_data }}", + [Duration of Admission:], "{{admission_duration|format_empty_data}}", + [Date of admission:], "{{ consultation.encounter_date }}", + [IP No:], "{{ consultation.patient_no }}", + [Weight:], + {% if consultation.weight == 0.0 %} + "N/A" + {% else %} + "{{ consultation.weight }} kg" + {% endif %}, + [Height:], + {% if consultation.height == 0.0 %} + "N/A" + {% else %} + "{{ consultation.height }} cm" + {% endif %}, + [Diagnosis at admission:],[#stack( + dir: ttb, + spacing: 10pt, + {% for diagnose in diagnoses %} + "{{ diagnose.label }} ({{diagnose.verification_status }})", + {% endfor %} + )], + [Reason for admission:],[#stack( + dir: ttb, + spacing: 10pt, + {% if primary_diagnoses %} + {% for diagnose in primary_diagnoses %} + "{{ diagnose.label }}", + {% endfor %} + {% else %} + "N/A" + {% endif %} + )], + [Symptoms at admission], [#stack( + dir: ttb, + spacing: 10pt, + {% if symptoms %} + {% for symptom in symptoms %} + {% if symptom.symptom == 9 %} + "{{ symptom.other_symptom }}", + {% else %} + "{{ symptom.get_symptom_display }}", + {% endif %} + {% endfor %} + {% else %} + "Asymptomatic" + {% endif %} + )], + {% else %} + [OP No:], "{{ consultation.patient_no }}", + [Weight:], + {% if consultation.weight == 0.0 %} + "N/A" + {% else %} + "{{ consultation.weight }} kg" + {% endif %}, + [Height:], + {% if consultation.height == 0.0 %} + "N/A" + {% else %} + "{{ consultation.height }} cm" + {% endif %}, + [Diagnosis:],[#stack( + dir: ttb, + spacing: 10pt, + {% for diagnose in diagnoses %} + "{{ diagnose.label }} ({{diagnose.verification_status }})", + {% endfor %} + )], + [Principal Diagnosis:],[#stack( + dir: ttb, + spacing: 10pt, + {% if primary_diagnoses %} + {% for diagnose in primary_diagnoses %} + "{{ diagnose.label }}", + {% endfor %} + {% else %} + "N/A" + {% endif %} + )], + [Symptoms], [#stack( + dir: ttb, + spacing: 10pt, + {% if symptoms %} + {% for symptom in symptoms %} + {% if symptom.symptom == 9 %} + "{{ symptom.other_symptom }}", + {% else %} + "{{ symptom.get_symptom_display }}", + {% endif %} + {% endfor %} + {% else %} + "Asymptomatic" + {% endif %} + )], + {% endif %} + [Reported Allergies:], "{{ patient.allergies |format_empty_data }}", +) + +#text("\n") + +#align(center, [#line(length: 40%, stroke: mygray)]) + +{% if medical_history.0.get_disease_display != "NO" %} + +#align(left, text(14pt,weight: "bold",)[=== Medication History:]) + +#table( + columns: (1.5fr, 3.5fr), + inset: 10pt, + align: horizon, + table.header( + [*COMORBIDITY*], [*DETAILS*], + ), + {% for disease in medical_history %} + "{{disease.get_disease_display }}", "{{disease.details|format_empty_data }}", + {% endfor %} +) +#align(center, [#line(length: 40%, stroke: mygray,)]) +{% endif %} +{% if consultation.suggestion != 'DD' %} + {% if patient.disease_status == 2 or prescriptions or consultation.investigation or consultation.procedure or investigations or samples %} + #align(left, text(18pt,)[== Treatment Summary]) + #text("") + {% endif %} + + {% if patient.disease_status == 2 %} + #grid( + columns: (1fr, 1fr), + gutter: 1.4em, + align: (left), + [COVID Disease Status:], [Positive], + {% if patient.date_of_result %} + [Test Result Date:], "{{ patient.date_of_result.date }}", + {% endif %} + [Vaccinated against COVID:], [ + {% if patient.is_vaccinated %} + Yes + {% else %} + No + {% endif %} + ], + ) + {% endif %} + + {% if prescriptions %} + #align(left, text(14pt,weight: "bold",)[=== Medication Administered:]) + #table( + columns: (1fr,), + inset: 10pt, + align: horizon, + stroke: 1pt, + table.header( + align(center, text([*MEDICATION DETAILS*])) + ), + {% for prescription in prescriptions %} + [#grid( + columns: (0.5fr, 9.5fr), + row-gutter: 1.2em, + align: (left), + "{{ forloop.counter }}", + "{{ prescription|format_prescription }}", + )], + {% endfor %} + ) + + #align(center, [#line(length: 40%, stroke: mygray,)]) + {% endif %} + + {% if consultation.investigation %} + #align(left, text(14pt,weight: "bold",)[=== Investigations Conducted:]) + + #table( + columns: (1.5fr, 1fr, 1.5fr), + inset: 10pt, + align: horizon, + table.header( + [*TYPE*], [*TIME*], [*NOTES*] + ), + {% for investigation in consultation.investigation %} + "{{ investigation.type|join:", " }}", + "{% if investigation.repetitive %}every {{ investigation.frequency }}{% else %}{{ investigation.time|date:"DATETIME_FORMAT" }}{% endif %}", + "{{ investigation.notes |format_empty_data }}", + {% endfor %} + ) + + #align(center, [#line(length: 40%, stroke: mygray,)]) + {% endif %} + + {% if consultation.procedure %} + #align(left, text(14pt,weight: "bold",)[=== Procedures Conducted:]) + + #table( + columns: (1fr, 1fr, 2fr), + inset: 10pt, + align: horizon, + table.header( + [*PROCEDURE*], [*TIME*], [*NOTES*] + ), + {% for procedure in consultation.procedure %} + "{{ procedure.procedure }}", + "{% if procedure.repetitive %} every {{procedure.frequency }} {% else %} {{procedure.time|parse_datetime }} {% endif %}", + "{{ procedure.notes |format_empty_data }}", + {% endfor %} + ) + + #align(center, [#line(length: 40%, stroke: mygray,)]) + {% endif %} + + {% if samples %} + #align(left, text(14pt,weight: "bold",)[=== Lab Reports:]) + + #table( + columns: (1fr, 1fr, 1fr,1fr), + inset: 10pt, + align: horizon, + table.header( + [*REQUESTED ON*], [*SAMPLE TYPE*], [*LABEL*],[*RESULT*], + ), + {% for sample in samples %} + "{{ sample.created_date }}", "{{ sample.get_sample_type_display }}", "{{ sample.icmr_label }}","{{ sample.get_result_display }}", + {% endfor %} + ) + + #align(center, [#line(length: 40%, stroke: mygray,)]) + {% endif %} + + {% if investigations %} + #align(left, text(14pt,weight: "bold")[=== Investigation History:]) + #table( + columns: (1fr,), + inset: 10pt, + align: horizon, + stroke: 1pt, + table.header( + align(center, text([*INVESTIGATION DETAILS*])) + ), + {% for investigation in investigations %} + [#grid( + columns: (1fr, 3fr), + row-gutter: 1.2em, + align: (left), + [Group:], "{{ investigation.investigation.groups.first }}", + [Name:], "{{ investigation.investigation.name }}", + [Result:], [{% if investigation.value %}{{ investigation.value }}{% else %}{{ investigation.notes }}{% endif %}], + [Range:], [{% if investigation.investigation.min_value and investigation.investigation.max_value %} + {{ investigation.investigation.min_value }} - {{ investigation.investigation.max_value }} + {% else %} + - + {% endif %} + {% if investigation.investigation.unit %} + {{ investigation.investigation.unit }} + {% endif %} + ], + [Date:], "{{ investigation.created_date }}", + )], + {% endfor %} + ) + + #align(center, [#line(length: 40%, stroke: mygray)]) + {% endif %} + +{% endif %} + +#align(left, text(18pt,)[== Discharge Summary]) +#grid( + columns: (1fr,3fr), + row-gutter: 1.2em, + align: (left), + [Discharge Date:], "{{consultation.discharge_date|format_empty_data }}", + [Discharge Reason:], "{{consultation.get_new_discharge_reason_display|format_to_sentence_case|format_empty_data }}", + [Discharge Advice:], "{{consultation.discharge_notes|format_empty_data }}", +) + +{% if consultation.new_discharge_reason == 1 %} + {% if discharge_prescriptions %} + #align(left, text(14pt,weight: "bold",)[=== Discharge Prescription :]) + #table( + columns: (1fr,), + inset: 10pt, + align: horizon, + stroke: 1pt, + table.header( + align(center, text([*MEDICATION DETAILS*])) + ), + {% for prescription in discharge_prescriptions %} + [#grid( + columns: (0.5fr, 9.5fr), + row-gutter: 1.2em, + align: (left), + "{{ forloop.counter }}", + "{{ prescription|format_prescription }}", + )], + {% endfor %} + ) + {% endif %} + +{% elif consultation.new_discharge_reason == 2 %} +{% elif consultation.new_discharge_reason == 3 %} +{% elif consultation.new_discharge_reason == 4 %} +{% endif %} + +#text("") + +#align(right)[#text(12pt,fill: mygray)[*Treating Physician* :] #text(10pt,weight: "bold")[{% if consultation.treating_physician %} + {{ consultation.treating_physician.first_name }} {{ consultation.treating_physician.last_name }} +{% else %} + - +{% endif %}]] + +{% if hcx %} + #align(center, [#line(length: 40%, stroke: mygray,)]) + + #align(left, text(14pt,weight: "bold")[=== Health Insurance Details]) + + #table( + columns: (1fr, 1fr, 1fr, 1fr), + inset: 10pt, + align: horizon, + table.header( + [*INSURER NAME*], [*ISSUER ID*], [*MEMBER ID*], [*POLICY ID*], + ), + {% for policy in hcx %} + "{{policy.insurer_name|format_empty_data }}", "{{policy.insurer_id|format_empty_data }}", "{{policy.subscriber_id }}", "{{policy.policy_id }}", + {% endfor %} + ) +{% endif %} + +{% if files %} + #align(center, [#line(length: 40%, stroke: mygray,)]) + + #align(left, text(18pt,)[== Annexes]) + #align(left, text(14pt,weight: "bold",)[=== Uploaded Files:]) + + #table( + columns: (1fr, 1fr,), + inset: 10pt, + align: horizon, + table.header( + [*UPLOADED AT*], [*NAME*], + ), + {% for file in files %} + "{{file.modified_date }}", "{{file.name }}", + {% endfor %} + ) +{% endif %} +#line(length: 100%, stroke: mygray) diff --git a/care/utils/assetintegration/base.py b/care/utils/assetintegration/base.py index 92d318c3a5..d43690b39d 100644 --- a/care/utils/assetintegration/base.py +++ b/care/utils/assetintegration/base.py @@ -12,6 +12,7 @@ class BaseAssetIntegration: def __init__(self, meta): self.meta = meta + self.id = self.meta.get("id", "") self.host = self.meta["local_ip_address"] self.middleware_hostname = self.meta["middleware_hostname"] self.insecure_connection = self.meta.get("insecure_connection", False) @@ -25,11 +26,17 @@ def get_url(self, endpoint): protocol += "s" return f"{protocol}://{self.middleware_hostname}/{endpoint}" + def get_headers(self): + return { + "Authorization": (self.auth_header_type + generate_jwt()), + "Accept": "application/json", + } + def api_post(self, url, data=None): req = requests.post( url, json=data, - headers={"Authorization": (self.auth_header_type + generate_jwt())}, + headers=self.get_headers(), ) try: response = req.json() @@ -37,13 +44,13 @@ def api_post(self, url, data=None): raise APIException(response, req.status_code) return response except json.decoder.JSONDecodeError: - return {"error": "Invalid Response"} + raise APIException({"error": "Invalid Response"}, req.status_code) def api_get(self, url, data=None): req = requests.get( url, params=data, - headers={"Authorization": (self.auth_header_type + generate_jwt())}, + headers=self.get_headers(), ) try: if req.status_code >= 400: @@ -51,4 +58,4 @@ def api_get(self, url, data=None): response = req.json() return response except json.decoder.JSONDecodeError: - return {"error": "Invalid Response"} + raise APIException({"error": "Invalid Response"}, req.status_code) diff --git a/care/utils/assetintegration/hl7monitor.py b/care/utils/assetintegration/hl7monitor.py index f7f1e7c783..fffe61c963 100644 --- a/care/utils/assetintegration/hl7monitor.py +++ b/care/utils/assetintegration/hl7monitor.py @@ -10,6 +10,7 @@ class HL7MonitorAsset(BaseAssetIntegration): class HL7MonitorActions(enum.Enum): GET_VITALS = "get_vitals" + GET_STREAM_TOKEN = "get_stream_token" def __init__(self, meta): try: @@ -26,4 +27,13 @@ def handle_action(self, action): request_params = {"device_id": self.host} return self.api_get(self.get_url("vitals"), request_params) + if action_type == self.HL7MonitorActions.GET_STREAM_TOKEN.value: + return self.api_post( + self.get_url("api/stream/getToken/vitals"), + { + "asset_id": self.id, + "ip": self.host, + }, + ) + raise ValidationError({"action": "invalid action type"}) diff --git a/care/utils/assetintegration/onvif.py b/care/utils/assetintegration/onvif.py index 8e21c77d43..6b26053f0b 100644 --- a/care/utils/assetintegration/onvif.py +++ b/care/utils/assetintegration/onvif.py @@ -14,6 +14,7 @@ class OnvifActions(enum.Enum): GOTO_PRESET = "goto_preset" ABSOLUTE_MOVE = "absolute_move" RELATIVE_MOVE = "relative_move" + GET_STREAM_TOKEN = "get_stream_token" def __init__(self, meta): try: @@ -54,4 +55,12 @@ def handle_action(self, action): if action_type == self.OnvifActions.RELATIVE_MOVE.value: return self.api_post(self.get_url("relativeMove"), request_body) + if action_type == self.OnvifActions.GET_STREAM_TOKEN.value: + return self.api_post( + self.get_url("api/stream/getToken/videoFeed"), + { + "stream_id": self.access_key, + }, + ) + raise ValidationError({"action": "invalid action type"}) diff --git a/care/utils/assetintegration/ventilator.py b/care/utils/assetintegration/ventilator.py index 10af39b50f..a74ec0deb0 100644 --- a/care/utils/assetintegration/ventilator.py +++ b/care/utils/assetintegration/ventilator.py @@ -10,6 +10,7 @@ class VentilatorAsset(BaseAssetIntegration): class VentilatorActions(enum.Enum): GET_VITALS = "get_vitals" + GET_STREAM_TOKEN = "get_stream_token" def __init__(self, meta): try: @@ -26,4 +27,13 @@ def handle_action(self, action): request_params = {"device_id": self.host} return self.api_get(self.get_url("vitals"), request_params) + if action_type == self.VentilatorActions.GET_STREAM_TOKEN.value: + return self.api_post( + self.get_url("api/stream/getToken/vitals"), + { + "asset_id": self.id, + "ip": self.host, + }, + ) + raise ValidationError({"action": "invalid action type"}) diff --git a/care/utils/notification_handler.py b/care/utils/notification_handler.py index ea38baf668..6451a9dade 100644 --- a/care/utils/notification_handler.py +++ b/care/utils/notification_handler.py @@ -384,7 +384,7 @@ def send_webpush_user(self, user, message): data=message, vapid_private_key=settings.VAPID_PRIVATE_KEY, vapid_claims={ - "sub": "mailto:info@coronasafe.network", + "sub": "mailto:info@ohc.network", }, ) except WebPushException as ex: diff --git a/care/utils/tests/test_utils.py b/care/utils/tests/test_utils.py index e396b9a51e..3b340ff5b0 100644 --- a/care/utils/tests/test_utils.py +++ b/care/utils/tests/test_utils.py @@ -6,19 +6,34 @@ from django.test import override_settings from django.utils.timezone import make_aware, now +from faker import Faker from rest_framework import status +from rest_framework_simplejwt.tokens import RefreshToken from care.facility.models import ( + BREATHLESSNESS_CHOICES, CATEGORY_CHOICES, DISEASE_CHOICES_MAP, + FACILITY_TYPES, + SHIFTING_STATUS_CHOICES, + VEHICLE_CHOICES, Ambulance, Disease, DiseaseStatusEnum, + EncounterSymptom, Facility, + InvestigationSession, + InvestigationValue, LocalBody, PatientConsultation, PatientExternalTest, + PatientInvestigation, + PatientInvestigationGroup, PatientRegistration, + PatientSample, + Prescription, + ShiftingRequest, + ShiftingRequestComment, User, Ward, ) @@ -36,8 +51,11 @@ PatientCodeStatusType, PatientConsent, ) +from care.hcx.models.policy import Policy from care.users.models import District, State +fake = Faker() + class override_cache(override_settings): """ @@ -164,6 +182,8 @@ def create_user( username = f"user{now().timestamp()}" data = { + "first_name": "Foo", + "last_name": "Bar", "email": f"{username}@somedomain.com", "phone_number": "5554446667", "date_of_birth": date(1992, 4, 1), @@ -284,7 +304,9 @@ def get_patient_data(cls, district, state) -> dict: } @classmethod - def create_patient(cls, district: District, facility: Facility, **kwargs): + def create_patient( + cls, district: District, facility: Facility, **kwargs + ) -> PatientRegistration: patient_data = cls.get_patient_data(district, district.state).copy() medical_history = patient_data.pop("medical_history", []) @@ -503,6 +525,227 @@ def create_ambulance(cls, district: District, user: User, **kwargs) -> Ambulance data.update(**kwargs) return Ambulance.objects.create(**data) + @classmethod + def get_patient_sample_data(cls, patient, consultation, facility, user) -> dict: + return { + "patient": patient, + "consultation": consultation, + "sample_type": 1, + "sample_type_other": "sample sample type other field", + "has_sari": False, + "has_ari": False, + "doctor_name": "Sample Doctor", + "diagnosis": "Sample diagnosis", + "diff_diagnosis": "Sample different diagnosis", + "etiology_identified": "Sample etiology identified", + "is_atypical_presentation": False, + "atypical_presentation": "Sample atypical presentation", + "is_unusual_course": False, + "icmr_category": 10, + "icmr_label": "Sample ICMR", + "date_of_sample": make_aware(datetime(2020, 4, 1, 15, 30, 00)), + "date_of_result": make_aware(datetime(2020, 4, 5, 15, 30, 00)), + "testing_facility": facility, + "created_by": user, + "last_edited_by": user, + } + + @classmethod + def create_patient_sample( + cls, + patient: PatientRegistration, + consultation: PatientConsultation, + facility: Facility, + user: User, + **kwargs, + ) -> PatientSample: + data = cls.get_patient_sample_data(patient, consultation, facility, user) + data.update(**kwargs) + sample = PatientSample.objects.create(**data) + + # To make date static updating the object here for pdf testing + sample.created_date = make_aware(datetime(2020, 4, 1, 15, 30, 00)) + sample.save() + return sample + + @classmethod + def get_policy_data(cls, patient, user) -> dict: + return { + "patient": patient, + "subscriber_id": "sample_subscriber_id", + "policy_id": "sample_policy_id", + "insurer_id": "sample_insurer_id", + "insurer_name": "Sample Insurer", + "status": "active", + "priority": "normal", + "purpose": "discovery", + "outcome": "complete", + "error_text": "No errors", + "created_by": user, + "last_modified_by": user, + } + + @classmethod + def create_policy( + cls, patient: PatientRegistration, user: User, **kwargs + ) -> Policy: + data = cls.get_policy_data(patient, user) + data.update(**kwargs) + return Policy.objects.create(**data) + + @classmethod + def get_encounter_symptom_data(cls, consultation, user) -> dict: + return { + "symptom": 2, + "onset_date": make_aware(datetime(2020, 4, 1, 15, 30, 00)), + "cure_date": make_aware(datetime(2020, 5, 1, 15, 30, 00)), + "clinical_impression_status": 3, + "consultation": consultation, + "created_by": user, + "updated_by": user, + "is_migrated": False, + } + + @classmethod + def create_encounter_symptom( + cls, consultation: PatientConsultation, user: User, **kwargs + ) -> EncounterSymptom: + data = cls.get_encounter_symptom_data(consultation, user) + data.update(**kwargs) + return EncounterSymptom.objects.create(**data) + + @classmethod + def get_patient_investigation_data(cls) -> dict: + return { + "name": "Sample Investigation", + "unit": "mg/dL", + "ideal_value": "50-100", + "min_value": 50.0, + "max_value": 100.0, + "investigation_type": "Choice", + "choices": "Option1,Option2,Option3", + } + + @classmethod + def create_patient_investigation( + cls, patient_investigation_group: PatientInvestigationGroup, **kwargs + ) -> PatientInvestigation: + data = cls.get_patient_investigation_data() + data.update(**kwargs) + investigation = PatientInvestigation.objects.create(**data) + if "groups" in kwargs: + investigation.groups.set(kwargs["groups"]) + else: + investigation.groups.set([patient_investigation_group]) + return investigation + + @classmethod + def get_patient_investigation_group_data(cls) -> dict: + return { + "name": "Sample Investigation group", + } + + @classmethod + def create_patient_investigation_group(cls, **kwargs) -> PatientInvestigationGroup: + data = cls.get_patient_investigation_group_data() + data.update(**kwargs) + investigation_group = PatientInvestigationGroup.objects.create(**data) + return investigation_group + + @classmethod + def get_patient_investigation_session_data(cls, user) -> dict: + return { + "created_by": user, + } + + @classmethod + def create_patient_investigation_session( + cls, user: User, **kwargs + ) -> InvestigationSession: + data = cls.get_patient_investigation_session_data(user) + data.update(**kwargs) + investigation_session = InvestigationSession.objects.create(**data) + return investigation_session + + @classmethod + def get_investigation_value_data( + cls, investigation, consultation, session, group + ) -> dict: + return { + "investigation": investigation, + "group": group, + "value": 5.0, + "notes": "Sample notes", + "consultation": consultation, + "session": session, + } + + @classmethod + def create_investigation_value( + cls, + investigation: PatientInvestigation, + consultation: PatientConsultation, + session: InvestigationSession, + group: PatientInvestigationGroup, + **kwargs, + ) -> InvestigationValue: + data = cls.get_investigation_value_data( + investigation, consultation, session, group + ) + data.update(**kwargs) + investigation_value = InvestigationValue.objects.create(**data) + # To make created date static updating the object here for pdf testing + investigation_value.created_date = make_aware(datetime(2020, 4, 1, 15, 30, 00)) + investigation_value.save() + return investigation_value + + @classmethod + def get_disease_data(cls, patient) -> dict: + return { + "patient": patient, + "disease": 4, + "details": "Sample disease details", + } + + @classmethod + def create_disease(cls, patient: PatientRegistration, **kwargs) -> Disease: + data = cls.get_disease_data(patient) + data.update(**kwargs) + return Disease.objects.create(**data) + + @classmethod + def get_prescription_data(cls, consultation, user) -> dict: + return { + "consultation": consultation, + "prescription_type": "REGULAR", + "medicine": None, # TODO : Create medibase medicine + "medicine_old": "Sample old Medicine", + "route": "Oral", + "base_dosage": "500mg", + "dosage_type": "REGULAR", + "target_dosage": "1000mg", + "instruction_on_titration": "Sample Instruction for titration", + "frequency": "8th hourly", + "days": 7, + # prn fields + "indicator": "Sample indicator", + "max_dosage": "2000mg", + "min_hours_between_doses": 6, + "notes": "Take with food", + "prescribed_by": user, + "discontinued": False, + "discontinued_reason": "sample discontinued reason", + "discontinued_date": date(2020, 4, 1), + } + + @classmethod + def create_prescription( + cls, consultation: PatientConsultation, user: User, **kwargs + ) -> Prescription: + data = cls.get_prescription_data(consultation, user) + data.update(**kwargs) + return Prescription.objects.create(**data) + def get_list_representation(self, obj) -> dict: """ Returns the dict representation of the obj in list API @@ -615,3 +858,74 @@ def get_facility_representation(self, facility): }, **self.get_local_body_district_state_representation(facility), } + + def create_patient_note( + self, patient=None, note="Patient is doing find", created_by=None, **kwargs + ): + data = { + "facility": patient.facility or self.facility, + "note": note, + } + data.update(kwargs) + patientId = patient.external_id + + refresh_token = RefreshToken.for_user(created_by) + self.client.credentials( + HTTP_AUTHORIZATION=f"Bearer {refresh_token.access_token}" + ) + + self.client.post(f"/api/v1/patient/{patientId}/notes/", data=data) + + @classmethod + def create_patient_shift( + cls, + facility: Facility = None, + user: User = None, + patient: PatientRegistration = None, + **kwargs, + ) -> None: + shifting_approving_facility = cls.create_facility( + user=cls.user, district=cls.district, local_body=cls.local_body + ) + assigned_facility = shifting_approving_facility + data = { + "origin_facility": assigned_facility, + "shifting_approving_facility": shifting_approving_facility, + "assigned_facility_type": fake.random_element(FACILITY_TYPES)[0], + "assigned_facility": assigned_facility, + "assigned_facility_external": "Assigned Facility External", + "patient": patient, + "emergency": False, + "is_up_shift": False, + "reason": "Reason", + "vehicle_preference": "Vehicle Preference", + "preferred_vehicle_choice": fake.random_element(VEHICLE_CHOICES)[0], + "comments": "Comments", + "refering_facility_contact_name": "9900199001", + "refering_facility_contact_number": "9900199001", + "is_kasp": False, + "status": fake.random_element(SHIFTING_STATUS_CHOICES)[0], + "breathlessness_level": fake.random_element(BREATHLESSNESS_CHOICES)[0], + "is_assigned_to_user": False, + "assigned_to": user, + "ambulance_driver_name": fake.name(), + "ambulance_phone_number": "9900199001", + "ambulance_number": fake.license_plate(), + "created_by": user, + "last_edited_by": user, + } + data.update(kwargs) + return ShiftingRequest.objects.create(**data) + + @classmethod + def create_patient_shift_comment( + cls, resource: ShiftingRequest = None, user: User = None, **kwargs + ) -> None: + kwargs.update( + { + "request": resource, + "comment": "comment", + "created_by": user, + } + ) + return ShiftingRequestComment.objects.create(**kwargs) diff --git a/config/authentication.py b/config/authentication.py index dbad94d669..b4efe830e0 100644 --- a/config/authentication.py +++ b/config/authentication.py @@ -183,7 +183,7 @@ def get_user(self, validated_token, facility): password = User.objects.make_random_password() asset_user = User( username=f"asset{str(asset_obj.external_id)}", - email="support@coronasafe.network", + email="support@ohc.network", password=f"{password}123", # The 123 makes it inaccessible without hashing gender=3, phone_number="919999999999", @@ -235,7 +235,7 @@ def get_user(self, validated_token): password = User.objects.make_random_password() user = User( username=settings.ABDM_USERNAME, - email="hcx@coronasafe.network", + email="hcx@ohc.network", password=f"{password}123", gender=3, phone_number="917777777777", diff --git a/config/settings/base.py b/config/settings/base.py index 8cac4e189a..e12c643dec 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -6,6 +6,7 @@ import json from datetime import datetime, timedelta from pathlib import Path +from django.utils.translation import gettext_lazy as _ import environ from authlib.jose import JsonWebKey @@ -54,6 +55,13 @@ # https://docs.djangoproject.com/en/dev/ref/settings/#locale-paths LOCALE_PATHS = [str(BASE_DIR / "locale")] + +LANGUAGES = [ + ("en-us", _("English")), + ("ml", _("Malayalam")), + ("hi", _("Hindi")), + ("ta", _("Tamil")), +] # DATABASES # ------------------------------------------------------------------------------ # https://docs.djangoproject.com/en/dev/ref/settings/#databases diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 0000000000..97490a9160 --- /dev/null +++ b/crowdin.yml @@ -0,0 +1,5 @@ +files: + - source: /locale/*/LC_MESSAGES/django.po + translation: /locale/%two_letters_code%/LC_MESSAGES/django.po +bundles: + - 4 diff --git a/data/dummy/facility.json b/data/dummy/facility.json index 45f4a12b71..10f924a2c4 100644 --- a/data/dummy/facility.json +++ b/data/dummy/facility.json @@ -1948,10 +1948,6 @@ "patient": 1, "patient_no": "88.99.44.66", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Moderate", "examination_details": "", @@ -1979,8 +1975,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -2000,9 +1994,7 @@ "weight": 0.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": [], - "discharge_advice": [] + "intubation_history": [] } }, { @@ -2016,10 +2008,6 @@ "patient": 2, "patient_no": "IP007", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -2047,8 +2035,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -2068,9 +2054,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -2084,10 +2068,6 @@ "patient": 3, "patient_no": "IP008", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -2115,8 +2095,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -2136,9 +2114,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -2152,10 +2128,6 @@ "patient": 4, "patient_no": "IP009", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -2183,8 +2155,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -2204,9 +2174,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -2220,10 +2188,6 @@ "patient": 5, "patient_no": "IP017", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -2251,8 +2215,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -2272,9 +2234,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -2288,10 +2248,6 @@ "patient": 6, "patient_no": "IP087", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -2319,8 +2275,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -2340,9 +2294,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -2356,10 +2308,6 @@ "patient": 7, "patient_no": "IP00527", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -2387,8 +2335,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -2408,9 +2354,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -2424,10 +2368,6 @@ "patient": 8, "patient_no": "IP0KI07", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -2455,8 +2395,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -2476,9 +2414,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -2492,10 +2428,6 @@ "patient": 9, "patient_no": "IP00767", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -2523,8 +2455,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -2544,9 +2474,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -2560,10 +2488,6 @@ "patient": 10, "patient_no": "IP001237", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -2591,8 +2515,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -2612,9 +2534,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -2628,10 +2548,6 @@ "patient": 11, "patient_no": "IP007963", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -2659,8 +2575,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -2680,9 +2594,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -2696,10 +2608,6 @@ "patient": 12, "patient_no": "IP0001257", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -2727,8 +2635,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -2748,9 +2654,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -2764,10 +2668,6 @@ "patient": 13, "patient_no": "IP075389007", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -2795,8 +2695,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -2816,9 +2714,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -2832,10 +2728,6 @@ "patient": 14, "patient_no": "IP099907", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -2863,8 +2755,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -2884,9 +2774,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -2900,10 +2788,6 @@ "patient": 15, "patient_no": "IP00700", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -2931,8 +2815,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -2952,9 +2834,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -2968,10 +2848,6 @@ "patient": 16, "patient_no": "IP00744", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -2999,8 +2875,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -3020,9 +2894,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -3036,10 +2908,6 @@ "patient": 17, "patient_no": "IP00117", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -3067,8 +2935,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -3088,9 +2954,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -3104,10 +2968,6 @@ "patient": 18, "patient_no": "IP02507", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -3135,8 +2995,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -3156,9 +3014,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -3172,10 +3028,6 @@ "patient": 18, "patient_no": "IP02578", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -3203,8 +3055,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -3224,9 +3074,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -3240,10 +3088,6 @@ "patient": 18, "patient_no": "IP1009", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -3271,8 +3115,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -3292,9 +3134,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -3308,10 +3148,6 @@ "patient": 18, "patient_no": "IP0010", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -3339,8 +3175,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -3360,9 +3194,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -3376,10 +3208,6 @@ "patient": 18, "patient_no": "IP011", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -3407,8 +3235,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -3428,9 +3254,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -3444,10 +3268,6 @@ "patient": 18, "patient_no": "IP012", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -3475,8 +3295,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -3496,9 +3314,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -3512,10 +3328,6 @@ "patient": 18, "patient_no": "IP013", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -3543,8 +3355,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -3564,9 +3374,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -3580,10 +3388,6 @@ "patient": 18, "patient_no": "IP014", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -3611,8 +3415,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -3632,9 +3434,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { @@ -3648,10 +3448,6 @@ "patient": 18, "patient_no": "IP015", "facility": 1, - "deprecated_diagnosis": "", - "deprecated_icd11_provisional_diagnoses": "[]", - "deprecated_icd11_diagnoses": "[]", - "deprecated_icd11_principal_diagnosis": "", "deprecated_covid_category": null, "category": "Stable", "examination_details": "Examination details and Clinical conditions", @@ -3679,8 +3475,6 @@ "discharge_reason": null, "new_discharge_reason": null, "discharge_notes": "", - "discharge_prescription": {}, - "discharge_prn_prescription": {}, "death_datetime": null, "death_confirmed_doctor": "", "bed_number": null, @@ -3700,9 +3494,7 @@ "weight": 170.0, "operation": null, "special_instruction": "", - "intubation_history": [], - "prn_prescription": {}, - "discharge_advice": {} + "intubation_history": [] } }, { diff --git a/docker-compose.local.yaml b/docker-compose.local.yaml index aeb971ccd6..6ac131e21d 100644 --- a/docker-compose.local.yaml +++ b/docker-compose.local.yaml @@ -1,4 +1,3 @@ -version: '3.4' services: backend: diff --git a/docker-compose.pre-built.yaml b/docker-compose.pre-built.yaml index 19dbd14194..1b4ed4cfe8 100644 --- a/docker-compose.pre-built.yaml +++ b/docker-compose.pre-built.yaml @@ -1,8 +1,7 @@ -version: '3.4' services: backend: - image: "ghcr.io/coronasafe/care:latest" + image: "ghcr.io/ohcnetwork/care:latest" env_file: - ./docker/.prebuilt.env entrypoint: [ "bash", "start-ecs.sh" ] @@ -18,7 +17,7 @@ services: - "9000:9000" celery-worker: - image: "ghcr.io/coronasafe/care:latest" + image: "ghcr.io/ohcnetwork/care:latest" env_file: - ./docker/.prebuilt.env entrypoint: [ "bash", "celery_worker-ecs.sh" ] @@ -32,7 +31,7 @@ services: condition: service_healthy celery-beat: - image: "ghcr.io/coronasafe/care:latest" + image: "ghcr.io/ohcnetwork/care:latest" env_file: - ./docker/.prebuilt.env entrypoint: [ "bash", "celery_beat-ecs.sh" ] diff --git a/docker-compose.yaml b/docker-compose.yaml index 11cfcc0a9c..166297a383 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,4 +1,3 @@ -version: '3.4' networks: default: diff --git a/docker/dev.Dockerfile b/docker/dev.Dockerfile index 6cc595fa0a..4cfd78d1c3 100644 --- a/docker/dev.Dockerfile +++ b/docker/dev.Dockerfile @@ -5,13 +5,30 @@ ENV PYTHONDONTWRITEBYTECODE 1 ENV PATH /venv/bin:$PATH +ARG TYPST_VERSION=0.11.0 RUN apt-get update && apt-get install --no-install-recommends -y \ build-essential libjpeg-dev zlib1g-dev \ - libpq-dev gettext wget curl gnupg chromium git \ + libpq-dev gettext wget curl gnupg git \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && rm -rf /var/lib/apt/lists/* +# Download and install Typst for the correct architecture +RUN ARCH=$(dpkg --print-architecture) && \ + if [ "$ARCH" = "amd64" ]; then \ + TYPST_ARCH="x86_64-unknown-linux-musl"; \ + elif [ "$ARCH" = "arm64" ]; then \ + TYPST_ARCH="aarch64-unknown-linux-musl"; \ + else \ + echo "Unsupported architecture: $ARCH"; \ + exit 1; \ + fi && \ + wget -qO typst.tar.xz https://github.com/typst/typst/releases/download/v${TYPST_VERSION}/typst-${TYPST_ARCH}.tar.xz && \ + tar -xf typst.tar.xz && \ + mv typst-${TYPST_ARCH}/typst /usr/local/bin/typst && \ + chmod +x /usr/local/bin/typst && \ + rm -rf typst.tar.xz typst-${TYPST_ARCH} + # use pipenv to manage virtualenv RUN python -m venv /venv RUN pip install pipenv @@ -19,6 +36,7 @@ RUN pip install pipenv COPY Pipfile Pipfile.lock ./ RUN pipenv install --system --categories "packages dev-packages" + COPY . /app RUN python3 /app/install_plugins.py diff --git a/docker/prod.Dockerfile b/docker/prod.Dockerfile index 0e89d39c17..a1fc627425 100644 --- a/docker/prod.Dockerfile +++ b/docker/prod.Dockerfile @@ -1,25 +1,44 @@ ARG PYTHON_VERSION=3.11-slim-bullseye -FROM python:${PYTHON_VERSION} as base +FROM python:${PYTHON_VERSION} AS base ENV PYTHONUNBUFFERED 1 ENV PYTHONDONTWRITEBYTECODE 1 # --- -FROM base as builder +FROM base AS builder ARG BUILD_ENVIRONMENT=production +ARG TYPST_VERSION=0.11.0 ENV PATH /venv/bin:$PATH RUN apt-get update && apt-get install --no-install-recommends -y \ - build-essential libjpeg-dev zlib1g-dev libpq-dev git + build-essential libjpeg-dev zlib1g-dev libpq-dev git wget \ + && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ + && rm -rf /var/lib/apt/lists/* + +# Download and install Typst for the correct architecture +RUN ARCH=$(dpkg --print-architecture) && \ + if [ "$ARCH" = "amd64" ]; then \ + TYPST_ARCH="x86_64-unknown-linux-musl"; \ + elif [ "$ARCH" = "arm64" ]; then \ + TYPST_ARCH="aarch64-unknown-linux-musl"; \ + else \ + echo "Unsupported architecture: $ARCH"; \ + exit 1; \ + fi && \ + wget -qO typst.tar.xz https://github.com/typst/typst/releases/download/v${TYPST_VERSION}/typst-${TYPST_ARCH}.tar.xz && \ + tar -xf typst.tar.xz && \ + mv typst-${TYPST_ARCH}/typst /usr/local/bin/typst && \ + rm -rf typst.tar.xz typst-${TYPST_ARCH} # use pipenv to manage virtualenv RUN python -m venv /venv RUN pip install pipenv + COPY Pipfile Pipfile.lock ./ RUN pipenv sync --system --categories "packages" @@ -27,8 +46,9 @@ COPY . /app RUN python3 /app/install_plugins.py + # --- -FROM base as runtime +FROM base AS runtime ARG BUILD_ENVIRONMENT=production ARG APP_HOME=/app @@ -44,13 +64,17 @@ ENV PATH /venv/bin:$PATH WORKDIR ${APP_HOME} RUN apt-get update && apt-get install --no-install-recommends -y \ - libpq-dev gettext wget curl gnupg chromium \ + libpq-dev gettext wget curl gnupg \ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ && rm -rf /var/lib/apt/lists/* +# copy typst binary from builder stage +COPY --from=builder --chmod=0755 /usr/local/bin/typst /usr/local/bin/typst + # copy in Python environment COPY --from=builder /venv /venv + COPY --chmod=0755 ./scripts/*.sh ./ HEALTHCHECK \ diff --git a/docs/conf.py b/docs/conf.py index ea31c5ef15..5bbd458924 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -23,7 +23,7 @@ project = "Care" copyright = """2023, Open Healthcare Network""" -author = "coronasafe" +author = "ohcnetwork" # -- General configuration --------------------------------------------------- diff --git a/docs/github-repo/configuration.rst b/docs/github-repo/configuration.rst index 6729d8a268..0623e0d86e 100644 --- a/docs/github-repo/configuration.rst +++ b/docs/github-repo/configuration.rst @@ -15,4 +15,4 @@ All PR's and issues are monitored by the code reviewers team and merged after a Any other forks for deployments **MUST** follow the same Github structure so as to remain in sync and to keep getting updates. -.. _here: https://github.com/coronasafe/care +.. _here: https://github.com/ohcnetwork/care diff --git a/docs/glossary/configuration.rst b/docs/glossary/configuration.rst index 7302c35c1f..02831dad20 100644 --- a/docs/glossary/configuration.rst +++ b/docs/glossary/configuration.rst @@ -2,7 +2,7 @@ Glossary =============== -**CARE** is a comprehensive capacity and patient management tool, built specifically for the COVID Pandemic Management. It is a web-based application hosted at  https://care.coronasafe.network/ +**CARE** is a comprehensive capacity and patient management tool, built specifically for the COVID Pandemic Management. It is a web-based application hosted at  https://care.ohcnetwork.network/ This document gives an overview of the Care System for the developers who are willing to contribute to it. @@ -21,7 +21,7 @@ Facility ----------- - Facilities represent **Hospitals** associated with the Ward. -- There are 15+ Facility **Types** in the Care System with its `ID Number Conventions `_ +- There are 15+ Facility **Types** in the Care System with its `ID Number Conventions `_ - Each Facility record has its Basic information, Bed Capacity, Oxygen Cylinder Capacity and Doctor Capacity. - Reference: Karunya Arogya Suraksha Padhathi `(KASP) `_ - Health Care Scheme diff --git a/docs/local-setup/configuration.rst b/docs/local-setup/configuration.rst index a59e3d6557..c6143b4b42 100644 --- a/docs/local-setup/configuration.rst +++ b/docs/local-setup/configuration.rst @@ -130,7 +130,7 @@ Pre-Commit is a package manager and tool for running and organising your git hoo $ pre-commit run --all-files * FAQs and Issues with pre-commit - - Reach out on the #coronasafe_django channel in slack to resolve the issues. + - Reach out on the #care_backend channel in slack to resolve the issues. .. _here: https://cookiecutter-django.readthedocs.io/en/latest/developing-locally.html .. _pre_commit_site: https://pre-commit.com/ diff --git a/docs/pluggable-apps/configuration.md b/docs/pluggable-apps/configuration.md index b017af6aa6..43c4bb7634 100644 --- a/docs/pluggable-apps/configuration.md +++ b/docs/pluggable-apps/configuration.md @@ -43,7 +43,7 @@ The order of precedence is as follows: ## Development -To get started with developing a plugin, use [care-plugin-cookiecutter](https://github.com/coronasafe/care-plugin-cookiecutter) +To get started with developing a plugin, use [care-plugin-cookiecutter](https://github.com/ohcnetwork/care-plugin-cookiecutter) The plugin follows the structure of a typical django app where you can define your models, views, urls, etc. in the plugin folder. The plugin manager will automatically load the required configurations and plugin urls under `/api/plugin-name/`. @@ -54,4 +54,4 @@ If you need to inherit the components from the core app, you can install care in ## Available Plugins -- [Care Scribe](https://github.com/coronasafe/care_scribe): Care Scribe is a plugin that provides autofill functionality for the care consultation forms. +- [Care Scribe](https://github.com/ohcnetwork/care_scribe): Care Scribe is a plugin that provides autofill functionality for the care consultation forms. diff --git a/docs/working-components/configuration.rst b/docs/working-components/configuration.rst index 2be911281a..4c26f9f58b 100644 --- a/docs/working-components/configuration.rst +++ b/docs/working-components/configuration.rst @@ -37,4 +37,4 @@ Care uses emails to send discharge summaries, reset password tokens, and crash r Reporting Infrastructure ------------------------ -Since care by itself cannot produce a really detailed summary of its data, it is advised to use Metabase or Superset as external Business Intelligence tools and connect a Read Replica of the primary database with PII fields masked. This will allow much higher visibility into the actual data and make better data-driven decisions. If you are using Metabase you can ask the coronasafe team to share the existing dashboard structure for simplicity. Care Databases are designed to provide easy and configurable Reporting. +Since care by itself cannot produce a really detailed summary of its data, it is advised to use Metabase or Superset as external Business Intelligence tools and connect a Read Replica of the primary database with PII fields masked. This will allow much higher visibility into the actual data and make better data-driven decisions. If you are using Metabase you can ask the ohcnetwork team to share the existing dashboard structure for simplicity. Care Databases are designed to provide easy and configurable Reporting. diff --git a/locale/hi/LC_MESSAGES/django.po b/locale/hi/LC_MESSAGES/django.po new file mode 100644 index 0000000000..d9eb9fd2d9 --- /dev/null +++ b/locale/hi/LC_MESSAGES/django.po @@ -0,0 +1,255 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-08-25 17:02+0530\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: care/abdm/apps.py:7 +msgid "ABDM Integration" +msgstr "" + +#: care/audit_log/apps.py:7 +msgid "Audit Log Management" +msgstr "" + +#: care/facility/apps.py:7 +msgid "Facility Management" +msgstr "" + +#: care/facility/models/encounter_symptom.py:16 +msgid "In Progress" +msgstr "" + +#: care/facility/models/encounter_symptom.py:17 +msgid "Completed" +msgstr "" + +#: care/facility/models/encounter_symptom.py:18 +#: care/facility/models/icd11_diagnosis.py:53 +msgid "Entered in Error" +msgstr "" + +#: care/facility/models/icd11_diagnosis.py:48 +msgid "Unconfirmed" +msgstr "" + +#: care/facility/models/icd11_diagnosis.py:49 +msgid "Provisional" +msgstr "" + +#: care/facility/models/icd11_diagnosis.py:50 +msgid "Differential" +msgstr "" + +#: care/facility/models/icd11_diagnosis.py:51 +msgid "Confirmed" +msgstr "" + +#: care/facility/models/icd11_diagnosis.py:52 +msgid "Refuted" +msgstr "" + +#: care/facility/models/patient.py:50 +msgid "Non-card holder" +msgstr "" + +#: care/facility/models/patient.py:51 +msgid "BPL" +msgstr "" + +#: care/facility/models/patient.py:52 +msgid "APL" +msgstr "" + +#: care/facility/models/patient_base.py:88 +msgid "Unknown" +msgstr "" + +#: care/facility/models/patient_base.py:89 +msgid "Recovered" +msgstr "" + +#: care/facility/models/patient_base.py:90 +msgid "Referred" +msgstr "" + +#: care/facility/models/patient_base.py:91 +msgid "Expired" +msgstr "" + +#: care/facility/models/patient_base.py:92 +msgid "LAMA" +msgstr "" + +#: care/facility/models/patient_base.py:127 +msgid "Outpatient/Emergency Room" +msgstr "" + +#: care/facility/models/patient_base.py:128 +msgid "Referred from another facility" +msgstr "" + +#: care/facility/models/patient_base.py:129 +msgid "Internal Transfer within the facility" +msgstr "" + +#: care/facility/models/patient_base.py:130 +msgid "(Unknown)" +msgstr "" + +#: care/hcx/apps.py:7 +msgid "HCX Integration" +msgstr "" + +#: care/templates/pages/home.html:8 +msgid "Open Healthcare Network" +msgstr "" + +#: care/templates/pages/home.html:9 +msgid "" +"Our Goal is to defend the Healthcare system of Kerala from overloading " +"beyond capacity." +msgstr "" + +#: care/users/apps.py:7 +msgid "Users" +msgstr "" + +#: care/users/forms.py:15 +msgid "This username has already been taken." +msgstr "" + +#: care/users/models.py:179 +msgid "username" +msgstr "" + +#: care/users/models.py:184 +msgid "A user with that username already exists." +msgstr "" + +#: care/users/reset_password_views.py:245 +msgid "" +"There is no active user associated with this username or the password can " +"not be changed" +msgstr "" + +#: care/utils/models/validators.py:54 +msgid "" +"Username must be 4 to 16 characters long. It may only contain lowercase " +"alphabets, numbers, underscores, hyphens and dots. It shouldn't start or end " +"with underscores, hyphens or dots. It shouldn't contain consecutive " +"underscores, hyphens or dots." +msgstr "" + +#: care/utils/ulid/serializers.py:9 +#, python-brace-format +msgid "\"{value}\" is not a valid ULID." +msgstr "" + +#: config/auth_views.py:19 +msgid "Too Many Requests Provide Captcha" +msgstr "" + +#: config/auth_views.py:27 +msgid "No active account found with the given credentials" +msgstr "" + +#: config/authentication.py:141 +msgid "Authorization header must contain two space-delimited values" +msgstr "" + +#: config/authentication.py:270 +msgid "" +"Used for authenticating requests from the middleware. The scheme requires a " +"valid JWT token in the Authorization header along with the facility id in " +"the X-Facility-Id header. --The value field is just for preview, filling it " +"will show allowed endpoints.--" +msgstr "" + +#: config/authentication.py:289 +msgid "" +"Used for authenticating requests from the middleware on behalf of assets. " +"The scheme requires a valid JWT token in the Authorization header along with " +"the facility id in the X-Facility-Id header. --The value field is just for " +"preview, filling it will show allowed endpoints.--" +msgstr "" + +#: config/authentication.py:306 config/authentication.py:320 +msgid "Do not use this scheme for production." +msgstr "" + +#: config/patient_otp_authentication.py:56 +msgid "Given token not valid for any token type" +msgstr "" + +#: config/settings/base.py:60 +msgid "English" +msgstr "" + +#: config/settings/base.py:61 +msgid "Malayalam" +msgstr "" + +#: config/settings/base.py:62 +msgid "Hindi" +msgstr "" + +#: config/settings/base.py:63 +msgid "Tamil" +msgstr "" + +#: config/validators.py:12 +msgid "The password must contain at least 1 digit, 0-9." +msgstr "" + +#: config/validators.py:17 +msgid "Your password must contain at least 1 digit, 0-9." +msgstr "" + +#: config/validators.py:24 +msgid "The password must contain at least 1 uppercase letter, A-Z." +msgstr "" + +#: config/validators.py:29 +msgid "Your password must contain at least 1 uppercase letter, A-Z." +msgstr "" + +#: config/validators.py:36 +msgid "The password must contain at least 1 lowercase letter, a-z." +msgstr "" + +#: config/validators.py:41 +msgid "Your password must contain at least 1 lowercase letter, a-z." +msgstr "" + +#: config/validators.py:49 +msgid "" +"The password must contain at least 1 symbol: ()[]{}|\\`~!@#$%^&*_-+=;:'\\\"," +"<>./?" +msgstr "" + +#: config/validators.py:57 +msgid "" +"Your password must contain at least 1 symbol: ()[]{}|\\`~!@#$%^&*_-+=;:'\\\"," +"<>./?" +msgstr "" + +#: config/validators.py:66 +msgid "" +"The domain name is invalid. It should not start with scheme and should not " +"end with a trailing slash." +msgstr "" diff --git a/locale/ml/LC_MESSAGES/django.po b/locale/ml/LC_MESSAGES/django.po new file mode 100644 index 0000000000..e71486fc84 --- /dev/null +++ b/locale/ml/LC_MESSAGES/django.po @@ -0,0 +1,255 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-08-25 17:02+0530\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: care/abdm/apps.py:7 +msgid "ABDM Integration" +msgstr "" + +#: care/audit_log/apps.py:7 +msgid "Audit Log Management" +msgstr "" + +#: care/facility/apps.py:7 +msgid "Facility Management" +msgstr "" + +#: care/facility/models/encounter_symptom.py:16 +msgid "In Progress" +msgstr "" + +#: care/facility/models/encounter_symptom.py:17 +msgid "Completed" +msgstr "" + +#: care/facility/models/encounter_symptom.py:18 +#: care/facility/models/icd11_diagnosis.py:53 +msgid "Entered in Error" +msgstr "" + +#: care/facility/models/icd11_diagnosis.py:48 +msgid "Unconfirmed" +msgstr "" + +#: care/facility/models/icd11_diagnosis.py:49 +msgid "Provisional" +msgstr "" + +#: care/facility/models/icd11_diagnosis.py:50 +msgid "Differential" +msgstr "" + +#: care/facility/models/icd11_diagnosis.py:51 +msgid "Confirmed" +msgstr "" + +#: care/facility/models/icd11_diagnosis.py:52 +msgid "Refuted" +msgstr "" + +#: care/facility/models/patient.py:50 +msgid "Non-card holder" +msgstr "" + +#: care/facility/models/patient.py:51 +msgid "BPL" +msgstr "" + +#: care/facility/models/patient.py:52 +msgid "APL" +msgstr "" + +#: care/facility/models/patient_base.py:88 +msgid "Unknown" +msgstr "" + +#: care/facility/models/patient_base.py:89 +msgid "Recovered" +msgstr "" + +#: care/facility/models/patient_base.py:90 +msgid "Referred" +msgstr "" + +#: care/facility/models/patient_base.py:91 +msgid "Expired" +msgstr "" + +#: care/facility/models/patient_base.py:92 +msgid "LAMA" +msgstr "" + +#: care/facility/models/patient_base.py:127 +msgid "Outpatient/Emergency Room" +msgstr "" + +#: care/facility/models/patient_base.py:128 +msgid "Referred from another facility" +msgstr "" + +#: care/facility/models/patient_base.py:129 +msgid "Internal Transfer within the facility" +msgstr "" + +#: care/facility/models/patient_base.py:130 +msgid "(Unknown)" +msgstr "" + +#: care/hcx/apps.py:7 +msgid "HCX Integration" +msgstr "" + +#: care/templates/pages/home.html:8 +msgid "Open Healthcare Network" +msgstr "ആരോഗ്യ സംരക്ഷണ ശൃംഖല" + +#: care/templates/pages/home.html:9 +msgid "" +"Our Goal is to defend the Healthcare system of Kerala from overloading " +"beyond capacity." +msgstr "" + +#: care/users/apps.py:7 +msgid "Users" +msgstr "" + +#: care/users/forms.py:15 +msgid "This username has already been taken." +msgstr "" + +#: care/users/models.py:179 +msgid "username" +msgstr "" + +#: care/users/models.py:184 +msgid "A user with that username already exists." +msgstr "" + +#: care/users/reset_password_views.py:245 +msgid "" +"There is no active user associated with this username or the password can " +"not be changed" +msgstr "" + +#: care/utils/models/validators.py:54 +msgid "" +"Username must be 4 to 16 characters long. It may only contain lowercase " +"alphabets, numbers, underscores, hyphens and dots. It shouldn't start or end " +"with underscores, hyphens or dots. It shouldn't contain consecutive " +"underscores, hyphens or dots." +msgstr "" + +#: care/utils/ulid/serializers.py:9 +#, python-brace-format +msgid "\"{value}\" is not a valid ULID." +msgstr "" + +#: config/auth_views.py:19 +msgid "Too Many Requests Provide Captcha" +msgstr "" + +#: config/auth_views.py:27 +msgid "No active account found with the given credentials" +msgstr "" + +#: config/authentication.py:141 +msgid "Authorization header must contain two space-delimited values" +msgstr "" + +#: config/authentication.py:270 +msgid "" +"Used for authenticating requests from the middleware. The scheme requires a " +"valid JWT token in the Authorization header along with the facility id in " +"the X-Facility-Id header. --The value field is just for preview, filling it " +"will show allowed endpoints.--" +msgstr "" + +#: config/authentication.py:289 +msgid "" +"Used for authenticating requests from the middleware on behalf of assets. " +"The scheme requires a valid JWT token in the Authorization header along with " +"the facility id in the X-Facility-Id header. --The value field is just for " +"preview, filling it will show allowed endpoints.--" +msgstr "" + +#: config/authentication.py:306 config/authentication.py:320 +msgid "Do not use this scheme for production." +msgstr "" + +#: config/patient_otp_authentication.py:56 +msgid "Given token not valid for any token type" +msgstr "" + +#: config/settings/base.py:60 +msgid "English" +msgstr "" + +#: config/settings/base.py:61 +msgid "Malayalam" +msgstr "" + +#: config/settings/base.py:62 +msgid "Hindi" +msgstr "" + +#: config/settings/base.py:63 +msgid "Tamil" +msgstr "" + +#: config/validators.py:12 +msgid "The password must contain at least 1 digit, 0-9." +msgstr "" + +#: config/validators.py:17 +msgid "Your password must contain at least 1 digit, 0-9." +msgstr "" + +#: config/validators.py:24 +msgid "The password must contain at least 1 uppercase letter, A-Z." +msgstr "" + +#: config/validators.py:29 +msgid "Your password must contain at least 1 uppercase letter, A-Z." +msgstr "" + +#: config/validators.py:36 +msgid "The password must contain at least 1 lowercase letter, a-z." +msgstr "" + +#: config/validators.py:41 +msgid "Your password must contain at least 1 lowercase letter, a-z." +msgstr "" + +#: config/validators.py:49 +msgid "" +"The password must contain at least 1 symbol: ()[]{}|\\`~!@#$%^&*_-+=;:'\\\"," +"<>./?" +msgstr "" + +#: config/validators.py:57 +msgid "" +"Your password must contain at least 1 symbol: ()[]{}|\\`~!@#$%^&*_-+=;:'\\\"," +"<>./?" +msgstr "" + +#: config/validators.py:66 +msgid "" +"The domain name is invalid. It should not start with scheme and should not " +"end with a trailing slash." +msgstr "" diff --git a/locale/ta/LC_MESSAGES/django.po b/locale/ta/LC_MESSAGES/django.po new file mode 100644 index 0000000000..d9eb9fd2d9 --- /dev/null +++ b/locale/ta/LC_MESSAGES/django.po @@ -0,0 +1,255 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-08-25 17:02+0530\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: care/abdm/apps.py:7 +msgid "ABDM Integration" +msgstr "" + +#: care/audit_log/apps.py:7 +msgid "Audit Log Management" +msgstr "" + +#: care/facility/apps.py:7 +msgid "Facility Management" +msgstr "" + +#: care/facility/models/encounter_symptom.py:16 +msgid "In Progress" +msgstr "" + +#: care/facility/models/encounter_symptom.py:17 +msgid "Completed" +msgstr "" + +#: care/facility/models/encounter_symptom.py:18 +#: care/facility/models/icd11_diagnosis.py:53 +msgid "Entered in Error" +msgstr "" + +#: care/facility/models/icd11_diagnosis.py:48 +msgid "Unconfirmed" +msgstr "" + +#: care/facility/models/icd11_diagnosis.py:49 +msgid "Provisional" +msgstr "" + +#: care/facility/models/icd11_diagnosis.py:50 +msgid "Differential" +msgstr "" + +#: care/facility/models/icd11_diagnosis.py:51 +msgid "Confirmed" +msgstr "" + +#: care/facility/models/icd11_diagnosis.py:52 +msgid "Refuted" +msgstr "" + +#: care/facility/models/patient.py:50 +msgid "Non-card holder" +msgstr "" + +#: care/facility/models/patient.py:51 +msgid "BPL" +msgstr "" + +#: care/facility/models/patient.py:52 +msgid "APL" +msgstr "" + +#: care/facility/models/patient_base.py:88 +msgid "Unknown" +msgstr "" + +#: care/facility/models/patient_base.py:89 +msgid "Recovered" +msgstr "" + +#: care/facility/models/patient_base.py:90 +msgid "Referred" +msgstr "" + +#: care/facility/models/patient_base.py:91 +msgid "Expired" +msgstr "" + +#: care/facility/models/patient_base.py:92 +msgid "LAMA" +msgstr "" + +#: care/facility/models/patient_base.py:127 +msgid "Outpatient/Emergency Room" +msgstr "" + +#: care/facility/models/patient_base.py:128 +msgid "Referred from another facility" +msgstr "" + +#: care/facility/models/patient_base.py:129 +msgid "Internal Transfer within the facility" +msgstr "" + +#: care/facility/models/patient_base.py:130 +msgid "(Unknown)" +msgstr "" + +#: care/hcx/apps.py:7 +msgid "HCX Integration" +msgstr "" + +#: care/templates/pages/home.html:8 +msgid "Open Healthcare Network" +msgstr "" + +#: care/templates/pages/home.html:9 +msgid "" +"Our Goal is to defend the Healthcare system of Kerala from overloading " +"beyond capacity." +msgstr "" + +#: care/users/apps.py:7 +msgid "Users" +msgstr "" + +#: care/users/forms.py:15 +msgid "This username has already been taken." +msgstr "" + +#: care/users/models.py:179 +msgid "username" +msgstr "" + +#: care/users/models.py:184 +msgid "A user with that username already exists." +msgstr "" + +#: care/users/reset_password_views.py:245 +msgid "" +"There is no active user associated with this username or the password can " +"not be changed" +msgstr "" + +#: care/utils/models/validators.py:54 +msgid "" +"Username must be 4 to 16 characters long. It may only contain lowercase " +"alphabets, numbers, underscores, hyphens and dots. It shouldn't start or end " +"with underscores, hyphens or dots. It shouldn't contain consecutive " +"underscores, hyphens or dots." +msgstr "" + +#: care/utils/ulid/serializers.py:9 +#, python-brace-format +msgid "\"{value}\" is not a valid ULID." +msgstr "" + +#: config/auth_views.py:19 +msgid "Too Many Requests Provide Captcha" +msgstr "" + +#: config/auth_views.py:27 +msgid "No active account found with the given credentials" +msgstr "" + +#: config/authentication.py:141 +msgid "Authorization header must contain two space-delimited values" +msgstr "" + +#: config/authentication.py:270 +msgid "" +"Used for authenticating requests from the middleware. The scheme requires a " +"valid JWT token in the Authorization header along with the facility id in " +"the X-Facility-Id header. --The value field is just for preview, filling it " +"will show allowed endpoints.--" +msgstr "" + +#: config/authentication.py:289 +msgid "" +"Used for authenticating requests from the middleware on behalf of assets. " +"The scheme requires a valid JWT token in the Authorization header along with " +"the facility id in the X-Facility-Id header. --The value field is just for " +"preview, filling it will show allowed endpoints.--" +msgstr "" + +#: config/authentication.py:306 config/authentication.py:320 +msgid "Do not use this scheme for production." +msgstr "" + +#: config/patient_otp_authentication.py:56 +msgid "Given token not valid for any token type" +msgstr "" + +#: config/settings/base.py:60 +msgid "English" +msgstr "" + +#: config/settings/base.py:61 +msgid "Malayalam" +msgstr "" + +#: config/settings/base.py:62 +msgid "Hindi" +msgstr "" + +#: config/settings/base.py:63 +msgid "Tamil" +msgstr "" + +#: config/validators.py:12 +msgid "The password must contain at least 1 digit, 0-9." +msgstr "" + +#: config/validators.py:17 +msgid "Your password must contain at least 1 digit, 0-9." +msgstr "" + +#: config/validators.py:24 +msgid "The password must contain at least 1 uppercase letter, A-Z." +msgstr "" + +#: config/validators.py:29 +msgid "Your password must contain at least 1 uppercase letter, A-Z." +msgstr "" + +#: config/validators.py:36 +msgid "The password must contain at least 1 lowercase letter, a-z." +msgstr "" + +#: config/validators.py:41 +msgid "Your password must contain at least 1 lowercase letter, a-z." +msgstr "" + +#: config/validators.py:49 +msgid "" +"The password must contain at least 1 symbol: ()[]{}|\\`~!@#$%^&*_-+=;:'\\\"," +"<>./?" +msgstr "" + +#: config/validators.py:57 +msgid "" +"Your password must contain at least 1 symbol: ()[]{}|\\`~!@#$%^&*_-+=;:'\\\"," +"<>./?" +msgstr "" + +#: config/validators.py:66 +msgid "" +"The domain name is invalid. It should not start with scheme and should not " +"end with a trailing slash." +msgstr "" diff --git a/scripts/celery-dev.sh b/scripts/celery-dev.sh index ac63afe1b3..75bc859d71 100755 --- a/scripts/celery-dev.sh +++ b/scripts/celery-dev.sh @@ -29,6 +29,7 @@ done >&2 echo 'PostgreSQL is available' python manage.py migrate --noinput +python manage.py compilemessages python manage.py load_redis_index diff --git a/scripts/celery_beat-ecs.sh b/scripts/celery_beat-ecs.sh index 540915a8b2..6c48e1e9bb 100755 --- a/scripts/celery_beat-ecs.sh +++ b/scripts/celery_beat-ecs.sh @@ -28,6 +28,7 @@ done >&2 echo 'PostgreSQL is available' python manage.py migrate --noinput +python manage.py compilemessages python manage.py load_redis_index python manage.py load_event_types diff --git a/scripts/celery_beat.sh b/scripts/celery_beat.sh index 9cc34f8075..136f095f59 100755 --- a/scripts/celery_beat.sh +++ b/scripts/celery_beat.sh @@ -28,6 +28,7 @@ done >&2 echo 'PostgreSQL is available' python manage.py migrate --noinput +python manage.py compilemessages python manage.py load_redis_index python manage.py load_event_types diff --git a/scripts/celery_worker-ecs.sh b/scripts/celery_worker-ecs.sh index 840b9e73b5..619f7a9f13 100755 --- a/scripts/celery_worker-ecs.sh +++ b/scripts/celery_worker-ecs.sh @@ -5,5 +5,6 @@ if [ -z "${DATABASE_URL}" ]; then export DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}" fi - +python manage.py collectstatic --noinput +python manage.py compilemessages celery --app=config.celery_app worker --max-tasks-per-child=6 --loglevel=info diff --git a/scripts/celery_worker.sh b/scripts/celery_worker.sh index 9c9e4d739d..a7f0a887d6 100755 --- a/scripts/celery_worker.sh +++ b/scripts/celery_worker.sh @@ -7,4 +7,6 @@ fi export NEW_RELIC_CONFIG_FILE=/etc/newrelic.ini +python manage.py collectstatic --noinput +python manage.py compilemessages newrelic-admin run-program celery --app=config.celery_app worker --max-tasks-per-child=6 --loglevel=info diff --git a/scripts/start-dev.sh b/scripts/start-dev.sh index b4996c3490..39abcfa4a0 100755 --- a/scripts/start-dev.sh +++ b/scripts/start-dev.sh @@ -7,6 +7,7 @@ cd /app echo "running collectstatic..." python manage.py collectstatic --noinput +python manage.py compilemessages echo "starting server..." if [[ "${DJANGO_DEBUG,,}" == "true" ]]; then diff --git a/scripts/start-ecs.sh b/scripts/start-ecs.sh index fb731bf198..c360864d9b 100755 --- a/scripts/start-ecs.sh +++ b/scripts/start-ecs.sh @@ -32,4 +32,5 @@ done >&2 echo 'PostgreSQL is available' python manage.py collectstatic --noinput +python manage.py compilemessages gunicorn config.wsgi:application --bind 0.0.0.0:9000 --chdir=/app --workers 2 diff --git a/scripts/start.sh b/scripts/start.sh index bebefa9a66..7d119b375a 100755 --- a/scripts/start.sh +++ b/scripts/start.sh @@ -33,4 +33,6 @@ done python manage.py collectstatic --noinput export NEW_RELIC_CONFIG_FILE=/etc/newrelic.ini + +python manage.py compilemessages newrelic-admin run-program gunicorn config.wsgi:application --bind 0.0.0.0:9000 --chdir=/app diff --git a/setup.py b/setup.py index a473e55c30..d4f320307f 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ description="A Django app for managing healthcare across hospitals and care centers.", license="MIT", keywords="django care ohc", - url="https://github.com/coronasafe/care", + url="https://github.com/ohcnetwork/care", classifiers=[ "Development Status :: 3 - Alpha", "Framework :: Django",