diff --git a/.travis.yml b/.travis.yml index 6cd64982..b05aa604 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,10 +8,6 @@ addons: - 159.203.182.32 env: global: - - SITE_URL: https://fga-gpp-mds.github.io/2018.1-Dr-Down/ - - GH_USER_NAME: "Robot Down" - - GH_USER_EMAIL: equipe.drdown@gmail.com - - GH_REF: github.com/fga-gpp-mds/2018.1-Dr-Down.git - secure: "wrb7hIKvhTmybgkW/kAubZmmdnIeKlXG6vczz8ct2ZbvVBvPflOQCDLQuqoRWDHDPs8PdLHwLZ6J3zlFCtkxBX0AKrSC1fCedkZSoTYEzrI3hj3k+IhTthWPao1GYuIyE+/GUIY82+4b8AHuE3weTSjl0JlOVpxIFfOXL9T2oRhZxjxdGJmUkJgWLXZIsDjvX1bmBZ/SbdMgGGer1YSu8UoiAAr94IrEU5dyJ9Yc8sX6HTZnCdkGgMckPMyZkVwbW9sw9DcjSCB0W/h3aYIP86zocBUk1xGD0tzbnd1mEYaScXRU1rxVBYoe0XnTmFAhyAae1NTtw+6Pqrz1RDudbfTxJBLvkkaBse1w5XN3oBUeuOFLGyoagItnxqzbprt3QN6Tno23LLrefhShVAvzemRceB/Ie6NWRmyhDbsEJpLgAhUpdAGY+Phh2iFRjAsfCnsHT1AKJIoNBoJoi8d79dSOHTK1XxgdBJi9zfhIXB3jjFPhKIx0UHd4aNsIzfuTQWWC8cm05UcdWiTAxunWumoh94jQ6flkIk7RdNyeM+dytJW9mqTvw2lxCRAuyYo7eGs5jqTMqokSAuSDzRFPMUDlP+t/lewAsuwLsxXVOjrMn8TnT28yimay4bK4ZocYP6M3EJPg1DsJ/QOyCqFIFqEMs8lAqJDNky/cJ/79ZIY=" - CC_TEST_REPORTER_ID=bf64f4cd10722061b8cad12ca638ebfa7d3c1494df117613b2acd357bfd7aeb0 notifications: @@ -21,11 +17,20 @@ notifications: services: - docker before_install: + - sudo apt-get remove docker docker-engine docker.io - sudo apt-get update - - sudo apt-get install -o Dpkg::Options::="--force-confold" --force-yes -y docker-ce - - docker-compose --version + - sudo apt-get install apt-transport-https ca-certificates curl software-properties-common + - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - + - sudo curl -L https://github.com/docker/compose/releases/download/1.21.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose + - sudo chmod +x /usr/local/bin/docker-compose + - sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" + - sudo apt-get update + - sudo apt-get install docker-ce + - docker-compose version + - docker version - sudo apt-get install texlive-latex-base texlive-fonts-recommended -y - sudo apt-get install texlive-fonts-extra texlive-latex-extra -y + - sudo apt-get install python-sphinx -y - python3 -m pip install pip -U - python3 -m pip install mkdocs before_script: @@ -36,23 +41,25 @@ before_script: - docker-compose -f local.yml pull - docker-compose -f local.yml up --build -d script: + - echo $DOCKER_ID_USER_PASSWORD | docker login -u $DOCKER_ID_USER --password-stdin - docker-compose -f local.yml run --rm django py.test - docker-compose -f local.yml run --rm django coverage run -m py.test - docker-compose -f local.yml run --rm django coverage xml -after_sucess: - - make -C docs/ latexpdf - - mv docs/_build/latex/drdown.pdf docs/drdown.pdf - - if [[ $DEPLOY_DOCS == "true" ]]; then echo "Preparing to build and deploy documentation" ; ./mkdocs-build.sh ; echo "Completed deploying documentation" ; fi deploy: # deploy develop to the staging environment - provider: script script: bash staging-deploy.sh + skip_cleanup: true on: branch: develop # deploy master to production - provider: script script: bash production-deploy.sh + skip_cleanup: true on: branch: master after_script: - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT -t coverage.py + - make -C docs/ latexpdf + - mv docs/_build/latex/drdown.pdf docs/drdown.pdf + - if [[ $DEPLOY_DOCS == "true" ]]; then echo "Preparing to build and deploy documentation" ; ./mkdocs-build.sh ; echo "Completed deploying documentation" ; fi diff --git a/config/settings/base.py b/config/settings/base.py index a233b463..fc8aca3d 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -85,6 +85,7 @@ 'drdown.core.apps.CoreConfig', 'drdown.careline.apps.CarelineConfig', 'drdown.medicalrecords.apps.MedicalRecordsConfig', + 'drdown.appointments.apps.AppointmentsConfig', ] # https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS diff --git a/config/urls.py b/config/urls.py index f8e9f700..d314a9f7 100644 --- a/config/urls.py +++ b/config/urls.py @@ -17,10 +17,8 @@ # Your stuff: custom urls includes go here url(r'^forum/', include('drdown.forum.urls', namespace='forum')), url(r'^careline/', include('drdown.careline.urls', namespace='careline')), - - # Medical Records urls - url(r'^medicalrecords/', include('drdown.medicalrecords.urls', namespace='medicalrecords')) - + url(r'^medicalrecords/', include('drdown.medicalrecords.urls', namespace='medicalrecords')), + url(r'^appointments/', include('drdown.appointments.urls', namespace='appointments')), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/docs/eps/EVM_AGILE.md b/docs/eps/EVM_AGILE.md index 7f63d212..b049c313 100644 --- a/docs/eps/EVM_AGILE.md +++ b/docs/eps/EVM_AGILE.md @@ -4,6 +4,7 @@ | Data | Versão | Descrição | Autores | | --- | --- | --- | --- | | 28/03/2018 | 0.0.1 | Criação do documento | João Pedro Sconetto | +| 29/04/2019 | 0.1.0 | Adição da EVM da segunda _release_ | João Pedro Sconetto e Mariana de Souza Mendes | ## EVM Agile @@ -13,6 +14,8 @@ O __EVM__ (_Earned Value Management_ ou Gerenciamento de Valor agregado) se trat - e etc. ### Dados Fixos + +#### _Release 1_ | Identificador | Descrição | Valor | | --- | --- | --- | | BAC | Orçamento disponível para a primeira _release_ | R$ 34.039,38 | @@ -21,9 +24,18 @@ O __EVM__ (_Earned Value Management_ ou Gerenciamento de Valor agregado) se trat | SD | Data de início | 05/03/2018 | | PRP | Pontos planejados para a primeira _release_ | 172 | +#### _Release 2_ +| Identificador | Descrição | Valor | +| --- | --- | --- | +| BAC | Orçamento disponível para a segunda _release_ | R$ 34.039,38 | +| L | Tamanho da sprint em dias | 7 | +| PS | Total de sprints planejadas | 8 | +| SD | Data de início | 14/04/2018 | +| PRP | Pontos planejados para a segunda _release_ | 200 | + ### Legenda: | Identificador | Descrição | -| --- | --- | +| --- | --- | | PRP | O PRP foi modificado para ser a soma de todos os pontos reavaliados das histórias. | | RPC | De forma análoga, o RPC é avaliado como o somatório dos pontos concluídos até a sprint atual. | | PPC | Esse valor é o somatório da razão entre a duração da sprint atual sobre o número de sprints da _release_ até a sprint atual. | @@ -44,6 +56,19 @@ O __EVM__ (_Earned Value Management_ ou Gerenciamento de Valor agregado) se trat ### Planilha EVM Link para a planilha EVM no [Google Docs](https://docs.google.com/spreadsheets/d/1ZHlVvq_5Sjnyp-sH-7Zfn_KFYzFxoZwtOBWQ92yfd3M/edit?usp=sharing). +### Imagem da EVM +#### _Release_ 1 +Abaixo segue a imagem da EVM para a primeira _release_, esta que já foi concluída. +As informações podem ser melhor vistas no link disponibilizado acima. + +![EVM-Release 01](https://i.imgur.com/eBpsQLy.png) + +#### _Release_ 2 +Abaixo segue a imagem da EVM da segunda _release_, que ainda está em execução, logo não está completamente preenchida. +As informações podem ser melhor vistas no link disponibilizado acima. + +![EVM-Release 02](https://i.imgur.com/xOnnli4.png) + ## Referências HiFlex Consultoria. Gerenciamento de valor agregado (EVM) em projetos agéis. Vitor Massari. Acesso em: codetiburon. Earned Value Management (EVM) for Agile Software Projects. Olga Yatskevich. Acesso em: diff --git a/docs/eps/MINDMAP.md b/docs/eps/MINDMAP.md new file mode 100644 index 00000000..c6fa9c51 --- /dev/null +++ b/docs/eps/MINDMAP.md @@ -0,0 +1,14 @@ +# MINDMAP + +| Data | Versão | Descrição | Autor | +|----|------|---------|-----| +|10/05/2018|0.0.1|Primeira Versão do mindmap|Mariana De Souza Mendes e João Pedro Sconetto| + + +## v.0.1. MINDMAP + +![MINDMAP.png](https://uploaddeimagens.com.br/images/001/411/446/original/Captura_de_tela_de_2018-05-10_15-12-22.png?1525975986) + +[Clique aqui para ampliar a imagem](https://uploaddeimagens.com.br/images/001/411/446/original/Captura_de_tela_de_2018-05-10_15-12-22.png?1525975986) + +[Ou aqui para acessar a imagem no próprio mindmap](https://www.mindmeister.com/1091544081/login?fullscreen=1) \ No newline at end of file diff --git a/docs/eps/PIPELINE.md b/docs/eps/PIPELINE.md new file mode 100644 index 00000000..e3414b01 --- /dev/null +++ b/docs/eps/PIPELINE.md @@ -0,0 +1,122 @@ +# Pipeline CI/CD + +## Histórico de Revisões +|Data|Versão|Descrição|Autor| +| --- | --- | --- | --- | +|06/05/2018|0.0.1|Versão inicial do documento do pipeline|João Pedro Sconetto e Mariana Mendes| + +## Processos de DevOps +O presente documento visa esclarecer e registrar todos os processos, a cultura implementada e os padrões que foram utilizados no projeto __Dr. Down__ no viés das práticas de DevOps, a fim de unificar o desenvolvimento e as operações inerentes do projeto supracitado. + +O documento se divide em duas partes: + +* Integração Contínua (CI - _Continuous Integration_) + +* Deploy Contínuo (CD - _Continuous Deploy_) + +No qual a primeira parte irá mostrar as técnicas e itens aplicados ao projeto no propósito de, como o nome da técnica diz, integrar continuamente o trabalho desenvolvido pela equipe. A segunda parte irá mostrar as técnicas e itens aplicados ao projeto com o objetivo de fazer a implantação contínua do projeto na infraestrutura utilizada pela equipe, de forma automatizada. + +### Integração Contínua: + +#### Padrão de _Commit_ + +##### Por questões de padronização documentamos o seguinte estilo de _commit_: + +* Os _commits_ devem ser todos em __inglês__; + +* Ele deve conter um título curto e objetivo do que foi feito naquele _commit_; + +* Após esse título, deve-se descrever, com um pouco mais de detalhes, todas as atividades executadas. + +* Caso esteja trabalhando com algum associado assine nos seus _commits_ os seus parceiros + +__Exemplo:__ + + Creating project community files (Título curto e objetivo) + + Adds project license (Descrição de uma das atividades) + + Adds project code of conduct file + + Adds project contributing file + + Adds project issue template file + + Adds projects pull request file + + Co-authored-by: John Doe (Assinatura de parceria) + +#### Política de _Branchs_ + +Tendo como meta manter a integralidade e confiabilidade do código do projeto, foi proposta a utilização de política de branches. +Essa Política de Branches deverá guiar os desenvolvedores na forma de organização de suas contribuições ao projeto. + +__OBS__: A política de _branchs_ foi idealizada para trabalhar em conjunto com a ferramenta do _git flow_, sua documentação e mais informações podem ser acessadas [aqui](https://github.com/nvie/gitflow). + +* __master__ - Branch principal do repositório, onde será permitida somente a integração de software consolidado e testado. Essa branch será exclusiva para a entrega de Releases, ou seja, um conjunto maior de funcionalidades que integram o software. Aqui estará a versão _**stable**_ do software. + +* __develop__ - Branch para integração de novas funcionalidades, onde será permitido a entrega das features desenvolvidas e que estão em um estágio avançado de completude. Será a branch base para o início do desenvolvimento das features e da correção de bugs. Aqui também serão _mergeadas_ as releases. + +* __feature/__ - Branch utilizada para o desenvolvimento de novas features do _backlog_. Caso a feature tenha sida proposta por uma _issue_ do repositório e aceita no _backlog_ o nome deverá conter o número da _issue_. +Ex: feature/1- (Considerando que a feature tenha sido solicitada na _issue_ #1) + +* __bugfix/__ - Branch utilizada para corrigir bugs de baixa/média urgência e que não estão presentes na branch __master__. Caso o bug tenha sido reportado por uma _issue_ do repositório o nome deverá conter o número da _issue_. + Ex: bugfix/1- (Considerando que o bug tenha sido reportado na _issue_ #1) + +* __hotfix/__ - Branch utilizada para corrigir bugs de alta urgência e que estão presentes na branch __master__. Caso o bug tenha sido reportado por uma _issue_ do repositório o nome deverá conter o número da _issue_. + Ex: bugfix/1- (Considerando que o bug tenha sido reportado na _issue_ #1) + +* __release/__ - Branch onde será feito os ajustes finais/build antes da entrega de uma versão do produto de software. Constará no nome da branch a versão da release a ser entregue. + +* __support/__ - Branch onde serão executadas tarefas de suporte relacionadas ao software, como elaboração de documentações, correções de natureza de gerência de configuração e etc. + +#### Testes e Estilo de Código + +Com o objetivo de garantir a qualidade de código, assim como a sua manutenibilidade, a equipe definiu técnicas e padrões a serem seguidos, quanto ao estilo de código foi definido uma folha de estilo que é considerada a padrão por programadores Python, se trata da [PEP8](https://www.python.org/dev/peps/pep-0008/). Com isto é possível verificar, com o auxílio da ferramenta Code Climate o quão manutenível é o código que está sendo feito. + +Em complemento ao estilo do código a equipe acordou em manter todo o código testado, pois com a união das duas técnicas é possível assegurar uma maior qualidade de código. Para isso foram usados técnicas padrões de teste do Python/Django, com o auxílio do [Coverage.py](https://coverage.readthedocs.io/en/coverage-4.5.1/) e do [pytest](https://docs.pytest.org/en/latest/), estes que, também, servem de _input_ para o Code Climate analisar a manutenibilidade do software. + +Ficou acordado entre os membros da equipe que a cobertura de teste deveria ser igual ou superior a 90% em todos os momentos do projeto. + +#### _Pull Requests_ + +Ao término da execução da codificação é necessário a abertura de um _Pull Request_ no repositório oficial do software para que possa ser apreciado o código solução. Com isso as ferramentas de CI/CD automático irão executar a fase de _build_ e teste para verificar se etapa de teste e estilo de código foram implementadas corretamente. Caso não tenha dívidas nessa fase, cabe a dois membros da equipe de EPS (com foco no P.O. na análise) analisar o produto para verificar se atende os critérios de aceitação e se está de acordo com o que foi definido para ser entregue. Com todas as técnicas e fases entregues em conformidade, cabe aos membros aprovarem o _pull request_ para que o mesmo possa ser _mergeado_ em branchs de entregue de _feature_. + +#### _Build_ e Testes + +Com o auxílio de ferramentas de automatização essa fase é executada, via [Travis-CI](https://travis-ci.org/), a fim de garantir a fase de Teste e Estilo de Código. Com isso a ferramenta vai verificar o código, executar todos os testes para procurar erros na lógica do software e após tentar construir (_build_) os _containers_ da aplicação. Caso qualquer passo dessa fase tenha algum problema a ferramenta irá informar (via e-mail e via repositório) que algo está errado e é preciso correções antes de avançar no pipeline. + +### Deploy Contínuo: + +Com a execução de todos os passos da integração contínua a ferramenta de automatização irá executar os passos de deploy, caso não tenho encontrado nenhum erro, que seguem com o deploy/entrega da aplicação no ambiente de homologação e produção. Os passos executados são: + +* Publica a última versão integrada na _branch_ no docker hub da aplicação; + +* Acessa as máquinas de deploy (Hosts no Digital Ocean); + +* Baixa a última versão do docker hub no host; + +* Executa atualizações necessárias com as novas funcionalidades (migrações, modificações no banco, traduções e etc); + +* Caso tenha algum problema a máquina envia um log para a ferramenta de logs (sentry.io). Caso contrário, o sistema mantém o funcionamento contínuamente. + +### Pipeline v0.0.1 + +![pipeline](https://i.imgur.com/v3m6lQr.png) + +#### Legenda + +Primeiro Estágio: +* No primeiro estágio estão as culturas de política de _branches_, padrão de _commits_, estilo de código e testes, onde durante o desenvolvimento a equipe segue as culturas propostas até a publicação do código com as novas adições. + +Segundo Estágio: +* Aqui o código publicado com as adições, chamada de versão, é alcançada pela ferramenta de CI, executado os testes (todos os implementados e os novos adicionados) e é feito a build, caso haja erro nesse estágio retorna-se ao primeiro fazendo as adições necessárias. + +Terceiro Estágio: +* Aqui a nova versão está em um estágio estável do seu ciclo de vida, se todas as adições esperadas para esta versão estiverem prontas a equipe espera uma abertura de um novo _pull request_ solicitando a junção dessa versão com a versão atual do software. Nesta fase é feito a verificação manual da concordância das adições, tanto com os estágios anteriores quanto com as especificações de produto levantado pelo _Product Owner_, caso positivo o pipeline avança, do contrário retorna a estágios anteriores. + +Quarto Estágio: +* Aqui com a nova versão aprovada e consolidada ela é direcionada para o ambiente o qual deve integrar (homologação ou produção) e a ferramenta de CI/CD faz o deploy e entrega automática dessas novas adições. + + +__OBS__: Os principais artefatos que estão inclusos no, e participam do, pipeline são: ```.travis.yml```, ```codeclimate.yml```, ```mkdocs-build.sh```, ```production-deploy.sh``` e ```staging-deploy.sh```, todos estão disponíveis no repositório da aplicação no [GitHub](https://github.com/fga-gpp-mds/2018.1-Dr-Down). diff --git a/docs/eps/RISKS.md b/docs/eps/RISKS.md index 87c21f44..984fd87e 100644 --- a/docs/eps/RISKS.md +++ b/docs/eps/RISKS.md @@ -50,6 +50,22 @@ |:--------------:|:-------------------|:-------------------| | Atraso na implementação da arquitetura do projeto | - apresentar as features com antecedência para o arquiteto do software para que ele possa planejar como implementá-las com antecedência;
- checar o andamento do planejamento e implementação da arquitetura constantemente com o arquiteto | - analisar o que houve de errado na implementação para remediar;
- incluir no planejamento das sprints seguintes histórias para tirar o atraso da implementação da arquitetura +## Sprint 6 + +### Score: 51 + +## Sprint 7 + +### Score: 45 + +| **Risco** | **Ações para prevení-lo** | **Ações para mitigá-lo** | +|:--------------:|:-------------------|:-------------------| +| Aceitação do software pelo cliente | - levantar o que o cliente o que ele acha do planejamento das features a serem implementadas, antes de elas serem incluídas em uma sprint;
-arrumar o que for necessário a partir do feedback do cliente | - levantar com o cliente o que está errado no que foi feito;
- elencar possíveis soluções para os problemas apontados e apresentá-las ao cliente, até que ele esteja de acordo;
- corrigir os erros nas sprints seguintes, o mais rápido possível + +## Sprint 8 + +### Score: 45 + ## Burndown de Riscos Essa escala deve ser usada para pontuar o impacto (usando como referência uma estimativa do número de dias necessários para mitigar os efeitos da ocorrência do risco): diff --git a/docs/mds/ARCHITECTURE_DOCUMENT.md b/docs/mds/ARCHITECTURE_DOCUMENT.md index 315d1ba3..7d6e5eae 100644 --- a/docs/mds/ARCHITECTURE_DOCUMENT.md +++ b/docs/mds/ARCHITECTURE_DOCUMENT.md @@ -23,6 +23,7 @@ | 15/04/2018 | 1.4.0 | Modificando imagem da arquitetura | Victor Arnaud e Geovana Ramos | | 22/04/2018 | 2.0.0 | Versão 2.0 do Arquitetura e componentes da sprint 07 | Victor Arnaud, Geovana Ramos e Gabriela Medeiros | | 26/04/2018 | 2.1.0 | Inserindo componentes da sprint 08 | Victor Arnaud | +| 01/05/2018 | 2.2.0 | Inserindo componentes para as sprints 09 a 12 | Victor Arnaud | ## 1: Introdução @@ -107,7 +108,7 @@ Critérios de aceitação de um componente: 5. **Extensibilidade**: Um componente pode ser estendido a partir de outro componente para fornecer um novo comportamento. 6. **Encapsulamento**: O componente deve expor uma interface para os invocadores utilizarem suas funcionalidades e não revelar detalhes do seu processo interno, das variáveis internas e de seu estado. 7. **Externo ao projeto**: O componente deve estar disponibilizado no **pypi**. -8. **Qualidade**: O componente deve estar testado e ter build funcionando, além de ser completo e estar em uma versão estável. +8. **Qualidade**: O componente deve estar testado e ter build funcionando, além de ser completo e estar em uma versão estável, ou seja, o componente deve funcionar na nova versão 2.0 do Django. A cada sprint do projeto será definido a utilização ou não de cada componente disponibilizado nas tabelas abaixo. Os microsserviços e APIs consumidas também serão listados nas tabelas abaixo. As tabelas abaixo está mapeada com a EAP do projeto. @@ -134,12 +135,8 @@ A cada sprint do projeto será definido a utilização ou não de cada component |Aplicação|Descrição da aplicação|Foi utilizado?|Motivo da utilização ou não| |---------|----------------------|:------------:|---------------------------| |[pinax-calendars](https://github.com/pinax/pinax-calendars/)|Aplicação django para publicar eventos como um calendario|A decidir|A aplicação ainda está sendo avaliada pela equipe.| -|[django-calendarium](https://github.com/bitlabstudio/django-calendarium)|Um aplicativo Django reutilizável para gerenciar e exibir um calendário em seus modelos.|A decidir|A aplicação ainda está sendo avaliada pela equipe.| |[django-scheduler](https://github.com/llazzaro/django-scheduler)|Uma aplicação de calendario do django|A decidir|A aplicação ainda está sendo avaliada pela equipe.| -|[django-schedule-thauber](https://github.com/thauber/django-schedule)|Uma aplicação de calendario do django|A decidir|A aplicação ainda está sendo avaliada| |[pinax-notifications](https://github.com/pinax/pinax-notifications/)|Gerenciamento de notificação de usuário para o framework web Django|A decidir|A aplicação ainda está sendo avaliada| -|[django-frontend-notification](https://github.com/areski/django-frontend-notification)|Aplicativo Django para exibir no frontend a lista de notificações e executar algumas ações básicas como "visualizar todas as notificações", "excluir notificações", ele também fornece ajudantes para exibir notificações|A decidir|A aplicação ainda está sendo avaliada| -|[django-webline-notifications](https://github.com/alireza-molaee/django-webline-notifications)|É uma biblioteca python, que permite notificar tudo para o(s) usuário(s)|A decidir|A aplicação ainda está sendo avaliada| #### Ficha de acompanhamento e Relatórios @@ -147,14 +144,16 @@ A cada sprint do projeto será definido a utilização ou não de cada component |---------|----------------------|:------------:|---------------------------| |[django-pagedown](https://github.com/timmyomahony/django-pagedown)|Um aplicativo django que permite a fácil adição do editor de marcação "PageDown" do Stack Overflow a um campo de formulário django, seja em um aplicativo personalizado ou no Django Admin.|Sim|O componente está sendo usado no prontuário| |[django-markdown-deux](https://github.com/trentm/django-markdown-deux)|Componente para evitar a inserção de código malicioso no markdown|Sim|O componente está sendo usado no prontuário| -|[pdf-report](https://github.com/Edinburgh-Genome-Foundry/pdf_reports)|Biblioteca Python e tema CSS para gerar relatórios em PDF a partir de HTML/Pug|A decidir|A aplicação está sendo avaliada pela equipe| -|[django-easy-pdf](https://github.com/nigma/django-easy-pdf)|Visualização de PDF de uma maneira fácil|A decidir|A aplicação está sendo avaliada pela equipe| +|[pdf-report](https://github.com/Edinburgh-Genome-Foundry/pdf_reports)|Biblioteca Python e tema CSS para gerar relatórios em PDF a partir de HTML/Pug|Não|A documentação do Django aconselha utilizar o ReportLab, logo iremos utilizat esse component.| +|[reportlab](https://pypi.org/project/reportlab/)|O Toolkit do ReportLab. Uma biblioteca Python de código aberto para gerar PDFs e gráficos.|Sim|Recomendação da documentação do [django](https://docs.djangoproject.com/pt-br/2.0/howto/outputting-pdf/), será utilizado para gerar os PDFs e gráficos do projeto| +|[django-easy-pdf](https://github.com/nigma/django-easy-pdf)|Visualização de PDF de uma maneira fácil|Não|A documentação do Django aconselha utilizar o ReportLab, logo iremos utilizar esse component.| #### Localização |Aplicação|Descrição da aplicação|Foi utilizado?|Motivo da utilização ou não| |---------|----------------------|:------------:|---------------------------| -|[GoogleMapsAPI](https://developers.google.com/places/web-service/?hl=pt-br)|API do Google Maps com informações sobre milhões de locais|A decidir|A API ainda está sendo avaliada pela equipe.| +|[GoogleMapsAPI](https://developers.google.com/places/web-service/?hl=pt-br)|API do Google Maps com informações sobre milhões de locais| Sim |Facil aplicação e atende as necessidades.| +|[google-maps-services-python](https://github.com/googlemaps/google-maps-services-python)|Componente python para utilização da API do google maps| Não | Não será ultilizado porque a API do google atendeu nossas necessidades e foi recomendada pela Gerência de projetos.| #### Outros @@ -162,17 +161,9 @@ A cada sprint do projeto será definido a utilização ou não de cada component |---------|----------------------|:------------:|---------------------------| |[django-role-permissions](https://github.com/vintasoftware/django-role-permissions)|É um aplicativo de Django para permissões baseadas em função. Ele é construído sobre as funcionalidades Group e Permission do usuário do Django contrib.auth e não adiciona nenhum outro modelo ao seu projeto, ou seja, é totalmente independente.|Sim|Ele será utilizado no projeto para a criação de permissões de cada tipo de usuário do sistema e as permissões de acesso a determinadas páginas| |[django-crispy-forms](http://django-crispy-forms.readthedocs.io/en/latest/)|É um aplicativo do Django que permite a construção, customização e reutilização de formulários facilmente, podendo usar qualquer framework CSS, sem escrever código de template e sem ter que cuidar de outros tipos de detalhes.|Sim|Foi utilizado para facilitar a criação de formulários| -|[django-simple-search](https://github.com/gregplaysguitar/django-simple-search)|A busca simples do Django fornece a mesma funcionalidade e conveniência que o search fields faz no admin do django.|A decidir|A aplicação ainda está sendo avaliada| +|[django-simple-search](https://github.com/gregplaysguitar/django-simple-search)|A busca simples do Django fornece a mesma funcionalidade e conveniência que o search fields faz no admin do django.|Não|Foi decidido a utilização do django-search-view pelo fato de utilizar CBV.| |[django-search-view](https://github.com/inmagik/django-search-views)|Componente para pesquisa e filtros usando Class Based Views|Sim|O componentes está sendo usando em algumas partes do software que precisa pesquisar algo.| - -#### Comunicação entre usuários (Removido do escopo) - -|Aplicação|Descrição da aplicação|Foi utilizado?|Motivo da utilização ou não| -|---------|----------------------|:------------:|---------------------------| -|[Rocket.Chat](https://github.com/jadolg/rocketchat_API)|É um microserviço de chat open source baseado no Slack e construído em Meteor|Não|O chat foi removido do escopo do projeto.| -|[Receita-Mais](https://github.com/fga-gpp-mds/2017.2-Receita-Mais)|Software responsável por auxiliar na prescrição de medicamentos|Não|Não passou em quase todos os critérios definidos acima, a aplicação chat do projeto está bastante acoplada, ou seja, teria dificuldade de desacoplar e empacotar o mesmo, gastando tempo e esforço| -|[django-private-chat](https://github.com/Bearle/django-private-chat)|Chat assíncrono baseado em WebSocket|Não|O chat foi removido do escopo do projeto.| -|[django-tawkto](https://github.com/CleitonDeLima/django-tawkto)|Projeto simples integrado com o chat [tawk.to](https://www.tawk.to/)|Não|O chat foi removido do escopo do projeto.| +|[django-anymail](https://github.com/anymail/django-anymail)|Backends e webhooks de e-mail do Django para Amazon SES, Mailgun, Mailjet, Carimbo Postal, SendGrid, SendinBlue, SparkPost e mais|A decidir|A equipe está avaliando a possibilidade de utiliza-lo.| ### 2.3 Banco de dados PostgreSQL diff --git a/docs/sprints/07/planning.md b/docs/sprints/07/planning.md new file mode 100644 index 00000000..32121fe2 --- /dev/null +++ b/docs/sprints/07/planning.md @@ -0,0 +1,67 @@ +# Planejamento da Sprint 7 + +## 1. Resumo da Sprint + +__Número da sprint:__ 7 + +__Data de início:__ 21/04/2018 + +__Data de Término:__ 27/04/2018 + +__Duração__: 6 dias + +__Pontos Planejados:__ 23 pontos + +__Membros presentes:__ Todos + +## 2. Papéis + +- Scrum Master: + - Diego França + +- Product Owner: + - Mariana Mendes + +- DevOps: + - João Sconetto + +- Arquiteto: + - Victor Arnaud + +- Time de Desenvolvimento: + - Daniel Maike + - Elias Bernardo + - Gabriela Medeiros + - Geovana Ramos + - Guilherme Guy + - Joberth Rodrigues + +## 3. Pareamento + +- Daniel e Guilherme + +- Elias e Joberth + +- Gabriela e Geovana + +## 4. Planejamento da Sprint + +Nessa sprint, serão iniciadas as histórias relacionadas à ficha de acompanhamento dos pacientes. As primeiras funcionalidades a serem feitas serão o prontuário eletrônico dos pacientes (que levará em conta as especificidades do paciente com Síndrome de Down) e também o checklist de cuidados e recomendações a serem feitos com pessoas com a Síndrome. + +Nela também será revisado tanto a integração contínua do projeto quanto a sua arquitetura. + +## 5. Mudanças + +Mudanças foram feitas nesta sprint relacionadas à arquitetura. A partir da Sprint 7, o arquiteto selecionará diversos componentes que poderão ser utilizados nas histórias, e caberá às duplas responsáveis por elas definir quais adotarão. + +## 6. Backlog da Sprint + +- [TS69 - Refatorar arquitetura do projeto e seu respectivo documento](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/160) +- [US70 - Prontuário](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/161) +- [US71 - Checklist](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/162) +- [TS72 - Refatorar equipe de saúde](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/163) +- [TS73 - Revisar a Integração Contínua](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/164) +- [TS74 - Documentar a Sprint 6](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/166) + +## 7. Risk Burndown +![Burndown de risco da Sprint 7](https://uploaddeimagens.com.br/images/001/398/142/full/riscos_S7.png?1525202634) diff --git a/docs/sprints/07/results.md b/docs/sprints/07/results.md new file mode 100644 index 00000000..7023e697 --- /dev/null +++ b/docs/sprints/07/results.md @@ -0,0 +1,48 @@ +# Fechamento da sprint + +## 1. Resumo da Sprint + +__Pontos Planejados__: 23 pontos + +__Pontos concluídos__: 23 pontos + +__Dívidas técnicas__: 0 pontos + +__Histórias entregues:__ + +- [TS69 - Refatorar arquitetura do projeto e seu respectivo documento](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/160) +- [US70 - Prontuário](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/161) +- [US71 - Checklist](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/162) +- [TS72 - Refatorar equipe de saúde](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/163) +- [TS73 - Revisar a Integração Contínua](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/164) +- [TS74 - Documentar a Sprint 6](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/166) + +## 2. Retrospectiva da Sprint + +| Pontos Positivos | Pontos Negativos | Sugestão de Melhoria | +| ----- | ----- | ---- | +| Os pontos positivos das sprints passada se mantiveram | Pareamento não deu tão certo pra uma dupla | Tomar mais cuidado na hora de pontuar as histórias | +| Foi criado um canal de bug no Slack e ele está ajudando todos | Issues depentes do término de outras | Maior preocupação em manter a uniformidade e padronização do frontend | +| - | Um dos clientes estava viajando, dificultando a comunicação com ele | - | + +## 3. Quadro de Conhecimento + +![Quadro de conhecimento da Sprint 7](https://uploaddeimagens.com.br/images/001/398/170/full/quadro_conhecimento_S7.png?1525204302) + +## 5. Gráfico do Burndown + +![Gráfico do burndown da Sprint 7](https://uploaddeimagens.com.br/images/001/398/174/full/burndown_S7.png?1525204456) + +## 6. Velocity + +![Gráfico do velocity da Sprint 7](https://uploaddeimagens.com.br/images/001/398/181/full/velocity_S7.png?1525204706) + +## 7. Gráfico de Commits + +![Gráfico de commits da Sprint 7](https://uploaddeimagens.com.br/images/001/398/189/full/commits_S7.png?1525204960) + +## 9. Análise do Scrum Master + +Nessa sprint, 2 das histórias tiveram pontuações abaixo do esforço necessário, de acordo com as duplas responsáveis por elas. Para evitar que isso se repita, já no planejamento da Sprint 8 a equipe terá um maior cuidado para pontuar as histórias. + +De resto, a sprint ocorreu com tranquilidade e sem dívidas, já que o problema apresentado com relação ao pareamento de uma das duplas foi devido à greve da universidade, que atrapalhou a programação deles trabalharem juntos mas não a entrega da história. diff --git a/docs/sprints/08/planning.md b/docs/sprints/08/planning.md new file mode 100644 index 00000000..4c7928ed --- /dev/null +++ b/docs/sprints/08/planning.md @@ -0,0 +1,68 @@ +# Planejamento da Sprint 8 + +## 1. Resumo da Sprint + +__Número da sprint:__ 8 + +__Data de início:__ 28/04/2018 + +__Data de Término:__ 04/05/2018 + +__Duração__: 6 dias + +__Pontos Planejados:__ 22 pontos + +__Membros ausentes:__ +- Daniel Mike + +## 2. Papéis + +- Scrum Master: + - Diego França + +- Product Owner: + - Mariana Mendes + +- DevOps: + - João Sconetto + +- Arquiteto: + - Victor Arnaud + +- Time de Desenvolvimento: + - Daniel Maike + - Elias Bernardo + - Gabriela Medeiros + - Geovana Ramos + - Guilherme Guy + - Joberth Rodrigues + +## 3. Pareamento + +- Daniel e Elias + +- Gabriela e Geovana + +- Guilherme e Joberth + +## 4. Planejamento da Sprint + +A Sprint 8 foi planejada para dar continuidade às histórias relacionadas à ficha de acompanhamento do paciente do Cris Down, que é uma importante feature do projeto. Além disso, há histórias dedicadas a atualizar planejamentos e documentos para esta segunda etapa do projeto e para a correção de bugs do aplicativo. + +## 5. Mudanças + +Para esta sprint, devido ao problema que houve na passada relacionado à pontuação de histórias não correspondendo ao esforço para entregá-las, na reunião de planejamento tivemos um maior cuidado com isso. Desta forma, cada história foi discutida por mais tempo, e as possíveis questões técnicas relacionadas à elas foram mais esmiuçadas antes que começássemos pontuação. + +## 6. Backlog da Sprint + +- [TS75 - Atualizar a documentação dos riscos para a Sprint 7](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/167) +- [TS77 - Elaborar a segunda versão da EVM](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/185) +- [US78 - Consulta](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/186) +- [TS79 - Correção de bugs](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/187) +- [US80 - Ficha de acompanhamento](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/188) +- [US81 - Calendário de vacina](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/189) +- [TS82 - Documentar a Sprint 7](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/191) + +## 7. Risk Burndown + +![Risk Burndown da Sprint 8](https://uploaddeimagens.com.br/images/001/409/241/full/riscos_S8.png?1525865981) diff --git a/docs/sprints/08/results.md b/docs/sprints/08/results.md new file mode 100644 index 00000000..2976f034 --- /dev/null +++ b/docs/sprints/08/results.md @@ -0,0 +1,62 @@ +# Fechamento da Sprint 8 + +## 1. Resumo da Sprint + +__Pontos Planejados__: 22 pontos + +__Pontos concluídos__: 21 pontos + +__Dívidas técnicas__: 1 pontos + +__Histórias entregues:__ + +- [TS77 - Elaborar a segunda versão da EVM](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/185) +- [US78 - Consulta](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/186) +- [TS79 - Correção de bugs](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/187) +- [US80 - Ficha de acompanhamento](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/188) +- [US81 - Calendário de vacina](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/189) +- [TS82 - Documentar a Sprint 7](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/191) + +__Histórias que viraram débitos:__ + +- [TS75 - Atualizar a documentação dos riscos para a Sprint 7](https://github.com/fga-gpp-mds/2018.1-Dr-Down/issues/167) + +## 2. Retrospectiva da Sprint + +| Pontos Positivos | Pontos Negativos | Sugestão de Melhoria | +| ----- | ----- | ---- | +| Tudo foi entregue | Trabalhos de outros matérias | Nas dailys não presenciais, tentar responder o mais cedo possível | +| A troca de conhecimento está funcionando. | A história de marcar consulta foi cansativa, mas a dupla conseguiu entregar | Tentar criar um horário de trabalho | +| As pontuações de histórias foram coerentes | Membro sem notebook temporariamente | - | +| O time de MDS está cada vez mais nivelado | - | - | + + +## 3. Quadro de Conhecimento + +![Quadro de conhecimento da Sprint 8](https://uploaddeimagens.com.br/images/001/409/436/full/quadro_conhecimento_S8.png?1525874883) + +## 5. Gráfico do Burndown + +![Gráfico do burndown da Sprint 8](https://uploaddeimagens.com.br/images/001/403/383/full/burndown_S8.png?1525482311) + +## 6. Velocity + +![Gráfico do velocity da Sprint 8](https://uploaddeimagens.com.br/images/001/403/385/full/velocity_S8.png?1525482341) + +## 7. Gráfico de Commits + +![Gráfico de commits da Sprint 8](https://uploaddeimagens.com.br/images/001/403/387/full/commits_S8.png?1525482367) + +## 8. EVM + +![Gráfico da EVM da Sprint 8](https://uploaddeimagens.com.br/images/001/403/395/full/evm_S8.png?1525482754) + +## 9. Análise do Scrum Master + +Nesta sprint, continuamos mantendo nossas entregas, com apenas uma dívida técnica. Apesar da semana complicada por causa de outras matérias, os membros de MDS mantiveram as entregas deles dentro do prazo. + +Como os membros de MDS adiantaram que a semana da Sprint 10 será complicada (mais do que foi a dessa sprint), teremos que nos planejar para que essa sprint tenha histórias menos complexas. Por isso, provavelmente para a próxima semana adiantaremos histórias que consideramos mais complexas e que possam já serem feitas. + +Quanto ao problema de um dos membros do grupo não ter um laptop temporariamente, isso já está sendo resolvido, já que ele comprou outro que deverá chegar na próxima semana. + +Por fim, a questão da história cansativa foi algo que nós todos não tínhamos previsto de antemão. Mas em outras sprints aproveitaremos a experiência adquirida nessa para evitar esse tipo de questão tomando providências como, por exemplo, quebrando a história em mais de uma. diff --git a/drdown/appointments/__init__.py b/drdown/appointments/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/drdown/appointments/admin.py b/drdown/appointments/admin.py new file mode 100644 index 00000000..d73342a1 --- /dev/null +++ b/drdown/appointments/admin.py @@ -0,0 +1,7 @@ +from django.contrib import admin +from .models.model_appointment import Appointment +from .models.model_request import AppointmentRequest + +# Register your models here. +admin.site.register(Appointment) +admin.site.register(AppointmentRequest) diff --git a/drdown/appointments/apps.py b/drdown/appointments/apps.py new file mode 100644 index 00000000..bfcf1faf --- /dev/null +++ b/drdown/appointments/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class AppointmentsConfig(AppConfig): + name = 'drdown.appointments' + verbose_name = 'Appointments' diff --git a/drdown/appointments/forms/appointments_form.py b/drdown/appointments/forms/appointments_form.py new file mode 100644 index 00000000..d7607cc5 --- /dev/null +++ b/drdown/appointments/forms/appointments_form.py @@ -0,0 +1,35 @@ +from drdown.appointments.models.model_appointment import Appointment +from django import forms +from drdown.users.models.model_health_team import HealthTeam +from drdown.users.models.model_patient import Patient +from django.utils.translation import ugettext_lazy as _ + + +class AppointmentSearchForm(forms.Form): + search_speciality = forms.CharField( + required=False, + label=_('Speciality'), + widget=forms.TextInput( + attrs={'placeholder': _('Speciality')} + ) + ) + + search_date = forms.DateField( + required=False, + label=_('Date'), + widget=forms.TextInput( + attrs={'placeholder': _('(Year)-(Month)-(Day)')} + ) + ) + + search_doctor = forms.ModelChoiceField( + queryset=HealthTeam.objects.all(), + required=False, + label=_('Doctor') + ) + + search_patient = forms.ModelChoiceField( + queryset=Patient.objects.all(), + required=False, + label=_('Patient') + ) diff --git a/drdown/appointments/forms/requests_form.py b/drdown/appointments/forms/requests_form.py new file mode 100644 index 00000000..b018c41e --- /dev/null +++ b/drdown/appointments/forms/requests_form.py @@ -0,0 +1,34 @@ +from django import forms +from drdown.users.models.model_health_team import HealthTeam +from drdown.users.models.model_patient import Patient +from django.utils.translation import ugettext_lazy as _ + + +class RequestSearchForm(forms.Form): + search_speciality = forms.CharField( + required=False, + label=_('Speciality'), + widget=forms.TextInput( + attrs={'placeholder': _('Speciality')} + ) + ) + + search_status = forms.CharField( + required=False, + label=_('Status'), + widget=forms.TextInput( + attrs={'placeholder': _('Status')} + ) + ) + + search_doctor = forms.ModelChoiceField( + queryset=HealthTeam.objects.all(), + required=False, + label=_('Doctor') + ) + + search_patient = forms.ModelChoiceField( + queryset=Patient.objects.all(), + required=False, + label=_('Patient') + ) diff --git a/drdown/appointments/locale/pt_BR/LC_MESSAGES/django.po b/drdown/appointments/locale/pt_BR/LC_MESSAGES/django.po new file mode 100644 index 00000000..99fc1801 --- /dev/null +++ b/drdown/appointments/locale/pt_BR/LC_MESSAGES/django.po @@ -0,0 +1,478 @@ +# 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: 2018-05-10 03:16+0000\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" + +#: drdown/appointments/forms/appointments_form.py:11 +#: drdown/appointments/forms/appointments_form.py:13 +#: drdown/appointments/forms/requests_form.py:10 +#: drdown/appointments/forms/requests_form.py:12 +#: drdown/appointments/models/model_appointment.py:40 +#: drdown/appointments/models/model_request.py:82 +#: drdown/appointments/templates/appointments/appointment_form.html:24 +#: drdown/appointments/templates/appointments/appointment_request_form.html:14 +msgid "Speciality" +msgstr "Especialidade" + +#: drdown/appointments/forms/appointments_form.py:19 +#: drdown/appointments/models/model_appointment.py:10 +#: drdown/appointments/templates/appointments/appointment_form.html:86 +#: drdown/appointments/templates/appointments/appointment_list.html:48 +#: drdown/appointments/templates/appointments/appointment_request_form.html:77 +msgid "Date" +msgstr "Data" + +#: drdown/appointments/forms/appointments_form.py:21 +msgid "(Year)-(Month)-(Day)" +msgstr "(Ano)-(Mês)-(Dia)" + +#: drdown/appointments/forms/appointments_form.py:28 +#: drdown/appointments/forms/requests_form.py:27 +#: drdown/appointments/models/model_appointment.py:49 +#: drdown/appointments/models/model_request.py:91 +#: drdown/appointments/templates/appointments/appointment_form.html:49 +#: drdown/appointments/templates/appointments/appointment_list.html:46 +#: drdown/appointments/templates/appointments/appointment_request_form.html:39 +#: drdown/appointments/templates/appointments/request_list.html:32 +msgid "Doctor" +msgstr "Médico" + +#: drdown/appointments/forms/appointments_form.py:34 +#: drdown/appointments/forms/requests_form.py:33 +#: drdown/appointments/models/model_appointment.py:56 +#: drdown/appointments/models/model_request.py:99 +#: drdown/appointments/templates/appointments/appointment_form.html:68 +#: drdown/appointments/templates/appointments/appointment_list.html:45 +#: drdown/appointments/templates/appointments/appointment_request_form.html:58 +#: drdown/appointments/templates/appointments/request_list.html:31 +msgid "Patient" +msgstr "Paciente" + +#: drdown/appointments/forms/requests_form.py:18 +#: drdown/appointments/forms/requests_form.py:20 +#: drdown/appointments/models/model_appointment.py:69 +#: drdown/appointments/models/model_request.py:113 +#: drdown/appointments/templates/appointments/appointment_list.html:51 +#: drdown/appointments/templates/appointments/appointment_list.html:53 +#: drdown/appointments/templates/appointments/appointment_list.html:55 +#: drdown/appointments/templates/appointments/request_list.html:39 +msgid "Status" +msgstr "Status" + +#: drdown/appointments/models/model_appointment.py:11 +msgid "Date of appointment" +msgstr "Dia da consulta" + +#: drdown/appointments/models/model_appointment.py:16 +#: drdown/appointments/templates/appointments/appointment_form.html:98 +#: drdown/appointments/templates/appointments/appointment_list.html:49 +#: drdown/appointments/templates/appointments/appointment_request_form.html:88 +msgid "Time" +msgstr "Horário" + +#: drdown/appointments/models/model_appointment.py:17 +msgid "Time of appointment" +msgstr "Hora da consulta" + +#: drdown/appointments/models/model_appointment.py:30 +#: drdown/appointments/models/model_request.py:72 +#: drdown/appointments/templates/appointments/appointment_form.html:28 +#: drdown/appointments/templates/appointments/appointment_form.html:37 +#: drdown/appointments/templates/appointments/appointment_request_form.html:18 +#: drdown/appointments/templates/appointments/appointment_request_form.html:27 +msgid "Speech Therapy" +msgstr "Fonoaudiologia" + +#: drdown/appointments/models/model_appointment.py:31 +#: drdown/appointments/models/model_request.py:73 +#: drdown/appointments/templates/appointments/appointment_form.html:29 +#: drdown/appointments/templates/appointments/appointment_form.html:38 +#: drdown/appointments/templates/appointments/appointment_request_form.html:19 +#: drdown/appointments/templates/appointments/appointment_request_form.html:28 +msgid "Psychology" +msgstr "Psicologia" + +#: drdown/appointments/models/model_appointment.py:32 +#: drdown/appointments/models/model_request.py:74 +#: drdown/appointments/templates/appointments/appointment_form.html:30 +#: drdown/appointments/templates/appointments/appointment_form.html:39 +#: drdown/appointments/templates/appointments/appointment_request_form.html:20 +#: drdown/appointments/templates/appointments/appointment_request_form.html:29 +msgid "Physiotherapy" +msgstr "Fisioterapia" + +#: drdown/appointments/models/model_appointment.py:33 +#: drdown/appointments/models/model_request.py:75 +#: drdown/appointments/templates/appointments/appointment_form.html:31 +#: drdown/appointments/templates/appointments/appointment_form.html:40 +#: drdown/appointments/templates/appointments/appointment_request_form.html:21 +#: drdown/appointments/templates/appointments/appointment_request_form.html:30 +msgid "Occupational Therapy" +msgstr "Terapia Ocupacional" + +#: drdown/appointments/models/model_appointment.py:34 +#: drdown/appointments/models/model_request.py:76 +#: drdown/appointments/templates/appointments/appointment_form.html:32 +#: drdown/appointments/templates/appointments/appointment_form.html:41 +#: drdown/appointments/templates/appointments/appointment_request_form.html:22 +#: drdown/appointments/templates/appointments/appointment_request_form.html:31 +msgid "Cardiology" +msgstr "Cardiologia" + +#: drdown/appointments/models/model_appointment.py:35 +#: drdown/appointments/models/model_request.py:77 +#: drdown/appointments/templates/appointments/appointment_form.html:33 +#: drdown/appointments/templates/appointments/appointment_form.html:42 +#: drdown/appointments/templates/appointments/appointment_request_form.html:23 +#: drdown/appointments/templates/appointments/appointment_request_form.html:32 +msgid "Neurology" +msgstr "Neurologia" + +#: drdown/appointments/models/model_appointment.py:36 +#: drdown/appointments/models/model_request.py:78 +#: drdown/appointments/templates/appointments/appointment_form.html:34 +#: drdown/appointments/templates/appointments/appointment_form.html:43 +#: drdown/appointments/templates/appointments/appointment_request_form.html:24 +#: drdown/appointments/templates/appointments/appointment_request_form.html:33 +msgid "Pediatrics" +msgstr "Pediatria" + +#: drdown/appointments/models/model_appointment.py:42 +#: drdown/appointments/models/model_request.py:84 +msgid "Speciality of appointment" +msgstr "Especialidade da consulta" + +#: drdown/appointments/models/model_appointment.py:64 +#: drdown/appointments/models/model_request.py:108 +msgid "Scheduled" +msgstr "Marcado" + +#: drdown/appointments/models/model_appointment.py:65 +msgid "Canceled" +msgstr "Cancelado" + +#: drdown/appointments/models/model_appointment.py:71 +msgid "Is this appointment still scheduled?" +msgstr "Esta consulta ainda está marcada?" + +#: drdown/appointments/models/model_appointment.py:78 +#: drdown/appointments/tests/test_model_appointment.py:125 +msgid "Appointment of " +msgstr "Consulta de " + +#: drdown/appointments/models/model_appointment.py:81 +msgid "Appointment" +msgstr "Consulta" + +#: drdown/appointments/models/model_appointment.py:82 +#: drdown/appointments/templates/appointments/appointment_confirm_cancel.html:3 +#: drdown/appointments/templates/appointments/appointment_list.html:9 +#: drdown/appointments/templates/appointments/appointment_list.html:19 +#: drdown/appointments/templates/appointments/request_confirm_cancel.html:3 +msgid "Appointments" +msgstr "Consultas" + +#: drdown/appointments/models/model_request.py:13 +msgid "Morning" +msgstr "Manhã" + +#: drdown/appointments/models/model_request.py:14 +msgid "Afternoon" +msgstr "Tarde" + +#: drdown/appointments/models/model_request.py:18 +#: drdown/appointments/templates/appointments/request_list.html:34 +msgid "Shift" +msgstr "Turno" + +#: drdown/appointments/models/model_request.py:20 +msgid "Shift of appointment" +msgstr "Turno da consulta" + +#: drdown/appointments/models/model_request.py:33 +msgid "Sunday" +msgstr "Domingo" + +#: drdown/appointments/models/model_request.py:34 +msgid "Monday" +msgstr "Segunda-feira" + +#: drdown/appointments/models/model_request.py:35 +msgid "Tuesday" +msgstr "Terça-feira" + +#: drdown/appointments/models/model_request.py:36 +msgid "Wednesday" +msgstr "Quarta-feira" + +#: drdown/appointments/models/model_request.py:37 +msgid "Thursday" +msgstr "Quinta-feira" + +#: drdown/appointments/models/model_request.py:38 +msgid "Friday" +msgstr "Sexta-feira" + +#: drdown/appointments/models/model_request.py:39 +msgid "Saturday" +msgstr "Sábado" + +#: drdown/appointments/models/model_request.py:43 +#: drdown/appointments/models/model_request.py:45 +#: drdown/appointments/templates/appointments/request_list.html:35 +msgid "Day of the week" +msgstr "Dia da semana" + +#: drdown/appointments/models/model_request.py:50 +#: drdown/appointments/templates/appointments/request_list.html:37 +msgid "Motive" +msgstr "Motivo" + +#: drdown/appointments/models/model_request.py:51 +msgid "Why are you requesting an appointment?" +msgstr "Porquê você está marcando esta consulta?" + +#: drdown/appointments/models/model_request.py:57 +#: drdown/appointments/templates/appointments/request_confirm_cancel.html:12 +#: drdown/appointments/templates/appointments/request_list.html:41 +msgid "Observation" +msgstr "Observação" + +#: drdown/appointments/models/model_request.py:58 +msgid "Why was it scheduled/declined?" +msgstr "Por que foi agendado/recusado?" + +#: drdown/appointments/models/model_request.py:109 +msgid "Declined" +msgstr "Recusado" + +#: drdown/appointments/models/model_request.py:114 +msgid "Was the request accepted?" +msgstr "O pedido foi aceito?" + +#: drdown/appointments/models/model_request.py:122 +#: drdown/appointments/tests/test_model_request.py:131 +msgid "Appointment request of " +msgstr "Pedido de consulta de" + +#: drdown/appointments/models/model_request.py:125 +msgid "Request" +msgstr "Pedido" + +#: drdown/appointments/models/model_request.py:126 +#: drdown/appointments/templates/appointments/appointment_list.html:15 +#: drdown/appointments/templates/appointments/appointment_list.html:17 +#: drdown/appointments/templates/appointments/request_list.html:9 +#: drdown/appointments/templates/appointments/request_list.html:16 +msgid "Requests" +msgstr "Pedidos" + +#: drdown/appointments/templates/appointments/appointment_confirm_cancel.html:6 +#: drdown/appointments/templates/appointments/request_confirm_cancel.html:6 +msgid "Cancel Appointment" +msgstr "Cancelar Consulta" + +#: drdown/appointments/templates/appointments/appointment_confirm_cancel.html:10 +msgid "Are you sure you want to cancel this appointment?" +msgstr "Tem certeza que deseja cancelar esta consulta?" + +#: drdown/appointments/templates/appointments/appointment_confirm_cancel.html:11 +#: drdown/appointments/templates/appointments/request_after_result_confirm_delete.html:16 +#: drdown/appointments/templates/appointments/request_confirm_cancel.html:15 +msgid "Yes" +msgstr "Sim" + +#: drdown/appointments/templates/appointments/appointment_confirm_cancel.html:12 +#: drdown/appointments/templates/appointments/request_after_result_confirm_delete.html:17 +#: drdown/appointments/templates/appointments/request_confirm_cancel.html:16 +msgid "No" +msgstr "Não" + +#: drdown/appointments/templates/appointments/appointment_form.html:7 +#: drdown/appointments/templates/appointments/appointment_form.html:17 +#: drdown/appointments/templates/appointments/appointment_list.html:14 +#: drdown/appointments/templates/appointments/appointment_request_form.html:5 +#: drdown/appointments/templates/appointments/appointment_request_form.html:10 +msgid "New Appointment" +msgstr "Nova Consulta" + +#: drdown/appointments/templates/appointments/appointment_form.html:9 +#: drdown/appointments/templates/appointments/appointment_form.html:19 +msgid "Edit Appointment" +msgstr "Editar Consulta" + +#: drdown/appointments/templates/appointments/appointment_form.html:107 +#: drdown/appointments/templates/appointments/appointment_request_form.html:96 +msgid "Schedule" +msgstr "Marcar" + +#: drdown/appointments/templates/appointments/appointment_list.html:26 +msgid "Search" +msgstr "Pesquisar" + +#: drdown/appointments/templates/appointments/appointment_list.html:41 +#: drdown/appointments/templates/appointments/request_confirm_delete.html:14 +msgid "Cancel" +msgstr "Cancelar" + +#: drdown/appointments/templates/appointments/appointment_list.html:42 +#: drdown/appointments/templates/appointments/request_list.html:23 +msgid "Edit" +msgstr "Editar" + +#: drdown/appointments/templates/appointments/appointment_list.html:47 +#: drdown/appointments/templates/appointments/request_list.html:33 +msgid "Especiality" +msgstr "Especialidade" + +#: drdown/appointments/templates/appointments/appointment_list.html:55 +msgid "Done" +msgstr "Concluído" + +#: drdown/appointments/templates/appointments/appointment_list.html:60 +msgid "There are no appointments scheduled" +msgstr "Não há consultas marcadas" + +#: drdown/appointments/templates/appointments/appointment_list.html:66 +msgid "Search All" +msgstr "Pesquisar tudo" + +#: drdown/appointments/templates/appointments/appointment_request_form.html:78 +msgid "Requested day of the week" +msgstr "Dia solicitado da semana" + +#: drdown/appointments/templates/appointments/appointment_request_form.html:89 +msgid "Requested shift" +msgstr "Turno solicitado" + +#: drdown/appointments/templates/appointments/request_after_result_confirm_delete.html:5 +#: drdown/appointments/templates/appointments/request_confirm_delete.html:5 +msgid "Delete Request" +msgstr "Apagar pedido" + +#: drdown/appointments/templates/appointments/request_after_result_confirm_delete.html:8 +msgid "Confirm" +msgstr "Confirmar" + +#: drdown/appointments/templates/appointments/request_after_result_confirm_delete.html:13 +msgid "Your request was" +msgstr "Seu pedido foi" + +#: drdown/appointments/templates/appointments/request_after_result_confirm_delete.html:13 +msgid "Are you aware" +msgstr "Você está ciente" + +#: drdown/appointments/templates/appointments/request_after_result_confirm_delete.html:14 +msgid "This request will be deleted" +msgstr "Este pedido será deletado" + +#: drdown/appointments/templates/appointments/request_confirm_cancel.html:10 +msgid "Are you sure you want to cancel this request?" +msgstr "Tem certeza que deseja cancelar esta consulta?" + +#: drdown/appointments/templates/appointments/request_confirm_delete.html:8 +#: drdown/appointments/templates/appointments/request_confirm_delete.html:13 +#: drdown/appointments/templates/appointments/request_list.html:22 +msgid "Delete" +msgstr "Excluir" + +#: drdown/appointments/templates/appointments/request_confirm_delete.html:12 +msgid "Are you sure you want to delete this request?" +msgstr "Tem certeza que deseja cancelar esta consulta?" + +#: drdown/appointments/templates/appointments/request_form.html:7 +#: drdown/appointments/templates/appointments/request_form.html:18 +#: drdown/appointments/templates/appointments/request_list.html:14 +msgid "New Request" +msgstr "Novo pedido" + +#: drdown/appointments/templates/appointments/request_form.html:9 +#: drdown/appointments/templates/appointments/request_form.html:20 +msgid "Edit Request" +msgstr "Editar pedido" + +#: drdown/appointments/templates/appointments/request_form.html:35 +msgid "Submit" +msgstr "Enviar" + +#: drdown/appointments/templates/appointments/request_list.html:25 +msgid "OK" +msgstr "OK" + +#: drdown/appointments/templates/appointments/request_list.html:28 +msgid "Accept" +msgstr "Aceitar" + +#: drdown/appointments/templates/appointments/request_list.html:29 +msgid "Decline" +msgstr "Recusar" + +#: drdown/appointments/templates/appointments/request_list.html:46 +msgid "There are no requests" +msgstr "Não há pedidos" + +#: drdown/appointments/views/view_appointment.py:45 +msgid "January" +msgstr "Janeiro" + +#: drdown/appointments/views/view_appointment.py:46 +msgid "February" +msgstr "Fevereiro" + +#: drdown/appointments/views/view_appointment.py:47 +msgid "March" +msgstr "Março" + +#: drdown/appointments/views/view_appointment.py:48 +msgid "April" +msgstr "Abril" + +#: drdown/appointments/views/view_appointment.py:49 +msgid "May" +msgstr "Maio" + +#: drdown/appointments/views/view_appointment.py:50 +msgid "June" +msgstr "Junho" + +#: drdown/appointments/views/view_appointment.py:51 +msgid "July" +msgstr "Julho" + +#: drdown/appointments/views/view_appointment.py:52 +msgid "August" +msgstr "Agosto" + +#: drdown/appointments/views/view_appointment.py:53 +msgid "September" +msgstr "Setembro" + +#: drdown/appointments/views/view_appointment.py:54 +msgid "October" +msgstr "Outubro" + +#: drdown/appointments/views/view_appointment.py:55 +msgid "November" +msgstr "Novembro" + +#: drdown/appointments/views/view_appointment.py:56 +msgid "December" +msgstr "Dezembro" + +#~ msgid "Nursing" +#~ msgstr "Enfermaria" diff --git a/drdown/appointments/migrations/0001_initial.py b/drdown/appointments/migrations/0001_initial.py new file mode 100644 index 00000000..c767675a --- /dev/null +++ b/drdown/appointments/migrations/0001_initial.py @@ -0,0 +1,50 @@ +# Generated by Django 2.0.3 on 2018-05-10 11:41 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('users', '0016_auto_20180506_2043'), + ] + + operations = [ + migrations.CreateModel( + name='Appointment', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('date', models.DateField(help_text='Date of appointment', max_length=50, verbose_name='Date')), + ('time', models.TimeField(help_text='Time of appointment', max_length=50, verbose_name='Time')), + ('speciality', models.CharField(choices=[('Speech Therapy', 'Speech Therapy'), ('Psychology', 'Psychology'), ('Physiotherapy', 'Physiotherapy'), ('Occupational Therapy', 'Occupational Therapy'), ('Cardiology', 'Cardiology'), ('Neurology', 'Neurology'), ('Pediatrics', 'Pediatrics')], help_text='Speciality of appointment', max_length=30, verbose_name='Speciality')), + ('status', models.CharField(choices=[('Scheduled', 'Scheduled'), ('Canceled', 'Canceled')], default='Scheduled', editable=False, help_text='Is this appointment still scheduled?', max_length=20, verbose_name='Status')), + ('doctor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='appointments', to='users.HealthTeam', verbose_name='Doctor')), + ('patient', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='appointments', to='users.Patient', verbose_name='Patient')), + ], + options={ + 'verbose_name': 'Appointment', + 'verbose_name_plural': 'Appointments', + }, + ), + migrations.CreateModel( + name='AppointmentRequest', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('shift', models.CharField(choices=[('M', 'Morning'), ('A', 'Afternoon')], help_text='Shift of appointment', max_length=10, verbose_name='Shift')), + ('day', models.CharField(choices=[('Sunday', 'Sunday'), ('Monday', 'Monday'), ('Tuesday', 'Tuesday'), ('Wednesday', 'Wednesday'), ('Thursday', 'Thursday'), ('Friday', 'Friday'), ('Saturday', 'Saturday')], help_text='Day of the week', max_length=10, verbose_name='Day of the week')), + ('motive', models.TextField(blank=True, help_text='Why are you requesting an appointment?', max_length=500, verbose_name='Motive')), + ('observation', models.TextField(blank=True, help_text='Why was it scheduled/declined?', max_length=500, verbose_name='Observation')), + ('speciality', models.CharField(choices=[('Speech Therapy', 'Speech Therapy'), ('Psychology', 'Psychology'), ('Physiotherapy', 'Physiotherapy'), ('Occupational Therapy', 'Occupational Therapy'), ('Cardiology', 'Cardiology'), ('Neurology', 'Neurology'), ('Pediatrics', 'Pediatrics')], help_text='Speciality of appointment', max_length=30, verbose_name='Speciality')), + ('status', models.CharField(choices=[('Scheduled', 'Scheduled'), ('Declined', 'Declined')], default='Pending', editable=False, help_text='Was the request accepted?', max_length=20, verbose_name='Status')), + ('doctor', models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, related_name='requests', to='users.HealthTeam', verbose_name='Doctor')), + ('patient', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='requests', to='users.Patient', verbose_name='Patient')), + ], + options={ + 'verbose_name': 'Request', + 'verbose_name_plural': 'Requests', + }, + ), + ] diff --git a/drdown/appointments/migrations/__init__.py b/drdown/appointments/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/drdown/appointments/models/__init__.py b/drdown/appointments/models/__init__.py new file mode 100644 index 00000000..b6df070f --- /dev/null +++ b/drdown/appointments/models/__init__.py @@ -0,0 +1,2 @@ +from .model_appointment import Appointment +from .model_request import AppointmentRequest diff --git a/drdown/appointments/models/model_appointment.py b/drdown/appointments/models/model_appointment.py new file mode 100644 index 00000000..e485d59e --- /dev/null +++ b/drdown/appointments/models/model_appointment.py @@ -0,0 +1,82 @@ +from django.db import models +from drdown.users.models.model_health_team import HealthTeam +from drdown.users.models.model_patient import Patient +from django.utils.translation import ugettext_lazy as _ + + +class Appointment(models.Model): + + date = models.DateField( + _('Date'), + help_text=_('Date of appointment'), + max_length=50 + ) + + time = models.TimeField( + _('Time'), + help_text=_('Time of appointment'), + max_length=50 + ) + + SPEECH_THERAPHY = "Speech Therapy" + PSYCHOLOGY = "Psychology" + PHYSIOTHERAPY = "Physiotherapy" + OCCUPATIONAL_THERAPY = "Occupational Therapy" + CARDIOLOGY = "Cardiology" + NEUROLOGY = "Neurology" + PEDIATRICS = "Pediatrics" + + SPECIALITY_APPOINTMENT_CHOICES = ( + (SPEECH_THERAPHY, _('Speech Therapy')), + (PSYCHOLOGY, _('Psychology')), + (PHYSIOTHERAPY, _('Physiotherapy')), + (OCCUPATIONAL_THERAPY, _('Occupational Therapy')), + (CARDIOLOGY, _('Cardiology')), + (NEUROLOGY, _('Neurology')), + (PEDIATRICS, _('Pediatrics')), + ) + + speciality = models.CharField( + _('Speciality'), + choices=SPECIALITY_APPOINTMENT_CHOICES, + help_text=_("Speciality of appointment"), + max_length=30 + ) + + doctor = models.ForeignKey( + HealthTeam, + on_delete=models.CASCADE, + verbose_name=_('Doctor'), + related_name='appointments', + ) + + patient = models.ForeignKey( + Patient, + on_delete=models.CASCADE, + verbose_name=_('Patient'), + related_name='appointments', + ) + + SCHEDULED = 'Scheduled' + CANCELED = 'Canceled' + + STATUS_CHOICES = ( + (SCHEDULED, _('Scheduled')), + (CANCELED, _('Canceled')), + ) + + status = models.CharField( + _('Status'), + choices=STATUS_CHOICES, + help_text=_("Is this appointment still scheduled?"), + default=SCHEDULED, + max_length=20, + editable=False, + ) + + def __str__(self): + return _('Appointment of ') + self.patient.user.name + + class Meta: + verbose_name = _("Appointment") + verbose_name_plural = _("Appointments") diff --git a/drdown/appointments/models/model_request.py b/drdown/appointments/models/model_request.py new file mode 100644 index 00000000..243c560a --- /dev/null +++ b/drdown/appointments/models/model_request.py @@ -0,0 +1,126 @@ +from django.db import models +from drdown.users.models.model_health_team import HealthTeam +from drdown.users.models.model_patient import Patient +from django.utils.translation import ugettext_lazy as _ + + +class AppointmentRequest(models.Model): + + MORNING = 'M' + AFTERNOON = 'A' + + SHIFT_CHOICES = ( + (MORNING, _('Morning')), + (AFTERNOON, _('Afternoon')), + ) + + shift = models.CharField( + _('Shift'), + choices=SHIFT_CHOICES, + help_text=_('Shift of appointment'), + max_length=10 + ) + + SUNDAY = 'Sunday' + MONDAY = 'Monday' + TUESDAY = 'Tuesday' + WEDNESDAY = 'Wednesday' + THURSDAY = 'Thursday' + FRIDAY = 'Friday' + SATURDAY = 'Saturday' + + DAYS_CHOICES = ( + (SUNDAY, _('Sunday')), + (MONDAY, _('Monday')), + (TUESDAY, _('Tuesday')), + (WEDNESDAY, _('Wednesday')), + (THURSDAY, _('Thursday')), + (FRIDAY, _('Friday')), + (SATURDAY, _('Saturday')), + ) + + day = models.CharField( + _('Day of the week'), + choices=DAYS_CHOICES, + help_text=_('Day of the week'), + max_length=10 + ) + + motive = models.TextField( + _('Motive'), + help_text=_('Why are you requesting an appointment?'), + max_length=500, + blank=True, + ) + + observation = models.TextField( + _('Observation'), + help_text=_('Why was it scheduled/declined?'), + max_length=500, + blank=True, + ) + + SPEECH_THERAPHY = "Speech Therapy" + PSYCHOLOGY = "Psychology" + PHYSIOTHERAPY = "Physiotherapy" + OCCUPATIONAL_THERAPY = "Occupational Therapy" + CARDIOLOGY = "Cardiology" + NEUROLOGY = "Neurology" + PEDIATRICS = "Pediatrics" + + SPECIALITY_REQUEST_CHOICES = ( + (SPEECH_THERAPHY, _('Speech Therapy')), + (PSYCHOLOGY, _('Psychology')), + (PHYSIOTHERAPY, _('Physiotherapy')), + (OCCUPATIONAL_THERAPY, _('Occupational Therapy')), + (CARDIOLOGY, _('Cardiology')), + (NEUROLOGY, _('Neurology')), + (PEDIATRICS, _('Pediatrics')), + ) + + speciality = models.CharField( + _('Speciality'), + choices=SPECIALITY_REQUEST_CHOICES, + help_text=_("Speciality of appointment"), + max_length=30 + ) + + doctor = models.ForeignKey( + HealthTeam, + on_delete=models.CASCADE, + verbose_name=_('Doctor'), + related_name='requests', + blank=True, + ) + + patient = models.ForeignKey( + Patient, + on_delete=models.CASCADE, + verbose_name=_('Patient'), + related_name='requests', + ) + + SCHEDULED = 'Scheduled' + PENDING = 'Pending' + DECLINED = 'Declined' + + STATUS_CHOICES = ( + (SCHEDULED, _('Scheduled')), + (DECLINED, _('Declined')), + ) + + status = models.CharField( + _('Status'), + help_text=_("Was the request accepted?"), + choices=STATUS_CHOICES, + default=PENDING, + max_length=20, + editable=False, + ) + + def __str__(self): + return _('Appointment request of ') + self.patient.user.name + + class Meta: + verbose_name = _("Request") + verbose_name_plural = _("Requests") diff --git a/drdown/appointments/static/appointments/css/appointment.css b/drdown/appointments/static/appointments/css/appointment.css new file mode 100644 index 00000000..54c92206 --- /dev/null +++ b/drdown/appointments/static/appointments/css/appointment.css @@ -0,0 +1,42 @@ +.panel-heading.collapsed .fa-chevron-down, +.panel-heading .fa-chevron-right { + display: none; +} + +.panel-heading.collapsed .fa-chevron-right, +.panel-heading .fa-chevron-down { + display: inline-block; +} + +i.fa { + cursor: pointer; + margin-right: 5px; +} + +.collapsed ~ .panel-body { + padding: 0; +} + +.h-100{ + height: 100%; +} + +.w-100{ + width: 100%; +} + +.w-82{ + width: 82%; +} + +.w-70{ + width: 70%; +} + +.w-18{ + width: 18%; +} + +.clear-right{ + clear:right; +} diff --git a/drdown/appointments/templates/appointments/appointment_confirm_cancel.html b/drdown/appointments/templates/appointments/appointment_confirm_cancel.html new file mode 100644 index 00000000..1661fe99 --- /dev/null +++ b/drdown/appointments/templates/appointments/appointment_confirm_cancel.html @@ -0,0 +1,16 @@ +{% extends "account/base.html" %} +{% load i18n %} +{% block head_title %}{% trans "Appointments" %}{% endblock %} + +{% block inner %} +

{% trans 'Cancel Appointment' %}

+ +
+ {% csrf_token %} +

{% trans 'Are you sure you want to cancel this appointment?' %}

+ + {% trans 'No' %} +
+ + +{% endblock %} diff --git a/drdown/appointments/templates/appointments/appointment_form.html b/drdown/appointments/templates/appointments/appointment_form.html new file mode 100644 index 00000000..88c5b8d0 --- /dev/null +++ b/drdown/appointments/templates/appointments/appointment_form.html @@ -0,0 +1,112 @@ +{% extends 'core/base.html' %} +{% load static i18n %} + +{% block title %} + {% url 'appointments:create_appointment' as url %} + {% if request.path == url %} + {% trans "New Appointment" %} + {% else %} + {% trans "Edit Appointment" %} + {% endif %} +{% endblock %} + +{% block content %} +
+ {% url 'appointments:create_appointment' as url %} + {% if request.path == url %} +

{% trans "New Appointment" %}

+ {% else %} +

{% trans "Edit Appointment" %}

+ {% endif %} +
+ {% csrf_token %} +
+ + +
+ +
+
+ +
+ +
+
+ +
+ +
+ + {% if object.date %} + + {% else %} + + {% endif %} + +
+ + + +
+ + {% if object.time %} + + {% else %} + + {% endif %} + +
+
+ {% trans 'Cancelar' %} + +
+
+
+{% endblock %} diff --git a/drdown/appointments/templates/appointments/appointment_list.html b/drdown/appointments/templates/appointments/appointment_list.html new file mode 100644 index 00000000..1ab78203 --- /dev/null +++ b/drdown/appointments/templates/appointments/appointment_list.html @@ -0,0 +1,107 @@ +{% extends "core/base.html" %} +{% load static i18n %} + +{% block css %} + {{block.super}} + +{% endblock %} + +{% block title %}{% trans "Appointments" %}{% endblock %} + +{% block content %} +
+ {% if request.user.employee %} + {% trans "New Appointment" %} + {% trans "Requests" %} + {% elif request.user.patient %} + {% trans "Requests" %} + {% endif %} +

{% trans 'Appointments' %}


+ + {% url 'appointments:list_appointments' as url %} + {% if request.path == url %} + + {% endif %} + +
+
+ {% for appointment in appointment_list %} + {% now 'm-d-Y' as today %} + {% now 'H:i' as time %} +
+
+ {% if request.user.employee and appointment.status != canceled %} + {% if appointment.date|date:"m-d-Y" > today %} + {% trans "Cancel" %} + {% trans "Edit" %} + {% elif appointment.date|date:"m-d-Y" == today and appointment.time|time:'H:i' > time %} + {% trans "Cancel" %} + {% trans "Edit" %} + {% endif %} + {% endif %} +
{% trans 'Patient'%}: {{appointment.patient.user.name}}
+ {% trans 'Doctor'%}: {{ appointment.doctor.user.name}}
+ {% trans 'Especiality'%}: {{appointment.get_speciality_display}}
+ {% trans 'Date'%}: {{ appointment.date}}
+ {% trans 'Time'%}: {{ appointment.time}}
+ {% if appointment.date|date:"m-d-Y" > today %} + {% trans 'Status'%}: {{ appointment.get_status_display}}
+ {% elif appointment.date|date:"m-d-Y" == today and appointment.time|time:'H:i' > time %} + {% trans 'Status'%}: {{ appointment.get_status_display}}
+ {% elif appointment.date|date:"m-d-Y" == today and appointment.time|time:'H:i' < time %} + {% trans 'Status'%}: {% trans 'Done' %}
+ {% endif %} +
+
+ {% empty %} +

{% trans 'There are no appointments scheduled'%}

+ {% endfor %} +
+ + +
+ {% include "core/pagination.html" %} +
+ +{% endblock %} diff --git a/drdown/appointments/templates/appointments/appointment_request_form.html b/drdown/appointments/templates/appointments/appointment_request_form.html new file mode 100644 index 00000000..681f3e16 --- /dev/null +++ b/drdown/appointments/templates/appointments/appointment_request_form.html @@ -0,0 +1,97 @@ +{% extends 'core/base.html' %} +{% load static i18n %} + +{% block title %} + {% trans "New Appointment" %} +{% endblock %} + +{% block content %} +
+

{% trans "New Appointment" %}

+
+ {% csrf_token %} +
+ + +
+ +
+
+ +
+ +
+
+ +
+ +
+ + + +
+ + +
+ + + +
+
+ {% trans "Cancel" %} + +
+
+
+{% endblock %} diff --git a/drdown/appointments/templates/appointments/request_after_result_confirm_delete.html b/drdown/appointments/templates/appointments/request_after_result_confirm_delete.html new file mode 100644 index 00000000..c6242ffc --- /dev/null +++ b/drdown/appointments/templates/appointments/request_after_result_confirm_delete.html @@ -0,0 +1,21 @@ +{% extends "account/base.html" %} + +{% load i18n %} + +{% block head_title %}{% trans "Delete Request" %}{% endblock %} + +{% block inner %} +

{% trans "Confirm" %}

+ +
+ {% csrf_token %} +

+ {% trans 'Your request was' %}: {{appointmentrequest.get_status_display}}. {% trans 'Are you aware' %}?
+ {% trans 'This request will be deleted'%}. +

+ + {% trans "No" %} +
+ + +{% endblock %} diff --git a/drdown/appointments/templates/appointments/request_confirm_cancel.html b/drdown/appointments/templates/appointments/request_confirm_cancel.html new file mode 100644 index 00000000..af6fceeb --- /dev/null +++ b/drdown/appointments/templates/appointments/request_confirm_cancel.html @@ -0,0 +1,20 @@ +{% extends "account/base.html" %} +{% load i18n %} +{% block head_title %}{% trans "Appointments" %}{% endblock %} + +{% block inner %} +

{% trans 'Cancel Appointment' %}

+ +
+ {% csrf_token %} +

{% trans 'Are you sure you want to cancel this request?' %}

+
+ + +
+ + {% trans 'No' %} +
+ + +{% endblock %} diff --git a/drdown/appointments/templates/appointments/request_confirm_delete.html b/drdown/appointments/templates/appointments/request_confirm_delete.html new file mode 100644 index 00000000..bee98c0c --- /dev/null +++ b/drdown/appointments/templates/appointments/request_confirm_delete.html @@ -0,0 +1,18 @@ +{% extends "account/base.html" %} + +{% load i18n %} + +{% block head_title %}{% trans "Delete Request" %}{% endblock %} + +{% block inner %} +

{% trans "Delete" %}

+ +
+ {% csrf_token %} +

{% trans 'Are you sure you want to delete this request?' %}

+ + {% trans "Cancel" %} +
+ + +{% endblock %} diff --git a/drdown/appointments/templates/appointments/request_form.html b/drdown/appointments/templates/appointments/request_form.html new file mode 100644 index 00000000..47673d56 --- /dev/null +++ b/drdown/appointments/templates/appointments/request_form.html @@ -0,0 +1,44 @@ +{% extends 'core/base.html' %} +{% load static i18n %} + +{% block title %} + {% url 'appointments:create_request' as url %} + {% if request.path == url %} + {% trans "New Request" %} + {% else %} + {% trans "Edit Request" %} + {% endif %} +{% endblock %} + +{% block content %} +
+ + {% url 'appointments:create_request' as url %} + {% if request.path == url %} +

{% trans "New Request" %}


+ {% else %} +

{% trans "Edit Request" %}


+ {% endif %} + +
+ {% csrf_token %} + {% for field in form %} +
+ {{ field.errors }} +

+ {% if field != form.motive and field != form.doctor %} + * + {% endif %} + {{ field.label_tag }}
+ {{ field }} +

+
+ {% endfor %} +
+ {% trans "Cancel" %} + +
+
+
+ +{% endblock %} diff --git a/drdown/appointments/templates/appointments/request_list.html b/drdown/appointments/templates/appointments/request_list.html new file mode 100644 index 00000000..2b0ff57d --- /dev/null +++ b/drdown/appointments/templates/appointments/request_list.html @@ -0,0 +1,54 @@ +{% extends "core/base.html" %} +{% load static i18n %} + +{% block css %} + {{block.super}} + +{% endblock %} + +{% block title %}{% trans "Requests" %}{% endblock %} + +{% block content %} +
+ {% trans 'Return' %} + {% if request.user.patient and request.user.age >= 13 or request.user.responsible %} + {% trans "New Request" %} + {% endif %} +

{% trans 'Requests' %}


+ {% for appointmentrequest in appointmentrequest_list %} +
+
+ {% if request.user.patient or request.user.responsible %} + {% if appointmentrequest.status != 'Declined' and appointmentrequest.status != 'Scheduled' %} + {% trans "Delete" %} + {% trans "Edit" %} + {% else %} + {% trans "OK" %}! + {% endif %} + {% elif request.user.employee and appointmentrequest.status != 'Declined' and appointmentrequest.status != 'Scheduled' %} + {% trans "Accept" %} + {% trans "Decline" %} + {% endif %} +
{% trans 'Patient'%}: {{appointmentrequest.patient.user.name}}
+ {% trans 'Doctor'%}: {{ appointmentrequest.doctor.user.name}}
+ {% trans 'Especiality'%}: {{appointmentrequest.get_speciality_display}}
+ {% trans 'Shift'%}: {{appointmentrequest.get_shift_display}}
+ {% trans 'Day of the week'%}: {{appointmentrequest.get_day_display}}
+ {% if appointmentrequest.motive %} + {% trans 'Motive'%}: {{appointmentrequest.motive}}
+ {% endif %} + {% trans 'Status'%}: {{appointmentrequest.get_status_display}}
+ {% if appointmentrequest.observation %} + {% trans 'Observation'%}: {{appointmentrequest.observation}}
+ {% endif %} +
+
+ {% empty %} +

{% trans 'There are no requests'%}

+ {% endfor %} +
+ + {% include "core/pagination.html" %} + + +{% endblock %} diff --git a/drdown/appointments/tests/__init__.py b/drdown/appointments/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/drdown/appointments/tests/test_model_appointment.py b/drdown/appointments/tests/test_model_appointment.py new file mode 100644 index 00000000..88b77646 --- /dev/null +++ b/drdown/appointments/tests/test_model_appointment.py @@ -0,0 +1,126 @@ +from test_plus.test import TestCase +from ..models.model_appointment import Appointment +from drdown.users.models.model_health_team import HealthTeam +from drdown.users.models.model_patient import Patient +from django.utils.translation import ugettext_lazy as _ + + +class TestModelAppointment(TestCase): + + def setUp(self): + """ + This method will run before any test case. + """ + + self.user = self.make_user(username='user_1') + self.user2 = self.make_user(username='user_2') + self.patient = Patient.objects.create( + ses="1234567", + user=self.user, + priority=1, + mother_name="Mother", + father_name="Father", + ethnicity=3, + sus_number="12345678911", + civil_registry_of_birth="12345678911", + declaration_of_live_birth="12345678911" + ) + + self.doctor = HealthTeam.objects.create( + cpf="057.641.271-65", + user=self.user2, + speciality=HealthTeam.NEUROLOGY, + council_acronym=HealthTeam.CRM, + register_number="1234567", + registration_state=HealthTeam.DF, + ) + + self.appointment = Appointment.objects.create( + date="2040-08-10", + time="15:45", + speciality=Appointment.SPEECH_THERAPHY, + doctor=self.doctor, + patient=self.patient, + status=Appointment.SCHEDULED + ) + + def test_one_to_one_relation(self): + """ + Test to verify if the relations work + """ + + self.assertIs(self.patient, self.appointment.patient) + self.assertIs(self.doctor, self.appointment.doctor) + + def test_delete_cascade_patient(self): + """ + Verify delete the relation objects + """ + + self.patient.delete() + with self.assertRaises(Appointment.DoesNotExist): + Appointment.objects.get() + + def test_delete_cascade_doctor(self): + """ + Verify delete the relation objects + """ + + self.doctor.delete() + with self.assertRaises(Appointment.DoesNotExist): + Appointment.objects.get() + + def test_save_date_ok(self): + """ + Test to verify if date is correctly passed + """ + + self.assertEquals(self.appointment.date, '2040-08-10') + + def test_save_time_ok(self): + """ + Test to verify if time is correctly passed + """ + + self.assertEquals(self.appointment.time, "15:45") + + def test_save_patient_ok(self): + """ + Test to verify if patient is correctly passed + """ + + self.assertEquals(self.appointment.patient, self.patient) + + def test_save_doctor_ok(self): + """ + Test to verify if doctor is correctly passed + """ + + self.assertEquals(self.appointment.doctor, self.doctor) + + def test_save_status_ok(self): + """ + Test to verify if status is correctly passed + """ + + self.assertEquals(self.appointment.status, Appointment.SCHEDULED) + + def test_save_speciality_ok(self): + """ + Test to verify if speciality is correctly passed + """ + + self.assertEquals( + self.appointment.speciality, + Appointment.SPEECH_THERAPHY + ) + + def test_str_is_equal_to_title(self): + """ + Test if method `__str__` is returning "Appointment of " + """ + self.user.name = 'User' + self.assertEqual( + str(self.appointment), + _('Appointment of ') + self.patient.user.name + ) diff --git a/drdown/appointments/tests/test_model_request.py b/drdown/appointments/tests/test_model_request.py new file mode 100644 index 00000000..7e1e1bfb --- /dev/null +++ b/drdown/appointments/tests/test_model_request.py @@ -0,0 +1,132 @@ +from test_plus.test import TestCase +from ..models.model_request import AppointmentRequest +from drdown.users.models.model_health_team import HealthTeam +from drdown.users.models.model_patient import Patient +from django.utils.translation import ugettext_lazy as _ + + +class TestModelRequest(TestCase): + + def setUp(self): + """ + This method will run before any test case. + """ + + self.user = self.make_user(username='user_1') + self.user2 = self.make_user(username='user_2') + self.patient = Patient.objects.create( + ses="1234567", + user=self.user, + priority=1, + mother_name="Mother", + father_name="Father", + ethnicity=3, + sus_number="12345678911", + civil_registry_of_birth="12345678911", + declaration_of_live_birth="12345678911" + ) + + self.doctor = HealthTeam.objects.create( + cpf="057.641.271-65", + user=self.user2, + speciality=HealthTeam.NEUROLOGY, + council_acronym=HealthTeam.CRM, + register_number="1234567", + registration_state=HealthTeam.DF, + ) + + self.request = AppointmentRequest.objects.create( + motive='Some motive', + observation='Some obs', + speciality=AppointmentRequest.SPEECH_THERAPHY, + doctor=self.doctor, + patient=self.patient, + status=AppointmentRequest.SCHEDULED + ) + + def test_one_to_one_relation(self): + """ + Test to verify if the relations work + """ + + self.assertIs(self.patient, self.request.patient) + self.assertIs(self.doctor, self.request.doctor) + + def test_delete_cascade_patient(self): + """ + Verify delete the relation objects + """ + + self.patient.delete() + with self.assertRaises(AppointmentRequest.DoesNotExist): + AppointmentRequest.objects.get() + + def test_delete_cascade_doctor(self): + """ + Verify delete the relation objects + """ + + self.doctor.delete() + with self.assertRaises(AppointmentRequest.DoesNotExist): + AppointmentRequest.objects.get() + + def test_save_patient_ok(self): + """ + Test to verify if patient is correctly passed + """ + + self.assertEquals(self.request.patient, self.patient) + + def test_save_doctor_ok(self): + """ + Test to verify if doctor is correctly passed + """ + + self.assertEquals(self.request.doctor, self.doctor) + + def test_save_status_ok(self): + """ + Test to verify if status is correctly passed + """ + + self.assertEquals(self.request.status, AppointmentRequest.SCHEDULED) + + def test_save_speciality_ok(self): + """ + Test to verify if speciality is correctly passed + """ + + self.assertEquals( + self.request.speciality, + AppointmentRequest.SPEECH_THERAPHY + ) + + def test_save_motive_ok(self): + """ + Test to verify if motive is correctly passed + """ + + self.assertEquals( + self.request.motive, + 'Some motive' + ) + + def test_save_observation_ok(self): + """ + Test to verify if observation is correctly passed + """ + + self.assertEquals( + self.request.observation, + 'Some obs' + ) + + def test_str_is_equal_to_title(self): + """ + Test if method `__str__` is returning "Request of " + """ + self.user.name = 'User' + self.assertEqual( + str(self.request), + _('Appointment request of ') + self.patient.user.name + ) diff --git a/drdown/appointments/tests/test_view_appointment.py b/drdown/appointments/tests/test_view_appointment.py new file mode 100644 index 00000000..5611295b --- /dev/null +++ b/drdown/appointments/tests/test_view_appointment.py @@ -0,0 +1,287 @@ +from test_plus.test import TestCase +from ..models.model_appointment import Appointment +from ..models.model_request import AppointmentRequest +from drdown.users.models.model_health_team import HealthTeam +from drdown.users.models.model_employee import Employee +from drdown.users.models.model_responsible import Responsible +from drdown.users.models.model_patient import Patient +from django.urls import reverse + + +class TestViewAppointment(TestCase): + + def setUp(self): + """ + This method will run before any test case. + """ + self.user = self.make_user(username='user_1') + self.user2 = self.make_user(username='user_2') + self.user3 = self.make_user(username='user_3') + self.user4 = self.make_user(username='user_4') + self.user5 = self.make_user(username='user_5') + + self.patient = Patient.objects.create( + ses="1234567", + user=self.user, + priority=1, + mother_name="Mother", + father_name="Father", + ethnicity=3, + sus_number="12345678911", + civil_registry_of_birth="12345678911", + declaration_of_live_birth="12345678911" + ) + + self.doctor = HealthTeam.objects.create( + cpf="057.641.271-65", + user=self.user2, + speciality=HealthTeam.NEUROLOGY, + council_acronym=HealthTeam.CRM, + register_number="1234567", + registration_state=HealthTeam.DF, + ) + + self.employee = Employee.objects.create( + cpf="974.220.200-16", + user=self.user3, + departament=Employee.ADMINISTRATION + ) + + self.responsible = Responsible.objects.create( + user=self.user4, + cpf="022.852.870-46", + patient=self.patient + ) + + self.appointment = Appointment.objects.create( + date="2040-08-10", + time="15:45", + speciality=Appointment.SPEECH_THERAPHY, + doctor=self.doctor, + patient=self.patient, + status=Appointment.SCHEDULED + ) + + self.client.force_login(user=self.user) + + def test_appointment_list_view(self): + """ + Makes sure that the appointment list view is loaded correctly + """ + + response = self.client.get( + path=reverse( + viewname='appointments:list_appointments' + ) + ) + self.assertEquals(response.status_code, 200) + + def test_appointment_create_view(self): + """ + Makes sure that the appointment create view is loaded correctly + """ + response = self.client.post( + path=reverse( + viewname='appointments:create_appointment' + ) + ) + self.assertEquals(response.status_code, 200) + + def test_appointment_update_view(self): + """ + Makes sure that the appointment update view is loaded correctly + """ + response = self.client.get( + path=reverse( + viewname='appointments:update_appointment', + args=(self.appointment.pk,) + ) + ) + self.assertEquals(response.status_code, 200) + + def test_post_cancel_view(self): + """ + Makes sure that the appointment update status is loaded correctly + """ + response = self.client.get( + path=reverse( + viewname='appointments:update_status_appointment', + args=(self.appointment.pk,) + ) + ) + self.assertEquals(response.status_code, 200) + + def test_appointment_form_valid_create_view(self): + """ + Test if create form is valid with all required fields + """ + self.client.force_login(user=self.user3) + data = { + 'speciality': Appointment.SPEECH_THERAPHY, + 'doctor': self.doctor.pk, + 'patient': self.patient.pk, + 'date': '2050-05-12', + 'time': '20:00', + } + response = self.client.post( + path=reverse('appointments:create_appointment'), + data=data, + follow=True) + self.assertEquals(response.status_code, 200) + + def test_appointment_form_valid_update_view(self): + """ + Test if update form is valid with all required fields + """ + self.client.force_login(user=self.user) + data = { + 'speciality': Appointment.SPEECH_THERAPHY, + 'doctor': self.doctor.pk, + 'patient': self.patient.pk, + 'date': '2050-05-12', + 'time': '20:00', + } + response = self.client.post( + path=reverse( + viewname='appointments:update_appointment', + args=(self.appointment.pk,) + ), + data=data, + follow=True) + self.assertEquals(response.status_code, 200) + + def test_redirect_delete_ok(self): + """ + Test the page url status code. + """ + + self.client.force_login(user=self.user) + data = { + 'speciality': Appointment.SPEECH_THERAPHY, + 'doctor': self.doctor.pk, + 'patient': self.patient.pk, + 'date': '2050-05-12', + 'time': '20:00', + } + + response = self.client.post( + path=reverse( + viewname='appointments:update_status_appointment', + args=(self.appointment.pk,) + ), + data=data, + follow=True + ) + self.assertEquals(response.status_code, 200) + + def test_list_view_appointments_patient(self): + self.client.force_login(user=self.user) + + response = self.client.get( + path=reverse( + viewname='appointments:archive_month', + args=('2040', '08'), + ) + ) + self.assertEquals(response.status_code, 200) + + def test_list_view_appointments_health_team(self): + self.client.force_login(user=self.user2) + + response = self.client.get( + path=reverse( + viewname='appointments:archive_month', + args=('2040', '08'), + ) + ) + self.assertEquals(response.status_code, 200) + + def test_list_view_appointments_employee(self): + self.client.force_login(user=self.user3) + + response = self.client.get( + path=reverse( + viewname='appointments:archive_month', + args=('2040', '08'), + ) + ) + self.assertEquals(response.status_code, 200) + + def test_list_view_appointments_responsible(self): + self.responsible.save() + self.client.force_login(user=self.user4) + + response = self.client.get( + path=reverse( + viewname='appointments:archive_month', + args=('2040', '08'), + ) + ) + self.assertEquals(response.status_code, 200) + + def test_list_view_appointments(self): + self.responsible.save() + self.client.force_login(user=self.user5) + + response = self.client.get( + path=reverse( + viewname='appointments:archive_month', + args=('2040', '08'), + ) + ) + self.assertEquals(response.status_code, 200) + + def test_appointment_from_request_context_data_create_view(self): + """ + Test if create form is valid with all required fields + """ + request = AppointmentRequest.objects.create( + shift=AppointmentRequest.MORNING, + day=AppointmentRequest.MONDAY, + speciality=AppointmentRequest.SPEECH_THERAPHY, + doctor=self.doctor, + patient=self.patient, + status=AppointmentRequest.PENDING + ) + self.client.force_login(user=self.user3) + response = self.client.get( + path=reverse( + viewname='appointments:create_from_request', + args=(request.pk,), + ), + follow=True + ) + self.assertEquals(response.status_code, 200) + self.assertContains(response, text=request.speciality) + self.assertContains(response, text=request.shift) + self.assertContains(response, text=request.get_day_display()) + + def test_appointment_from_request_form_valid_create_view(self): + """ + Test if create form is valid with all required fields + """ + request = AppointmentRequest.objects.create( + shift=AppointmentRequest.MORNING, + day=AppointmentRequest.MONDAY, + speciality=AppointmentRequest.SPEECH_THERAPHY, + doctor=self.doctor, + patient=self.patient, + status=AppointmentRequest.PENDING + ) + self.client.force_login(user=self.user3) + data = { + 'speciality': Appointment.SPEECH_THERAPHY, + 'doctor': self.doctor.pk, + 'patient': self.patient.pk, + 'date': '2050-05-12', + 'time': '20:00', + } + response = self.client.post( + path=reverse( + viewname='appointments:create_from_request', + args=(request.pk,), + ), + data=data, + follow=True) + self.assertEquals(response.status_code, 200) + diff --git a/drdown/appointments/tests/test_view_request.py b/drdown/appointments/tests/test_view_request.py new file mode 100644 index 00000000..b11d0a36 --- /dev/null +++ b/drdown/appointments/tests/test_view_request.py @@ -0,0 +1,163 @@ +from test_plus.test import TestCase +from ..models.model_appointment import Appointment +from ..models.model_request import AppointmentRequest +from drdown.users.models.model_health_team import HealthTeam +from drdown.users.models.model_employee import Employee +from drdown.users.models.model_responsible import Responsible +from drdown.users.models.model_patient import Patient +from django.urls import reverse + + +class TestViewRequest(TestCase): + + def setUp(self): + """ + This method will run before any test case. + """ + self.user = self.make_user(username='user_1') + self.user2 = self.make_user(username='user_2') + self.user3 = self.make_user(username='user_3') + self.user4 = self.make_user(username='user_4') + self.user5 = self.make_user(username='user_5') + + self.patient = Patient.objects.create( + ses="1234567", + user=self.user, + priority=1, + mother_name="Mother", + father_name="Father", + ethnicity=3, + sus_number="12345678911", + civil_registry_of_birth="12345678911", + declaration_of_live_birth="12345678911" + ) + + self.doctor = HealthTeam.objects.create( + cpf="057.641.271-65", + user=self.user2, + speciality=HealthTeam.NEUROLOGY, + council_acronym=HealthTeam.CRM, + register_number="1234567", + registration_state=HealthTeam.DF, + ) + + self.employee = Employee.objects.create( + cpf="974.220.200-16", + user=self.user3, + departament=Employee.ADMINISTRATION + ) + + self.responsible = Responsible.objects.create( + user=self.user4, + cpf="022.852.870-46", + patient=self.patient + ) + + self.appointment = Appointment.objects.create( + date="2040-08-10", + time="15:45", + speciality=Appointment.SPEECH_THERAPHY, + doctor=self.doctor, + patient=self.patient, + status=Appointment.SCHEDULED + ) + + self.request = AppointmentRequest.objects.create( + shift=AppointmentRequest.MORNING, + day=AppointmentRequest.MONDAY, + speciality=AppointmentRequest.SPEECH_THERAPHY, + doctor=self.doctor, + patient=self.patient, + status=AppointmentRequest.PENDING + ) + + def test_request_list_view_patient(self): + """ + Makes sure that the request list view is loaded correctly + """ + self.client.force_login(user=self.user) + response = self.client.get( + path=reverse( + viewname='appointments:list_requests' + ) + ) + self.assertEquals(response.status_code, 200) + + def test_request_list_view_doctor(self): + """ + Makes sure that the request list view is loaded correctly + """ + self.client.force_login(user=self.user2) + response = self.client.get( + path=reverse( + viewname='appointments:list_requests' + ) + ) + self.assertEquals(response.status_code, 200) + + def test_request_list_view_employee(self): + """ + Makes sure that the request list view is loaded correctly + """ + self.client.force_login(user=self.user3) + response = self.client.get( + path=reverse( + viewname='appointments:list_requests' + ) + ) + self.assertEquals(response.status_code, 200) + + def test_request_list_view_responsible(self): + """ + Makes sure that the request list view is loaded correctly + """ + self.client.force_login(user=self.user4) + response = self.client.get( + path=reverse( + viewname='appointments:list_requests' + ) + ) + self.assertEquals(response.status_code, 200) + + def test_request_create_view(self): + """ + Makes sure that the request create view is loaded correctly + """ + self.client.force_login(user=self.user) + response = self.client.post( + path=reverse( + viewname='appointments:create_request' + ) + ) + self.assertEquals(response.status_code, 200) + + def test_request_update_view(self): + """ + Makes sure that the request update view is loaded correctly + """ + self.client.force_login(user=self.user) + response = self.client.get( + path=reverse( + viewname='appointments:update_request', + args=(self.request.pk,) + ) + ) + self.assertEquals(response.status_code, 200) + + def test_request_update_status_view_form_valid(self): + """ + Test if create form is valid with all required fields + """ + self.client.force_login(user=self.user3) + data = { + 'observation': 'Some motive' + } + response = self.client.post( + path=reverse( + viewname='appointments:update_status_request', + args=(self.request.pk,), + ), + data=data, + follow=True) + self.assertEquals(response.status_code, 200) + diff --git a/drdown/appointments/urls.py b/drdown/appointments/urls.py new file mode 100644 index 00000000..31e50db9 --- /dev/null +++ b/drdown/appointments/urls.py @@ -0,0 +1,82 @@ +from django.conf.urls import url +from drdown.appointments.views.view_appointment import ( + AppointmentListView, + AppointmentCreateView, + AppointmentUpdateView, + AppointmentMonthArchiveView, + AppointmentUpdateStatusView, + AppointmentFromRequestCreateView, +) +from drdown.appointments.views.view_request import ( + RequestListView, + RequestCreateView, + RequestUpdateView, + RequestDeleteView, + RequestUpdateStatusView, + RequestAfterResultDeleteView +) + + +app_name = 'appointments' +urlpatterns = [ + url( + regex=r'^$', + view=AppointmentListView.as_view(), + name='list_appointments' + ), + url( + regex=r'^request/new/$', + view=RequestCreateView.as_view(), + name='create_request' + ), + url( + regex=r'^requests/$', + view=RequestListView.as_view(), + name='list_requests' + ), + url( + regex=r'^request/update/(?P\d+)/$', + view=RequestUpdateView.as_view(), + name='update_request' + ), + url( + regex=r'^request/delete/(?P\d+)/$', + view=RequestDeleteView.as_view(), + name='delete_request' + ), + url( + regex=r'^request/result/delete/(?P\d+)/$', + view=RequestAfterResultDeleteView.as_view(), + name='delete_request_after_result' + ), + url( + regex=r'^new/$', + view=AppointmentCreateView.as_view(), + name='create_appointment' + ), + url( + regex=r'^new/(?P\d+)/$', + view=AppointmentFromRequestCreateView.as_view(), + name='create_from_request' + ), + url( + regex=r'^(?P\d{4})/(?P\d+)/$', + view=AppointmentMonthArchiveView.as_view(month_format='%m'), + name="archive_month" + ), + url( + regex=r'^update/(?P\d+)/$', + view=AppointmentUpdateView.as_view(), + name='update_appointment' + ), + url( + regex=r'^cancel/(?P\d+)/$', + view=AppointmentUpdateStatusView.as_view(), + name='update_status_appointment' + ), + url( + regex=r'^request/cancel/(?P\d+)/$', + view=RequestUpdateStatusView.as_view(), + name='update_status_request' + ), +] diff --git a/drdown/appointments/views/__init__.py b/drdown/appointments/views/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/drdown/appointments/views/view_appointment.py b/drdown/appointments/views/view_appointment.py new file mode 100644 index 00000000..92d5bbda --- /dev/null +++ b/drdown/appointments/views/view_appointment.py @@ -0,0 +1,228 @@ +from django.utils.translation import ugettext_lazy as _ +from django.views.generic import CreateView +from django.views.generic import UpdateView +from django.views.generic.dates import MonthArchiveView +from django.contrib.auth.mixins import LoginRequiredMixin +from django.utils import timezone +from django.urls import reverse, reverse_lazy +from search_views.search import SearchListView +from search_views.filters import BaseFilter +from drdown.appointments.models import Appointment +from drdown.appointments.models import AppointmentRequest +from drdown.users.models.model_health_team import HealthTeam +from drdown.users.models.model_patient import Patient +from ..forms.appointments_form import AppointmentSearchForm + + +class AppointmentFilter(LoginRequiredMixin, BaseFilter): + search_fields = { + 'search_date': ['date'], + 'search_speciality': ['speciality'], + 'search_doctor': ['doctor__id'], + 'search_patient': ['patient__id'], + } + + +class AppointmentListView(LoginRequiredMixin, SearchListView): + model = Appointment + template_name = 'appointments/appointment_list.html' + form_class = AppointmentSearchForm + filter_class = AppointmentFilter + paginate_by = 10 + + @staticmethod + def get_list_of_years(request): + years = [] + for appointment in AppointmentListView.prepare_queryset(request): + if appointment.date.year not in years: + years.append(appointment.date.year) + years.sort(reverse=True) + return years + + @staticmethod + def get_list_of_months(request): + months = [ + _('January'), + _('February'), + _('March'), + _('April'), + _('May'), + _('June'), + _('July'), + _('August'), + _('September'), + _('October'), + _('November'), + _('December'), + ] + + return months + + @staticmethod + def prepare_context(context, request): + context['years'] = AppointmentListView.get_list_of_years(request) + context['months'] = AppointmentListView.get_list_of_months(request) + context['current_year'] = timezone.now().year + context['canceled'] = Appointment.CANCELED + return context + + @staticmethod + def prepare_queryset(request): + user = request.user + if hasattr(user, 'patient'): + queryset = Appointment.objects.filter( + patient=user.patient + ).order_by('-date', '-time') + elif hasattr(user, 'responsible'): + queryset = Appointment.objects.filter( + patient__in=user.responsible.patient_set.all() + ).order_by('-date', '-time') + elif hasattr(user, 'employee'): + queryset = Appointment.objects.all( + ).order_by('-date', '-time') + elif hasattr(user, 'healthteam'): + queryset = Appointment.objects.filter( + doctor=user.healthteam + ).order_by('-date', '-time') + else: + queryset = Appointment.objects.none() + return queryset + + def get_context_data(self, **kwargs): + context = super(AppointmentListView, self).get_context_data(**kwargs) + return self.prepare_context(context, self.request) + + def get_queryset(self): + return self.prepare_queryset(self.request) + + +class AppointmentCreateView(LoginRequiredMixin, CreateView): + model = Appointment + template_name = 'appointments/appointment_form.html' + fields = [ + 'speciality', + 'doctor', + 'patient', + 'date', + 'time', + ] + + def get_success_url(self, **kwargs): + success_create_url = reverse( + viewname='appointments:list_appointments', + ) + + return success_create_url + + def get_context_data(self, **kwargs): + context = super(AppointmentCreateView, self).get_context_data(**kwargs) + + context['health_team'] = HealthTeam.objects.all() + context['patients'] = Patient.objects.all() + return context + + +class AppointmentMonthArchiveView(LoginRequiredMixin, MonthArchiveView): + date_field = "date" + allow_future = True + template_name = 'appointments/appointment_list.html' + allow_empty = True + paginate_by = 10 + + def get_context_data(self, **kwargs): + context = super(AppointmentMonthArchiveView, + self).get_context_data(**kwargs) + return AppointmentListView.prepare_context(context, self.request) + + def get_queryset(self): + return AppointmentListView.prepare_queryset(self.request) + + +class AppointmentUpdateView(LoginRequiredMixin, UpdateView): + model = Appointment + template_name = 'appointments/appointment_form.html' + fields = [ + 'speciality', + 'doctor', + 'patient', + 'date', + 'time', + ] + + def get_success_url(self, **kwargs): + success_update_url = reverse( + viewname='appointments:list_appointments', + ) + + return success_update_url + + def get_object(self): + appointment = Appointment.objects.get( + pk=self.kwargs.get('appointment_pk') + ) + return appointment + + def get_context_data(self, **kwargs): + context = super(AppointmentUpdateView, self).get_context_data(**kwargs) + + context['health_team'] = HealthTeam.objects.all() + context['patients'] = Patient.objects.all() + return context + + +class AppointmentUpdateStatusView(LoginRequiredMixin, UpdateView): + model = Appointment + template_name = 'appointments/appointment_confirm_cancel.html' + fields = [] + + def get_success_url(self, **kwargs): + success_update_status_url = reverse( + viewname='appointments:list_appointments', + ) + + return success_update_status_url + + def get_object(self): + appointment = Appointment.objects.get( + pk=self.kwargs.get('appointment_pk') + ) + return appointment + + def form_valid(self, form): + form.instance.status = Appointment.CANCELED + form.save() + return super(AppointmentUpdateStatusView, self).form_valid(form) + + +class AppointmentFromRequestCreateView(LoginRequiredMixin, CreateView): + model = Appointment + template_name = 'appointments/appointment_request_form.html' + fields = [ + 'speciality', + 'doctor', + 'patient', + 'date', + 'time', + ] + success_url = reverse_lazy( + viewname='appointments:list_appointments', + ) + + def get_context_data(self, **kwargs): + context = super( + AppointmentFromRequestCreateView, self).get_context_data(**kwargs) + context['health_team'] = HealthTeam.objects.all() + context['patients'] = Patient.objects.all() + context['appointment_request'] = AppointmentRequest.objects.get( + pk=self.kwargs.get('request_pk') + ) + return context + + def form_valid(self, form): + request = AppointmentRequest.objects.get( + pk=self.kwargs.get('request_pk') + ) + request.status = AppointmentRequest.SCHEDULED + request.save() + form.save() + return super(AppointmentFromRequestCreateView, self).form_valid(form) diff --git a/drdown/appointments/views/view_request.py b/drdown/appointments/views/view_request.py new file mode 100644 index 00000000..8694e34e --- /dev/null +++ b/drdown/appointments/views/view_request.py @@ -0,0 +1,113 @@ +from django.utils.translation import ugettext_lazy as _ +from django.views.generic import CreateView +from django.views.generic import UpdateView +from django.views.generic import DeleteView +from django.contrib.auth.mixins import LoginRequiredMixin +from django.urls import reverse_lazy +from search_views.search import SearchListView +from search_views.filters import BaseFilter +from drdown.appointments.models import AppointmentRequest +from ..forms.requests_form import RequestSearchForm + + +class RequestFilter(LoginRequiredMixin, BaseFilter): + search_fields = { + 'search_speciality': ['speciality'], + 'search_doctor': ['doctor__id'], + 'search_patient': ['patient__id'], + 'search_status': ['status'], + } + + +class RequestListView(LoginRequiredMixin, SearchListView): + model = AppointmentRequest + template_name = 'appointments/request_list.html' + form_class = RequestSearchForm + filter_class = RequestFilter + paginate_by = 10 + + def prepare_queryset(self, request): + user = request.user + if hasattr(user, 'patient'): + queryset = AppointmentRequest.objects.filter( + patient=user.patient + ).order_by('id') + elif hasattr(user, 'responsible'): + queryset = AppointmentRequest.objects.filter( + patient__in=user.responsible.patient_set.all() + ).order_by('id') + elif hasattr(user, 'employee'): + queryset = AppointmentRequest.objects.all( + ).order_by('id') + else: + queryset = AppointmentRequest.objects.none() + return queryset + + def get_queryset(self): + return self.prepare_queryset(self.request) + + +class RequestCreateView(LoginRequiredMixin, CreateView): + model = AppointmentRequest + template_name = 'appointments/request_form.html' + fields = [ + 'speciality', + 'doctor', + 'patient', + 'shift', + 'day', + 'motive', + ] + success_url = reverse_lazy( + viewname='appointments:list_requests', + ) + + +class RequestUpdateView(LoginRequiredMixin, UpdateView): + model = AppointmentRequest + template_name = 'appointments/request_form.html' + fields = [ + 'speciality', + 'doctor', + 'patient', + 'shift', + 'day', + 'motive', + ] + success_url = reverse_lazy( + viewname='appointments:list_requests', + ) + pk_url_kwarg = 'request_pk' + + +class RequestDeleteView(LoginRequiredMixin, DeleteView): + model = AppointmentRequest + template_name = 'appointments/request_confirm_delete.html' + success_url = reverse_lazy( + viewname='appointments:list_requests', + ) + pk_url_kwarg = 'request_pk' + + +class RequestUpdateStatusView(LoginRequiredMixin, UpdateView): + model = AppointmentRequest + template_name = 'appointments/request_confirm_cancel.html' + fields = ['observation'] + success_url = reverse_lazy( + viewname='appointments:list_requests', + ) + pk_url_kwarg = 'request_pk' + + def form_valid(self, form): + form.instance.status = AppointmentRequest.DECLINED + form.save() + return super(RequestUpdateStatusView, self).form_valid(form) + + +class RequestAfterResultDeleteView(LoginRequiredMixin, DeleteView): + model = AppointmentRequest + template_name = 'appointments/request_after_result_confirm_delete.html' + success_url = reverse_lazy( + viewname='appointments:list_requests', + ) + pk_url_kwarg = 'request_pk' diff --git a/drdown/careline/locale/pt_BR/LC_MESSAGES/django.po b/drdown/careline/locale/pt_BR/LC_MESSAGES/django.po index 8cc8bbe2..a0394424 100644 --- a/drdown/careline/locale/pt_BR/LC_MESSAGES/django.po +++ b/drdown/careline/locale/pt_BR/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-04-27 21:38+0000\n" +"POT-Creation-Date: 2018-05-04 10:24+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -92,8 +92,6 @@ msgstr "Pesquisa para Doença Celíaca (anticorpo antigliadina)" #: drdown/careline/templates/careline/checklist_detail.html:5 #: drdown/careline/templates/careline/checklist_detail.html:102 -#: drdown/careline/templates/careline/checklist_list.html:3 -#: drdown/careline/templates/careline/checklist_list.html:7 msgid "Care Line" msgstr "Linha de Cuidado" @@ -101,59 +99,63 @@ msgstr "Linha de Cuidado" msgid "Name: " msgstr "Nome: " -#: drdown/careline/templates/careline/checklist_detail.html:107 -#: drdown/careline/templates/careline/checklist_detail.html:109 -#: drdown/careline/templates/careline/checklist_detail.html:111 +#: drdown/careline/templates/careline/checklist_detail.html:105 +msgid "Vaccine Schedule" +msgstr "Calendário de Vacinas" + +#: drdown/careline/templates/careline/checklist_detail.html:108 +#: drdown/careline/templates/careline/checklist_detail.html:110 +#: drdown/careline/templates/careline/checklist_detail.html:112 msgid "Age: " msgstr "Idade: " -#: drdown/careline/templates/careline/checklist_detail.html:107 -#: drdown/careline/templates/careline/checklist_detail.html:128 +#: drdown/careline/templates/careline/checklist_detail.html:108 +#: drdown/careline/templates/careline/checklist_detail.html:130 msgid "Newborn" msgstr "Recém-Nascido" -#: drdown/careline/templates/careline/checklist_detail.html:109 +#: drdown/careline/templates/careline/checklist_detail.html:110 msgid "Less than 1 year old" msgstr "Menos de 1 ano de idade" -#: drdown/careline/templates/careline/checklist_detail.html:114 +#: drdown/careline/templates/careline/checklist_detail.html:115 #: drdown/careline/templates/careline/checklist_list.html:20 msgid "SES: " msgstr "SES: " -#: drdown/careline/templates/careline/checklist_detail.html:121 +#: drdown/careline/templates/careline/checklist_detail.html:123 msgid "AGE" msgstr "IDADE" -#: drdown/careline/templates/careline/checklist_detail.html:127 +#: drdown/careline/templates/careline/checklist_detail.html:129 msgid "Interventions / Evaluation" msgstr "Intervenções / Avaliação" -#: drdown/careline/templates/careline/checklist_detail.html:130 +#: drdown/careline/templates/careline/checklist_detail.html:132 msgid "Six Months" msgstr "Seis Meses" -#: drdown/careline/templates/careline/checklist_detail.html:133 +#: drdown/careline/templates/careline/checklist_detail.html:135 msgid "One Year" msgstr "Um Ano" -#: drdown/careline/templates/careline/checklist_detail.html:136 +#: drdown/careline/templates/careline/checklist_detail.html:138 msgid "Two Years" msgstr "Dois Anos" -#: drdown/careline/templates/careline/checklist_detail.html:139 +#: drdown/careline/templates/careline/checklist_detail.html:141 msgid "Three Years" msgstr "Três Anos" -#: drdown/careline/templates/careline/checklist_detail.html:142 +#: drdown/careline/templates/careline/checklist_detail.html:144 msgid "Five Years" msgstr "Cinco Anos" -#: drdown/careline/templates/careline/checklist_detail.html:145 +#: drdown/careline/templates/careline/checklist_detail.html:147 msgid "Six to Ten Years" msgstr "Seis a Dez Anos" -#: drdown/careline/templates/careline/checklist_detail.html:345 +#: drdown/careline/templates/careline/checklist_detail.html:347 msgid "" "* Routine as suggested and, if necessary, when initiating physical " "examination or surgical procedure with cervical manipulation." @@ -161,7 +163,7 @@ msgstr "" "* Rotina como sugerido e, se preciso, ao iniciar atividade física ou em " "procedimento cirúrgico com manuseio cervical." -#: drdown/careline/templates/careline/checklist_detail.html:349 +#: drdown/careline/templates/careline/checklist_detail.html:351 msgid "" "** Thyrogram: TSH, free T4. For antithyroid antibodies, routinely request " "between 9 and 12 years or when needed." @@ -169,24 +171,19 @@ msgstr "" "** Tireograma: TSH, T4 livre. Para os anticorpos antitiroidiano, solicitar " "como rotina entre 9 e 12 anos ou quando necessário." -#: drdown/careline/templates/careline/checklist_detail.html:353 +#: drdown/careline/templates/careline/checklist_detail.html:355 msgid "Required" msgstr "Obrigatório" -#: drdown/careline/templates/careline/checklist_detail.html:354 +#: drdown/careline/templates/careline/checklist_detail.html:356 msgid "When Needed" msgstr "Quando Necessário" -#: drdown/careline/templates/careline/checklist_detail.html:355 +#: drdown/careline/templates/careline/checklist_detail.html:357 msgid "Done" msgstr "Feito" -#: drdown/careline/templates/careline/checklist_list.html:25 -msgid "There are no patients for this user." -msgstr "Não há pacientes para este usuário." - -#: drdown/careline/views/view_checklist.py:184 -#| msgid "Error: You cannot change data on this form." +#: drdown/careline/views/view_checklist.py:131 msgid "" "Error: You cannot change data on this form. You need to be at least 13 years " "old." @@ -194,6 +191,9 @@ msgstr "" "Erro: Você não pode mudar os dados neste formulário. Você deve ter pelo " "menos 13 anos de idade." -#: drdown/careline/views/view_checklist.py:199 +#: drdown/careline/views/view_checklist.py:146 msgid "Success! Your changes were saved." msgstr "Sucesso! Suas mudanças foram salvas." + +msgid "There are no patients for this user." +msgstr "Não há pacientes para este usuário." diff --git a/drdown/careline/templates/careline/checklist_detail.html b/drdown/careline/templates/careline/checklist_detail.html index 998fa6a7..29abd173 100644 --- a/drdown/careline/templates/careline/checklist_detail.html +++ b/drdown/careline/templates/careline/checklist_detail.html @@ -102,6 +102,7 @@

{% trans "Care Line" %}


{% trans 'Name: ' %}{{ checklist.patient.user.name }}
+ {% trans 'Vaccine Schedule' %} {% if age == 0 %}
{% trans 'Age: ' %} {% trans "Newborn" %}
@@ -114,17 +115,16 @@
{% trans 'Age: ' %} {{ age }}
{% trans 'SES: ' %} {{ checklist.patient.ses}}
+ - + - - - + {% if age >= 0.5 %} @@ -159,184 +159,534 @@
{% trans 'SES: ' %} {{ checklist.pati 6 = 6...10 = 6_10Y --> - {%for procedure in checklist.procedure_set.all%} + {% for procedure in checklist.procedure_set.all %}
- + {% if age < 0.5 %} + {% if procedure.proc_id != 11 and procedure.proc_id != 8 and procedure.proc_id != 13 %} + + {% for check_item in procedure.get_checkitens_ordered %} + {% if age >= 0 and forloop.counter0 == 0 %} + {% if check_item.required %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% elif check_item.when_needed %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% else %} + + + + {% endif %} + + + {% elif age >= 0.5 and forloop.counter0 == 1 %} + + {% if check_item.required %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% elif check_item.when_needed %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% else %} + + + + {% endif %} + + {% elif age >= 1 and forloop.counter0 == 2 %} + + {% if check_item.required %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% elif check_item.when_needed %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% else %} + + + + {% endif %} + + {% elif age >= 2 and forloop.counter0 == 3 %} + + {% if check_item.required %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% elif check_item.when_needed %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% else %} + + - {% for check_item in procedure.get_checkitens_ordered %} + {% endif %} + {% elif age >= 3 or age is 4 and forloop.counter0 == 4 %} - {% if age >= 0 and forloop.counter0 == 0 %} - {% if check_item.required %} + {% if check_item.required %} - {% if check_item.check %} - - {% else %} - - {% endif %} + {% if check_item.check %} + + {% else %} + + {% endif %} - {% elif check_item.when_needed %} + {% elif check_item.when_needed %} - {% if check_item.check %} - - {% else %} - - {% endif %} + {% if check_item.check %} + + {% else %} + + {% endif %} + {% else %} + + + + {% endif %} + + {% elif age >= 5 and forloop.counter0 == 5 %} + {% if check_item.required %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% elif check_item.when_needed %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% else %} + + + + {% endif %} + + {% elif age >= 6 and forloop.counter0 == 6 %} + + {% if check_item.required %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% elif check_item.when_needed %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% else %} + + + + {% endif %} + {% endif %} + {% endfor %} + {% endif %} + {% elif age <= 1 and procedure.proc_id != 13 %} + + {% for check_item in procedure.get_checkitens_ordered %} + + + {% if age >= 0 and forloop.counter0 == 0 %} + {% if check_item.required %} + + {% if check_item.check %} + {% else %} + + {% endif %} - + {% elif check_item.when_needed %} + {% if check_item.check %} + + {% else %} + {% endif %} + {% else %} - {% elif age >= 0.5 and forloop.counter0 == 1 %} + - {% if check_item.required %} + {% endif %} - {% if check_item.check %} - - {% else %} - - {% endif %} - {% elif check_item.when_needed %} + {% elif age >= 0.5 and forloop.counter0 == 1 %} - {% if check_item.check %} - - {% else %} - - {% endif %} + {% if check_item.required %} + {% if check_item.check %} + {% else %} + + {% endif %} - + {% elif check_item.when_needed %} + {% if check_item.check %} + + {% else %} + {% endif %} - {% elif age >= 1 and forloop.counter0 == 2 %} + {% else %} - {% if check_item.required %} + - {% if check_item.check %} - - {% else %} - - {% endif %} + {% endif %} - {% elif check_item.when_needed %} + {% elif age >= 1 and forloop.counter0 == 2 %} - {% if check_item.check %} - - {% else %} - - {% endif %} + {% if check_item.required %} + {% if check_item.check %} + {% else %} + + {% endif %} - + {% elif check_item.when_needed %} + {% if check_item.check %} + + {% else %} + {% endif %} - {% elif age >= 2 and forloop.counter0 == 3 %} + {% else %} - {% if check_item.required %} + - {% if check_item.check %} - - {% else %} - - {% endif %} + {% endif %} - {% elif check_item.when_needed %} + {% elif age >= 2 and forloop.counter0 == 3 %} - {% if check_item.check %} - - {% else %} - - {% endif %} + {% if check_item.required %} + {% if check_item.check %} + {% else %} + + {% endif %} - + {% elif check_item.when_needed %} + {% if check_item.check %} + + {% else %} + {% endif %} - {% elif age >= 3 or age is 4 and forloop.counter0 == 4 %} + {% else %} - {% if check_item.required %} + - {% if check_item.check %} - - {% else %} - - {% endif %} + {% endif %} - {% elif check_item.when_needed %} + {% elif age >= 3 or age is 4 and forloop.counter0 == 4 %} - {% if check_item.check %} - - {% else %} - - {% endif %} + {% if check_item.required %} + {% if check_item.check %} + {% else %} + + {% endif %} - + {% elif check_item.when_needed %} + {% if check_item.check %} + + {% else %} + {% endif %} - {% elif age >= 5 and forloop.counter0 == 5 %} - {% if check_item.required %} + {% else %} - {% if check_item.check %} - - {% else %} - - {% endif %} + - {% elif check_item.when_needed %} + {% endif %} - {% if check_item.check %} - - {% else %} - - {% endif %} + {% elif age >= 5 and forloop.counter0 == 5 %} + {% if check_item.required %} + {% if check_item.check %} + {% else %} + + {% endif %} - + {% elif check_item.when_needed %} + {% if check_item.check %} + + {% else %} + {% endif %} - {% elif age >= 6 and forloop.counter0 == 6 %} + {% else %} - {% if check_item.required %} + - {% if check_item.check %} - - {% else %} - - {% endif %} + {% endif %} - {% elif check_item.when_needed %} + {% elif age >= 6 and forloop.counter0 == 6 %} - {% if check_item.check %} - - {% else %} - - {% endif %} + {% if check_item.required %} + {% if check_item.check %} + {% else %} + + {% endif %} - + {% elif check_item.when_needed %} + {% if check_item.check %} + + {% else %} + {% endif %} + {% else %} + + + {% endif %} + {% endif %} - {% endfor %} + {% endfor %} + + {% elif age > 1 %} + + {% for check_item in procedure.get_checkitens_ordered %} + + + {% if age >= 0 and forloop.counter0 == 0 %} + {% if check_item.required %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% elif check_item.when_needed %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% else %} + + + + {% endif %} + + + {% elif age >= 0.5 and forloop.counter0 == 1 %} + + {% if check_item.required %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% elif check_item.when_needed %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% else %} + + + + {% endif %} + + {% elif age >= 1 and forloop.counter0 == 2 %} + + {% if check_item.required %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% elif check_item.when_needed %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% else %} + + + + {% endif %} + + {% elif age >= 2 and forloop.counter0 == 3 %} + + {% if check_item.required %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% elif check_item.when_needed %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% else %} + + + + {% endif %} + + {% elif age >= 3 or age is 4 and forloop.counter0 == 4 %} + + {% if check_item.required %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% elif check_item.when_needed %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% else %} + + + + {% endif %} + + {% elif age >= 5 and forloop.counter0 == 5 %} + {% if check_item.required %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% elif check_item.when_needed %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% else %} + + + + {% endif %} + + {% elif age >= 6 and forloop.counter0 == 6 %} + + {% if check_item.required %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% elif check_item.when_needed %} + + {% if check_item.check %} + + {% else %} + + {% endif %} + + {% else %} + + + + {% endif %} + + {% endif %} + + {% endfor %} + + {% endif %} {%endfor%} diff --git a/drdown/careline/templates/careline/checklist_list.html b/drdown/careline/templates/careline/checklist_list.html deleted file mode 100644 index e80c112d..00000000 --- a/drdown/careline/templates/careline/checklist_list.html +++ /dev/null @@ -1,29 +0,0 @@ -{% extends "core/base.html" %} -{% load static i18n %} -{% block title %}{% trans "Care Line" %}{% endblock %} - -{% block content %} -
-

{% trans "Care Line" %}

- -
- {% for patient in patient_list %} - -
- {% if patient.user.photo %} - - {% else %} - - {% endif %} -
-

{{ patient.user.name }}

-

{% trans 'SES: ' %} {{patient.ses}}

-
-
-
- {% empty %} -

{% trans 'There are no patients for this user.'%}

- {% endfor %} -
-
-{% endblock content %} diff --git a/drdown/careline/tests/test_view_checklist_detail.py b/drdown/careline/tests/test_view_checklist_detail.py index 74b1674e..f37edef7 100644 --- a/drdown/careline/tests/test_view_checklist_detail.py +++ b/drdown/careline/tests/test_view_checklist_detail.py @@ -4,7 +4,7 @@ from django.utils import timezone from drdown.careline.models import Procedure -from drdown.users.models import Patient, Responsible +from drdown.users.models import Patient, Responsible, HealthTeam from drdown.careline.views import ChecklistDetailView @@ -66,6 +66,22 @@ def setUp(self): responsible=self.user_responsible.responsible ) + self.user_health_team = self.make_user() + self.user_health_team.birthday = timezone.datetime(2000, 1, 1) + + self.user_health_team.save() + self.user_health_team.refresh_from_db() + + self.health_team = HealthTeam.objects.create( + cpf="057.641.271-65", + user=self.user_health_team, + speciality=HealthTeam.NEUROLOGY, + council_acronym=HealthTeam.CRM, + register_number="1234567", + registration_state=HealthTeam.DF, + ) + + self.client = Client() self.view = ChecklistDetailView() @@ -84,6 +100,21 @@ def test_has_permission_for_responsible(self): True ) + def test_has_permission_for_healthteam(self): + """ + Test if a healthteam have access to a patient + """ + + self.assertEquals( + self.view.has_permission(current_user=self.user_health_team, target_user=self.user_patient1), + True + ) + + self.assertEquals( + self.view.has_permission(current_user=self.user_health_team, target_user=self.user_patient2), + True + ) + def test_has_permission_for_not_responsible(self): """ Test if a user that is not a responsible for a patient cannot access a patient data diff --git a/drdown/careline/tests/test_view_checklist_update.py b/drdown/careline/tests/test_view_checklist_update.py index d2abfccb..0530aacc 100644 --- a/drdown/careline/tests/test_view_checklist_update.py +++ b/drdown/careline/tests/test_view_checklist_update.py @@ -76,14 +76,15 @@ def test_get_redirect(self): self.client.force_login(user=self.user_responsible) - expected_url = reverse(viewname='careline:checklist_list') response = self.client.get( reverse(viewname="careline:checklist_update") ) - self.assertRedirects( - response=response, - expected_url=expected_url + expected_status_codes = [301, 302] + + self.assertIn( + response.status_code, + expected_status_codes ) def test_process_change(self): diff --git a/drdown/careline/tests/test_view_checklst_redirect.py b/drdown/careline/tests/test_view_checklst_redirect.py new file mode 100644 index 00000000..50cd6962 --- /dev/null +++ b/drdown/careline/tests/test_view_checklst_redirect.py @@ -0,0 +1,49 @@ +from test_plus.test import TestCase +from django.test.client import Client +from django.shortcuts import reverse +from django.utils import timezone + +from drdown.careline.models import Procedure +from drdown.users.models import Patient, Responsible, Employee + +from drdown.careline.views import ChecklistRedirectView + + +class TestViewChecklistRedirectView(TestCase): + """ + Test if the List View of Checklist is working correctly + """ + + def setUp(self): + """ + Runs before every test + """ + + self.user_responsible = self.make_user(username='resp') + + self.user_responsible.birthday = timezone.datetime(1950, 1, 1) + + self.user_responsible.save() + self.user_responsible.refresh_from_db() + + Responsible.objects.create( + user=self.user_responsible, + cpf="974.220.200-16" + ) + + def test_redirect(self): + + self.client.force_login(self.user_responsible) + + response = self.client.get( + path=reverse( + viewname='careline:checklist_list', + ), + follow=True + ) + + url = self.client.get( + path=reverse(viewname='users:patient_list') + ).url + + self.assertRedirects(response=response, expected_url=url) \ No newline at end of file diff --git a/drdown/careline/tests/test_view_checlist_list.py b/drdown/careline/tests/test_view_checlist_list.py deleted file mode 100644 index d473ff35..00000000 --- a/drdown/careline/tests/test_view_checlist_list.py +++ /dev/null @@ -1,162 +0,0 @@ -from test_plus.test import TestCase -from django.test.client import Client -from django.shortcuts import reverse -from django.utils import timezone - -from drdown.careline.models import Procedure -from drdown.users.models import Patient, Responsible, Employee - -from drdown.careline.views import ChecklistListView - - -class TestViewChecklistListView(TestCase): - """ - Test if the List View of Checklist is working correctly - """ - - def setUp(self): - """ - Runs before every test - """ - - self.user_responsible = self.make_user(username='resp') - - self.user_responsible.birthday = timezone.datetime(1950, 1, 1) - - self.user_responsible.save() - self.user_responsible.refresh_from_db() - - Responsible.objects.create( - user=self.user_responsible, - cpf="974.220.200-16" - ) - - self.user_patient1 = self.make_user(username='pat1') - - self.user_patient1.birthday = timezone.datetime(2000, 1, 1) - - Patient.objects.create( - ses="1234567", - user=self.user_patient1, - priority=1, - mother_name="Mae", - father_name="Pai", - ethnicity=3, - sus_number="12345678911", - civil_registry_of_birth="12345678911", - declaration_of_live_birth="12345678911", - responsible=self.user_responsible.responsible - ) - - self.user_patient1.refresh_from_db() - - self.user_patient2 = self.make_user(username='pat2') - - self.user_patient2.birthday = timezone.datetime(2000, 1, 1) - - Patient.objects.create( - ses="1234213", - user=self.user_patient2, - priority=1, - mother_name="Mae", - father_name="Pai", - ethnicity=3, - sus_number="12345633912", - civil_registry_of_birth="12345123911", - declaration_of_live_birth="1212338911", - responsible=self.user_responsible.responsible - ) - - self.client = Client() - self.view = ChecklistListView() - - def test_get_redirect_for_patient(self): - """ - Test if a patient is redirected for its checklist when accessing Checklist List View - """ - - self.client.force_login(self.user_patient1) - - response = self.client.get( - path=reverse( - viewname='careline:checklist_list', - ), - follow=True - ) - - url = reverse(viewname='careline:checklist_detail', kwargs={'username': self.user_patient1.username}) - - self.assertRedirects(response=response, expected_url=url) - - def test_get_redirect_for_not_authenticated(self): - """ - Test if a not authenticated user is redirected to login screen - """ - - response = self.client.get( - path=reverse( - viewname='careline:checklist_list', - ), - follow=True - ) - - url = reverse(viewname='account_login') - - self.assertRedirects(response=response, expected_url=url) - - def test_get_redirect_for_other_specializations_or_no_specialization(self): - """ - Test if a user that is not patient or responsible is redirected for its profile - when accessing Checklist List View - """ - - user = self.make_user(username='nope') - user.birthday = timezone.datetime(1950, 1, 1) - user.save() - - self.client.force_login(user) - - response = self.client.get( - path=reverse( - viewname='careline:checklist_list', - ), - follow=True - ) - - url = reverse(viewname='users:detail', kwargs={'username': user.username}) - - self.assertRedirects(response=response, expected_url=url) - - Employee.objects.create( - cpf="306.585.340-09", - user=user - ) - - user.refresh_from_db() - - response = self.client.get( - path=reverse( - viewname='careline:checklist_list', - ), - follow=True - ) - - url = reverse(viewname='users:detail', kwargs={'username': user.username}) - - self.assertRedirects(response=response, expected_url=url) - - def test_get_page_when_responsible(self): - """ - Test if the page loads when a responsible is the current user - """ - - self.client.force_login(self.user_responsible) - - response = self.client.get( - path=reverse( - viewname='careline:checklist_list', - ), - follow=True - ) - - self.assertEquals(response.status_code, 200) diff --git a/drdown/careline/urls.py b/drdown/careline/urls.py index a260ee47..914958ed 100644 --- a/drdown/careline/urls.py +++ b/drdown/careline/urls.py @@ -2,7 +2,7 @@ from .views import ( ChecklistDetailView, - ChecklistListView, + ChecklistRedirectView, ChecklistUpdateView ) @@ -10,7 +10,7 @@ urlpatterns = [ url( regex=r'^$', - view=ChecklistListView.as_view(), + view=ChecklistRedirectView.as_view(), name='checklist_list' ), url( diff --git a/drdown/careline/views/__init__.py b/drdown/careline/views/__init__.py index a4ad3f92..9a41a18d 100644 --- a/drdown/careline/views/__init__.py +++ b/drdown/careline/views/__init__.py @@ -1,5 +1,5 @@ from .view_checklist import ( ChecklistDetailView, - ChecklistListView, + ChecklistRedirectView, ChecklistUpdateView ) diff --git a/drdown/careline/views/view_checklist.py b/drdown/careline/views/view_checklist.py index 0dfc4158..facae6df 100644 --- a/drdown/careline/views/view_checklist.py +++ b/drdown/careline/views/view_checklist.py @@ -1,82 +1,27 @@ -from django.shortcuts import get_object_or_404, render, redirect +from django.shortcuts import get_object_or_404, redirect from django.http import ( - HttpResponseRedirect, HttpResponse, HttpResponseForbidden, - HttpResponseServerError ) -from django.urls import reverse +from django.urls import reverse, reverse_lazy from django.utils.translation import ugettext_lazy as _ from drdown.careline.models import ( Checklist, - Procedure, - CheckItem ) from django.views.generic import ( DetailView, - ListView, - TemplateView, RedirectView ) -from drdown.users.models import User, Patient +from drdown.users.models import User -class ChecklistListView(ListView): +class ChecklistRedirectView(RedirectView): - # the List View for Checklists will list the patients that belong to the - # current user (specialized as a responsible), only responsibles will - # access this view - model = Checklist - template_name = 'careline/checklist_list.html' - - def get(self, request, *args, **kwargs): - - if not request.user.is_authenticated: - # redirect not not authenticated to login screen - url = reverse( - viewname='account_login', - ) - return redirect(url) - - if hasattr(request.user, 'patient'): - # redirect user_patient to the checklist detail view - url = reverse( - viewname='careline:checklist_detail', - kwargs={'username': request.user.username} - ) - return redirect(url) - - if not hasattr(request.user, 'responsible'): - url = reverse( - viewname='users:detail', - kwargs={'username': request.user.username} - ) - return redirect(url) - - return super().get(request, *args, **kwargs) - - def get_queryset(self, *args, **kwargs): - - user = self.request.user - - queryset = None - - if hasattr(user, "responsible"): - queryset = Patient.objects.filter(responsible=user.responsible) - - return queryset - - def get_context_data(self, **kwargs): - context = super().get_context_data(**kwargs) - - user = self.request.user - patients = Patient.objects.filter(responsible=user.responsible) - - context['patient_list'] = patients - - return context + # redirect this page to user list of + # medical follow-up sheet page + url = reverse_lazy('users:patient_list') class ChecklistDetailView(DetailView): @@ -135,6 +80,8 @@ def has_permission(current_user, target_user): for patient in current_user.responsible.patient_set.all(): if patient.user == target_user: allowed = True + elif hasattr(current_user, 'healthteam'): + allowed = True return allowed diff --git a/drdown/core/locale/pt_BR/LC_MESSAGES/django.po b/drdown/core/locale/pt_BR/LC_MESSAGES/django.po index 35fc1e88..57c8f1a2 100644 --- a/drdown/core/locale/pt_BR/LC_MESSAGES/django.po +++ b/drdown/core/locale/pt_BR/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-04-28 01:16+0000\n" +"POT-Creation-Date: 2018-05-04 10:24+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -407,7 +407,7 @@ msgstr "Eventos" #: drdown/core/templates/core/base.html:84 #: drdown/core/templates/core/base.html:92 msgid "Care Line" -msgstr "" +msgstr "Linha de Cuidado" #: drdown/core/templates/core/base.html:87 msgid "My Patient" @@ -417,7 +417,11 @@ msgstr "Meu paciente" msgid "Schedules" msgstr "Agenda" -#: drdown/core/templates/core/base.html:103 +#: drdown/core/templates/core/base.html:101 +msgid "Appointments" +msgstr "Consultas" + +#: drdown/core/templates/core/base.html:104 msgid "Edit Profile" msgstr "Editar Perfil" @@ -473,8 +477,8 @@ msgid "" "communicate with the doctor and visualize general information." msgstr "" "Dr. Down é uma ferramenta de gerenciamento para o CRIS DOWN (Centro de " -"Referência em Síndrome de Down) que possibilita agendar consultas, " -"comunicar-se com o médico e visualizar informações." +"Referência em Síndrome de Down) que possibilita agendar consultas, comunicar-" +"se com o médico e visualizar informações." #: drdown/core/templates/core/home.html:39 msgid "" @@ -486,6 +490,11 @@ msgstr "" "lugar especializado no cuidado e acompanhamento de pacientes portadores de " "Síndrome de Down." +#: drdown/core/templates/core/home.html:67 +#| msgid "CRIS DOWN" +msgid "CRIS Down " +msgstr "CRIS DOWN" + #: drdown/core/templates/core/info.html:25 msgid "Down's Syndrome infos" msgstr "Informações sobre a Síndrome de Down" @@ -503,24 +512,24 @@ msgid "Frequently Asked Questions (FAQ)" msgstr "Dúvidas Frequentes" #: drdown/core/templates/core/info.html:37 -#: drdown/core/templates/core/info.html:96 +#: drdown/core/templates/core/info.html:98 msgid "What can be done to prevent Down's Syndrome?" msgstr "Como prevenir a Síndrome de Down?" #: drdown/core/templates/core/info.html:40 -#: drdown/core/templates/core/info.html:105 +#: drdown/core/templates/core/info.html:107 msgid "Is Down Syndrome a Disease? Can I catch it during my life?" msgstr "" "A Síndrome de Down é uma doença? Eu posso pegar/desenvolver ela durante " "minha vida?" #: drdown/core/templates/core/info.html:41 -#: drdown/core/templates/core/info.html:115 +#: drdown/core/templates/core/info.html:117 msgid "How can I identify Down Syndrome?" msgstr "Como posso identificar a Síndrome de Down?" #: drdown/core/templates/core/info.html:42 -#: drdown/core/templates/core/info.html:125 +#: drdown/core/templates/core/info.html:127 msgid "How far does the autonomy of a child with Down syndrome develop?" msgstr "" "Até onde se desenvolve a autonomia de uma criança com Síndrome de Down?" @@ -606,7 +615,7 @@ msgstr "" msgid "Frequently Asked Questions" msgstr "Dúvidas Frequentes" -#: drdown/core/templates/core/info.html:99 +#: drdown/core/templates/core/info.html:101 msgid "" "Even though the chance of Down's syndrome increases according to the age " "range of the child's parents, Down's syndrome is not caused by the parents, " @@ -620,7 +629,7 @@ msgstr "" "Essa síndrome afeta pessoas de todas as raças, níveis de estudo, classes " "sociais e outros." -#: drdown/core/templates/core/info.html:108 +#: drdown/core/templates/core/info.html:110 msgid "" "Down Syndrome is not a disease, just a condition that affects the life of an " "individual since birth and requires greater attention and care from the " @@ -630,7 +639,7 @@ msgstr "" "um indivíduo desde o seu nascimento, o que exige uma maior atenção e cuidado " "por parte dos pais e familiares." -#: drdown/core/templates/core/info.html:118 +#: drdown/core/templates/core/info.html:120 msgid "" "Down Syndrome can be detected during pregnancy. You should see a doctor for " "the diagnosis." @@ -638,7 +647,7 @@ msgstr "" "A Síndrome de Down pode ser detectada durante a gestação. Deve-se procurar " "um médico para que o diagnóstico seja feito." -#: drdown/core/templates/core/info.html:128 +#: drdown/core/templates/core/info.html:130 msgid "" "There is no fixed limit that represents a developmental apex of a child with " "Down Syndrome. It is common for medical monitoring and the help of family " @@ -649,19 +658,525 @@ msgstr "" "a ajuda dos familiares ou responsáveis facilitem o desenvolvimento da " "criança." -#: drdown/core/templates/core/info.html:137 +#: drdown/core/templates/core/info.html:139 msgid "Further reading" msgstr "Leituras complementares" -msgid "Hey! You have procedures to be made." -msgstr "Oi! Você tem procedimentos que precisam ser feitos." +#: drdown/core/templates/core/info.html:144 +#: drdown/core/templates/core/vaccine_schedule.html:19 +#, fuzzy +#| msgid "My Schedule" +msgid "Vaccine Schedule" +msgstr "Calendário de Vacinas" + +#: drdown/core/templates/core/pagination.html:8 +#: drdown/core/templates/core/pagination.html:12 +msgid "Previous" +msgstr "Anterior" + +#: drdown/core/templates/core/pagination.html:30 +#: drdown/core/templates/core/pagination.html:34 +msgid "Next" +msgstr "Próximo" + +#: drdown/core/templates/core/vaccination_locations.html:25 +#: drdown/core/templates/core/vaccine_schedule.html:20 +#| msgid "Locations" +msgid "Vaccination Locations" +msgstr "Locais de Vacinação" + +#: drdown/core/templates/core/vaccination_locations.html:33 +#: drdown/core/templates/core/vaccination_locations.html:79 +#: drdown/core/templates/core/vaccination_locations.html:110 +#: drdown/core/templates/core/vaccination_locations.html:128 +#: drdown/core/templates/core/vaccination_locations.html:146 +#: drdown/core/templates/core/vaccination_locations.html:212 +#: drdown/core/templates/core/vaccination_locations.html:230 +#: drdown/core/templates/core/vaccination_locations.html:248 +#: drdown/core/templates/core/vaccination_locations.html:278 +#: drdown/core/templates/core/vaccination_locations.html:316 +#: drdown/core/templates/core/vaccination_locations.html:346 +#: drdown/core/templates/core/vaccination_locations.html:368 +#: drdown/core/templates/core/vaccination_locations.html:390 +#: drdown/core/templates/core/vaccination_locations.html:412 +#: drdown/core/templates/core/vaccination_locations.html:430 +#: drdown/core/templates/core/vaccination_locations.html:452 +#: drdown/core/templates/core/vaccination_locations.html:530 +#: drdown/core/templates/core/vaccination_locations.html:552 +#: drdown/core/templates/core/vaccination_locations.html:570 +#: drdown/core/templates/core/vaccination_locations.html:592 +#: drdown/core/templates/core/vaccination_locations.html:622 +#: drdown/core/templates/core/vaccination_locations.html:644 +#: drdown/core/templates/core/vaccination_locations.html:694 +msgid "Local" +msgstr "Local" + +#: drdown/core/templates/core/vaccination_locations.html:34 +#: drdown/core/templates/core/vaccination_locations.html:80 +#: drdown/core/templates/core/vaccination_locations.html:111 +#: drdown/core/templates/core/vaccination_locations.html:129 +#: drdown/core/templates/core/vaccination_locations.html:147 +#: drdown/core/templates/core/vaccination_locations.html:213 +#: drdown/core/templates/core/vaccination_locations.html:231 +#: drdown/core/templates/core/vaccination_locations.html:249 +#: drdown/core/templates/core/vaccination_locations.html:279 +#: drdown/core/templates/core/vaccination_locations.html:317 +#: drdown/core/templates/core/vaccination_locations.html:347 +#: drdown/core/templates/core/vaccination_locations.html:369 +#: drdown/core/templates/core/vaccination_locations.html:391 +#: drdown/core/templates/core/vaccination_locations.html:413 +#: drdown/core/templates/core/vaccination_locations.html:431 +#: drdown/core/templates/core/vaccination_locations.html:453 +#: drdown/core/templates/core/vaccination_locations.html:531 +#: drdown/core/templates/core/vaccination_locations.html:553 +#: drdown/core/templates/core/vaccination_locations.html:571 +#: drdown/core/templates/core/vaccination_locations.html:593 +#: drdown/core/templates/core/vaccination_locations.html:623 +#: drdown/core/templates/core/vaccination_locations.html:645 +#: drdown/core/templates/core/vaccination_locations.html:695 +msgid "Phone" +msgstr "Telefone" + +#: drdown/core/templates/core/vaccine_schedule.html:26 +#: drdown/core/templates/core/vaccine_schedule.html:225 +#: drdown/core/templates/core/vaccine_schedule.html:267 +#: drdown/core/templates/core/vaccine_schedule.html:376 +msgid "Vaccines" +msgstr "Vacinas" + +#: drdown/core/templates/core/vaccine_schedule.html:26 +#: drdown/core/templates/core/vaccine_schedule.html:244 +#| msgid "OF BIRTH TO THE 10 YEARS OF AGE" +msgid "OF BIRTH TO THE 6 YEARS OF AGE" +msgstr "DO NASCIMENTO AOS 6 ANOS DE IDADE" + +#: drdown/core/templates/core/vaccine_schedule.html:30 +#: drdown/core/templates/core/vaccine_schedule.html:225 +msgid "At Birth" +msgstr "Ao Nascer" + +#: drdown/core/templates/core/vaccine_schedule.html:31 +#: drdown/core/templates/core/vaccine_schedule.html:226 +msgid "1 Month" +msgstr "1 Mês" + +#: drdown/core/templates/core/vaccine_schedule.html:32 +#: drdown/core/templates/core/vaccine_schedule.html:227 +msgid "2 Months" +msgstr "2 Meses" + +#: drdown/core/templates/core/vaccine_schedule.html:33 +#: drdown/core/templates/core/vaccine_schedule.html:228 +msgid "3 Months" +msgstr "3 Meses" + +#: drdown/core/templates/core/vaccine_schedule.html:34 +#: drdown/core/templates/core/vaccine_schedule.html:229 +msgid "4 Months" +msgstr "4 Meses" + +#: drdown/core/templates/core/vaccine_schedule.html:35 +#: drdown/core/templates/core/vaccine_schedule.html:230 +msgid "5 Months" +msgstr "5 Meses" + +#: drdown/core/templates/core/vaccine_schedule.html:36 +#: drdown/core/templates/core/vaccine_schedule.html:231 +msgid "6 Months" +msgstr "6 Meses" + +#: drdown/core/templates/core/vaccine_schedule.html:37 +#: drdown/core/templates/core/vaccine_schedule.html:232 +msgid "7 Months" +msgstr "7 Meses" + +#: drdown/core/templates/core/vaccine_schedule.html:38 +#: drdown/core/templates/core/vaccine_schedule.html:233 +msgid "8 Months" +msgstr "8 Meses" + +#: drdown/core/templates/core/vaccine_schedule.html:39 +#: drdown/core/templates/core/vaccine_schedule.html:234 +msgid "9 Months" +msgstr "9 Meses" + +#: drdown/core/templates/core/vaccine_schedule.html:40 +#: drdown/core/templates/core/vaccine_schedule.html:235 +msgid "12 Months" +msgstr "12 Meses" + +#: drdown/core/templates/core/vaccine_schedule.html:41 +#: drdown/core/templates/core/vaccine_schedule.html:236 +msgid "15 Months" +msgstr "15 Meses" + +#: drdown/core/templates/core/vaccine_schedule.html:42 +#: drdown/core/templates/core/vaccine_schedule.html:237 +msgid "18 Months" +msgstr "18 Meses" + +#: drdown/core/templates/core/vaccine_schedule.html:43 +#: drdown/core/templates/core/vaccine_schedule.html:238 +msgid "24 Months" +msgstr "24 Meses" + +#: drdown/core/templates/core/vaccine_schedule.html:44 +#: drdown/core/templates/core/vaccine_schedule.html:239 +msgid "4 Years" +msgstr "4 Anos" + +#: drdown/core/templates/core/vaccine_schedule.html:45 +#: drdown/core/templates/core/vaccine_schedule.html:240 +msgid "5 Years" +msgstr "5 Anos" + +#: drdown/core/templates/core/vaccine_schedule.html:46 +#: drdown/core/templates/core/vaccine_schedule.html:241 +msgid "6 Years" +msgstr "6 Anos" + +#: drdown/core/templates/core/vaccine_schedule.html:52 +#: drdown/core/templates/core/vaccine_schedule.html:283 +msgid "BCG ID" +msgstr "BCG ID" + +#: drdown/core/templates/core/vaccine_schedule.html:53 +#: drdown/core/templates/core/vaccine_schedule.html:365 +msgid "One dose" +msgstr "Uma dose" + +#: drdown/core/templates/core/vaccine_schedule.html:54 +#: drdown/core/templates/core/vaccine_schedule.html:60 +#: drdown/core/templates/core/vaccine_schedule.html:83 +#: drdown/core/templates/core/vaccine_schedule.html:168 +#: drdown/core/templates/core/vaccine_schedule.html:198 +#: drdown/core/templates/core/vaccine_schedule.html:288 +#: drdown/core/templates/core/vaccine_schedule.html:334 +#: drdown/core/templates/core/vaccine_schedule.html:344 +#: drdown/core/templates/core/vaccine_schedule.html:350 +msgid "Vaccinate the previously unvaccinated" +msgstr "Vacinar os não vacinados anteriormente" + +#: drdown/core/templates/core/vaccine_schedule.html:55 +#: drdown/core/templates/core/vaccine_schedule.html:284 +msgid "Vaccinate people who contacted leprosy" +msgstr "Vacinar pessoas contactantes de hanseníase" + +#: drdown/core/templates/core/vaccine_schedule.html:58 +#: drdown/core/templates/core/vaccine_schedule.html:287 +msgid "Hepatitis B" +msgstr "Hepatite B" + +#: drdown/core/templates/core/vaccine_schedule.html:59 +msgid "Three or four doses from birth" +msgstr "Três ou quatro doses a partir do nascimento" + +#: drdown/core/templates/core/vaccine_schedule.html:63 +#: drdown/core/templates/core/vaccine_schedule.html:291 +msgid "Rotavirus" +msgstr "Rotavírus" + +#: drdown/core/templates/core/vaccine_schedule.html:66 +msgid "Two or three doses. Initiate vaccination before 15 weeks of age" +msgstr "Duas ou três doses. Iniciar vacinação antes das 15 semanas de vida" + +#: drdown/core/templates/core/vaccine_schedule.html:67 +#: drdown/core/templates/core/vaccine_schedule.html:219 +#: drdown/core/templates/core/vaccine_schedule.html:292 +#: drdown/core/templates/core/vaccine_schedule.html:370 +msgid "CONTRAINDICATED" +msgstr "CONTRAINDICADA" + +#: drdown/core/templates/core/vaccine_schedule.html:70 +#: drdown/core/templates/core/vaccine_schedule.html:295 +msgid "Bacterial triple (DTPw, DTPa, ou dTpa)" +msgstr "Tríplice bacteriana (DTPw, DTPa, ou dTpa)" + +#: drdown/core/templates/core/vaccine_schedule.html:73 +msgid "Four doses of DTPa or DTPw starting at 2 months of age" +msgstr "Quatro doses DTPa ou DTPw iniciando aos 2 meses de idade" + +#: drdown/core/templates/core/vaccine_schedule.html:75 +msgid "Reinforcement with DTPa, DTPw or dTpa" +msgstr "Reforço com DTPa, DTPw ou dTpa" + +#: drdown/core/templates/core/vaccine_schedule.html:79 +#: drdown/core/templates/core/vaccine_schedule.html:301 +msgid "Haemophilus influenzae type b" +msgstr "Haemophilus influenzae tipo b" + +#: drdown/core/templates/core/vaccine_schedule.html:82 +msgid "Four doses starting at 2 months of age" +msgstr "Quatro doses iniciando aos 2 meses de idade" + +#: drdown/core/templates/core/vaccine_schedule.html:84 +#: drdown/core/templates/core/vaccine_schedule.html:91 +#: drdown/core/templates/core/vaccine_schedule.html:215 +#: drdown/core/templates/core/vaccine_schedule.html:302 +#: drdown/core/templates/core/vaccine_schedule.html:306 +#: drdown/core/templates/core/vaccine_schedule.html:317 +#: drdown/core/templates/core/vaccine_schedule.html:322 +#: drdown/core/templates/core/vaccine_schedule.html:335 +#: drdown/core/templates/core/vaccine_schedule.html:345 +#: drdown/core/templates/core/vaccine_schedule.html:356 +msgid "Vaccinate people in special risk situations" +msgstr "Vacinar pessoas em situações especiais de risco" + +#: drdown/core/templates/core/vaccine_schedule.html:87 +#: drdown/core/templates/core/vaccine_schedule.html:305 +msgid "Poliomyelitis (inactivated virus)" +msgstr "Poliomielite (vírus inativados)" + +#: drdown/core/templates/core/vaccine_schedule.html:90 +msgid "Five doses starting at 2 months of age" +msgstr "Cinco doses iniciando aos 2 meses de idade" + +#: drdown/core/templates/core/vaccine_schedule.html:94 +#: drdown/core/templates/core/vaccine_schedule.html:309 +msgid "Pneumococcal conjugate" +msgstr "Pneumocócica conjugada" + +#: drdown/core/templates/core/vaccine_schedule.html:97 +msgid "Four doses starting at 2 months of age - VPC10 or VPC13" +msgstr "" + +#: drdown/core/templates/core/vaccine_schedule.html:98 +msgid "VPC10 or VPC13 - Vaccinate the previously unvaccinated" +msgstr "Quatro doses iniciando aos 2 meses de idade - VPC10 ou VPC13" + +#: drdown/core/templates/core/vaccine_schedule.html:99 +#: drdown/core/templates/core/vaccine_schedule.html:310 +msgid "PCV13: vaccinating people in special risk situations" +msgstr "PCV13: vacinar pessoas em situações especiais de risco" + +#: drdown/core/templates/core/vaccine_schedule.html:102 +#: drdown/core/templates/core/vaccine_schedule.html:314 +msgid "Meningococcal conjugate C or ACWY" +msgstr "Meningocócica conjugada C ou ACWY" + +#: drdown/core/templates/core/vaccine_schedule.html:106 +msgid "" +"With menACWY: three doses beginning at 3 months of age. Or with menC: two " +"doses beginning at 3 months of age" +msgstr "" +"Com menACWY: três doses iniciando aos 3 meses de idade. Ou com menC: duas " +"doses iniciando aos 3 meses de idade" + +#: drdown/core/templates/core/vaccine_schedule.html:107 +#: drdown/core/templates/core/vaccine_schedule.html:109 +#: drdown/core/templates/core/vaccine_schedule.html:117 +msgid "REINFORCEMENT" +msgstr "REFORÇO" + +#: drdown/core/templates/core/vaccine_schedule.html:112 +#: drdown/core/templates/core/vaccine_schedule.html:320 +msgid "Meningococcal B" +msgstr "Meningocócica B" + +#: drdown/core/templates/core/vaccine_schedule.html:116 +msgid "Three doses beginning at 3 months of age" +msgstr "Três doses iniciando aos 3 meses de idade" + +#: drdown/core/templates/core/vaccine_schedule.html:118 +#: drdown/core/templates/core/vaccine_schedule.html:321 +msgid "For those not previously vaccinated: two doses" +msgstr "Para os não vacinados anteriormente: duas doses" + +#: drdown/core/templates/core/vaccine_schedule.html:121 +msgid "Oral poliomyelitis (live attenuated virus)" +msgstr "Poliomielite oral (vírus vivos atenuados)" + +#: drdown/core/templates/core/vaccine_schedule.html:129 +msgid "NATIONAL VACCINATION CAMPAIGNS" +msgstr "CAMPANHAS NACIONAIS DE VACINAÇÃO" + +#: drdown/core/templates/core/vaccine_schedule.html:133 +#: drdown/core/templates/core/vaccine_schedule.html:325 +msgid "Influenza (flu)" +msgstr "Influenza (gripe)" + +#: drdown/core/templates/core/vaccine_schedule.html:140 +#: drdown/core/templates/core/vaccine_schedule.html:326 +msgid "ANNUAL VACCINATION" +msgstr "VACINAÇÃO ANUAL" + +#: drdown/core/templates/core/vaccine_schedule.html:143 +#: drdown/core/templates/core/vaccine_schedule.html:329 +msgid "Yellow fever" +msgstr "Febre amarela" + +#: drdown/core/templates/core/vaccine_schedule.html:153 +#: drdown/core/templates/core/vaccine_schedule.html:330 +msgid "" +"IN REGIONS WITH RECOMMENDATION OF VACCINATION (ACCORDING TO CLASSIFICATION " +"OF MS) - single dose at 9 months of age. Not previously vaccinated: single " +"dose" +msgstr "" +"EM REGIÕES COM RECOMENDAÇÃO DE VACINAÇÃO (DE ACORDO COM CLASSIFICAÇÃO DO MS) " +"- dose única aos 9 meses de idade. Para não vacinados anteriormente: dose " +"única" + +#: drdown/core/templates/core/vaccine_schedule.html:156 +#: drdown/core/templates/core/vaccine_schedule.html:333 +msgid "Viral triple (measles, mumps and rubella)" +msgstr "Tríplice viral (sarampo,caxumba e rubéola)" + +#: drdown/core/templates/core/vaccine_schedule.html:167 +#: drdown/core/templates/core/vaccine_schedule.html:182 +#: drdown/core/templates/core/vaccine_schedule.html:197 +msgid "Two doses after 12 months" +msgstr "Duas doses a partir dos 12 meses" + +#: drdown/core/templates/core/vaccine_schedule.html:171 +#: drdown/core/templates/core/vaccine_schedule.html:338 +msgid "Varicella (chickenpox)" +msgstr "Varicela (catapora)" + +#: drdown/core/templates/core/vaccine_schedule.html:183 +#: drdown/core/templates/core/vaccine_schedule.html:339 +msgid "Vaccinate previously unvaccinated susceptibles" +msgstr "Vacinar os suscetíveis não vacinados anteriormente" + +#: drdown/core/templates/core/vaccine_schedule.html:186 +#: drdown/core/templates/core/vaccine_schedule.html:343 +msgid "Hepatitis A" +msgstr "Hepatite A" + +#: drdown/core/templates/core/vaccine_schedule.html:201 +#: drdown/core/templates/core/vaccine_schedule.html:355 +msgid "Pneumococcal 23 courageous" +msgstr "Pneumocócica 23 valente" + +#: drdown/core/templates/core/vaccine_schedule.html:218 +#: drdown/core/templates/core/vaccine_schedule.html:368 +msgid "Dengue" +msgstr "Dengue" + +#: drdown/core/templates/core/vaccine_schedule.html:248 +msgid "Subtitle: " +msgstr "Legenda: " + +#: drdown/core/templates/core/vaccine_schedule.html:250 +msgid "Routine" +msgstr "Rotina" + +#: drdown/core/templates/core/vaccine_schedule.html:252 +msgid "Vaccinate Unvaccinated" +msgstr "Vacinar não vacinados" + +#: drdown/core/templates/core/vaccine_schedule.html:254 +msgid "Special Situations" +msgstr "Situações especiais" + +#: drdown/core/templates/core/vaccine_schedule.html:256 +msgid "Contraindicated" +msgstr "Contraindicada" + +#: drdown/core/templates/core/vaccine_schedule.html:267 +#: drdown/core/templates/core/vaccine_schedule.html:383 +msgid "9 TO 10 YEARS OLD" +msgstr "9 ATÉ 10 ANOS DE IDADE" + +#: drdown/core/templates/core/vaccine_schedule.html:268 +#: drdown/core/templates/core/vaccine_schedule.html:384 +msgid "ADOLESCENT" +msgstr "ADOLESCENTE" + +#: drdown/core/templates/core/vaccine_schedule.html:269 +#: drdown/core/templates/core/vaccine_schedule.html:385 +msgid "ADULT" +msgstr "ADULTO" + +#: drdown/core/templates/core/vaccine_schedule.html:270 +#: drdown/core/templates/core/vaccine_schedule.html:386 +msgid "OLD MAN" +msgstr "IDOSO" + +#: drdown/core/templates/core/vaccine_schedule.html:274 +#: drdown/core/templates/core/vaccine_schedule.html:376 +msgid "9 Years" +msgstr "9 Anos" + +#: drdown/core/templates/core/vaccine_schedule.html:275 +#: drdown/core/templates/core/vaccine_schedule.html:377 +msgid "10 Years" +msgstr "10 Anos" + +#: drdown/core/templates/core/vaccine_schedule.html:276 +#: drdown/core/templates/core/vaccine_schedule.html:378 +msgid "11-19 Years" +msgstr "11-19 Anos" + +#: drdown/core/templates/core/vaccine_schedule.html:277 +#: drdown/core/templates/core/vaccine_schedule.html:379 +msgid "20-59 Years" +msgstr "20-59 Anos" + +#: drdown/core/templates/core/vaccine_schedule.html:278 +#: drdown/core/templates/core/vaccine_schedule.html:380 +msgid "60+ Years" +msgstr "60+ Anos" + +#: drdown/core/templates/core/vaccine_schedule.html:297 +#: drdown/core/templates/core/vaccine_schedule.html:298 +#: drdown/core/templates/core/vaccine_schedule.html:299 +msgid "" +"Reinforcement with dTpa from 9 years of age and every 10 years (or, in the " +"case of dTpa, do dT)" +msgstr "" +"Reforço com dTpa a partir dos 9 anos de idade e a cada dez anos (ou, na " +"impossibilidade de dTpa, fazer dT)" + +#: drdown/core/templates/core/vaccine_schedule.html:311 +msgid "VPC13: one dose" +msgstr "VPC13: uma dose" + +#: drdown/core/templates/core/vaccine_schedule.html:316 +msgid "REINFORCED at age 11. For those not previously vaccinated: two doses" +msgstr "REFORÇO aos 11 anos. Para os não vacinados anteriormente: duas doses" + +#: drdown/core/templates/core/vaccine_schedule.html:348 +msgid "HPV" +msgstr "HPV" + +#: drdown/core/templates/core/vaccine_schedule.html:349 +msgid "Three doses for girls and boys" +msgstr "Três doses para meninas e meninos" -msgid "Click here to check it" -msgstr "Clique aqui para conferir" +#: drdown/core/templates/core/vaccine_schedule.html:351 +msgid "" +"Vaccinate the non-vaccinated formerly: at the discretion of the physician" +msgstr "Vacinar os não vacinados anteriormente: a critério do médico" + +#: drdown/core/templates/core/vaccine_schedule.html:357 +msgid "Two doses at five-year intervals" +msgstr "Duas doses com intervalo de cinco anos" + +#: drdown/core/templates/core/vaccine_schedule.html:360 +msgid "Herpes zoster" +msgstr "Herpes zóster" + +#: drdown/core/templates/core/vaccine_schedule.html:364 +msgid "From 50 to 59 years old: at medical discretion" +msgstr "De 50 a 59 anos: a critério médico" +#: drdown/core/templates/core/vaccine_schedule.html:369 msgid "" -"One or more of your patients needs attention. Some procedures may be " -"behind schedule." +"To vaccinate people aged 9 to 45 years previously infected with the virus " +"(seropositive) with three doses: 0 - 6 - 12 months" msgstr "" -"Um ou mais de seus pacientes precisa de atenção. Alguns procedimentos " -"podem estar atrasados." +"Vacinar pessoas de 9 a 45 anos previamente infectadas pelo vírus " +"(soropositivas) com três doses: 0 - 6 - 12 meses" + +#~ msgid "Hey! You have procedures to be made." +#~ msgstr "Oi! Você tem procedimentos que precisam ser feitos." + +#~ msgid "Click here to check it" +#~ msgstr "Clique aqui para conferir" + +#~ msgid "" +#~ "One or more of your patients needs attention. Some procedures may be " +#~ "behind schedule." +#~ msgstr "" +#~ "Um ou mais de seus pacientes precisa de atenção. Alguns procedimentos " +#~ "podem estar atrasados." diff --git a/drdown/core/static/core/css/home.css b/drdown/core/static/core/css/home.css index cfead6e4..ae14f9a2 100644 --- a/drdown/core/static/core/css/home.css +++ b/drdown/core/static/core/css/home.css @@ -5,3 +5,15 @@ hr.bg-star-blue:after{ background-color: #CAE1FF; } + +#location{ + width: 100%; +} + +.text-blue-1{ + color: #2C3E50; +} + +a.hover-yellow:hover { + color: #0A0A2A; +} diff --git a/drdown/core/templates/account/email.html b/drdown/core/templates/account/email.html index 84251e8f..c93d9d8d 100644 --- a/drdown/core/templates/account/email.html +++ b/drdown/core/templates/account/email.html @@ -7,10 +7,12 @@ {% block head_title %}{% trans "Account" %}{% endblock %} {% block inner %} -

{% trans "E-mail Addresses" %}

+
+

{% trans "E-mail Addresses" %}

+
{% if user.emailaddress_set.all %} -

{% trans 'The following e-mail addresses are associated with your account:' %}

+

{% trans 'The following e-mail addresses are associated with your account:' %}

{% csrf_token %} @@ -18,25 +20,33 @@

{% trans "E-mail Addresses" %}

{% for emailaddress in user.emailaddress_set.all %}
- -
+ + + {% endfor %}
- - - +
+
+
+
+
@@ -48,13 +58,21 @@

{% trans "E-mail Addresses" %}

{% endif %} -

{% trans "Add E-mail Address" %}

+
+

{% trans "Add E-mail Address" %}

+
+ + +
+ {% csrf_token %} +
{{ form|crispy }}
+
+ +
+
+ + -
- {% csrf_token %} - {{ form|crispy }} - - {% endblock %} diff --git a/drdown/core/templates/account/email_confirm.html b/drdown/core/templates/account/email_confirm.html index a0882b87..e55a05b0 100644 --- a/drdown/core/templates/account/email_confirm.html +++ b/drdown/core/templates/account/email_confirm.html @@ -17,7 +17,7 @@

{% trans "Confirm E-mail Address" %}

{% csrf_token %} - + {% else %} diff --git a/drdown/core/templates/account/logout.html b/drdown/core/templates/account/logout.html index 8677277b..e88b2c40 100644 --- a/drdown/core/templates/account/logout.html +++ b/drdown/core/templates/account/logout.html @@ -12,12 +12,12 @@

{% trans "Log Out" %}

{% csrf_token %} {% if redirect_field_value %} - + {% endif %} - + - + {% endblock %} diff --git a/drdown/core/templates/core/base.html b/drdown/core/templates/core/base.html index b3739606..731ca0fe 100644 --- a/drdown/core/templates/core/base.html +++ b/drdown/core/templates/core/base.html @@ -70,39 +70,40 @@ {% else %} diff --git a/drdown/core/templates/core/home.html b/drdown/core/templates/core/home.html index 4863cc53..b84d726c 100644 --- a/drdown/core/templates/core/home.html +++ b/drdown/core/templates/core/home.html @@ -4,7 +4,7 @@ {% block css %} - + @@ -42,5 +42,20 @@

{% trans "About" %}

+
+ +
+

{% trans "CRIS Down " %}

+
+ + +
+
{% endblock content %} diff --git a/drdown/core/templates/core/info.html b/drdown/core/templates/core/info.html index 3927e1c3..0fddb0a5 100644 --- a/drdown/core/templates/core/info.html +++ b/drdown/core/templates/core/info.html @@ -141,6 +141,7 @@

{%

+

{% trans "Vaccine Schedule" %}

O que é Síndrome de Down? - Movimento Down

O que é Síndrome de Down? - Fundação Síndrome de Down

CUIDADOS DE SAÚDE ÀS PESSOAS COM SÍNDROME DE DOWN - MINISTÉRIO DA SAÚDE (PDF)

diff --git a/drdown/forum/templates/forum/pagination.html b/drdown/core/templates/core/pagination.html similarity index 100% rename from drdown/forum/templates/forum/pagination.html rename to drdown/core/templates/core/pagination.html diff --git a/drdown/core/templates/core/vaccination_locations.html b/drdown/core/templates/core/vaccination_locations.html new file mode 100644 index 00000000..a6ab7cf2 --- /dev/null +++ b/drdown/core/templates/core/vaccination_locations.html @@ -0,0 +1,780 @@ +{% extends "core/base.html" %} +{% load static %} +{% load i18n %} + +{% block css %} + {{block.super}} + + } +{% endblock %} + +{% block script %} + +{% endblock %} + +{% block content %} +
+

{% trans "Vaccination Locations" %}

+
+
+ +

{% trans 'Interventions / Evaluation'%} {% trans 'AGE'%}
{% trans 'Interventions / Evaluation'%}{% trans 'Newborn'%}{% trans 'Six Months'%}
{{procedure.description}}{{procedure.description}}{{procedure.description}}{{procedure.description}}
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +{% endblock %} \ No newline at end of file diff --git a/drdown/core/templates/core/vaccine_schedule.html b/drdown/core/templates/core/vaccine_schedule.html new file mode 100644 index 00000000..5dcf4108 --- /dev/null +++ b/drdown/core/templates/core/vaccine_schedule.html @@ -0,0 +1,394 @@ +{% extends "core/base.html" %} +{% load static %} +{% load i18n %} +{% block css %} + + + + + + + + + +{% endblock css %} + +{% block content %} + +






+

{% trans "Vaccine Schedule" %}

+ {% trans "Vaccination Locations" %} +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

{% trans 'Vaccines'%}

{% trans 'OF BIRTH TO THE 6 YEARS OF AGE'%}
{% trans 'At Birth'%}{% trans '1 Month'%}{% trans '2 Months'%}{% trans '3 Months'%}{% trans '4 Months'%}{% trans '5 Months'%}{% trans '6 Months'%}{% trans '7 Months'%}{% trans '8 Months'%}{% trans '9 Months'%}{% trans '12 Months'%}{% trans '15 Months'%}{% trans '18 Months'%}{% trans '24 Months'%}{% trans '4 Years'%}{% trans '5 Years'%}{% trans '6 Years'%}
{% trans 'BCG ID'%}{% trans 'One dose'%}{% trans 'Vaccinate the previously unvaccinated'%}{% trans 'Vaccinate people who contacted leprosy'%}
{% trans 'Hepatitis B'%}{% trans 'Three or four doses from birth'%}{% trans 'Vaccinate the previously unvaccinated'%}
{% trans 'Rotavirus'%}{% trans 'Two or three doses. Initiate vaccination before 15 weeks of age'%}{% trans 'CONTRAINDICATED'%}
{% trans 'Bacterial triple (DTPw, DTPa, ou dTpa)'%}{% trans 'Four doses of DTPa or DTPw starting at 2 months of age'%}{% trans 'Reinforcement with DTPa, DTPw or dTpa'%}
{% trans 'Haemophilus influenzae type b'%}{% trans 'Four doses starting at 2 months of age'%}{% trans 'Vaccinate the previously unvaccinated'%}{% trans 'Vaccinate people in special risk situations'%}
{% trans 'Poliomyelitis (inactivated virus)'%}{% trans 'Five doses starting at 2 months of age'%}{% trans 'Vaccinate people in special risk situations'%}
{% trans 'Pneumococcal conjugate'%}{% trans 'Four doses starting at 2 months of age - VPC10 or VPC13'%}{% trans 'VPC10 or VPC13 - Vaccinate the previously unvaccinated'%}{% trans 'PCV13: vaccinating people in special risk situations'%}
{% trans 'Meningococcal conjugate C or ACWY'%}{% trans 'With menACWY: three doses beginning at 3 months of age. Or with menC: two doses beginning at 3 months of age'%}{% trans 'REINFORCEMENT'%}{% trans 'REINFORCEMENT'%}
{% trans 'Meningococcal B'%}{% trans 'Three doses beginning at 3 months of age'%}{% trans 'REINFORCEMENT'%}{% trans 'For those not previously vaccinated: two doses'%}
{% trans 'Oral poliomyelitis (live attenuated virus)'%}{% trans 'NATIONAL VACCINATION CAMPAIGNS'%}
{% trans 'Influenza (flu)'%}{% trans 'ANNUAL VACCINATION'%}
{% trans 'Yellow fever'%}{% trans 'IN REGIONS WITH RECOMMENDATION OF VACCINATION (ACCORDING TO CLASSIFICATION OF MS) - single dose at 9 months of age. Not previously vaccinated: single dose'%}
{% trans 'Viral triple (measles, mumps and rubella)'%}{% trans 'Two doses after 12 months'%}{% trans 'Vaccinate the previously unvaccinated'%}
{% trans 'Varicella (chickenpox)'%}{% trans 'Two doses after 12 months'%}{% trans 'Vaccinate previously unvaccinated susceptibles'%}
{% trans 'Hepatitis A'%}{% trans 'Two doses after 12 months'%}{% trans 'Vaccinate the previously unvaccinated'%}
{% trans 'Pneumococcal 23 courageous'%}{% trans 'Vaccinate people in special risk situations'%}
{% trans 'Dengue'%}{% trans 'CONTRAINDICATED'%}

{% trans 'Vaccines'%}

{% trans 'At Birth'%}{% trans '1 Month'%}{% trans '2 Months'%}{% trans '3 Months'%}{% trans '4 Months'%}{% trans '5 Months'%}{% trans '6 Months'%}{% trans '7 Months'%}{% trans '8 Months'%}{% trans '9 Months'%}{% trans '12 Months'%}{% trans '15 Months'%}{% trans '18 Months'%}{% trans '24 Months'%}{% trans '4 Years'%}{% trans '5 Years'%}{% trans '6 Years'%}
{% trans 'OF BIRTH TO THE 6 YEARS OF AGE'%}
{% trans 'Subtitle: '%}
{% trans 'Routine'%}
{% trans 'Vaccinate Unvaccinated'%}
{% trans 'Special Situations'%}
{% trans 'Contraindicated'%}
+
+

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

{% trans 'Vaccines'%}

{% trans '9 TO 10 YEARS OLD'%}{% trans 'ADOLESCENT'%}{% trans 'ADULT'%}{% trans 'OLD MAN'%}
{% trans '9 Years'%}{% trans '10 Years'%}{% trans '11-19 Years'%}{% trans '20-59 Years'%}{% trans '60+ Years'%}
{% trans 'BCG ID'%}{% trans 'Vaccinate people who contacted leprosy'%}
{% trans 'Hepatitis B'%}{% trans 'Vaccinate the previously unvaccinated'%}
{% trans 'Rotavirus'%}{% trans 'CONTRAINDICATED'%}
{% trans 'Bacterial triple (DTPw, DTPa, ou dTpa)'%}{% trans 'Reinforcement with dTpa from 9 years of age and every 10 years (or, in the case of dTpa, do dT)'%}{% trans 'Reinforcement with dTpa from 9 years of age and every 10 years (or, in the case of dTpa, do dT)'%}
{% trans 'Haemophilus influenzae type b'%}{% trans 'Vaccinate people in special risk situations'%}
{% trans 'Poliomyelitis (inactivated virus)'%}{% trans 'Vaccinate people in special risk situations'%}
{% trans 'Pneumococcal conjugate'%}{% trans 'PCV13: vaccinating people in special risk situations'%}{% trans 'VPC13: one dose'%}
{% trans 'Meningococcal conjugate C or ACWY'%}{% trans 'REINFORCED at age 11. For those not previously vaccinated: two doses'%}{% trans 'Vaccinate people in special risk situations'%}
{% trans 'Meningococcal B'%}{% trans 'For those not previously vaccinated: two doses'%}{% trans 'Vaccinate people in special risk situations'%}
{% trans 'Influenza (flu)'%}{% trans 'ANNUAL VACCINATION'%}
{% trans 'Yellow fever'%}{% trans 'IN REGIONS WITH RECOMMENDATION OF VACCINATION (ACCORDING TO CLASSIFICATION OF MS) - single dose at 9 months of age. Not previously vaccinated: single dose'%}
{% trans 'Viral triple (measles, mumps and rubella)'%}{% trans 'Vaccinate the previously unvaccinated'%}{% trans 'Vaccinate people in special risk situations'%}
{% trans 'Varicella (chickenpox)'%}{% trans 'Vaccinate previously unvaccinated susceptibles'%}
{% trans 'Hepatitis A'%}{% trans 'Vaccinate the previously unvaccinated'%}{% trans 'Vaccinate people in special risk situations'%}
{% trans 'HPV'%}{% trans 'Three doses for girls and boys'%}{% trans 'Vaccinate the previously unvaccinated'%}{% trans 'Vaccinate the non-vaccinated formerly: at the discretion of the physician'%}
{% trans 'Pneumococcal 23 courageous'%}{% trans 'Vaccinate people in special risk situations'%}{% trans 'Two doses at five-year intervals'%}
{% trans 'Herpes zoster'%}{% trans 'From 50 to 59 years old: at medical discretion'%}{% trans 'One dose'%}
{% trans 'Dengue'%}{% trans 'To vaccinate people aged 9 to 45 years previously infected with the virus (seropositive) with three doses: 0 - 6 - 12 months'%}{% trans 'CONTRAINDICATED'%}

{% trans 'Vaccines'%}

{% trans '9 Years'%}{% trans '10 Years'%}{% trans '11-19 Years'%}{% trans '20-59 Years'%}{% trans '60+ Years'%}
{% trans '9 TO 10 YEARS OLD'%}{% trans 'ADOLESCENT'%}{% trans 'ADULT'%}{% trans 'OLD MAN'%}
+
+

+ +{% endblock content %} diff --git a/drdown/core/urls.py b/drdown/core/urls.py index cf64f569..d928cd20 100644 --- a/drdown/core/urls.py +++ b/drdown/core/urls.py @@ -14,4 +14,17 @@ view=TemplateView.as_view(template_name='core/info.html'), name='about' ), + url( + regex=r'^vaccine/$', + view=TemplateView.as_view(template_name='core/vaccine_schedule.html'), + name='vaccine' + ), + url( + regex=r'^vaccine/location$', + view=TemplateView.as_view( + template_name='core/vaccination_locations.html' + ), + name='locations' + ), + ] diff --git a/drdown/forum/form/__init__.py b/drdown/forum/form/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/drdown/forum/form/forum_forms.py b/drdown/forum/form/forum_forms.py new file mode 100644 index 00000000..fac77a6e --- /dev/null +++ b/drdown/forum/form/forum_forms.py @@ -0,0 +1,22 @@ +from django import forms +from drdown.forum.models.model_commentary import Commentary +from drdown.forum.models.model_post import Post +from pagedown.widgets import PagedownWidget + + +class ComentaryForm(forms.ModelForm): + + message = forms.CharField(widget=PagedownWidget()) + + class Meta: + model = Commentary + fields = ["message"] + + +class PostForm(forms.ModelForm): + + message = forms.CharField(widget=PagedownWidget()) + + class Meta: + model = Post + fields = ["title", "message"] diff --git a/drdown/forum/locale/pt_BR/LC_MESSAGES/django.po b/drdown/forum/locale/pt_BR/LC_MESSAGES/django.po index 2ec81bf8..84d24fdc 100644 --- a/drdown/forum/locale/pt_BR/LC_MESSAGES/django.po +++ b/drdown/forum/locale/pt_BR/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-04-24 01:32+0000\n" +"POT-Creation-Date: 2018-05-04 10:24+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -45,7 +45,6 @@ msgid "Category" msgstr "Categoria" #: drdown/forum/models/model_category.py:28 -#: drdown/forum/templates/forum/category_list.html:3 #: drdown/forum/templates/forum/category_list.html:7 #: drdown/forum/templates/forum/commentary_list.html:16 #: drdown/forum/templates/forum/form_commentary.html:9 @@ -128,6 +127,10 @@ msgstr "Mensagem do post" msgid "Posts" msgstr "Posts" +#: drdown/forum/templates/forum/category_list.html:3 +msgid "Care ine" +msgstr "" + #: drdown/forum/templates/forum/category_list.html:16 msgid "There are no categories." msgstr "Não há categorias" @@ -194,16 +197,6 @@ msgstr "Novo Comentário" msgid "New Post" msgstr "Nova Postagem" -#: drdown/forum/templates/forum/pagination.html:8 -#: drdown/forum/templates/forum/pagination.html:12 -msgid "Previous" -msgstr "Anterior" - -#: drdown/forum/templates/forum/pagination.html:30 -#: drdown/forum/templates/forum/pagination.html:34 -msgid "Next" -msgstr "Próximo" - #: drdown/forum/templates/forum/post_confirm_delete.html:12 msgid "Are you sure you want to delete " msgstr "Você tem certeza que deseja deletar " @@ -228,3 +221,9 @@ msgstr "Não há posts nessa categoria" #: drdown/forum/tests/test_view_post.py:94 msgid "This field is required." msgstr "Esse campo é obrigatório." + +#~ msgid "Previous" +#~ msgstr "Anterior" + +#~ msgid "Next" +#~ msgstr "Próximo" diff --git a/drdown/forum/templates/forum/category_list.html b/drdown/forum/templates/forum/category_list.html index 403f63a2..60ea288a 100644 --- a/drdown/forum/templates/forum/category_list.html +++ b/drdown/forum/templates/forum/category_list.html @@ -1,11 +1,18 @@ {% extends "core/base.html" %} {% load static i18n %} -{% block title %}{% trans "Care ine" %}{% endblock %} +{% block title %}{% trans "Categories" %}{% endblock %} {% block content %} diff --git a/drdown/forum/templates/forum/form_commentary.html b/drdown/forum/templates/forum/form_commentary.html index 0244629c..8e92f961 100644 --- a/drdown/forum/templates/forum/form_commentary.html +++ b/drdown/forum/templates/forum/form_commentary.html @@ -1,32 +1,20 @@ {% extends 'core/base.html' %} {% load static i18n %} - -{% block title %}{% trans "New Commentary" %}{% endblock %} - +{% block title %}{% trans 'New Medical Record' %}{% endblock %} +{% block css %} +{{block.super}} + +{% endblock %} {% block content %} -
-

{% trans "New Commentary" %}


+

{% trans 'New Commentary' %}

+ {{ form.media }}
{% csrf_token %} - {% for field in form %} -
- {{ field.errors }} -

- {{ field.label_tag }}
- {{ field }} -

-
- {% endfor %} - +
{{ form.message }}

+
-
+ + {% endblock %} diff --git a/drdown/forum/templates/forum/form_post.html b/drdown/forum/templates/forum/form_post.html index bc73f485..086aca5a 100644 --- a/drdown/forum/templates/forum/form_post.html +++ b/drdown/forum/templates/forum/form_post.html @@ -1,31 +1,20 @@ {% extends 'core/base.html' %} {% load static i18n %} - -{% block title %}{% trans "New Post" %}{% endblock %} - +{% block title %}{% trans 'New Medical Record' %}{% endblock %} +{% block css %} +{{block.super}} + +{% endblock %} {% block content %} -
-

{% trans "New Post" %}


+

{% trans 'New Post' %}

+ {{ form.media }}
{% csrf_token %} - {% for field in form %} -
- {{ field.errors }} -

- {{ field.label_tag }}
- {{ field }} -

-
- {% endfor %} - +
{{ form.title }}

+
{{ form.message }}

+
-
- + +

{% endblock %} diff --git a/drdown/forum/templates/forum/post_list.html b/drdown/forum/templates/forum/post_list.html index fab3a020..5cdba82a 100644 --- a/drdown/forum/templates/forum/post_list.html +++ b/drdown/forum/templates/forum/post_list.html @@ -51,7 +51,7 @@

{% trans 'There are no posts in t {% endfor %} - {% include "forum/pagination.html" %} + {% include "core/pagination.html" %} {% endblock content %} diff --git a/drdown/forum/views/view_commentary.py b/drdown/forum/views/view_commentary.py index 859763e1..041bd34b 100644 --- a/drdown/forum/views/view_commentary.py +++ b/drdown/forum/views/view_commentary.py @@ -6,6 +6,7 @@ from django.views.generic import UpdateView from django.urls import reverse_lazy from django.utils import timezone +from drdown.forum.form.forum_forms import ComentaryForm class CommentaryListView(ListView): @@ -25,7 +26,7 @@ def get_queryset(self): class CommentaryCreateView(CreateView): model = Commentary template_name = 'forum/form_commentary.html' - fields = ['message'] + form_class = ComentaryForm def get_success_url(self, **kwargs): success_create_url = reverse_lazy( diff --git a/drdown/forum/views/view_post.py b/drdown/forum/views/view_post.py index 648b4d4e..de71621a 100644 --- a/drdown/forum/views/view_post.py +++ b/drdown/forum/views/view_post.py @@ -6,6 +6,7 @@ from django.views.generic import UpdateView from django.urls import reverse_lazy from django.utils import timezone +from drdown.forum.form.forum_forms import PostForm class PostListView(ListView): @@ -28,8 +29,8 @@ def get_queryset(self): class PostCreateView(CreateView): model = Post + form_class = PostForm template_name = 'forum/form_post.html' - fields = ['title', 'message'] def get_success_url(self, **kwargs): success_create_url = reverse_lazy( @@ -78,8 +79,8 @@ def get_object(self): class PostUpdateView(UpdateView): model = Post + form_class = PostForm template_name = 'forum/form_post.html' - fields = ['message'] def get_success_url(self, **kwargs): success_update_url = reverse_lazy( diff --git a/drdown/medicalrecords/admin.py b/drdown/medicalrecords/admin.py index 5dedd698..fd590f7a 100644 --- a/drdown/medicalrecords/admin.py +++ b/drdown/medicalrecords/admin.py @@ -1,4 +1,14 @@ from django.contrib import admin from .models.model_medical_record import MedicalRecord +from .models.model_static_data import StaticData +from .models.model_medicines import Medicine +from .models.model_specific_exams import SpecificExam +from .models.model_complaint import Complaint +from .models.model_exams import Exam admin.site.register(MedicalRecord) +admin.site.register(StaticData) +admin.site.register(Medicine) +admin.site.register(SpecificExam) +admin.site.register(Complaint) +admin.site.register(Exam) diff --git a/drdown/medicalrecords/apps.py b/drdown/medicalrecords/apps.py index ba90297e..a31d0787 100644 --- a/drdown/medicalrecords/apps.py +++ b/drdown/medicalrecords/apps.py @@ -1,6 +1,7 @@ from django.apps import AppConfig +from django.utils.translation import ugettext_lazy as _ class MedicalRecordsConfig(AppConfig): name = 'drdown.medicalrecords' - verbose_name = 'Medical Records' + verbose_name = _("Medical Record") diff --git a/drdown/medicalrecords/forms/complaint_forms.py b/drdown/medicalrecords/forms/complaint_forms.py new file mode 100644 index 00000000..d2d53b1c --- /dev/null +++ b/drdown/medicalrecords/forms/complaint_forms.py @@ -0,0 +1,12 @@ +from drdown.medicalrecords.models.model_complaint import Complaint +from django import forms +from pagedown.widgets import PagedownWidget + + +class ComplaintForm(forms.ModelForm): + + description = forms.CharField(widget=PagedownWidget()) + + class Meta: + model = Complaint + fields = ["description", "complaint_day", "complaint_time"] diff --git a/drdown/medicalrecords/forms/exam_forms.py b/drdown/medicalrecords/forms/exam_forms.py new file mode 100644 index 00000000..ff94375d --- /dev/null +++ b/drdown/medicalrecords/forms/exam_forms.py @@ -0,0 +1,9 @@ +from drdown.medicalrecords.models.model_exams import Exam +from django import forms + + +class ExamForm(forms.ModelForm): + + class Meta: + model = Exam + fields = ["file", "day", "status", "name"] diff --git a/drdown/medicalrecords/forms/medicalrecords_forms.py b/drdown/medicalrecords/forms/medicalrecords_forms.py index 1b0f3e63..3429267c 100644 --- a/drdown/medicalrecords/forms/medicalrecords_forms.py +++ b/drdown/medicalrecords/forms/medicalrecords_forms.py @@ -1,9 +1,6 @@ from drdown.medicalrecords.models.model_medical_record import MedicalRecord from django import forms -from drdown.users.models.model_health_team import HealthTeam -from drdown.users.models.model_patient import Patient from pagedown.widgets import PagedownWidget -from django.utils.translation import ugettext_lazy as _ class MedicalRecordForm(forms.ModelForm): @@ -13,66 +10,3 @@ class MedicalRecordForm(forms.ModelForm): class Meta: model = MedicalRecord fields = ["message", "document"] - - -class MedicalRecordSearchForm(forms.Form): - search_text = forms.CharField( - required=False, - label='Search patient!', - widget=forms.TextInput( - attrs={'placeholder': _('search here!')} - ) - ) - - search_date = forms.DateField( - required=False, - label='Search date!', - widget=forms.TextInput( - attrs={'placeholder': _('(Year)-(Month)-(Day)')} - ) - ) - - author = forms.ModelChoiceField( - queryset=HealthTeam.objects.all(), - required=False, - label=_('Search author!') - ) - - -class MedicalRecordCompleteSearchForm(forms.Form): - search_text = forms.CharField( - required=False, - label=_('Search patient!'), - widget=forms.TextInput( - attrs={'placeholder': _('search here!')} - ) - ) - - search_date = forms.DateField( - required=False, - label=_('Search date!'), - widget=forms.TextInput( - attrs={'placeholder': _('(Year)-(Month)-(Day)')} - ) - ) - - author = forms.ModelChoiceField( - queryset=HealthTeam.objects.all(), - required=False, - label=_('Search author!') - ) - - patient = forms.ModelChoiceField( - queryset=Patient.objects.all(), - required=False, - label=_('Search patient!') - ) - - -class PatientSearchForm(forms.Form): - - list_patient = forms.ModelChoiceField( - queryset=Patient.objects.all(), - required=False, - label=_('Search patient!') - ) diff --git a/drdown/medicalrecords/forms/medicines_forms.py b/drdown/medicalrecords/forms/medicines_forms.py new file mode 100644 index 00000000..870cdff1 --- /dev/null +++ b/drdown/medicalrecords/forms/medicines_forms.py @@ -0,0 +1,9 @@ +from drdown.medicalrecords.models.model_medicines import Medicine +from django import forms + + +class MedicineForm(forms.ModelForm): + + class Meta: + model = Medicine + fields = ["medicine_name", "medicine_dosage", "medicine_in_use"] diff --git a/drdown/medicalrecords/forms/specific_exams_forms.py b/drdown/medicalrecords/forms/specific_exams_forms.py new file mode 100644 index 00000000..4b99d68f --- /dev/null +++ b/drdown/medicalrecords/forms/specific_exams_forms.py @@ -0,0 +1,10 @@ +from drdown.medicalrecords.models.model_specific_exams import SpecificExam +from django import forms + + +class SpecificExamsForm(forms.ModelForm): + + class Meta: + model = SpecificExam + fields = ["structured_physical_exam", "vision", "ear", "hearth", + "muscle_skeletal_system", "nervous_system"] diff --git a/drdown/medicalrecords/forms/static_data_forms.py b/drdown/medicalrecords/forms/static_data_forms.py new file mode 100644 index 00000000..dd45278a --- /dev/null +++ b/drdown/medicalrecords/forms/static_data_forms.py @@ -0,0 +1,9 @@ +from drdown.medicalrecords.models.model_static_data import StaticData +from django import forms + + +class StaticDataForm(forms.ModelForm): + + class Meta: + model = StaticData + fields = ["weight", "APGAR", "heart_test", "ear_test"] diff --git a/drdown/medicalrecords/locale/pt_BR/LC_MESSAGES/django.po b/drdown/medicalrecords/locale/pt_BR/LC_MESSAGES/django.po index bb8b09d7..5224ca1b 100644 --- a/drdown/medicalrecords/locale/pt_BR/LC_MESSAGES/django.po +++ b/drdown/medicalrecords/locale/pt_BR/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-04-27 20:13+0000\n" +"POT-Creation-Date: 2018-05-10 00:54+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,211 +18,449 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: drdown/medicalrecords/forms/medicalrecords_forms.py:22 -#: drdown/medicalrecords/forms/medicalrecords_forms.py:42 -msgid "search here!" -msgstr "busque aqui!" - -#: drdown/medicalrecords/forms/medicalrecords_forms.py:28 -#: drdown/medicalrecords/forms/medicalrecords_forms.py:48 -msgid "(Year)-(Month)-(Day)" -msgstr "(Ano)-(Mês)-(Dia)" - -#: drdown/medicalrecords/forms/medicalrecords_forms.py:34 -#: drdown/medicalrecords/forms/medicalrecords_forms.py:54 -#, fuzzy -#| msgid "author" -msgid "Search author!" -msgstr "Buscar autor" - -#: drdown/medicalrecords/forms/medicalrecords_forms.py:41 -#: drdown/medicalrecords/forms/medicalrecords_forms.py:60 -#: drdown/medicalrecords/forms/medicalrecords_forms.py:69 -msgid "Search patient!" -msgstr "Buscar paciente" - -#: drdown/medicalrecords/forms/medicalrecords_forms.py:47 -#, fuzzy -#| msgid "Search" -msgid "Search date!" -msgstr "Buscar data" +#: drdown/medicalrecords/apps.py:7 +#: drdown/medicalrecords/models/model_medical_record.py:41 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_confirm_delete.html:5 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:38 +msgid "Medical Record" +msgstr "Prontuário" +#: drdown/medicalrecords/models/model_complaint.py:12 #: drdown/medicalrecords/models/model_medical_record.py:14 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:158 msgid "Created at" msgstr "Criado em" -#: drdown/medicalrecords/models/model_medical_record.py:15 -msgid "Patient Care Day" -msgstr "Dia de criação do prontuário" +#: drdown/medicalrecords/models/model_complaint.py:13 +msgid "Date of creation" +msgstr "Data de criação" + +#: drdown/medicalrecords/models/model_complaint.py:18 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_complaint_form.html:28 +msgid "Day of complaint" +msgstr "Dia da queixa" + +#: drdown/medicalrecords/models/model_complaint.py:22 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_complaint_form.html:33 +msgid "Time of complaint" +msgstr "Hora da queixa" +#: drdown/medicalrecords/models/model_complaint.py:28 +#: drdown/medicalrecords/models/model_exams.py:12 #: drdown/medicalrecords/models/model_medical_record.py:22 -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_patient_list.html:17 +#: drdown/medicalrecords/models/model_medicines.py:12 +#: drdown/medicalrecords/models/model_specific_exams.py:12 +#: drdown/medicalrecords/models/model_static_data.py:13 msgid "Patient" msgstr "Paciente" -#: drdown/medicalrecords/models/model_medical_record.py:26 -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_form.html:14 -msgid "Message" -msgstr "Mensagem" +#: drdown/medicalrecords/models/model_complaint.py:32 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_complaint_form.html:23 +msgid "Description" +msgstr "Descriçao" -#: drdown/medicalrecords/models/model_medical_record.py:27 -#, fuzzy -#| msgid "There are no Medical Records." -msgid "Message of medical records" -msgstr "Não há prontuários.Mensagem do prontuário" +#: drdown/medicalrecords/models/model_complaint.py:33 +msgid "Description of the complaint" +msgstr "Descrição da queixa" +#: drdown/medicalrecords/models/model_complaint.py:40 +#: drdown/medicalrecords/models/model_exams.py:45 #: drdown/medicalrecords/models/model_medical_record.py:34 +#: drdown/medicalrecords/models/model_medicines.py:33 +#: drdown/medicalrecords/models/model_specific_exams.py:54 +#: drdown/medicalrecords/models/model_static_data.py:39 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:153 msgid "Author" msgstr "Autor" -#: drdown/medicalrecords/models/model_medical_record.py:38 -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_confirm_delete.html:5 -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:14 -msgid "Medical Record" -msgstr "Prontuário" +#: drdown/medicalrecords/models/model_complaint.py:44 +msgid "Complaint" +msgstr "Queixa" + +#: drdown/medicalrecords/models/model_complaint.py:45 +msgid "Complaints" +msgstr "Queixas" + +#: drdown/medicalrecords/models/model_complaint.py:52 +msgid "The complaint cannot be in the future!" +msgstr "A queixa não pode ser no futuro!" + +#: drdown/medicalrecords/models/model_exams.py:17 +#: drdown/medicalrecords/models/model_exams.py:52 +msgid "Exam" +msgstr "Exame" + +#: drdown/medicalrecords/models/model_exams.py:21 +msgid "Exam day" +msgstr "Dia de atendimento" -#: drdown/medicalrecords/models/model_medical_record.py:39 -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_patient_list.html:13 -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_search_list.html:12 +#: drdown/medicalrecords/models/model_exams.py:22 +msgid "Day the exam was performed" +msgstr "Dia em que o exame foi realizado" + +#: drdown/medicalrecords/models/model_exams.py:26 +msgid "Executed" +msgstr "Relizado" + +#: drdown/medicalrecords/models/model_exams.py:27 +msgid "Collected" +msgstr "Coletado" + +#: drdown/medicalrecords/models/model_exams.py:28 +msgid "Marked examination" +msgstr "Marcado" + +#: drdown/medicalrecords/models/model_exams.py:32 +msgid "Status" +msgstr "Status" + +#: drdown/medicalrecords/models/model_exams.py:34 +msgid "Please, insert the status of the exam" +msgstr "Por favor, insira o status do exame" + +#: drdown/medicalrecords/models/model_exams.py:38 +msgid "Exam Name" +msgstr "Nome do exame" + +#: drdown/medicalrecords/models/model_exams.py:53 +msgid "Exams" +msgstr "Exames" + +#: drdown/medicalrecords/models/model_medical_record.py:15 +msgid "Patient Care Day" +msgstr "Dia de criação do prontuário" + +#: drdown/medicalrecords/models/model_medical_record.py:26 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_form.html:38 +msgid "Message" +msgstr "Mensagem" + +#: drdown/medicalrecords/models/model_medical_record.py:27 +msgid "Message of medical records" +msgstr "Mensagem do prontuário" + +#: drdown/medicalrecords/models/model_medical_record.py:42 msgid "Medical Records" msgstr "Prontuários" +#: drdown/medicalrecords/models/model_medicines.py:17 +msgid "Medicine Name" +msgstr "Nome do remério" + +#: drdown/medicalrecords/models/model_medicines.py:22 +msgid "Medicine dosage" +msgstr "Dosagem do remédio" + +#: drdown/medicalrecords/models/model_medicines.py:26 +msgid "In use?" +msgstr "Em uso?" + +#: drdown/medicalrecords/models/model_medicines.py:27 +msgid "Does the patient still use this medication?" +msgstr "O paciente ainda usa esse medicamento?" + +#: drdown/medicalrecords/models/model_medicines.py:40 +msgid "Patient Medicine" +msgstr "Remédio do Paciente" + +#: drdown/medicalrecords/models/model_specific_exams.py:18 +msgid "Structured Physical Exam" +msgstr "Exame Físico Estruturado" + +#: drdown/medicalrecords/models/model_specific_exams.py:24 +msgid "Vision Exam" +msgstr "Exame de vista" + +#: drdown/medicalrecords/models/model_specific_exams.py:30 +msgid "Ear Exam" +msgstr "Exame de audição" + +#: drdown/medicalrecords/models/model_specific_exams.py:36 +msgid "Hearth Exam" +msgstr "Exame do coração" + +#: drdown/medicalrecords/models/model_specific_exams.py:42 +msgid "Muscle skeletal system Exam" +msgstr "Sistema músculo esquelético" + +#: drdown/medicalrecords/models/model_specific_exams.py:48 +msgid "Nervous system Exam" +msgstr "Exame do sistema nervoso" + +#: drdown/medicalrecords/models/model_specific_exams.py:61 +msgid "Specific Exam" +msgstr "Exame específico" + +#: drdown/medicalrecords/models/model_specific_exams.py:62 +msgid "Specific Exams" +msgstr "Exames específicos" + +#: drdown/medicalrecords/models/model_static_data.py:17 +msgid "Weight at birth" +msgstr "Peso ao nascer" + +#: drdown/medicalrecords/models/model_static_data.py:18 +msgid "In grams" +msgstr "Em gramas" + +#: drdown/medicalrecords/models/model_static_data.py:28 +msgid "Heart Test" +msgstr "Teste do coraçãozinho" + +#: drdown/medicalrecords/models/model_static_data.py:33 +msgid "Test of the Ear" +msgstr "Teste da orelinha" + +#: drdown/medicalrecords/models/model_static_data.py:46 +msgid "Medical Record Static Data" +msgstr "Prontuário - Dados Estáticos" + +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_complaint_form.html:4 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_exam_form.html:4 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_form.html:4 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_form.html:23 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_medicine_form.html:4 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_specific_exams_form.html:4 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_static_data_form.html:4 +msgid "New Medical Record" +msgstr "Novo prontuário" + +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_complaint_form.html:15 +msgid "Add new Complaint" +msgstr "Adicionar nova queixa" + +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_complaint_form.html:37 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_exam_form.html:30 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_form.html:64 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_medicine_form.html:30 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_specific_exams_form.html:60 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_static_data_form.html:60 +msgid "Save" +msgstr "Salvar" + +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_complaint_form.html:39 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_confirm_delete.html:16 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_exam_form.html:32 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_form.html:70 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_medicine_form.html:32 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_specific_exams_form.html:64 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_static_data_form.html:64 +msgid "Cancel" +msgstr "Cancelar" + #: drdown/medicalrecords/templates/medicalrecords/medicalrecord_confirm_delete.html:8 -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_confirm_delete.html:14 -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:66 -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_search_list.html:42 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_confirm_delete.html:18 msgid "Delete" msgstr "Apagar" -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_confirm_delete.html:12 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_confirm_delete.html:14 msgid "Are you sure you want to delete this medical record?" msgstr "Você tem certeza que deseja apagar este prontuário?" -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_confirm_delete.html:13 -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_form.html:17 -msgid "Cancel" -msgstr "Cancelar" - -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_form.html:3 -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_form.html:10 -msgid "New Medical Record" -msgstr "Novo prontuário" +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_exam_form.html:14 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_specific_exams_form.html:16 +msgid "Add Specific Exams" +msgstr "Adicionar exame específico" -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_form.html:15 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_form.html:53 msgid "Attachments" msgstr "Anexos" -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_form.html:16 -msgid "Save" -msgstr "Salvar" - #: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:4 -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_patient_list.html:4 -msgid "Medical Records:" +msgid "Medical Record:" msgstr "Prontuários:" -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:14 -msgid "'s" -msgstr "do(a)" +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:42 +msgid "Return" +msgstr "Retornar" -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:16 -msgid "There are no Medical Records for this patient." -msgstr "Não prontuário para este paciente." +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:51 +msgid "Patient data" +msgstr "Dados do paciente" -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:18 -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:26 -msgid "New" -msgstr "Novo" +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:55 +msgid "Important notes" +msgstr "Observações importantes" -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:22 #: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:59 -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_search_list.html:16 -msgid "author" -msgstr "autor" - -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:23 -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_search_list.html:18 -msgid "date" -msgstr "data" - -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:24 -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_patient_list.html:18 -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_search_list.html:21 -msgid "Search" -msgstr "Buscar" - -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:28 -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_search_list.html:22 -msgid "Return" -msgstr "Retornar" +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:188 +msgid "Postnatal data" +msgstr "Dados do pós-natal" -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:41 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:63 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:275 +msgid "Medical Exams" +msgstr "Exames Médicos" + +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:92 msgid "Name: " msgstr "Nome: " -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:42 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:98 msgid "SUS: " msgstr "SUS: " -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:43 -msgid "birthday: " +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:104 +msgid "Birthday: " msgstr "Data de nascimento: " -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:45 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:112 msgid "cpf: " msgstr "CPF" -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:61 -msgid "Anexo:" -msgstr "Anexo:" +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:126 +msgid "Important Notes" +msgstr "Observações importantes" -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:63 -msgid "care day" -msgstr "Dia de atendimento" +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:130 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:196 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:281 +msgid "New" +msgstr "Novo" -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:65 -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_search_list.html:41 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:167 +msgid "Attachment:" +msgstr "Anexos:" + +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:176 +msgid "There are no Important notes for this patient." +msgstr "Não há observações importantes para este paciente." + +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:194 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:283 msgid "Edit" msgstr "Editar" -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_patient_list.html:19 -msgid "Advanced Search" -msgstr "Busca avançada" +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:213 +msgid "Weight at birth: " +msgstr "Peso ao nascer:" + +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:215 +msgid "grams" +msgstr "gramas" -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_patient_list.html:30 -msgid "There are no Medical Records." -msgstr "Não há prontuários." +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:221 +msgid "APGAR: " +msgstr "APGAR:" -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_search_list.html:3 -msgid "Search a Medical Records:" -msgstr "Buscar um prontuário:" +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:234 +msgid "Heart Test:" +msgstr "Teste do coraçãozinho:" -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_search_list.html:17 -msgid "message" -msgstr "mensagem" +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:244 +msgid "Ear Test:" +msgstr "Teste da orelinha:" -#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_search_list.html:19 -msgid "paciente" -msgstr "paciente" +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:258 +msgid "No postnatal data for this patient." +msgstr "Não há dados de pós-natal para este paciente." -#: drdown/medicalrecords/templates/medicalrecords/pagination.html:8 -#: drdown/medicalrecords/templates/medicalrecords/pagination.html:12 -msgid "Previous" -msgstr "Anterior" +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:298 +msgid "Structured Physical:" +msgstr "Físico Estruturado" -#: drdown/medicalrecords/templates/medicalrecords/pagination.html:30 -#: drdown/medicalrecords/templates/medicalrecords/pagination.html:34 -msgid "Next" -msgstr "Proximo" +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:309 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:330 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:350 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:375 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:395 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:415 +msgid "Not send" +msgstr "Não enviado" -#: drdown/medicalrecords/tests/test_medical_records_view.py:82 +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:320 +msgid "Vision:" +msgstr "Visão" + +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:340 +msgid "Ear:" +msgstr "Audição" + +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:365 +msgid "Heart:" +msgstr "Coração" + +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:385 +msgid "Muscle skeletal system:" +msgstr "Sistema músculo esquelético:" + +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html:405 +msgid "Nervous System:" +msgstr "Sistema nervoso:" + +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_medicine_form.html:14 +msgid "New Medicine" +msgstr "Novo Remédio" + +#: drdown/medicalrecords/templates/medicalrecords/medicalrecord_static_data_form.html:16 +#, fuzzy +#| msgid "Static Data" +msgid "Update Static Data" +msgstr "Dados estáticos" + +#: drdown/medicalrecords/tests/test_medical_records_view.py:136 msgid "This field is required." msgstr "Este campo é obrigatório." -#, fuzzy -#~| msgid "Attachments" +#~ msgid "data" +#~ msgstr "dados" + +#~ msgid "Update Neonatal Data" +#~ msgstr "Atualizar dados neonatais" + +#~ msgid "'s" +#~ msgstr "do(a)" + +#~ msgid "search here!" +#~ msgstr "busque aqui!" + +#~ msgid "(Year)-(Month)-(Day)" +#~ msgstr "(Ano)-(Mês)-(Dia)" + +#~ msgid "Search author!" +#~ msgstr "Buscar autor!" + +#~ msgid "Search patient!" +#~ msgstr "Buscar paciente!" + +#~ msgid "Search date!" +#~ msgstr "Buscar data!" + +#~ msgid "author" +#~ msgstr "autor" + +#~ msgid "date" +#~ msgstr "data" + +#~ msgid "Search" +#~ msgstr "Buscar" + +#~ msgid "Anexo:" +#~ msgstr "Anexo:" + +#~ msgid "Advanced Search" +#~ msgstr "Busca avançada" + +#~ msgid "There are no Medical Records." +#~ msgstr "Não há prontuários." + +#~ msgid "Search a Medical Records:" +#~ msgstr "Buscar um prontuário:" + +#~ msgid "paciente" +#~ msgstr "paciente" + +#~ msgid "Previous" +#~ msgstr "Anterior" + +#~ msgid "Next" +#~ msgstr "Próximo" + +#~ msgid "message" +#~ msgstr "mensagem" + #~ msgid "Documents" -#~ msgstr "Anexos" +#~ msgstr "Documentos" #~ msgid "Create" #~ msgstr "Criar" diff --git a/drdown/medicalrecords/migrations/0003_complaint_exam_medicine_specificexam_staticdata.py b/drdown/medicalrecords/migrations/0003_complaint_exam_medicine_specificexam_staticdata.py new file mode 100644 index 00000000..343903e8 --- /dev/null +++ b/drdown/medicalrecords/migrations/0003_complaint_exam_medicine_specificexam_staticdata.py @@ -0,0 +1,95 @@ +# Generated by Django 2.0.3 on 2018-05-10 00:17 + +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0016_auto_20180506_2043'), + ('medicalrecords', '0002_auto_20180428_0044'), + ] + + operations = [ + migrations.CreateModel( + name='Complaint', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True, help_text='Date of creation', verbose_name='Created at')), + ('complaint_day', models.DateField(verbose_name='Day of complaint')), + ('complaint_time', models.TimeField(verbose_name='Time of complaint')), + ('description', models.TextField(help_text='Description of the complaint', max_length=4000, verbose_name='Description')), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.HealthTeam', verbose_name='Author')), + ('patient', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.Patient', verbose_name='Patient')), + ], + options={ + 'verbose_name': 'Complaint', + 'verbose_name_plural': 'Complaints', + }, + ), + migrations.CreateModel( + name='Exam', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('file', models.FileField(upload_to='media/medicalrecords/exams', verbose_name='Exam')), + ('day', models.DateTimeField(help_text='Day the exam was performed', verbose_name='Exam day')), + ('status', models.IntegerField(choices=[(3, 'Executed'), (2, 'Collected'), (1, 'Marked examination')], help_text='Please, insert the status of the exam', verbose_name='Status')), + ('name', models.CharField(max_length=200, verbose_name='Exam Name')), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.HealthTeam', verbose_name='Author')), + ('patient', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.Patient', verbose_name='Patient')), + ], + options={ + 'verbose_name': 'Exam', + 'verbose_name_plural': 'Exams', + }, + ), + migrations.CreateModel( + name='Medicine', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('medicine_name', models.CharField(max_length=100, verbose_name='Medicine Name')), + ('medicine_dosage', models.CharField(max_length=100, verbose_name='Medicine dosage')), + ('medicine_in_use', models.BooleanField(help_text='Does the patient still use this medication?', verbose_name='In use?')), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.HealthTeam', verbose_name='Author')), + ('patient', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.Patient', verbose_name='Patient')), + ], + options={ + 'verbose_name': 'Patient Medicine', + }, + ), + migrations.CreateModel( + name='SpecificExam', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('structured_physical_exam', models.FileField(blank=True, upload_to='media/medicalrecords/specificexams', verbose_name='Structured Physical Exam')), + ('vision', models.FileField(blank=True, upload_to='media/medicalrecords/specificexams', verbose_name='Vision Exam')), + ('ear', models.FileField(blank=True, upload_to='media/medicalrecords/specificexams', verbose_name='Ear Exam')), + ('hearth', models.FileField(blank=True, upload_to='media/medicalrecords/specificexams', verbose_name='Hearth Exam')), + ('muscle_skeletal_system', models.FileField(blank=True, upload_to='media/medicalrecords/specificexams', verbose_name='Muscle skeletal system Exam')), + ('nervous_system', models.FileField(blank=True, upload_to='media/medicalrecords/specificexams', verbose_name='Nervous system Exam')), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.HealthTeam', verbose_name='Author')), + ('patient', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='users.Patient', verbose_name='Patient')), + ], + options={ + 'verbose_name': 'Specific Exam', + 'verbose_name_plural': 'Specific Exams', + }, + ), + migrations.CreateModel( + name='StaticData', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('weight', models.PositiveIntegerField(help_text='In grams', validators=[django.core.validators.MaxValueValidator(9999)], verbose_name='Weight at birth')), + ('APGAR', models.IntegerField(choices=[(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9), (10, 10)])), + ('heart_test', models.FileField(upload_to='media/medicalrecords', verbose_name='Heart Test')), + ('ear_test', models.FileField(upload_to='media/medicalrecords', verbose_name='Test of the Ear')), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.HealthTeam', verbose_name='Author')), + ('patient', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='users.Patient', verbose_name='Patient')), + ], + options={ + 'verbose_name': 'Medical Record Static Data', + }, + ), + ] diff --git a/drdown/medicalrecords/models/model_complaint.py b/drdown/medicalrecords/models/model_complaint.py new file mode 100644 index 00000000..7266f6a1 --- /dev/null +++ b/drdown/medicalrecords/models/model_complaint.py @@ -0,0 +1,59 @@ +from django.db import models +from drdown.users.models.model_health_team import HealthTeam +from drdown.users.models.model_patient import Patient +from django.utils.translation import ugettext_lazy as _ +from django.utils import timezone +from django.core.exceptions import ValidationError + + +class Complaint(models.Model): + + created_at = models.DateTimeField( + _('Created at'), + help_text=_('Date of creation'), + auto_now_add=True + ) + + complaint_day = models.DateField( + _('Day of complaint'), + ) + + complaint_time = models.TimeField( + _('Time of complaint'), + ) + + patient = models.ForeignKey( + Patient, + on_delete=models.CASCADE, + verbose_name=_('Patient') + ) + + description = models.TextField( + _('Description'), + help_text=_('Description of the complaint'), + max_length=4000 + ) + + author = models.ForeignKey( + HealthTeam, + on_delete=models.CASCADE, + verbose_name=_("Author") + ) + + class Meta: + verbose_name = _("Complaint") + verbose_name_plural = _("Complaints") + + def clean(self, *args, **kwargs): + if self.complaint_day: + if timezone.localdate().isoformat() < str(self.complaint_day): + raise ValidationError( + {'complaint_day': + _("The complaint cannot be in the future!")} + ) + + return super(Complaint, self).clean() + + def __str__(self): + return self.patient.user.get_username() + " - Comptaint ID: " + \ + str(self.id) diff --git a/drdown/medicalrecords/models/model_exams.py b/drdown/medicalrecords/models/model_exams.py new file mode 100644 index 00000000..df02b6bc --- /dev/null +++ b/drdown/medicalrecords/models/model_exams.py @@ -0,0 +1,53 @@ +from django.db import models +from drdown.users.models.model_health_team import HealthTeam +from drdown.users.models.model_patient import Patient +from django.utils.translation import ugettext_lazy as _ + + +class Exam(models.Model): + + patient = models.ForeignKey( + Patient, + on_delete=models.CASCADE, + verbose_name=_('Patient') + ) + + file = models.FileField( + upload_to='media/medicalrecords/exams', + verbose_name=_('Exam') + ) + + day = models.DateTimeField( + _('Exam day'), + help_text=_('Day the exam was performed'), + ) + + STATUS = ( + (3, _('Executed')), + (2, _('Collected')), + (1, _('Marked examination')), + ) + + status = models.IntegerField( + _('Status'), + choices=STATUS, + help_text=_("Please, insert the status of the exam"), + ) + + name = models.CharField( + _('Exam Name'), + max_length=200 + ) + + author = models.ForeignKey( + HealthTeam, + on_delete=models.CASCADE, + verbose_name=_("Author") + ) + + def __str__(self): + return self.patient.user.get_username() + " - " + self.name + + class Meta: + verbose_name = _("Exam") + verbose_name_plural = _("Exams") diff --git a/drdown/medicalrecords/models/model_medical_record.py b/drdown/medicalrecords/models/model_medical_record.py index d962c004..7dd727d9 100644 --- a/drdown/medicalrecords/models/model_medical_record.py +++ b/drdown/medicalrecords/models/model_medical_record.py @@ -34,6 +34,9 @@ class MedicalRecord(models.Model): verbose_name=_("Author") ) + def __str__(self): + return self.patient.user.get_username() + class Meta: verbose_name = _("Medical Record") verbose_name_plural = _("Medical Records") diff --git a/drdown/medicalrecords/models/model_medicines.py b/drdown/medicalrecords/models/model_medicines.py new file mode 100644 index 00000000..6f888644 --- /dev/null +++ b/drdown/medicalrecords/models/model_medicines.py @@ -0,0 +1,40 @@ +from django.db import models +from drdown.users.models.model_health_team import HealthTeam +from drdown.users.models.model_patient import Patient +from django.utils.translation import ugettext_lazy as _ + + +class Medicine(models.Model): + + patient = models.ForeignKey( + Patient, + on_delete=models.CASCADE, + verbose_name=_('Patient') + ) + + medicine_name = models.CharField( + max_length=100, + verbose_name=_('Medicine Name') + ) + + medicine_dosage = models.CharField( + max_length=100, + verbose_name=_('Medicine dosage') + ) + + medicine_in_use = models.BooleanField( + verbose_name=_('In use?'), + help_text=_('Does the patient still use this medication?') + ) + + author = models.ForeignKey( + HealthTeam, + on_delete=models.CASCADE, + verbose_name=_("Author") + ) + + def __str__(self): + return self.patient.user.get_username() + " - " + self.medicine_name + + class Meta: + verbose_name = _("Patient Medicine") diff --git a/drdown/medicalrecords/models/model_specific_exams.py b/drdown/medicalrecords/models/model_specific_exams.py new file mode 100644 index 00000000..034f796e --- /dev/null +++ b/drdown/medicalrecords/models/model_specific_exams.py @@ -0,0 +1,62 @@ +from django.db import models +from drdown.users.models.model_health_team import HealthTeam +from drdown.users.models.model_patient import Patient +from django.utils.translation import ugettext_lazy as _ + + +class SpecificExam(models.Model): + + patient = models.OneToOneField( + Patient, + on_delete=models.CASCADE, + verbose_name=_('Patient') + ) + + structured_physical_exam = models.FileField( + upload_to='media/medicalrecords/specificexams', + blank=True, + verbose_name=_('Structured Physical Exam') + ) + + vision = models.FileField( + upload_to='media/medicalrecords/specificexams', + blank=True, + verbose_name=_('Vision Exam') + ) + + ear = models.FileField( + upload_to='media/medicalrecords/specificexams', + blank=True, + verbose_name=_('Ear Exam') + ) + + hearth = models.FileField( + upload_to='media/medicalrecords/specificexams', + blank=True, + verbose_name=_('Hearth Exam') + ) + + muscle_skeletal_system = models.FileField( + upload_to='media/medicalrecords/specificexams', + blank=True, + verbose_name=_('Muscle skeletal system Exam') + ) + + nervous_system = models.FileField( + upload_to='media/medicalrecords/specificexams', + blank=True, + verbose_name=_('Nervous system Exam') + ) + + author = models.ForeignKey( + HealthTeam, + on_delete=models.CASCADE, + verbose_name=_("Author") + ) + + def __str__(self): + return self.patient.user.get_username() + + class Meta: + verbose_name = _("Specific Exam") + verbose_name_plural = _("Specific Exams") diff --git a/drdown/medicalrecords/models/model_static_data.py b/drdown/medicalrecords/models/model_static_data.py new file mode 100644 index 00000000..a1824652 --- /dev/null +++ b/drdown/medicalrecords/models/model_static_data.py @@ -0,0 +1,46 @@ +from django.db import models +from drdown.users.models.model_health_team import HealthTeam +from drdown.users.models.model_patient import Patient +from django.utils.translation import ugettext_lazy as _ +from django.core.validators import MaxValueValidator + + +class StaticData(models.Model): + + patient = models.OneToOneField( + Patient, + on_delete=models.CASCADE, + verbose_name=_('Patient') + ) + + weight = models.PositiveIntegerField( + verbose_name=_('Weight at birth'), + help_text=_('In grams'), + validators=[MaxValueValidator(9999)] + ) + + APGAR = models.IntegerField( + choices=list(zip(range(1, 11), range(1, 11))), + ) + + heart_test = models.FileField( + upload_to='media/medicalrecords', + verbose_name=_('Heart Test') + ) + + ear_test = models.FileField( + upload_to='media/medicalrecords', + verbose_name=_('Test of the Ear') + ) + + author = models.ForeignKey( + HealthTeam, + on_delete=models.CASCADE, + verbose_name=_("Author") + ) + + def __str__(self): + return self.patient.user.get_username() + + class Meta: + verbose_name = _("Medical Record Static Data") diff --git a/drdown/medicalrecords/static/medicalrecords/css/medicalrecords.css b/drdown/medicalrecords/static/medicalrecords/css/medicalrecords.css index 0ae54f7e..f4037f8d 100644 --- a/drdown/medicalrecords/static/medicalrecords/css/medicalrecords.css +++ b/drdown/medicalrecords/static/medicalrecords/css/medicalrecords.css @@ -1,15 +1,7 @@ -.left-btn{ - margin-left: 75%; -} - .search{ padding: 20px; } -.align-btn{ - margin-top: 22px; -} - .align-photo{ position: relative; padding-right: 20px; @@ -41,3 +33,32 @@ word-wrap: break-word; } + +.tab-pane { + + border-left: 2px solid #ddd; + border-right: 2px solid #ddd; + border-bottom: 2px solid #ddd; + border-radius: 0px 0px 5px 5px; + padding: 10px; +} + +.nav-tabs-extension { + margin-bottom: 0; + background: transparent; +} + +.nav-link-extension{ + color: #ddd; + background: #2C3E50; +} + +.nav-link-extension:hover{ + font-weight: bold; + color: #ddd; + background: #1a252f; +} + + + + diff --git a/drdown/medicalrecords/templates/medicalrecords/medicalrecord_complaint_form.html b/drdown/medicalrecords/templates/medicalrecords/medicalrecord_complaint_form.html new file mode 100644 index 00000000..5d1ba225 --- /dev/null +++ b/drdown/medicalrecords/templates/medicalrecords/medicalrecord_complaint_form.html @@ -0,0 +1,48 @@ +{% extends 'core/base.html' %} +{% load static i18n %} + +{% block title %}{% trans 'New Medical Record' %}{% endblock %} + +{% block css %} +{{block.super}} + +{% endblock %} + +{% block content %} + + + +
+
+ +{% endblock %} diff --git a/drdown/medicalrecords/templates/medicalrecords/medicalrecord_confirm_delete.html b/drdown/medicalrecords/templates/medicalrecords/medicalrecord_confirm_delete.html index c875375e..3d7a9074 100644 --- a/drdown/medicalrecords/templates/medicalrecords/medicalrecord_confirm_delete.html +++ b/drdown/medicalrecords/templates/medicalrecords/medicalrecord_confirm_delete.html @@ -8,9 +8,13 @@

{% trans 'Delete' %}

+ {% csrf_token %} +

{% trans 'Are you sure you want to delete this medical record?' %}

+ {% trans 'Cancel' %} +
diff --git a/drdown/medicalrecords/templates/medicalrecords/medicalrecord_exam_form.html b/drdown/medicalrecords/templates/medicalrecords/medicalrecord_exam_form.html new file mode 100644 index 00000000..49e5f4bd --- /dev/null +++ b/drdown/medicalrecords/templates/medicalrecords/medicalrecord_exam_form.html @@ -0,0 +1,41 @@ +{% extends 'core/base.html' %} +{% load static i18n %} + +{% block title %}{% trans 'New Medical Record' %}{% endblock %} + +{% block css %} +{{block.super}} + +{% endblock %} + +{% block content %} +
+ +

{% trans 'Add Specific Exams' %}

+ +
+ + {% csrf_token %} + + {% for field in form %} +
+ {{ field.errors }} +

+ {{ field.label_tag }}
+ {{ field }} +

+
+ {% endfor %} + + + + {% trans "Cancel" %} + +
+ +
+ +
+
+ +{% endblock %} diff --git a/drdown/medicalrecords/templates/medicalrecords/medicalrecord_form.html b/drdown/medicalrecords/templates/medicalrecords/medicalrecord_form.html index 1c31c615..06172f25 100644 --- a/drdown/medicalrecords/templates/medicalrecords/medicalrecord_form.html +++ b/drdown/medicalrecords/templates/medicalrecords/medicalrecord_form.html @@ -1,20 +1,81 @@ {% extends 'core/base.html' %} {% load static i18n %} + {% block title %}{% trans 'New Medical Record' %}{% endblock %} + {% block css %} {{block.super}} {% endblock %} -{% block content %} -
-

{% trans 'New Medical Record' %}

+ +{% block script %} + {{ form.media }} -
- {% csrf_token %} -
{{ form.message }}

-
{{ form.document }}

- - {% trans "Cancel" %} -
-


+ +{% endblock script %} + +{% block content %} +
+ + +
+
+

{% trans 'New Medical Record' %}

+
+
+ +
+
+
+ + {% csrf_token %} + +
+ +
+ + + + +
+ {{ form.message }} +
+ +
+
+ + +
+
+ + {{ form.document }} + +
+
+ +
+ +
+ +
+ + + +
+ + +
+ + +
+
+
+
+ {% endblock %} diff --git a/drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html b/drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html index 05e24a06..9684f537 100644 --- a/drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html +++ b/drdown/medicalrecords/templates/medicalrecords/medicalrecord_list.html @@ -1,75 +1,434 @@ {% extends "core/base.html" %} {% load markdown_deux_tags %} {% load static i18n %} -{% block title %}{% trans "Medical Records:" %}{% endblock %} +{% block title %}{% trans "Medical Record:" %} {{ related_patient.user.name }}{% endblock %} {% block css %} {{block.super}} {% endblock %} +{% block script %} + + + + + +{%endblock script%} + + {% block content %} -
-

{% trans 'Medical Record' %} {% trans "'s"%} {{ view.related_patient.user.name }}

- {% if elect_count == 0 %} -

{% trans 'There are no Medical Records for this patient.'%}

- {% if user.healthteam %} - {% trans "New" %} - {% endif %} - {% else %} -
- - - - {% if user.healthteam %} - {% trans "New" %} - {% endif %} - -
- {% endif %} - {% trans "Return" %} -
- -
- {% if view.related_patient.user.patient %} - {% if view.related_patient.user.photo %} - - {% else %} - - {% endif %} -
-
-
-
- {% if view.related_patient.user.cpf %} - {{ view.related_patient.cpf }} - {% endif %} -
- {% endif %} -
- - - -
-
- {% for medicalrecord in medicalrecord_list %} - {% if view.kwargs.username == medicalrecord.patient.user.username %} -
-

{{ medicalrecord.message|markdown }}

-

{{ medicalrecord.author.user.name }}

- {% if medicalrecord.document %} -

{% trans 'Anexo:' %} {{ medicalrecord.document.name }}

- {% endif %} -

{{ medicalrecord.day }}

- {% if request.user.username == medicalrecord.author.user.username %} - {% trans "Edit" %} - {% trans "Delete" %}

- {% endif %} +
+ +
+
+

{% trans 'Medical Record' %}: {{ related_patient.user.name }}

+
+ + + +
+ +
+
+ + +
+ +
+ +
+ +
+ {% if related_patient.user.photo %} + + {% else %} + + {% endif %} +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ + {% if related_patient.user.cpf %} + +
+ {{ related_patient.cpf }} +
+ + {% endif %} + +
+ +
+
+ + + + + + + +
- {% endif %} - {% endfor %} -
+
-
+
{% endblock content %} diff --git a/drdown/medicalrecords/templates/medicalrecords/medicalrecord_medicine_form.html b/drdown/medicalrecords/templates/medicalrecords/medicalrecord_medicine_form.html new file mode 100644 index 00000000..459753b7 --- /dev/null +++ b/drdown/medicalrecords/templates/medicalrecords/medicalrecord_medicine_form.html @@ -0,0 +1,41 @@ +{% extends 'core/base.html' %} +{% load static i18n %} + +{% block title %}{% trans 'New Medical Record' %}{% endblock %} + +{% block css %} +{{block.super}} + +{% endblock %} + +{% block content %} +
+ +

{% trans 'New Medicine' %}

+ +
+ + {% csrf_token %} + + {% for field in form %} +
+ {{ field.errors }} +

+ {{ field.label_tag }}
+ {{ field }} +

+
+ {% endfor %} + + + + {% trans "Cancel" %} + +
+ +
+ +
+
+ +{% endblock %} diff --git a/drdown/medicalrecords/templates/medicalrecords/medicalrecord_patient_list.html b/drdown/medicalrecords/templates/medicalrecords/medicalrecord_patient_list.html deleted file mode 100644 index 3f1d93e5..00000000 --- a/drdown/medicalrecords/templates/medicalrecords/medicalrecord_patient_list.html +++ /dev/null @@ -1,34 +0,0 @@ -{% extends "core/base.html" %} -{% load static i18n %} - -{% block title %}{% trans 'Medical Records:' %}{% endblock %} - -{% block css %} -{{block.super}} - -{% endblock %} - -{% block content %} -
-

{% trans 'Medical Records' %}

-
- {% if user.is_authenticated %} -
- - - {% trans 'Advanced Search' %} - -
- {% endif %} -
-
- {% for patients in patient_list %} - -

{{ patients.user.username }}

-
- {% empty %} -

{% trans 'There are no Medical Records.'%}

- {% endfor %} -
-
-{% endblock content %} diff --git a/drdown/medicalrecords/templates/medicalrecords/medicalrecord_search_list.html b/drdown/medicalrecords/templates/medicalrecords/medicalrecord_search_list.html deleted file mode 100644 index dcee7aac..00000000 --- a/drdown/medicalrecords/templates/medicalrecords/medicalrecord_search_list.html +++ /dev/null @@ -1,49 +0,0 @@ -{% extends "core/base.html" %} -{% load static i18n %} -{% block title %}{% trans "Search a Medical Records:" %}{% endblock %} - -{% block css %} -{{block.super}} - -{% endblock %} - -{% block content %} -
-

{% trans 'Medical Records' %}

-
-

-

- - - - - - {% trans "Return" %} - -
-

- -
- -
-
- {% for medicalrecord in medicalrecord_list %} - -
-

{{ medicalrecord.patient }}

-

{{ medicalrecord.message }}

-

{{ medicalrecord.author }}

- {% if medicalrecord.document %} -

Anexo: {{ medicalrecord.document.name }}

- {% endif %} -

{{ medicalrecord.day }}

- {% trans 'Edit' %} - {% trans 'Delete' %}

-
- - {% endfor %} -
-

{% include "medicalrecords/pagination.html" %}

-
-
-{% endblock content %} diff --git a/drdown/medicalrecords/templates/medicalrecords/medicalrecord_specific_exams_form.html b/drdown/medicalrecords/templates/medicalrecords/medicalrecord_specific_exams_form.html new file mode 100644 index 00000000..8ca2b71c --- /dev/null +++ b/drdown/medicalrecords/templates/medicalrecords/medicalrecord_specific_exams_form.html @@ -0,0 +1,74 @@ +{% extends 'core/base.html' %} +{% load static i18n %} + +{% block title %}{% trans 'New Medical Record' %}{% endblock %} + +{% block css %} +{{block.super}} + +{% endblock %} + +{% block content %} +
+ +
+
+

{% trans 'Add Specific Exams' %}

+
+
+ +
+
+ +
+ + {% csrf_token %} + + {% for field in form %} + +
+ +
+ + + {% if field.errors %} +
+ {{ field.errors }} +
+ {% endif %} + + +
+ {{ field.label_tag }} +
+ +
+ {{ field }} +
+ +
+ +
+ + {% endfor %} +
+ +
+
+ +
+ +
+ + +
+
+ +
+
+ +
+ +{% endblock %} diff --git a/drdown/medicalrecords/templates/medicalrecords/medicalrecord_static_data_form.html b/drdown/medicalrecords/templates/medicalrecords/medicalrecord_static_data_form.html new file mode 100644 index 00000000..3e645f51 --- /dev/null +++ b/drdown/medicalrecords/templates/medicalrecords/medicalrecord_static_data_form.html @@ -0,0 +1,74 @@ +{% extends 'core/base.html' %} +{% load static i18n %} + +{% block title %}{% trans 'New Medical Record' %}{% endblock %} + +{% block css %} +{{block.super}} + +{% endblock %} + +{% block content %} +
+ +
+
+

{% trans 'Update Static Data' %}

+
+
+ +
+
+ +
+ + {% csrf_token %} + + {% for field in form %} + +
+ +
+ + + {% if field.errors %} +
+ {{ field.errors }} +
+ {% endif %} + + +
+ {{ field.label_tag }} +
+ +
+ {{ field }} +
+ +
+ +
+ + {% endfor %} +
+ +
+
+ +
+ +
+ + +
+
+ +
+
+ +
+ +{% endblock %} diff --git a/drdown/medicalrecords/templates/medicalrecords/pagination.html b/drdown/medicalrecords/templates/medicalrecords/pagination.html deleted file mode 100644 index 16db9600..00000000 --- a/drdown/medicalrecords/templates/medicalrecords/pagination.html +++ /dev/null @@ -1,39 +0,0 @@ -{% load i18n %} - -{% if is_paginated %} - -{% endif %} diff --git a/drdown/medicalrecords/tests/test_medical_records_view.py b/drdown/medicalrecords/tests/test_medical_records_view.py index 24b4b752..fc52bf41 100644 --- a/drdown/medicalrecords/tests/test_medical_records_view.py +++ b/drdown/medicalrecords/tests/test_medical_records_view.py @@ -1,14 +1,19 @@ from test_plus.test import TestCase -from ..models.model_medical_record import MedicalRecord -from ..views.view_medical_record import MedicalRecordsSearchList -from ..views.view_medical_record import MedicalRecordCompleteSearchForm +from django.core.exceptions import ValidationError from drdown.users.models.model_health_team import HealthTeam from drdown.users.models.model_patient import Patient -from drdown.users.models.model_user import User +from drdown.users.models.model_employee import Employee +from ..models.model_exams import Exam +from ..models.model_medical_record import MedicalRecord +from ..models.model_static_data import StaticData +from ..models.model_medicines import Medicine +from ..models.model_specific_exams import SpecificExam +from ..models.model_complaint import Complaint from django.test.client import Client -from django.urls import reverse, reverse_lazy +from django.urls import reverse from django.utils.translation import ugettext_lazy as _ from django.utils import timezone +from unittest.mock import * class TestViewMedicalRecords(TestCase): @@ -22,6 +27,7 @@ def setUp(self): self.user_1 = self.make_user() self.user_2 = self.make_user(username="teste_2") self.user_3 = self.make_user(username="teste_3") + self.user_4 = self.make_user(username="teste_4") self.patient = Patient.objects.create(ses="1234567", user=self.user_2, priority=1, mother_name="Mãe", @@ -48,6 +54,51 @@ def setUp(self): document="test.txt", ) + self.complaint = Complaint.objects.create( + created_at=timezone.datetime.today(), + complaint_day=timezone.now() - timezone.timedelta(days=1), + complaint_time='15:40', + patient=self.patient, + description="Não tô legal", + author=self.health_team + ) + + self.employee = Employee.objects.create( + cpf="974.220.200-16", + user=self.user_4, + departament=Employee.ADMINISTRATION + ) + + self.exam = Exam.objects.create( + patient=self.patient, + day=timezone.now() - timezone.timedelta(days=1), + status=3, + name="Sangue", + author=self.health_team + ) + + self.medicine = Medicine.objects.create( + patient=self.patient, + medicine_name="Neosaldina", + medicine_dosage="2", + medicine_in_use=True, + author=self.health_team + ) + + self.specificexams = SpecificExam.objects.create( + patient=self.patient, + author=self.health_team + ) + + self.staticdata = StaticData.objects.create( + patient=self.patient, + APGAR=9, + weight=800, + ear_test="text.txt", + heart_test="teuxt.txt", + author=self.health_team + ) + self.medicalrecord.save() self.patient.save() @@ -85,54 +136,7 @@ def test_form_invalid(self): self.assertFormError(response, 'form', 'message', _('This field is required.')) self.assertEquals(response.status_code, 200) - def test_delete_medical_records_ok(self): - """ - Test is medical records is being correcty updated. - """ - - self.client.force_login(user=self.user_1) - - - - response = self.client.post( - path=reverse( - viewname='medicalrecords:delete_medicalrecords', - args=(self.patient.user.username,self.medicalrecord.pk,) - ), - follow=True - ) - - self.assertEquals( - response.status_code, - 200 - ) - - def test_updated_medical_records_ok(self): - """ - Test is medical records is being correcty updated. - """ - - self.client.force_login(user=self.user_1) - - data = { - 'message': 'test', - 'patient': 'self.patient', - 'author': 'self.user_1', - 'document': 'test.txt', - } - - response = self.client.post( - path=reverse( - viewname='medicalrecords:update_medicalrecords', - args=(self.patient.user.username,self.medicalrecord.pk,) - ), - follow=True, - data=data - ) - - self.assertEquals(response.status_code,200) - - def test_search_list_view(self): + def test_list_view(self): """ Makes sure that the medicalrecord search view is loaded correctly """ @@ -141,47 +145,18 @@ def test_search_list_view(self): self.url = () response = self.client.get( path=reverse( - viewname='medicalrecords:list_search_medicalrecords', + viewname='medicalrecords:list_medicalrecords', + args=(self.patient.user.username,) ) ) self.assertEquals(response.status_code, 200) - def test_search_list_view_logout(self): - """ - Makes sure that the medicalrecord search view gives 302 on a logout - """ - - self.client.force_login(user=self.user_1) - self.client.logout() - self.url = () - response = self.client.get( - path=reverse( - viewname='medicalrecords:list_search_medicalrecords', - ) - ) - self.assertEquals(response.status_code, 302) - - def test_search_list_view_no_permissions(self): - """ - Makes sure that the medicalrecord gives 302 on a user without - permissions - """ - - self.client.force_login(user=self.user_2) - self.url = () - response = self.client.get( - path=reverse( - viewname='medicalrecords:list_search_medicalrecords', - ) - ) - self.assertEquals(response.status_code, 302) - - def test_list_view(self): + def test_list_view_employee(self): """ Makes sure that the medicalrecord search view is loaded correctly """ - self.client.force_login(user=self.user_1) + self.client.force_login(user=self.user_4) self.url = () response = self.client.get( path=reverse( @@ -237,3 +212,57 @@ def test_list_view_not_specialized(self): ) ) self.assertEquals(response.status_code, 302) + + def test_complaint_invalid_date(self): + """ + Test if complaint day cannot be in future + """ + + + with self.assertRaises(ValidationError): + complaint = Complaint.objects.create( + created_at=timezone.datetime.today(), + complaint_day=timezone.now() + timezone.timedelta(days=1), + complaint_time='15:40', + patient=self.patient, + description="Não tô legal", + author=self.health_team + ) + + complaint.clean() + + def test_complaint_valid_date(self): + """ + Test if create form is valid with all required fields + """ + self.client.force_login(user=self.user_1) + data = { + 'description': 'test', + 'complaint_day': timezone.now() - timezone.timedelta(days=1), + 'complaint_time': '10:40', + } + response = self.client.post( + path=reverse( + viewname='medicalrecords:create_complaint_medicalrecords', + args=(self.patient.user.username,) + ), + data=data, + follow=True) + self.assertEquals(response.status_code, 200) + + def test__str__(self): + """ + This test check if __str__ is returning the data correctly. + """ + + self.assertEqual(self.medicalrecord.__str__(), 'teste_2') + + self.assertEqual(self.complaint.__str__(), 'teste_2 - Comptaint ID: 1') + + self.assertEqual(self.exam.__str__(), 'teste_2 - Sangue') + + self.assertEqual(self.medicine.__str__(), 'teste_2 - Neosaldina') + + self.assertEqual(self.specificexams.__str__(), 'teste_2') + + self.assertEqual(self.staticdata.__str__(), 'teste_2') diff --git a/drdown/medicalrecords/urls.py b/drdown/medicalrecords/urls.py index a83abf58..6a2199cf 100644 --- a/drdown/medicalrecords/urls.py +++ b/drdown/medicalrecords/urls.py @@ -1,9 +1,12 @@ from django.conf.urls import url -from django.conf import settings -from django.views.generic import TemplateView -from django.conf.urls.static import static +from drdown.medicalrecords.forms.exam_forms import ExamForm from drdown.medicalrecords.forms.medicalrecords_forms import MedicalRecordForm -from drdown.medicalrecords.views import view_medical_record +from drdown.medicalrecords.forms.static_data_forms import StaticDataForm +from drdown.medicalrecords.forms.medicines_forms import MedicineForm +from drdown.medicalrecords.forms.complaint_forms import ComplaintForm +from drdown.medicalrecords.forms.specific_exams_forms import SpecificExamsForm +from drdown.medicalrecords.views import view_medical_record, view_static_data,\ + view_medicines, view_specific_exams, view_complaint, view_exams app_name = 'medicalrecords' urlpatterns = [ @@ -12,38 +15,60 @@ view=view_medical_record.MedicalRecordsList.as_view(), name='list_medicalrecords' ), + url( - regex=r'^$', - view=view_medical_record.PatientSearchList.as_view( - template_name='medicalrecords/medicalrecord_patient_list.html'), - name='list_users_medicalrecords' + regex=r'^(?P[\w.@+-]+)/new/$', + view=view_medical_record.MedicalRecordsCreateView.as_view( + form_class=MedicalRecordForm), + name='create_medicalrecords' ), url( - regex=r'search/$', - view=view_medical_record.MedicalRecordsSearchList.as_view( - template_name='medicalrecords/medicalrecord_search_list.html'), - name='list_search_medicalrecords' + regex=r'^(?P[\w.@+-]+)/new-static-data/$', + view=view_static_data.StaticDataCreateView.as_view( + form_class=StaticDataForm), + name='create_static_data_medicalrecords' ), + url( + regex=r'^(?P[\w.@+-]+)/new-medicine/$', + view=view_medicines.MedicinesCreateView.as_view( + form_class=MedicineForm), + name='create_medicine_medicalrecords' + ), url( - regex=r'^(?P[\w.@+-]+)/new', - view=view_medical_record.MedicalRecordsCreateView.as_view( - form_class=MedicalRecordForm), - name='create_medicalrecords' + regex=r'^(?P[\w.@+-]+)/new-specific-exam/$', + view=view_specific_exams.SpecificExamCreateView.as_view( + form_class=SpecificExamsForm), + name='create_specific_exam_medicalrecords' ), url( - regex=r'^(?P[\w.@+-]+)/(?P\d+)/delete/$', - view=view_medical_record.MedicalRecordsDeleteView.as_view(), - name='delete_medicalrecords' + regex=r'^(?P[\w.@+-]+)/new-complaint/$', + view=view_complaint.ComplaintCreateView.as_view( + form_class=ComplaintForm), + name='create_complaint_medicalrecords' ), url( - regex=r'^(?P[\w.@+-]+)/(?P\d+)/update/$', - view=view_medical_record.MedicalRecordsUpdateView.as_view( - form_class=MedicalRecordForm), - name='update_medicalrecords' + regex=r'^(?P[\w.@+-]+)/new-exam/$', + view=view_exams.ExamCreateView.as_view( + form_class=ExamForm), + name='create_exam_medicalrecords' + ), + + url( + regex=r'^(?P[\w.@+-]+)/update-exams/$', + view=view_specific_exams.SpecificExamUpdateView.as_view( + form_class=SpecificExamsForm), + name='update_exams_medicalrecords' + ), + + url( + regex=r'^(?P[\w.@+-]+)/update-static-data/$', + view=view_static_data.StaticDataUpdateView.as_view( + form_class=StaticDataForm), + name='update_static_data_medicalrecords' ), ] diff --git a/drdown/medicalrecords/views/__init__.py b/drdown/medicalrecords/views/__init__.py index cd1ee5b0..ef0db865 100644 --- a/drdown/medicalrecords/views/__init__.py +++ b/drdown/medicalrecords/views/__init__.py @@ -1 +1,9 @@ -from ..views import view_medical_record +from ..views import ( + view_medical_record, + view_complaint, + view_exams, + view_medicines, + view_specific_exams, + view_static_data, + views_base, +) diff --git a/drdown/medicalrecords/views/view_complaint.py b/drdown/medicalrecords/views/view_complaint.py new file mode 100644 index 00000000..a71c6bfe --- /dev/null +++ b/drdown/medicalrecords/views/view_complaint.py @@ -0,0 +1,20 @@ +from drdown.users.models.model_health_team import HealthTeam +from ..models.model_complaint import Complaint +from drdown.users.models.model_user import User +from drdown.users.models.model_patient import Patient +from django.views.generic import CreateView, UpdateView +from django.urls import reverse_lazy +from ..forms.complaint_forms import ComplaintForm +from ..views.views_base import BaseViewForm, BaseViewUrl + + +class ComplaintCreateView(BaseViewForm, BaseViewUrl, CreateView): + model = Complaint + form_class = ComplaintForm + template_name = 'medicalrecords/medicalrecord_complaint_form.html' + + +class ComplaintUpdateView(BaseViewUrl, UpdateView): + model = Complaint + form_class = ComplaintForm + template_name = 'medicalrecords/medicalrecord_complaint_form.html' diff --git a/drdown/medicalrecords/views/view_exams.py b/drdown/medicalrecords/views/view_exams.py new file mode 100644 index 00000000..d8b260e2 --- /dev/null +++ b/drdown/medicalrecords/views/view_exams.py @@ -0,0 +1,20 @@ +from drdown.users.models.model_health_team import HealthTeam +from ..models.model_exams import Exam +from drdown.users.models.model_user import User +from drdown.users.models.model_patient import Patient +from django.views.generic import CreateView, UpdateView +from django.urls import reverse_lazy +from ..forms.exam_forms import ExamForm +from ..views.views_base import BaseViewForm, BaseViewUrl + + +class ExamCreateView(BaseViewForm, BaseViewUrl, CreateView): + model = Exam + form_class = ExamForm + template_name = 'medicalrecords/medicalrecord_exam_form.html' + + +class ExamUpdateView(BaseViewUrl, UpdateView): + model = Exam + form_class = ExamForm + template_name = 'medicalrecords/medicalrecord_exam_form.html' diff --git a/drdown/medicalrecords/views/view_medical_record.py b/drdown/medicalrecords/views/view_medical_record.py index e77db7ca..4259ab8a 100644 --- a/drdown/medicalrecords/views/view_medical_record.py +++ b/drdown/medicalrecords/views/view_medical_record.py @@ -1,52 +1,40 @@ from drdown.users.models.model_health_team import HealthTeam from ..models.model_medical_record import MedicalRecord +from ..models.model_static_data import StaticData +from ..models.model_specific_exams import SpecificExam +from ..models.model_medicines import Medicine +from ..models.model_exams import Exam +from ..models.model_complaint import Complaint from drdown.users.models.model_user import User from drdown.users.models.model_patient import Patient -from django.views.generic import CreateView, DeleteView, UpdateView +from django.views.generic import CreateView, DeleteView, UpdateView, ListView from django.urls import reverse_lazy -from search_views.search import SearchListView from django.contrib.auth.mixins import UserPassesTestMixin from search_views.filters import BaseFilter -from ..forms.medicalrecords_forms import MedicalRecordSearchForm,\ - MedicalRecordCompleteSearchForm, PatientSearchForm, MedicalRecordForm +from ..forms.medicalrecords_forms import MedicalRecordForm +from ..views.views_base import BaseViewForm, BaseViewUrl class MedicalRecordsFilter(BaseFilter): search_fields = { - 'search_text': ['message'], - 'search_date': ['day'], - 'author': ['author_id__id'], - 'patient': ['patient__id'], - 'message': ['message'], 'list_patient': ['id'] } -class CheckPermissions(UserPassesTestMixin): - def test_func(self): - return hasattr(self.request.user, 'healthteam') - - def get_login_url(self): - if self.request.user.is_authenticated: - # redirect if user is not a HealthTeam - login_url = reverse_lazy( - viewname='users:detail', - kwargs={'username': self.request.user.username} - ) - return login_url - login_MedicalRecordsList_url = reverse_lazy('account_login') - return login_MedicalRecordsList_url - - -class MedicalRecordsList(UserPassesTestMixin, SearchListView): +class MedicalRecordsList(UserPassesTestMixin, ListView): model = MedicalRecord template_name = "medicalrecords/medicalrecord_list.html" - form_class = MedicalRecordSearchForm - filter_class = MedicalRecordsFilter + slug_url_kwarg = 'username' + slug_field = 'patient__user__username' + ordering = ['-day'] def test_func(self): return hasattr(self.request.user, 'healthteam') or \ - self.request.user.username == self.kwargs.get('username') + hasattr(self.request.user, 'employee') or \ + self.request.user.username == self.kwargs.get('username') or \ + (hasattr(self.request.user, 'responsible') and + self.request.user.responsible.patient_set.filter( + user__username=self.kwargs.get('username'))) def get_login_url(self): if self.request.user.is_authenticated: @@ -59,101 +47,32 @@ def get_login_url(self): login_MedicalRecordsList_url = reverse_lazy('account_login') return login_MedicalRecordsList_url - def related_patient(self): - user = User.objects.get( - username=self.kwargs.get('username') - ) - patient = Patient.objects.get( - user=user - ) - return patient - - def get_queryset(self): - queryset = MedicalRecord.objects.all().order_by('-day') - return queryset - def get_context_data(self, **kwargs): - context = super(MedicalRecordsList, self).get_context_data(**kwargs) - elect_count = 0 - for device in MedicalRecord.objects.all(): - if device.patient.user.username == self.kwargs.get('username'): - elect_count += 1 - context['elect_count'] = elect_count - return context - -class MedicalRecordsSearchList(CheckPermissions, SearchListView): - model = MedicalRecord - template_name = "medicalrecords/medicalrecord_search_list.html" - form_class = MedicalRecordCompleteSearchForm - filter_class = MedicalRecordsFilter - paginate_by = 10 - - def get_queryset(self): - queryset = MedicalRecord.objects.all().order_by('-day') - return queryset - - -class PatientSearchList(CheckPermissions, SearchListView): - model = Patient - template_name = "medicalrecords/medicalrecord_patient_list.html" - form_class = PatientSearchForm - filter_class = MedicalRecordsFilter - paginate_by = 20 - - -class MedicalRecordsCreateView(CreateView): - model = MedicalRecord - form_class = MedicalRecordForm - template_name = 'medicalrecords/medicalrecord_form.html' + context = super().get_context_data(**kwargs) - def get_success_url(self, **kwargs): - success_create_url = reverse_lazy( - viewname='medicalrecords:list_medicalrecords', - kwargs={ - 'username': self.kwargs.get('username') - } - ) - return success_create_url - - def form_valid(self, form): - for patient in Patient.objects.all(): - if patient.user.username == self.kwargs.get('username'): - form.instance.patient = patient - user = User.objects.get( - username=self.request.user - ) - healthteam = HealthTeam.objects.get( - user=user + patient = Patient.objects.get( + user__username=self.kwargs.get('username') ) - form.instance.author = healthteam - form.save() - return super(MedicalRecordsCreateView, self).form_valid(form) + staticdata = StaticData.objects.filter(patient=patient) + specificexams = SpecificExam.objects.filter(patient=patient).first() + medicines = Medicine.objects.filter(patient=patient) + exams = Exam.objects.filter(patient=patient) + complaints = Complaint.objects.filter(patient=patient) -class MedicalRecordsDeleteView(DeleteView): - model = MedicalRecord + context['complaints'] = complaints + context['exams'] = exams + context['medicines'] = medicines + context['specificexams'] = specificexams + context['staticdata'] = staticdata + context['medicalrecordlist'] = context['object_list'] + context['related_patient'] = patient - def get_success_url(self, **kwargs): - success_delete_url = reverse_lazy( - viewname='medicalrecords:list_medicalrecords', - kwargs={ - 'username': self.kwargs.get('username'), - } - ) - return success_delete_url + return context -class MedicalRecordsUpdateView(UpdateView): +class MedicalRecordsCreateView(BaseViewUrl, BaseViewForm, CreateView): model = MedicalRecord form_class = MedicalRecordForm template_name = 'medicalrecords/medicalrecord_form.html' - - def get_success_url(self, **kwargs): - success_update_url = reverse_lazy( - viewname='medicalrecords:list_medicalrecords', - kwargs={ - 'username': self.kwargs.get('username'), - } - ) - return success_update_url diff --git a/drdown/medicalrecords/views/view_medicines.py b/drdown/medicalrecords/views/view_medicines.py new file mode 100644 index 00000000..7eee7383 --- /dev/null +++ b/drdown/medicalrecords/views/view_medicines.py @@ -0,0 +1,22 @@ +from drdown.users.models.model_health_team import HealthTeam +from ..models.model_medicines import Medicine +from ..models.model_medical_record import MedicalRecord +from drdown.users.models.model_user import User +from drdown.users.models.model_patient import Patient +from django.views.generic import CreateView, DeleteView, UpdateView, ListView +from django.urls import reverse_lazy +from django.contrib.auth.mixins import UserPassesTestMixin +from ..forms.medicines_forms import MedicineForm +from ..views.views_base import BaseViewForm, BaseViewUrl + + +class MedicinesCreateView(BaseViewForm, BaseViewUrl, CreateView): + model = Medicine + form_class = MedicineForm + template_name = 'medicalrecords/medicalrecord_static_data_form.html' + + +class MedicinesUpdateView(BaseViewUrl, UpdateView): + model = Medicine + form_class = MedicineForm + template_name = 'medicalrecords/medicalrecord_static_data_form.html' diff --git a/drdown/medicalrecords/views/view_specific_exams.py b/drdown/medicalrecords/views/view_specific_exams.py new file mode 100644 index 00000000..0a9bc5ad --- /dev/null +++ b/drdown/medicalrecords/views/view_specific_exams.py @@ -0,0 +1,22 @@ +from drdown.users.models.model_health_team import HealthTeam +from ..models.model_specific_exams import SpecificExam +from drdown.users.models.model_user import User +from drdown.users.models.model_patient import Patient +from django.views.generic import CreateView, UpdateView +from django.urls import reverse_lazy +from ..forms.specific_exams_forms import SpecificExamsForm +from ..views.views_base import BaseViewForm, BaseViewUrl + + +class SpecificExamCreateView(BaseViewForm, BaseViewUrl, CreateView): + model = SpecificExam + form_class = SpecificExamsForm + template_name = 'medicalrecords/medicalrecord_specific_exams_form.html' + + +class SpecificExamUpdateView(BaseViewUrl, UpdateView): + model = SpecificExam + form_class = SpecificExamsForm + template_name = 'medicalrecords/medicalrecord_specific_exams_form.html' + slug_url_kwarg = 'username' + slug_field = 'patient__user__username' diff --git a/drdown/medicalrecords/views/view_static_data.py b/drdown/medicalrecords/views/view_static_data.py new file mode 100644 index 00000000..d8dd1c77 --- /dev/null +++ b/drdown/medicalrecords/views/view_static_data.py @@ -0,0 +1,24 @@ +from drdown.users.models.model_health_team import HealthTeam +from ..models.model_static_data import StaticData +from ..models.model_medical_record import MedicalRecord +from drdown.users.models.model_user import User +from drdown.users.models.model_patient import Patient +from django.views.generic import CreateView, DeleteView, UpdateView, ListView +from django.urls import reverse_lazy +from django.contrib.auth.mixins import UserPassesTestMixin +from ..forms.static_data_forms import StaticDataForm +from ..views.views_base import BaseViewForm, BaseViewUrl + + +class StaticDataCreateView(BaseViewUrl, BaseViewForm, CreateView): + model = StaticData + form_class = StaticDataForm + template_name = 'medicalrecords/medicalrecord_static_data_form.html' + + +class StaticDataUpdateView(BaseViewUrl, UpdateView): + model = StaticData + form_class = StaticDataForm + template_name = 'medicalrecords/medicalrecord_static_data_form.html' + slug_url_kwarg = 'username' + slug_field = 'patient__user__username' diff --git a/drdown/medicalrecords/views/views_base.py b/drdown/medicalrecords/views/views_base.py new file mode 100644 index 00000000..0f5bb6ac --- /dev/null +++ b/drdown/medicalrecords/views/views_base.py @@ -0,0 +1,33 @@ +from drdown.users.models.model_user import User +from drdown.users.models.model_patient import Patient +from drdown.users.models.model_health_team import HealthTeam + +from django.urls import reverse_lazy + + +class BaseViewForm(): + + def form_valid(self, form): + + form.instance.patient = Patient.objects.get( + user__username=self.kwargs.get('username') + ) + + form.instance.author = self.request.user.healthteam + form.save() + + return super().form_valid(form) + + +class BaseViewUrl(): + + def get_success_url(self, **kwargs): + + success_url = reverse_lazy( + viewname='medicalrecords:list_medicalrecords', + kwargs={ + 'username': self.kwargs.get('username') + } + ) + + return success_url diff --git a/drdown/users/apps.py b/drdown/users/apps.py index a9f4d7dc..da73017e 100644 --- a/drdown/users/apps.py +++ b/drdown/users/apps.py @@ -1,9 +1,10 @@ from django.apps import AppConfig +from django.utils.translation import ugettext_lazy as _ class UsersConfig(AppConfig): name = 'drdown.users' - verbose_name = "Users" + verbose_name = _("Users") def ready(self): """Override this to put in: diff --git a/drdown/users/forms/__init__.py b/drdown/users/forms/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/drdown/users/forms/users_forms.py b/drdown/users/forms/users_forms.py new file mode 100644 index 00000000..fa77c911 --- /dev/null +++ b/drdown/users/forms/users_forms.py @@ -0,0 +1,12 @@ +from django import forms +from drdown.users.models.model_patient import Patient +from django.utils.translation import ugettext_lazy as _ + + +class PatientSearchForm(forms.Form): + + list_patient = forms.ModelChoiceField( + queryset=Patient.objects.all(), + required=False, + label=_('Search patient!') + ) diff --git a/drdown/users/locale/pt_BR/LC_MESSAGES/django.po b/drdown/users/locale/pt_BR/LC_MESSAGES/django.po index ceb7546f..a714ca5b 100644 --- a/drdown/users/locale/pt_BR/LC_MESSAGES/django.po +++ b/drdown/users/locale/pt_BR/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-04-24 21:10+0000\n" +"POT-Creation-Date: 2018-05-04 10:24+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,9 +18,17 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" +#: drdown/users/apps.py:7 drdown/users/templates/users/user_list.html:7 +msgid "Users" +msgstr "Usuários" + +#: drdown/users/forms/users_forms.py:11 +msgid "Search patient!" +msgstr "Pesquisar paciente!" + #: drdown/users/models/model_employee.py:21 #: drdown/users/models/model_health_team.py:20 -#: drdown/users/models/model_patient.py:20 +#: drdown/users/models/model_patient.py:25 #: drdown/users/models/model_responsible.py:17 msgid "User" msgstr "Usuário" @@ -55,13 +63,13 @@ msgstr "O departamento no qual o usuário trabalha" #: drdown/users/models/model_employee.py:74 #: drdown/users/models/model_health_team.py:198 -#: drdown/users/models/model_patient.py:110 -#: drdown/users/models/model_responsible.py:35 +#: drdown/users/models/model_patient.py:157 +#: drdown/users/models/model_responsible.py:47 msgid "Don't change users" msgstr "Não alterar usuário" #: drdown/users/models/model_employee.py:123 -#: drdown/users/templates/users/user_detail.html:67 +#: drdown/users/templates/users/user_detail.html:89 msgid "Employee" msgstr "Funcionário" @@ -155,126 +163,128 @@ msgstr "A especialidade do membro da equipe médica." msgid "" "The %(register)s doesn't inscribe professionalswith %(speciality)s " "graduation, please correct" -msgstr "O %(register)s não registra profissionais com formação em %(speciality)s, favor corrigir" +msgstr "" +"O %(register)s não registra profissionais com formação em %(speciality)s, " +"favor corrigir" #: drdown/users/models/model_health_team.py:252 #: drdown/users/models/model_health_team.py:253 -#: drdown/users/templates/users/user_detail.html:95 +#: drdown/users/templates/users/user_detail.html:119 msgid "Health Team" msgstr "Equipe Médica" -#: drdown/users/models/model_patient.py:23 +#: drdown/users/models/model_patient.py:28 msgid "Please, enter the valid SES number" msgstr "Por favor, insira um número de SES válido" -#: drdown/users/models/model_patient.py:34 -#: drdown/users/models/model_responsible.py:58 -#: drdown/users/templates/users/user_detail.html:221 +#: drdown/users/models/model_patient.py:39 +#: drdown/users/models/model_responsible.py:70 +#: drdown/users/templates/users/user_detail.html:247 msgid "Responsible" msgstr "Responsável" -#: drdown/users/models/model_patient.py:38 +#: drdown/users/models/model_patient.py:43 msgid "Not urgent" msgstr "Não urgente" -#: drdown/users/models/model_patient.py:39 +#: drdown/users/models/model_patient.py:44 msgid "Not very urgent" msgstr "Não muito urgente" -#: drdown/users/models/model_patient.py:40 +#: drdown/users/models/model_patient.py:45 msgid "Urgent" msgstr "Urgente" -#: drdown/users/models/model_patient.py:41 +#: drdown/users/models/model_patient.py:46 msgid "Very urgent" msgstr "Muito urgente" -#: drdown/users/models/model_patient.py:42 +#: drdown/users/models/model_patient.py:47 msgid "Emerging" msgstr "Emergencial" -#: drdown/users/models/model_patient.py:45 +#: drdown/users/models/model_patient.py:50 msgid "Priority" msgstr "Prioridade" -#: drdown/users/models/model_patient.py:47 +#: drdown/users/models/model_patient.py:52 msgid "Please, insert the degree of priority of the patient" msgstr "Por favor, insira o grau de priodade do paciente" -#: drdown/users/models/model_patient.py:51 +#: drdown/users/models/model_patient.py:56 msgid "Name of mother" msgstr "Nome da mãe" -#: drdown/users/models/model_patient.py:52 +#: drdown/users/models/model_patient.py:57 msgid "Please, insert your mother name" msgstr "Por favor, insira o nome da sua mãe" -#: drdown/users/models/model_patient.py:58 +#: drdown/users/models/model_patient.py:63 msgid "Name of father" msgstr "Nome do pai" -#: drdown/users/models/model_patient.py:59 +#: drdown/users/models/model_patient.py:64 msgid "Please, insert your father name" msgstr "Por favor, insira o nome do seu pai" -#: drdown/users/models/model_patient.py:65 +#: drdown/users/models/model_patient.py:70 msgid "White" msgstr "Branco" -#: drdown/users/models/model_patient.py:66 +#: drdown/users/models/model_patient.py:71 msgid "Black" msgstr "Negro" -#: drdown/users/models/model_patient.py:67 +#: drdown/users/models/model_patient.py:72 msgid "Yellow" msgstr "Amarelo" -#: drdown/users/models/model_patient.py:68 +#: drdown/users/models/model_patient.py:73 msgid "Brown" msgstr "Pardo" -#: drdown/users/models/model_patient.py:69 +#: drdown/users/models/model_patient.py:74 msgid "Indigenous" msgstr "Indígena" -#: drdown/users/models/model_patient.py:72 +#: drdown/users/models/model_patient.py:77 msgid "Ethnicity" msgstr "Etnia" -#: drdown/users/models/model_patient.py:74 +#: drdown/users/models/model_patient.py:79 msgid "Please insert the ethnicity of the patient" msgstr "Por favor, insira a etnia do paciente" -#: drdown/users/models/model_patient.py:77 +#: drdown/users/models/model_patient.py:82 msgid "SUS number" msgstr "Número do SUS" -#: drdown/users/models/model_patient.py:78 +#: drdown/users/models/model_patient.py:83 msgid "Please, enter valid SUS in format: XXXXXXXXXXXXXXX" msgstr "Por favor, insira o número do SUS no seguinte formato: XXXXXXXXXXXXXXX" -#: drdown/users/models/model_patient.py:84 +#: drdown/users/models/model_patient.py:89 msgid "Civil register of birth" msgstr "Registro civil de nascimento" -#: drdown/users/models/model_patient.py:85 +#: drdown/users/models/model_patient.py:90 msgid "Please, enter the civil registry of birth number" msgstr "Por favor, insira o número do seu registro civil de nascimento" -#: drdown/users/models/model_patient.py:92 +#: drdown/users/models/model_patient.py:97 msgid "Declaration of live birth" msgstr "Declaração de nascido vivo" -#: drdown/users/models/model_patient.py:93 +#: drdown/users/models/model_patient.py:98 msgid "Please, enter the declaration of live birth number" msgstr "Por favor, insira o número da declaração de nascido vivo" -#: drdown/users/models/model_patient.py:130 -#: drdown/users/templates/users/user_detail.html:140 +#: drdown/users/models/model_patient.py:177 +#: drdown/users/templates/users/user_detail.html:165 msgid "Patient" msgstr "Paciente" -#: drdown/users/models/model_patient.py:131 +#: drdown/users/models/model_patient.py:178 msgid "Patients" msgstr "Pacientes" @@ -282,85 +292,182 @@ msgstr "Pacientes" msgid "Please, use enter a valid CPF inthe following format: XXX.XXX.XXX-XX" msgstr "Por favor, insira um número de CPF no seguinte formato: XXX.XXX.XXX-XX" -#: drdown/users/models/model_responsible.py:59 +#: drdown/users/models/model_responsible.py:71 msgid "Responsibles" msgstr "Responsáveis" -#: drdown/users/models/model_user.py:17 +#: drdown/users/models/model_user.py:18 msgid "Photo of user." -msgstr "Foto do usuário" +msgstr "Foto do usuário." -#: drdown/users/models/model_user.py:18 -#: drdown/users/templates/users/user_form.html:89 +#: drdown/users/models/model_user.py:19 +#: drdown/users/templates/users/user_form.html:123 msgid "Photo" msgstr "Foto" -#: drdown/users/models/model_user.py:24 -#: drdown/users/templates/users/user_form.html:46 +#: drdown/users/models/model_user.py:25 +#: drdown/users/templates/users/user_form.html:47 msgid "Name" msgstr "Nome" -#: drdown/users/models/model_user.py:27 -#: drdown/users/templates/users/user_form.html:51 +#: drdown/users/models/model_user.py:28 +#: drdown/users/templates/users/user_form.html:55 msgid "Full user name" msgstr "Nome do usuário" -#: drdown/users/models/model_user.py:32 -#: drdown/users/templates/users/user_form.html:57 +#: drdown/users/models/model_user.py:33 +#: drdown/users/templates/users/user_form.html:62 msgid "Gender" msgstr "Gênero" -#: drdown/users/models/model_user.py:34 -#: drdown/users/templates/users/user_form.html:63 +#: drdown/users/models/model_user.py:35 +#: drdown/users/templates/users/user_form.html:73 +#: drdown/users/templates/users/user_form.html:78 msgid "Male" msgstr "Masculino" -#: drdown/users/models/model_user.py:35 -#: drdown/users/templates/users/user_form.html:65 +#: drdown/users/models/model_user.py:36 +#: drdown/users/templates/users/user_form.html:75 +#: drdown/users/templates/users/user_form.html:77 msgid "Female" msgstr "Feminino" -#: drdown/users/models/model_user.py:43 -#: drdown/users/templates/users/user_form.html:73 +#: drdown/users/models/model_user.py:44 +#: drdown/users/templates/users/user_form.html:86 msgid "Telephone" msgstr "Telefone" -#: drdown/users/models/model_user.py:48 +#: drdown/users/models/model_user.py:49 msgid "(xx)xxxxx-xxxx or (xx)xxxx-xxxx" msgstr "(xx)xxxxx-xxxx ou (xx)xxxx-xxxx" -#: drdown/users/models/model_user.py:53 -#: drdown/users/templates/users/user_form.html:81 +#: drdown/users/models/model_user.py:54 +#: drdown/users/templates/users/user_form.html:105 msgid "Birthday" msgstr "Data de aniversário" -#: drdown/users/models/model_user.py:54 +#: drdown/users/models/model_user.py:55 msgid "xx/xx/xxxx" msgstr "xx/xx/xxxx" -#: drdown/users/models/model_user.py:60 +#: drdown/users/models/model_user.py:61 msgid "Created at" msgstr "Criado em" -#: drdown/users/models/model_user.py:66 +#: drdown/users/models/model_user.py:67 msgid "Updated at" msgstr "Atualizado em" -#: drdown/users/models/model_user.py:114 +#: drdown/users/models/model_user.py:129 msgid "This user is already specialized!" msgstr "Esse usuário já é éspecializado!" +#: drdown/users/models/model_user.py:142 +msgid "The birthday cannot be in the future!" +msgstr "A data de nascimento não pode estar no futuro!" + +#: drdown/users/models/model_user.py:149 +msgid "This birthday is too old." +msgstr "Essa data de nascimento é muito antiga." + #: drdown/users/templates/admin/users/change_form.html:5 msgid "Make sure user is confirmed before adding a specialization." msgstr "Tenha certeza de ter um usuário criado antes de especializá-lo." +#: drdown/users/templates/users/healthteam_patient_list.html:3 +#: drdown/users/templates/users/healthteam_patient_list.html:13 +#: drdown/users/templates/users/responsible_patient_list.html:3 +#: drdown/users/templates/users/responsible_patient_list.html:7 +msgid "Select a patient" +msgstr "Selecione um paciente" + +#: drdown/users/templates/users/healthteam_patient_list.html:16 +#: drdown/users/templates/users/patient_detail.html:21 +#: drdown/users/templates/users/patient_detail.html:23 +msgid "Return" +msgstr "Retornar" + +#: drdown/users/templates/users/healthteam_patient_list.html:23 +#| msgid "Patient: " +msgid "Patient:" +msgstr "Paciente:" + +#: drdown/users/templates/users/healthteam_patient_list.html:25 +msgid "Search" +msgstr "Buscar" + +#: drdown/users/templates/users/healthteam_patient_list.html:37 +#: drdown/users/templates/users/patient_detail.html:40 +#: drdown/users/templates/users/healthteam_patient_list.html:56 +#: drdown/users/templates/users/healthteam_patient_list.html:47 +#: drdown/users/templates/users/patient_detail.html:65 +#: drdown/users/templates/users/responsible_patient_list.html:24 +#: drdown/users/templates/users/user_detail.html:170 +msgid "SES: " +msgstr "SES: " + +#: drdown/users/templates/users/healthteam_patient_list.html:65 +#: drdown/users/templates/users/patient_detail.html:53 +#| msgid "My Medical Records" +msgid "Medical Records" +msgstr "Prontuário" + +#: drdown/users/templates/users/healthteam_patient_list.html:71 +#| msgid "My Medical Follow-up Sheet" +msgid "Medical Sheet" +msgstr "Ficha de Acompanhamento" + +#: drdown/users/templates/users/healthteam_patient_list.html:79 +#: drdown/users/templates/users/healthteam_patient_list.html:43 +#: drdown/users/templates/users/responsible_patient_list.html:30 +msgid "There are no patients for this user." +msgstr "Não há pacientes para estes usuário." + +#: drdown/users/templates/users/patient_detail.html:3 +msgid "Detail patient" +msgstr "Detalhes do paciente" + +#: drdown/users/templates/users/patient_detail.html:14 +#: drdown/users/templates/users/user_detail.html:260 +msgid "Patient: " +msgstr "Paciente: " + +#: drdown/users/templates/users/patient_detail.html:46 +msgid "Checklist" +msgstr "Checklist" + +#: drdown/users/templates/users/patient_detail.html:37 +#: drdown/users/templates/users/user_detail.html:48 +msgid "Name: " +msgstr "Nome: " + +#: drdown/users/templates/users/patient_detail.html:38 +#: drdown/users/templates/users/user_detail.html:74 +msgid "Birthday: " +msgstr "Data de nascimento: " + +#: drdown/users/templates/users/patient_detail.html:39 +#: drdown/users/templates/users/user_detail.html:213 +msgid "SUS: " +msgstr "SUS: " + +#: drdown/users/templates/users/patient_detail.html:41 +#: drdown/users/templates/users/user_detail.html:222 +msgid "Civil registry of birth: " +msgstr "Registro civil de nascimento: " + +#: drdown/users/templates/users/patient_detail.html:42 +#: drdown/users/templates/users/user_detail.html:231 +msgid "Declaration of live birth: " +msgstr "Declaração de nascido vivo: " + #: drdown/users/templates/users/user_confirm_delete.html:5 msgid "Log Out" msgstr "Sair" #: drdown/users/templates/users/user_confirm_delete.html:8 #: drdown/users/templates/users/user_confirm_delete.html:13 -#: drdown/users/templates/users/user_detail.html:254 +#: drdown/users/templates/users/user_detail.html:290 msgid "Delete" msgstr "Excluir" @@ -376,89 +483,86 @@ msgstr "Cancelar" msgid "User:" msgstr "Usuário: " +#: drdown/users/templates/users/user_detail.html:17 +msgid "Hey! You have procedures to be made." +msgstr "Oi! Você tem procedimentos a serem feitos." + +#: drdown/users/templates/users/user_detail.html:17 #: drdown/users/templates/users/user_detail.html:26 -msgid "Name: " -msgstr "Nome: " +msgid "Click here to check it" +msgstr "Clique aqui para conferir" + +#: drdown/users/templates/users/user_detail.html:26 +msgid "" +"One or more of your patients needs attention. Some procedures may be behind " +"schedule." +msgstr "" +"Um, ou mais, de seus pacientes precisa de atenção. Alguns procedimentos " +"podem estar atrasados." -#: drdown/users/templates/users/user_detail.html:35 +#: drdown/users/templates/users/user_detail.html:57 msgid "Gender: " msgstr "Gênero: " -#: drdown/users/templates/users/user_detail.html:44 +#: drdown/users/templates/users/user_detail.html:65 msgid "Telephone: " msgstr "Telefone: " -#: drdown/users/templates/users/user_detail.html:53 -msgid "Birthday: " -msgstr "Data de nascimento: " - -#: drdown/users/templates/users/user_detail.html:71 -#: drdown/users/templates/users/user_detail.html:98 -#: drdown/users/templates/users/user_detail.html:224 +#: drdown/users/templates/users/user_detail.html:93 +#: drdown/users/templates/users/user_detail.html:122 +#: drdown/users/templates/users/user_detail.html:250 msgid "CPF: " msgstr "CPF: " -#: drdown/users/templates/users/user_detail.html:80 +#: drdown/users/templates/users/user_detail.html:102 msgid "Department: " msgstr "Departamento: " -#: drdown/users/templates/users/user_detail.html:116 +#: drdown/users/templates/users/user_detail.html:139 msgid "Registration State: " msgstr "Estado do Registro: " -#: drdown/users/templates/users/user_detail.html:125 +#: drdown/users/templates/users/user_detail.html:148 msgid "Speciality: " msgstr "Especialidade: " -#: drdown/users/templates/users/user_detail.html:143 -msgid "SES: " -msgstr "SES: " - -#: drdown/users/templates/users/user_detail.html:152 +#: drdown/users/templates/users/user_detail.html:177 msgid "Priority: " msgstr "Prioridade: " -#: drdown/users/templates/users/user_detail.html:161 +#: drdown/users/templates/users/user_detail.html:186 msgid "Mother Name: " msgstr "Nome da Mãe: " -#: drdown/users/templates/users/user_detail.html:170 +#: drdown/users/templates/users/user_detail.html:195 msgid "Father Name: " msgstr "Nome do Pai: " -#: drdown/users/templates/users/user_detail.html:179 +#: drdown/users/templates/users/user_detail.html:204 msgid "Ethnicity: " msgstr "Etnia: " -#: drdown/users/templates/users/user_detail.html:188 -msgid "SUS: " -msgstr "SUS: " - -#: drdown/users/templates/users/user_detail.html:197 -msgid "Civil registry of birth: " -msgstr "Registro civil de nascimento: " +#: drdown/users/templates/users/user_detail.html:278 +msgid "My Patients" +msgstr "Meus Pacientes" -#: drdown/users/templates/users/user_detail.html:206 -msgid "Declaration of live birth: " -msgstr "Declaração de nascido vivo: " +#: drdown/users/templates/users/user_detail.html:282 +msgid "My Medical Records" +msgstr "Meu Histórico Médico" -#: drdown/users/templates/users/user_detail.html:233 -msgid "Patient: " -msgstr "Paciente" +#: drdown/users/templates/users/user_detail.html:283 +msgid "My Medical Follow-up Sheet" +msgstr "Ficha de Acompanhamento" -#: drdown/users/templates/users/user_detail.html:249 +#: drdown/users/templates/users/user_detail.html:286 msgid "Confirm data" msgstr "Confirmar dados" -#: drdown/users/templates/users/user_detail.html:252 -msgid "My Medical Records" -msgstr "Minhas Consultas" - -#: drdown/users/templates/users/user_form.html:93 +#: drdown/users/templates/users/user_form.html:113 msgid "Photo of user" msgstr "Foto do usuário" -#: drdown/users/templates/users/user_form.html:99 +#: drdown/users/templates/users/user_form.html:133 msgid "Update" msgstr "Atualizar" @@ -466,10 +570,6 @@ msgstr "Atualizar" msgid "Members" msgstr "Membros" -#: drdown/users/templates/users/user_list.html:7 -msgid "Users" -msgstr "Usuários" - #: drdown/users/utils/validators.py:19 msgid "Wrong CPF format" msgstr "CPF inválido" @@ -479,10 +579,9 @@ msgid "This CPF is not permitted" msgstr "Esse CPF não é permitido" #: drdown/users/utils/validators.py:71 -#, fuzzy, python-format #| msgid "%(value)s is a invalid CPF, the verification digit is wrong" msgid "%(value)s is a invalid CPF, the verification digit is wrong" -msgstr "%(value) é um CPF inválido, o dígito de verificação está incorreto" +msgstr "%(value)s é um CPF inválido, o dígito de verificação está incorreto" #: drdown/users/utils/validators.py:85 msgid "Wrong SES format" @@ -509,14 +608,14 @@ msgstr "Telefone inválido" msgid "Wrong CRM format" msgstr "CRM inválido" -#~ msgid "A %(speciality)s cannot have a %(register)s" -#~ msgstr "%(speciality)s não pode ter %(register)s" +msgid "A %(speciality)s cannot have a %(register)s" +msgstr "%(speciality)s não pode ter %(register)s" -#~ msgid "COFFITO" -#~ msgstr "COFFITO" +msgid "COFFITO" +msgstr "COFFITO" -#~ msgid "Council Acronym: " -#~ msgstr "Acrônim do Conselho" +msgid "Council Acronym: " +msgstr "Acrônimo do Conselho" -#~ msgid "This SES is not permited" -#~ msgstr "Esse SES não é permitido" +msgid "This SES is not permited" +msgstr "Esse SES não é permitido" diff --git a/drdown/users/migrations/0016_auto_20180506_2043.py b/drdown/users/migrations/0016_auto_20180506_2043.py new file mode 100644 index 00000000..03c0509c --- /dev/null +++ b/drdown/users/migrations/0016_auto_20180506_2043.py @@ -0,0 +1,17 @@ +# Generated by Django 2.0.3 on 2018-05-06 20:43 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0015_auto_20180428_1306'), + ] + + operations = [ + migrations.AlterModelOptions( + name='patient', + options={'verbose_name': 'Patient', 'verbose_name_plural': 'Patients'}, + ), + ] diff --git a/drdown/users/models/model_patient.py b/drdown/users/models/model_patient.py index 515a548c..50d4e90f 100644 --- a/drdown/users/models/model_patient.py +++ b/drdown/users/models/model_patient.py @@ -173,13 +173,13 @@ def delete(self, *args, **kwargs): self.user.save() super().delete(*args, **kwargs) + class Meta: + verbose_name = _("Patient") + verbose_name_plural = _("Patients") + @receiver(post_save, sender=Patient) def create_procedures(sender, instance, **kwargs): if not hasattr(instance, 'checklist'): apps.get_model('careline', 'Checklist') \ .objects.create(patient=instance) - - class Meta: - verbose_name = _('Patient') - verbose_name_plural = _('Patients') diff --git a/drdown/users/models/model_user.py b/drdown/users/models/model_user.py index 5431460e..36a979e4 100644 --- a/drdown/users/models/model_user.py +++ b/drdown/users/models/model_user.py @@ -90,7 +90,7 @@ def age(self): today.day) < (self.birthday.month, self.birthday.day)) - if age is 0: + if age <= 0: diff_month = (today.year - self.birthday.year) * 12 + \ today.month - self.birthday.month age = 0 if diff_month < 6 else 0.5 @@ -133,6 +133,22 @@ def clean(self, *args, **kwargs): else: self.has_specialization = (self.count_user_specialization() is 1) + if isinstance(self.birthday, timezone.datetime): + self.birthday = self.birthday.date() + + if self.birthday: + if timezone.localdate().isoformat() < str(self.birthday): + raise ValidationError( + {'birthday': _("The birthday cannot be in the future!")} + ) + elif ( + timezone.datetime.strptime(str(self.birthday), "%Y-%m-%d") < + timezone.datetime.strptime("1900-01-01", "%Y-%m-%d") + ): + raise ValidationError( + {'birthday': _("This birthday is too old.")} + ) + return data def save(self, *args, **kwargs): diff --git a/drdown/users/static/users/css/user_detail.css b/drdown/users/static/users/css/user_detail.css index db5ed936..059e721d 100644 --- a/drdown/users/static/users/css/user_detail.css +++ b/drdown/users/static/users/css/user_detail.css @@ -46,4 +46,15 @@ .pr-13 { padding-right: 13rem; -} \ No newline at end of file +} + +.move-div{ + padding-left: 70px; + margin-top: 45px; + margin-top: -120px; +} + +.content-margin { + margin-top: 10rem; + margin-bottom: 0rem; +} diff --git a/drdown/users/templates/users/healthteam_patient_list.html b/drdown/users/templates/users/healthteam_patient_list.html new file mode 100644 index 00000000..2a9aa360 --- /dev/null +++ b/drdown/users/templates/users/healthteam_patient_list.html @@ -0,0 +1,87 @@ +{% extends "core/base.html" %} +{% load static i18n %} +{% block title %}{% trans "Select a patient" %}{% endblock %} + +{% block css %} +{{block.super}} + +{% endblock %} + +{% block content %} +
+
+

{% trans "Select a patient" %}

+ + +
+ +
+
+
+ + + +
+
+
+ +
+
+
+ + {% for patient in object_list %} +
  • + +
    +
    + +
    + +
    + + +
    + +
    +

    {{ patient.user.name }}

    +

    {% trans 'SES: ' %} {{patient.ses}}

    +
    + +
    +
    + + + + + + +
    + +
  • + {% empty %} +

    {% trans 'There are no patients for this user.'%}

    + {% endfor %} + + +
    +
    +
    +
    +{% endblock content %} diff --git a/drdown/users/templates/users/patient_detail.html b/drdown/users/templates/users/patient_detail.html new file mode 100644 index 00000000..b9f88f63 --- /dev/null +++ b/drdown/users/templates/users/patient_detail.html @@ -0,0 +1,74 @@ +{% extends "core/base.html" %} +{% load static i18n %} +{% block title %}{% trans "Detail patient" %}{% endblock %} + +{% block css %} +{{block.super}} + + +{% endblock %} + +{% block content %} + +
    + +
    +

    {% trans 'Patient: ' %} {{ view.object.user.name }}

    + +
    + + {% if user.patient %} + {% trans "Return" %} + {% else %} + {% trans "Return" %} + {% endif %} + +
    +
    + +
    + + {% if view.object.user.patient %} +
    + +
    + + {% if view.object.user.photo %} + + {% else %} + + {% endif %} + + +
    + + + + {% if user.healthteam %} + +
    + + {% endif %} + +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + {% endif %} +
    +
    +{% endblock content %} + diff --git a/drdown/users/templates/users/responsible_patient_list.html b/drdown/users/templates/users/responsible_patient_list.html new file mode 100644 index 00000000..f7ddaef2 --- /dev/null +++ b/drdown/users/templates/users/responsible_patient_list.html @@ -0,0 +1,36 @@ +{% extends "core/base.html" %} +{% load static i18n %} +{% block title %}{% trans "Select a patient" %}{% endblock %} + +{% block content %} +
    +

    {% trans "Select a patient" %}

    + +
    + + {% for patient in object_list %} + + +
    + + {% if patient.user.photo %} + + {% else %} + + {% endif %} + +
    +

    {{ patient.user.name }}

    +

    {% trans 'SES: ' %} {{patient.ses}}

    +
    +
    + +
    + {% empty %} +

    {% trans 'There are no patients for this user.'%}

    + {% endfor %} + + +
    +
    +{% endblock content %} diff --git a/drdown/users/templates/users/user_confirm_delete.html b/drdown/users/templates/users/user_confirm_delete.html index de10d37d..558196ae 100644 --- a/drdown/users/templates/users/user_confirm_delete.html +++ b/drdown/users/templates/users/user_confirm_delete.html @@ -5,15 +5,13 @@ {% block head_title %}{% trans "Log Out" %}{% endblock %} {% block inner %} -

    {% trans "Delete" %}

    - -
    - {% csrf_token %} -

    {% trans 'Are you sure you want to delete ' %}{{ object }} ?

    - -
    - - - +

    {% trans "Delete" %}

    +
    + {% csrf_token %} +

    {% trans 'Are you sure you want to delete ' %}{{ object }} ?

    + +
    + + {% endblock %} diff --git a/drdown/users/templates/users/user_detail.html b/drdown/users/templates/users/user_detail.html index 4580ee94..4f7e7f6d 100644 --- a/drdown/users/templates/users/user_detail.html +++ b/drdown/users/templates/users/user_detail.html @@ -5,30 +5,31 @@ {% block title %}{% trans "User:" %} {{ object.username }}{% endblock %} {% block css %} -{{block.super}} - + {{block.super}} + {% endblock %} {% block content %}
    {% if user.is_authenticated %} - {% if user.patient and user.patient.have_procedures_almost_late %} - - {% endif %} - {% if user.responsible and user.responsible.have_patient_needing_atention %} - - {% endif %} + {% if user.patient and user.patient.have_procedures_almost_late %} + + {% endif %} + {% if user.responsible and user.responsible.have_patient_needing_atention %} + + {% endif %} {% endif %}
    @@ -58,6 +59,7 @@

    {{ object.username }}

    +
    {% endif %} {% if object.telephone %} @@ -81,8 +83,9 @@

    {{ object.username }}

    + {% if user.employee %} -
    +

    {% trans 'Employee' %}

    @@ -107,10 +110,12 @@

    {% trans 'Employee' %}

    + + {% endif %} {% if user.healthteam %} -
    +

    {% trans 'Health Team' %}

    @@ -132,8 +137,8 @@

    {% trans 'Health Team' %}

    {% endif %} {% if health_team_registration_state %} -
    - +
    +
    @@ -151,10 +156,12 @@

    {% trans 'Health Team' %}

    +
    + {% endif %} {% if user.patient %} -
    +

    {% trans 'Patient' %}

    @@ -232,10 +239,11 @@

    {% trans 'Patient' %}

    +
    {% endif %} {% if user.responsible %} -
    +

    {% trans 'Responsible' %}

    @@ -247,32 +255,44 @@

    {% trans 'Responsible' %}

    {% endif %} + {% for patient in responsible_patient %} - {% if patient %} +
    - {% endif %} + {% endfor %} + - - + {% endif %} {% if object == request.user %} -
    -
    - {% trans 'Confirm data' %} - E-Mail - {% if user.patient %} - {% trans 'My Medical Records' %} - {% endif %} - {% trans 'Delete' %} - +
    +
    +
    + {% if user.responsible or user.healthteam%} + {% trans 'My Patients' %} + {% endif %} + + {% if user.patient %} + {% trans 'My Medical Records' %} + {% trans 'My Medical Follow-up Sheet' %} + {% endif %} + + {% trans 'Edit data' %} + {% trans 'Change E-Mail' %} + + + {% trans 'Delete' %} + +
    +
    diff --git a/drdown/users/templates/users/user_form.html b/drdown/users/templates/users/user_form.html index 445868c7..6093dceb 100644 --- a/drdown/users/templates/users/user_form.html +++ b/drdown/users/templates/users/user_form.html @@ -86,6 +86,13 @@

    {{ user.username }}

    {% trans 'Telephone' %}*
    + + {% for error in form.telephone.errors %} + + {% endfor %} + {% if object.telephone %} {% else %} @@ -97,6 +104,13 @@

    {{ user.username }}

    + + {% for error in form.birthday.errors %} + + {% endfor %} + {% if object.birthday %} {% else %} @@ -116,9 +130,12 @@

    {{ user.username }}

    - +
    + {% if object.name %} + + {% endif %}
    {% endblock %} diff --git a/drdown/users/tests/test_model_user.py b/drdown/users/tests/test_model_user.py index 1522f077..aba1a8aa 100644 --- a/drdown/users/tests/test_model_user.py +++ b/drdown/users/tests/test_model_user.py @@ -2,6 +2,8 @@ from drdown.users.models import User from django.core.exceptions import ValidationError from django.utils import timezone +from dateutil.relativedelta import relativedelta +from datetime import date from ..models import Employee, HealthTeam, Patient, Responsible @@ -55,7 +57,7 @@ def test_age(self): 5, 10, 4, 66, 12 ] - today = timezone.datetime.today() + today = timezone.localdate() for test_age in test_ages: self.user.birthday = timezone.datetime( @@ -73,6 +75,7 @@ def test_age(self): ) edge_cases_months = [ + -1, 0, 1, 5, @@ -86,7 +89,7 @@ def test_age(self): ] for months in edge_cases_months: - self.user.birthday = today - timezone.timedelta(days=30*months) + self.user.birthday = today + relativedelta(months=-months) self.user.save() self.user.refresh_from_db() @@ -109,6 +112,21 @@ def test_age(self): 1 ) + def test_invalid_birthday(self): + today = timezone.localdate() + tomorrow = today + relativedelta(days=1) + past = date(1800, 1, 1) + + with self.assertRaises(ValidationError): + self.user.birthday = tomorrow + self.user.save() + self.user.clean() + + with self.assertRaises(ValidationError): + self.user.birthday = past + self.user.save() + self.user.clean() + class TestField(TestCase): diff --git a/drdown/users/tests/test_view_user.py b/drdown/users/tests/test_view_user.py index ab8c8a10..ec2563b6 100644 --- a/drdown/users/tests/test_view_user.py +++ b/drdown/users/tests/test_view_user.py @@ -2,8 +2,12 @@ from django.urls import reverse_lazy from django.test.client import Client from django.urls import reverse +from django.utils import timezone from test_plus.test import TestCase -from ..models import User +from ..models import ( + User, Responsible, Employee, + HealthTeam, Patient +) from ..views import ( UserRedirectView, UserUpdateView @@ -153,3 +157,236 @@ def test_not_logged_user_redirect_detail_view(self): self.assertEquals(response.status_code, 200) + +class TestPatientListViewSelector(TestCase): + """ + Test if the Selector of List View of user is working correctly + """ + + def setUp(self): + """ + Runs before every test + """ + + self.user_responsible = self.make_user(username='resp') + + self.user_responsible.birthday = timezone.datetime(1950, 1, 1) + + self.user_responsible.save() + self.user_responsible.refresh_from_db() + + Responsible.objects.create( + user=self.user_responsible, + cpf="974.220.200-16" + ) + + self.user_patient1 = self.make_user(username='pat1') + + self.user_patient1.birthday = timezone.datetime(2000, 1, 1) + + self.user_patient1.save() + self.user_patient1.refresh_from_db() + + Patient.objects.create( + ses="1234567", + user=self.user_patient1, + priority=1, + mother_name="Mae", + father_name="Pai", + ethnicity=3, + sus_number="12345678911", + civil_registry_of_birth="12345678911", + declaration_of_live_birth="12345678911", + responsible=self.user_responsible.responsible + ) + + self.user_patient1.refresh_from_db() + + self.user_patient2 = self.make_user(username='pat2') + + self.user_patient2.birthday = timezone.datetime(2000, 1, 1) + + self.user_patient2.save() + self.user_patient2.refresh_from_db() + + Patient.objects.create( + ses="1234213", + user=self.user_patient2, + priority=1, + mother_name="Mae", + father_name="Pai", + ethnicity=3, + sus_number="12345633912", + civil_registry_of_birth="12345123911", + declaration_of_live_birth="1212338911", + responsible=self.user_responsible.responsible + ) + + self.user_health_team = self.make_user() + self.user_health_team.birthday = timezone.datetime(2000, 1, 1) + + self.user_health_team.save() + self.user_health_team.refresh_from_db() + + self.health_team = HealthTeam.objects.create( + cpf="057.641.271-65", + user=self.user_health_team, + speciality=HealthTeam.NEUROLOGY, + council_acronym=HealthTeam.CRM, + register_number="1234567", + registration_state=HealthTeam.DF, + ) + + self.user_employee = self.make_user(username="empl") + self.user_employee.birthday = timezone.datetime(2000, 1, 1) + + self.user_employee.save() + self.user_employee.refresh_from_db() + + self.employee = Employee.objects.create( + cpf="057.641.271-65", + user=self.user_employee + ) + + self.client = Client() + + def test_get_redirect_for_patient(self): + """ + Test if a patient is redirected for its medical follow-up sheet when accessing the List View + """ + + self.client.force_login(self.user_patient1) + + response = self.client.get( + path=reverse( + viewname='users:patient_list', + ), + follow=True + ) + + url = reverse( + viewname='users:patient_medical_sheet', + kwargs={'username': self.user_patient1.username} + ) + + self.assertRedirects(response=response, expected_url=url) + + def test_get_redirect_for_not_authenticated(self): + """ + Test if a not authenticated user is redirected to login screen + """ + + response = self.client.get( + path=reverse( + viewname='users:patient_list', + ), + follow=True + ) + + url = reverse(viewname='account_login') + + self.assertRedirects(response=response, expected_url=url) + + def test_get_redirect_for_other_specializations_or_no_specialization(self): + """ + Test if a user that is not specialized is redirected for its profile + when accessing Checklist List View + """ + + user = self.make_user(username='nope') + user.birthday = timezone.datetime(1950, 1, 1) + user.save() + + self.client.force_login(user) + + response = self.client.get( + path=reverse(viewname='careline:checklist_list') + ) + + expected_status_codes = [301, 302] + + self.assertIn( + response.status_code, + expected_status_codes + ) + + response = self.client.get( + path=reverse(viewname='users:healthteam_patient_list') + ) + + expected_status_codes = [301, 302] + + self.assertIn( + response.status_code, + expected_status_codes + ) + + response = self.client.get( + path=reverse(viewname='users:responsible_patient_list') + ) + + expected_status_codes = [301, 302] + + self.assertIn( + response.status_code, + expected_status_codes + ) + + + def test_get_redirect_for_healthteam(self): + """ + Test if the page loads when a health team + is the current user + """ + + self.client.force_login(self.user_health_team) + + response = self.client.get( + path=reverse( + viewname='users:patient_list', + ), + follow=True + ) + + url = reverse(viewname='users:healthteam_patient_list') + + self.assertRedirects(response=response, expected_url=url) + + + def test_get_redirect_for_employee(self): + """ + Test if the page loads when a employee + is the current user + """ + + self.client.force_login(self.user_employee) + + response = self.client.get( + path=reverse( + viewname='users:patient_list', + ), + follow=True + ) + + url = reverse(viewname='users:healthteam_patient_list') + + self.assertRedirects(response=response, expected_url=url) + + + def test_get_redirect_for_responsible(self): + """ + Test if the page loads when a responsible is the current user + """ + + self.client.force_login(self.user_responsible) + + response = self.client.get( + path=reverse( + viewname='users:patient_list', + ), + follow=True + ) + + url = reverse(viewname='users:responsible_patient_list') + + self.assertRedirects(response=response, expected_url=url) diff --git a/drdown/users/urls.py b/drdown/users/urls.py index ac7a4232..e3df0f80 100644 --- a/drdown/users/urls.py +++ b/drdown/users/urls.py @@ -31,4 +31,24 @@ view=views.UserDeleteView.as_view(), name='delete' ), + url( + regex=r'^~patients/$', + view=views.PatientListViewSelector.as_view(), + name='patient_list' + ), + url( + regex=r'^~responsible/patients/$', + view=views.ResponsiblePatientListView.as_view(), + name='responsible_patient_list' + ), + url( + regex=r'^~healthteam/patients/$', + view=views.HealthTeamPatientListView.as_view(), + name='healthteam_patient_list' + ), + url( + regex=r'^~patients/(?P[\w.@+-]+)$', + view=views.PatientDetailView.as_view(), + name='patient_medical_sheet' + ), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/drdown/users/utils/validators.py b/drdown/users/utils/validators.py index bcc14f94..0b97726d 100644 --- a/drdown/users/utils/validators.py +++ b/drdown/users/utils/validators.py @@ -1,4 +1,3 @@ - import re from django.core.exceptions import ValidationError @@ -208,7 +207,7 @@ def validate_phone(value): def validate_register_number(value): - regex_code = r"^[0-9]{1,7}$" + regex_code = r"^[0-9]{1,9}$" regex_validator = RegexValidator( regex=regex_code, message=_('Wrong CRM format') diff --git a/drdown/users/views/__init__.py b/drdown/users/views/__init__.py index 9e43be1b..ad787129 100644 --- a/drdown/users/views/__init__.py +++ b/drdown/users/views/__init__.py @@ -1,2 +1,7 @@ -from .view_user import (UserDetailView, UserRedirectView, - UserUpdateView, UserListView, UserDeleteView, ) +from .view_user import ( + UserDetailView, UserRedirectView, + UserUpdateView, UserListView, + UserDeleteView, ResponsiblePatientListView, + PatientDetailView, PatientListViewSelector, + HealthTeamPatientListView +) diff --git a/drdown/users/views/view_user.py b/drdown/users/views/view_user.py index 2650b627..295ea1b7 100644 --- a/drdown/users/views/view_user.py +++ b/drdown/users/views/view_user.py @@ -3,10 +3,20 @@ from django.contrib.auth.decorators import user_passes_test from django.utils.decorators import method_decorator from django.urls import reverse +from django.shortcuts import redirect from django.views.generic import (DetailView, ListView, RedirectView, - UpdateView, DeleteView) + UpdateView, DeleteView, View) +from search_views.search import SearchListView +from search_views.filters import BaseFilter from django.urls import reverse_lazy -from ..models import User +from ..models import User, Patient, Employee, HealthTeam, Responsible +from ..forms.users_forms import PatientSearchForm + + +class PatientFilter(BaseFilter): + search_fields = { + 'list_patient': ['id'], + } class UserDeleteView (LoginRequiredMixin, DeleteView): @@ -121,3 +131,100 @@ class UserListView(LoginRequiredMixin, ListView): # These next two lines tell the view to index lookups by username slug_field = 'username' slug_url_kwarg = 'username' + + +class PatientListViewSelector(RedirectView): + + def get(self, request, *args, **kwargs): + + if hasattr(request.user, 'patient'): + # redirect user_patient to the its medical sheet view + url = reverse( + viewname='users:patient_medical_sheet', + kwargs={'username': request.user.username} + ) + return redirect(url) + + if hasattr(request.user, 'responsible'): + url = reverse( + viewname='users:responsible_patient_list', + ) + return redirect(url) + + if ( + hasattr(request.user, 'healthteam') or + hasattr(request.user, 'employee') + ): + url = reverse( + viewname='users:healthteam_patient_list', + ) + return redirect(url) + + # redirect not not authenticated or not specialized + # to login screen + url = reverse( + viewname='account_login', + ) + return redirect(url) + + +class ResponsiblePatientListView(ListView): + + # the List View will list the patients that belong to the + # current user (specialized as a responsible), only responsibles will + # access this view + model = Patient + template_name = 'users/responsible_patient_list.html' + + def get(self, request, *args, **kwargs): + + if not hasattr(request.user, 'responsible'): + # redirect user_patient to the its medical sheet view + url = reverse( + viewname='account_login', + ) + return redirect(url) + + return super().get(request, *args, **kwargs) + + def get_queryset(self, *args, **kwargs): + + user = self.request.user + return super().get_queryset(*args, **kwargs).filter( + responsible=user.responsible + ) + + +class HealthTeamPatientListView(SearchListView): + + # the List View will list patients and will allow + # for the current user (specialized as a healthteam), + # to search them + + model = Patient + template_name = 'users/healthteam_patient_list.html' + form_class = PatientSearchForm + filter_class = PatientFilter + paginate_by = 20 + ordering = ['user_id'] + + def get(self, request, *args, **kwargs): + + if ( + not hasattr(request.user, 'healthteam') and + not hasattr(request.user, 'employee') + ): + # redirect user_patient to the its medical sheet view + url = reverse( + viewname='account_login', + ) + return redirect(url) + + return super().get(request, *args, **kwargs) + + +class PatientDetailView(DetailView): + model = Patient + template_name = 'users/patient_detail.html' + slug_url_kwarg = 'username' + slug_field = 'user__username' diff --git a/mkdocs-build.sh b/mkdocs-build.sh old mode 100644 new mode 100755 index ea445bd5..c72c169f --- a/mkdocs-build.sh +++ b/mkdocs-build.sh @@ -16,7 +16,7 @@ rev=$(git rev-parse --short HEAD) ( git add docs/drdown.pdf git commit -m "Rebuild sphinx documentation at ${rev} " - git push --force origin develop + git push origin develop ) # Running mkdocs build to gh-pages diff --git a/mkdocs.yml b/mkdocs.yml index 2be5eae3..f32c710e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -5,7 +5,7 @@ theme: readthedocs pages: - Home: index.md - - Abertura: + - Abertura: - Termo de abertura: eps/TAP.md - EAP: eps/EAP.md - Código de conduta: CODE_OF_CONDUCT.md @@ -15,9 +15,10 @@ pages: - Documento de arquitetura: mds/ARCHITECTURE_DOCUMENT.md - Especificação Suplementar: mds/ADDITIONAL_SPECIFICATION.md - Mapa de Requisitos: eps/REQUIREMENTS_MAP.md - - Gerenciamento de Qualidade: eps/QUALITY_MANAGEMENT_PLAN.md + - Gerenciamento de Qualidade: eps/QUALITY_MANAGEMENT_PLAN.md - ROADMAP: eps/ROADMAP.md - ROADMAP dos Papéis: eps/ROADMAP_ROLES.md + - MINDMAP: eps/MINDMAP.md - Protótipo de baixa qualidade: mds/LOW_FIDELITY_PROTOTYPE.md - Protótipo de alta qualidade: mds/HIGH_FIDELITY_PROTOTYPE.md - Viabilidade Técnica: @@ -26,6 +27,7 @@ pages: - EVM: eps/EVM_AGILE.md - Ferramentas: eps/PROJECT_TOOLS.md - Riscos: eps/RISKS.md + - Pipeline: eps/PIPELINE.md - Sprint 0: - Planejamento: sprints/00/planning.md - Resultado: sprints/00/results.md @@ -47,4 +49,9 @@ pages: - Sprint 6: - Planejamento: sprints/06/planning.md - Resultado: sprints/06/results.md - + - Sprint 7: + - Planejamento: sprints/07/planning.md + - Resultado: sprints/07/results.md + - Sprint 8: + - Planejamento: sprints/08/planning.md + - Resultado: sprints/08/results.md diff --git a/production-deploy.sh b/production-deploy.sh index bab4b50e..de9c19a1 100755 --- a/production-deploy.sh +++ b/production-deploy.sh @@ -4,8 +4,7 @@ # # Author: João Pedro Sconetto -echo $DOCKER_ID_USER_PASSWORD | docker login --username $DOCKER_ID_USER --password-stdin -docker tag 20181drdown_django_1 $DOCKER_ID_USER/20181-dr-down_django +docker tag 20181-dr-down_django:latest $DOCKER_ID_USER/20181-dr-down_django docker push $DOCKER_ID_USER/20181-dr-down_django sudo apt-get install sshpass -y diff --git a/requirements/base.txt b/requirements/base.txt index 294dfe8b..fa276617 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -6,6 +6,7 @@ whitenoise==3.3.1 # https://github.com/evansd/whitenoise redis>=2.10.5 # https://github.com/antirez/redis celery==3.1.25 # pyup: <4.0 # https://github.com/celery/celery raven==6.6.0 # https://github.com/getsentry/raven-python +python-dateutil==2.7.2 # https://github.com/dateutil/dateutil # Django # ------------------------------------------------------------------------------ diff --git a/staging-deploy.sh b/staging-deploy.sh index e09aa00e..ccc1e6df 100755 --- a/staging-deploy.sh +++ b/staging-deploy.sh @@ -4,8 +4,7 @@ # # Author: João Pedro Sconetto -echo $DOCKER_ID_USER_PASSWORD | docker login --username $DOCKER_ID_USER --password-stdin -docker tag 20181drdown_django_1 $DOCKER_ID_USER/20181-dr-down_django +docker tag 20181-dr-down_django:latest $DOCKER_ID_USER/20181-dr-down_django docker push $DOCKER_ID_USER/20181-dr-down_django sudo apt-get install sshpass -y