diff --git a/README.md b/README.md index 817b8c7..833749f 100644 --- a/README.md +++ b/README.md @@ -1,62 +1,51 @@ -# Venha para Recomb - -O desafio é desenvolver um programa que permita realizar as seguintes buscas: - -1) Listar os valores e data de Vencimento dos boletos presentes em um nota fiscal conforme o CPF ou CNPJ de um fornecedor. -2) Apresentar o nome, identificador (CPF ou CNPJ), endereço dos clientes de um fornecedor. - -**Escolha as tecnologias que você vai usar e tente montar uma solução completa para rodar a aplicação.** - -Para enviar o resultado, basta realiazar um Fork deste repositório e abra um Pull Request, com seu nome. - -É importante comentar que deve ser enviado apenas o código fonte. Não aceitaremos códigos compilados. - -Por fim, o candidato deve atualizar o Readme.md com as seguintes informações: - - 1) Documentação da solução; - 2) Lista dos diferenciais implementados - -## Avaliação - -O programa será avaliado levando em conta os seguintes critérios: -|Critério| Valor| -|-------|--------| -|Legibilidade do Código |10| -|Organização do Código|10| -|Documentação do código |10| -|Documentação da solução |10| -|Tratamento de Erros |10| -|Total| 50| - -A pontuação do candidato será a soma dos valores obtidos nos critérios acima. - -## Diferenciais - -O candidato pode aumentar a sua pontuação na seleção implementando um ou mais dos itens abaixo: -|Item | Pontos Ganhos| -|-----|--------------| -|Criar um serviço com o problema |30| -|Utilizar banco de dados |30| -|Implementar Clean Code |20| -|Implementar o padrão de programação da tecnologia escolhida |20| -|Qualidade de Código com SonarQube| 15| -|Implementar testes unitários |15| -|Implementar testes comportamentais | 15| -|Implementar integração com Travis |10| -|Implementar integração com Travis + SonarQube |10| -|Implementar usando Docker |5| -|Total | 170| - -A nota final do candidato será acrescido dos pontos referente ao item implementado corretamente. - -## Penalizações - -O candidato será desclassifiado nas seguintes situações: - -1) Submeter um solução que não funcione; -2) Não cumprir os critérios presentes no seção Avaliação; -3) Plágio; - - - - +## Documentação da Solução + +### Tecnologias Utilizadas +- Django: Framework web em Python. +- Sqlite3: Serviço de banco de dados local do Django. +- HTML, CSS e Bootstrap: para a interface do usuário. +- Docker. + +### Funcionalidades Implementadas +1. **Parse de XML**: A função parse_xml recebe um arquivo XML de uma nota fiscal e extrai as informações relevantes, como fornecedor, clientes, endereços e boletos. +2. **Página Inicial**: A view index renderiza a página inicial do sistema, permitindo aos usuários enviar arquivos XML para processamento. +3. **Cadastro de Notas Fiscais**: Ao submeter um arquivo XML válido, as informações da nota fiscal são salvas no banco de dados, incluindo fornecedor, clientes e boletos associados. +4. **Listagem de Notas Fiscais**: A view list_nfs apresenta uma lista de todas as notas fiscais cadastradas no sistema. +5. **Detalhes da Nota Fiscal**: A view detail_nf permite visualizar os detalhes de uma nota fiscal específica, incluindo clientes e boletos associados. +6. **Exclusão de Notas Fiscais**: A view delete_nf permite excluir uma nota fiscal do banco de dados, mas não exclui dados de fornecedor e clientes. +7. **Listagem de Fornecedores**: A view list_fornecedores lista todos os fornecedores cadastrados no sistema. +8. **Exclusão de Fornecedores**: A view delete_fornecedor permite excluir um fornecedor do banco de dados. Ao excluir um fornecedor do banco de dados as notas fiscais associadas também são apagadas. +9. **Listagem de Clientes**: A view list_clientes lista todos os clientes cadastrados no sistema. +10. **Exclusão de Clientes**: A view delete_cliente permite excluir um cliente do banco de dados. Ao apagar um cliente, as notas fiscais relacionadas são apagadas. + +### Como Executar a Aplicação +1. Clone o repositório do projeto: + ``` + git clone https://github.com/jcquadros/venhapararecomb-backend.git + ``` +2. Certifique-se de estar dentro do diretorio venhapararecomb/ Execute: + ``` + docker-compose build + docker-compose up + ``` + Acesse 'http://localhost:8000/' no navegador. + +3. Testes: + Para executar os testes, certifique estar dentro do diretório venhapararecomb/ de instalar as bibliotecas e executar o teste: + ``` + pip install -r requirements.txt + python manage.py test + ``` + De forma semelhante, se optar por nao usar o Docker, a aplicação pode ser executada com os seguintes comandos: + ``` + pip install -r requirements.txt + python manage.py runserver + ``` + Após isso acesse 'http://127.0.0.1:8000/' no navegador. +## Diferenciais Implementados +- Interface de Usuário Responsiva: A interface do usuário foi desenvolvida de forma simples com Bootstrap, mas responsiva. +- Tratamento de Erros: O sistema trata erros comuns, como tentativa de envio de nota fiscal fornecedores e clientes duplicados. +- Padrão de programação Django MTV (Model, Template, View) +- Uso de banco de dados: A aplicação utiliza o Sqlite3 como serviço de banco de dados local. +- Implementação de Testes Unitários: Os testes cobrem as principais funções da aplicação, incluindo as views e os modelos do Django. +- Uso de docker. diff --git a/venhapararecomb/Dockerfile b/venhapararecomb/Dockerfile new file mode 100644 index 0000000..b82fc1b --- /dev/null +++ b/venhapararecomb/Dockerfile @@ -0,0 +1,20 @@ +# Imagem base do Python +FROM python:3.10 + +# Configuração do diretório de trabalho dentro do contêiner +WORKDIR /app + +# Copia o arquivo requirements.txt para o contêiner +COPY requirements.txt . + +# Instala as dependências do projeto +RUN pip install -r requirements.txt + +# Copia o restante do código-fonte para o contêiner +COPY . . + +# Expõe a porta 8000 do contêiner +EXPOSE 8000 + +# Comando para executar o servidor Django +CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"] diff --git a/venhapararecomb/db.sqlite3 b/venhapararecomb/db.sqlite3 new file mode 100644 index 0000000..b0dac5e Binary files /dev/null and b/venhapararecomb/db.sqlite3 differ diff --git a/venhapararecomb/docker-compose.yml b/venhapararecomb/docker-compose.yml new file mode 100644 index 0000000..e4f24f4 --- /dev/null +++ b/venhapararecomb/docker-compose.yml @@ -0,0 +1,10 @@ +version: '3' + +services: + web: + build: . + command: python manage.py runserver 0.0.0.0:8000 + volumes: + - .:/app + ports: + - "8000:8000" diff --git a/venhapararecomb/manage.py b/venhapararecomb/manage.py new file mode 100755 index 0000000..3018984 --- /dev/null +++ b/venhapararecomb/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'venhapararecomb.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/venhapararecomb/notafiscal/__init__.py b/venhapararecomb/notafiscal/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venhapararecomb/notafiscal/__pycache__/__init__.cpython-310.pyc b/venhapararecomb/notafiscal/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..96b8196 Binary files /dev/null and b/venhapararecomb/notafiscal/__pycache__/__init__.cpython-310.pyc differ diff --git a/venhapararecomb/notafiscal/__pycache__/__init__.cpython-311.pyc b/venhapararecomb/notafiscal/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..6811ac7 Binary files /dev/null and b/venhapararecomb/notafiscal/__pycache__/__init__.cpython-311.pyc differ diff --git a/venhapararecomb/notafiscal/__pycache__/__init__.cpython-312.pyc b/venhapararecomb/notafiscal/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..7cafaa7 Binary files /dev/null and b/venhapararecomb/notafiscal/__pycache__/__init__.cpython-312.pyc differ diff --git a/venhapararecomb/notafiscal/__pycache__/admin.cpython-310.pyc b/venhapararecomb/notafiscal/__pycache__/admin.cpython-310.pyc new file mode 100644 index 0000000..9189878 Binary files /dev/null and b/venhapararecomb/notafiscal/__pycache__/admin.cpython-310.pyc differ diff --git a/venhapararecomb/notafiscal/__pycache__/admin.cpython-311.pyc b/venhapararecomb/notafiscal/__pycache__/admin.cpython-311.pyc new file mode 100644 index 0000000..4350716 Binary files /dev/null and b/venhapararecomb/notafiscal/__pycache__/admin.cpython-311.pyc differ diff --git a/venhapararecomb/notafiscal/__pycache__/admin.cpython-312.pyc b/venhapararecomb/notafiscal/__pycache__/admin.cpython-312.pyc new file mode 100644 index 0000000..33fd7ab Binary files /dev/null and b/venhapararecomb/notafiscal/__pycache__/admin.cpython-312.pyc differ diff --git a/venhapararecomb/notafiscal/__pycache__/apps.cpython-310.pyc b/venhapararecomb/notafiscal/__pycache__/apps.cpython-310.pyc new file mode 100644 index 0000000..ae5645b Binary files /dev/null and b/venhapararecomb/notafiscal/__pycache__/apps.cpython-310.pyc differ diff --git a/venhapararecomb/notafiscal/__pycache__/apps.cpython-311.pyc b/venhapararecomb/notafiscal/__pycache__/apps.cpython-311.pyc new file mode 100644 index 0000000..9a12de3 Binary files /dev/null and b/venhapararecomb/notafiscal/__pycache__/apps.cpython-311.pyc differ diff --git a/venhapararecomb/notafiscal/__pycache__/apps.cpython-312.pyc b/venhapararecomb/notafiscal/__pycache__/apps.cpython-312.pyc new file mode 100644 index 0000000..e5a548d Binary files /dev/null and b/venhapararecomb/notafiscal/__pycache__/apps.cpython-312.pyc differ diff --git a/venhapararecomb/notafiscal/__pycache__/forms.cpython-310.pyc b/venhapararecomb/notafiscal/__pycache__/forms.cpython-310.pyc new file mode 100644 index 0000000..33daadb Binary files /dev/null and b/venhapararecomb/notafiscal/__pycache__/forms.cpython-310.pyc differ diff --git a/venhapararecomb/notafiscal/__pycache__/models.cpython-310.pyc b/venhapararecomb/notafiscal/__pycache__/models.cpython-310.pyc new file mode 100644 index 0000000..f55b6fc Binary files /dev/null and b/venhapararecomb/notafiscal/__pycache__/models.cpython-310.pyc differ diff --git a/venhapararecomb/notafiscal/__pycache__/models.cpython-311.pyc b/venhapararecomb/notafiscal/__pycache__/models.cpython-311.pyc new file mode 100644 index 0000000..2682e1b Binary files /dev/null and b/venhapararecomb/notafiscal/__pycache__/models.cpython-311.pyc differ diff --git a/venhapararecomb/notafiscal/__pycache__/models.cpython-312.pyc b/venhapararecomb/notafiscal/__pycache__/models.cpython-312.pyc new file mode 100644 index 0000000..88934e4 Binary files /dev/null and b/venhapararecomb/notafiscal/__pycache__/models.cpython-312.pyc differ diff --git a/venhapararecomb/notafiscal/__pycache__/tests.cpython-311.pyc b/venhapararecomb/notafiscal/__pycache__/tests.cpython-311.pyc new file mode 100644 index 0000000..77cf883 Binary files /dev/null and b/venhapararecomb/notafiscal/__pycache__/tests.cpython-311.pyc differ diff --git a/venhapararecomb/notafiscal/__pycache__/tests.cpython-312.pyc b/venhapararecomb/notafiscal/__pycache__/tests.cpython-312.pyc new file mode 100644 index 0000000..79e16dc Binary files /dev/null and b/venhapararecomb/notafiscal/__pycache__/tests.cpython-312.pyc differ diff --git a/venhapararecomb/notafiscal/__pycache__/urls.cpython-310.pyc b/venhapararecomb/notafiscal/__pycache__/urls.cpython-310.pyc new file mode 100644 index 0000000..e133bee Binary files /dev/null and b/venhapararecomb/notafiscal/__pycache__/urls.cpython-310.pyc differ diff --git a/venhapararecomb/notafiscal/__pycache__/urls.cpython-311.pyc b/venhapararecomb/notafiscal/__pycache__/urls.cpython-311.pyc new file mode 100644 index 0000000..19a5c5e Binary files /dev/null and b/venhapararecomb/notafiscal/__pycache__/urls.cpython-311.pyc differ diff --git a/venhapararecomb/notafiscal/__pycache__/urls.cpython-312.pyc b/venhapararecomb/notafiscal/__pycache__/urls.cpython-312.pyc new file mode 100644 index 0000000..6f1d87f Binary files /dev/null and b/venhapararecomb/notafiscal/__pycache__/urls.cpython-312.pyc differ diff --git a/venhapararecomb/notafiscal/__pycache__/views.cpython-310.pyc b/venhapararecomb/notafiscal/__pycache__/views.cpython-310.pyc new file mode 100644 index 0000000..c4e8ead Binary files /dev/null and b/venhapararecomb/notafiscal/__pycache__/views.cpython-310.pyc differ diff --git a/venhapararecomb/notafiscal/__pycache__/views.cpython-311.pyc b/venhapararecomb/notafiscal/__pycache__/views.cpython-311.pyc new file mode 100644 index 0000000..cffbeb4 Binary files /dev/null and b/venhapararecomb/notafiscal/__pycache__/views.cpython-311.pyc differ diff --git a/venhapararecomb/notafiscal/__pycache__/views.cpython-312.pyc b/venhapararecomb/notafiscal/__pycache__/views.cpython-312.pyc new file mode 100644 index 0000000..07e486b Binary files /dev/null and b/venhapararecomb/notafiscal/__pycache__/views.cpython-312.pyc differ diff --git a/venhapararecomb/notafiscal/admin.py b/venhapararecomb/notafiscal/admin.py new file mode 100644 index 0000000..84259e1 --- /dev/null +++ b/venhapararecomb/notafiscal/admin.py @@ -0,0 +1,8 @@ +from django.contrib import admin +from .models import Fornecedor, Cliente, Boleto, NotaFiscal, Endereco + +admin.site.register(Fornecedor) +admin.site.register(Cliente) +admin.site.register(Boleto) +admin.site.register(NotaFiscal) +admin.site.register(Endereco) diff --git a/venhapararecomb/notafiscal/apps.py b/venhapararecomb/notafiscal/apps.py new file mode 100644 index 0000000..66eaea5 --- /dev/null +++ b/venhapararecomb/notafiscal/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class NotafiscalConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'notafiscal' diff --git a/venhapararecomb/notafiscal/migrations/0001_initial.py b/venhapararecomb/notafiscal/migrations/0001_initial.py new file mode 100644 index 0000000..0127622 --- /dev/null +++ b/venhapararecomb/notafiscal/migrations/0001_initial.py @@ -0,0 +1,65 @@ +# Generated by Django 5.0.3 on 2024-03-10 21:02 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Endereco', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('logradouro', models.CharField(max_length=100)), + ('numero', models.CharField(max_length=10)), + ('bairro', models.CharField(max_length=50)), + ('cidade', models.CharField(max_length=50)), + ('estado', models.CharField(max_length=2)), + ('cep', models.CharField(max_length=8)), + ('pais', models.CharField(max_length=50)), + ('telefone', models.CharField(max_length=15)), + ], + ), + migrations.CreateModel( + name='Fornecedor', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('nome', models.CharField(max_length=100)), + ('cnpj', models.CharField(max_length=14, unique=True)), + ], + ), + migrations.CreateModel( + name='Cliente', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('nome', models.CharField(max_length=100)), + ('tipo_documento', models.CharField(choices=[('CPF', 'CPF'), ('CNPJ', 'CNPJ')], max_length=4)), + ('documento', models.CharField(max_length=14, unique=True)), + ('endereco', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='notafiscal.endereco')), + ], + ), + migrations.CreateModel( + name='NotaFiscal', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('identificador', models.CharField(max_length=50, unique=True)), + ('clientes', models.ManyToManyField(related_name='notas_fiscais', to='notafiscal.cliente')), + ('fornecedor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='notafiscal.fornecedor')), + ], + ), + migrations.CreateModel( + name='Boleto', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('valor', models.DecimalField(decimal_places=2, max_digits=10)), + ('data_vencimento', models.DateField()), + ('nota_fiscal', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='notafiscal.notafiscal')), + ], + ), + ] diff --git a/venhapararecomb/notafiscal/migrations/__init__.py b/venhapararecomb/notafiscal/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venhapararecomb/notafiscal/migrations/__pycache__/0001_initial.cpython-310.pyc b/venhapararecomb/notafiscal/migrations/__pycache__/0001_initial.cpython-310.pyc new file mode 100644 index 0000000..de66abe Binary files /dev/null and b/venhapararecomb/notafiscal/migrations/__pycache__/0001_initial.cpython-310.pyc differ diff --git a/venhapararecomb/notafiscal/migrations/__pycache__/0001_initial.cpython-311.pyc b/venhapararecomb/notafiscal/migrations/__pycache__/0001_initial.cpython-311.pyc new file mode 100644 index 0000000..00c821a Binary files /dev/null and b/venhapararecomb/notafiscal/migrations/__pycache__/0001_initial.cpython-311.pyc differ diff --git a/venhapararecomb/notafiscal/migrations/__pycache__/0001_initial.cpython-312.pyc b/venhapararecomb/notafiscal/migrations/__pycache__/0001_initial.cpython-312.pyc new file mode 100644 index 0000000..d57277b Binary files /dev/null and b/venhapararecomb/notafiscal/migrations/__pycache__/0001_initial.cpython-312.pyc differ diff --git a/venhapararecomb/notafiscal/migrations/__pycache__/0002_notafiscal_identificador_alter_notafiscal_id.cpython-311.pyc b/venhapararecomb/notafiscal/migrations/__pycache__/0002_notafiscal_identificador_alter_notafiscal_id.cpython-311.pyc new file mode 100644 index 0000000..5224d4a Binary files /dev/null and b/venhapararecomb/notafiscal/migrations/__pycache__/0002_notafiscal_identificador_alter_notafiscal_id.cpython-311.pyc differ diff --git a/venhapararecomb/notafiscal/migrations/__pycache__/0002_remove_boleto_fornecedor_remove_cliente_fornecedor_and_more.cpython-311.pyc b/venhapararecomb/notafiscal/migrations/__pycache__/0002_remove_boleto_fornecedor_remove_cliente_fornecedor_and_more.cpython-311.pyc new file mode 100644 index 0000000..bf22680 Binary files /dev/null and b/venhapararecomb/notafiscal/migrations/__pycache__/0002_remove_boleto_fornecedor_remove_cliente_fornecedor_and_more.cpython-311.pyc differ diff --git a/venhapararecomb/notafiscal/migrations/__pycache__/0002_remove_boleto_fornecedor_remove_cliente_fornecedor_and_more.cpython-312.pyc b/venhapararecomb/notafiscal/migrations/__pycache__/0002_remove_boleto_fornecedor_remove_cliente_fornecedor_and_more.cpython-312.pyc new file mode 100644 index 0000000..14fa797 Binary files /dev/null and b/venhapararecomb/notafiscal/migrations/__pycache__/0002_remove_boleto_fornecedor_remove_cliente_fornecedor_and_more.cpython-312.pyc differ diff --git a/venhapararecomb/notafiscal/migrations/__pycache__/0003_rename_identificador_cliente_documento.cpython-311.pyc b/venhapararecomb/notafiscal/migrations/__pycache__/0003_rename_identificador_cliente_documento.cpython-311.pyc new file mode 100644 index 0000000..5fe1f5c Binary files /dev/null and b/venhapararecomb/notafiscal/migrations/__pycache__/0003_rename_identificador_cliente_documento.cpython-311.pyc differ diff --git a/venhapararecomb/notafiscal/migrations/__pycache__/0003_rename_identificador_cliente_documento.cpython-312.pyc b/venhapararecomb/notafiscal/migrations/__pycache__/0003_rename_identificador_cliente_documento.cpython-312.pyc new file mode 100644 index 0000000..6ba5951 Binary files /dev/null and b/venhapararecomb/notafiscal/migrations/__pycache__/0003_rename_identificador_cliente_documento.cpython-312.pyc differ diff --git a/venhapararecomb/notafiscal/migrations/__pycache__/0004_remove_cliente_nota_fiscal_notafiscal_clientes_and_more.cpython-311.pyc b/venhapararecomb/notafiscal/migrations/__pycache__/0004_remove_cliente_nota_fiscal_notafiscal_clientes_and_more.cpython-311.pyc new file mode 100644 index 0000000..bd99087 Binary files /dev/null and b/venhapararecomb/notafiscal/migrations/__pycache__/0004_remove_cliente_nota_fiscal_notafiscal_clientes_and_more.cpython-311.pyc differ diff --git a/venhapararecomb/notafiscal/migrations/__pycache__/0004_remove_cliente_nota_fiscal_notafiscal_clientes_and_more.cpython-312.pyc b/venhapararecomb/notafiscal/migrations/__pycache__/0004_remove_cliente_nota_fiscal_notafiscal_clientes_and_more.cpython-312.pyc new file mode 100644 index 0000000..9d65413 Binary files /dev/null and b/venhapararecomb/notafiscal/migrations/__pycache__/0004_remove_cliente_nota_fiscal_notafiscal_clientes_and_more.cpython-312.pyc differ diff --git a/venhapararecomb/notafiscal/migrations/__pycache__/0005_endereco_cliente_endereco.cpython-311.pyc b/venhapararecomb/notafiscal/migrations/__pycache__/0005_endereco_cliente_endereco.cpython-311.pyc new file mode 100644 index 0000000..4a51327 Binary files /dev/null and b/venhapararecomb/notafiscal/migrations/__pycache__/0005_endereco_cliente_endereco.cpython-311.pyc differ diff --git a/venhapararecomb/notafiscal/migrations/__pycache__/0005_endereco_cliente_endereco.cpython-312.pyc b/venhapararecomb/notafiscal/migrations/__pycache__/0005_endereco_cliente_endereco.cpython-312.pyc new file mode 100644 index 0000000..026bd52 Binary files /dev/null and b/venhapararecomb/notafiscal/migrations/__pycache__/0005_endereco_cliente_endereco.cpython-312.pyc differ diff --git a/venhapararecomb/notafiscal/migrations/__pycache__/0006_alter_notafiscal_id.cpython-311.pyc b/venhapararecomb/notafiscal/migrations/__pycache__/0006_alter_notafiscal_id.cpython-311.pyc new file mode 100644 index 0000000..89de3f5 Binary files /dev/null and b/venhapararecomb/notafiscal/migrations/__pycache__/0006_alter_notafiscal_id.cpython-311.pyc differ diff --git a/venhapararecomb/notafiscal/migrations/__pycache__/__init__.cpython-310.pyc b/venhapararecomb/notafiscal/migrations/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..0fa3941 Binary files /dev/null and b/venhapararecomb/notafiscal/migrations/__pycache__/__init__.cpython-310.pyc differ diff --git a/venhapararecomb/notafiscal/migrations/__pycache__/__init__.cpython-311.pyc b/venhapararecomb/notafiscal/migrations/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..7d921f9 Binary files /dev/null and b/venhapararecomb/notafiscal/migrations/__pycache__/__init__.cpython-311.pyc differ diff --git a/venhapararecomb/notafiscal/migrations/__pycache__/__init__.cpython-312.pyc b/venhapararecomb/notafiscal/migrations/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..a56155b Binary files /dev/null and b/venhapararecomb/notafiscal/migrations/__pycache__/__init__.cpython-312.pyc differ diff --git a/venhapararecomb/notafiscal/models.py b/venhapararecomb/notafiscal/models.py new file mode 100644 index 0000000..48d758d --- /dev/null +++ b/venhapararecomb/notafiscal/models.py @@ -0,0 +1,67 @@ +from typing import Any +from django.db import models + +class Fornecedor(models.Model): + """ + Modelo que representa um fornecedor de produtos. Cada fornecedor possui um nome e um CNPJ. + """ + nome = models.CharField(max_length=100) + cnpj = models.CharField(max_length=14, unique=True) + + def __str__(self) -> str: + return self.nome + +class NotaFiscal(models.Model): + """ + Modelo que representa uma nota fiscal. Cada nota fiscal possui um identificador único, um fornecedor e uma lista de clientes. + """ + identificador = models.CharField(max_length=50, unique=True) + fornecedor = models.ForeignKey(Fornecedor, on_delete=models.CASCADE) + clientes = models.ManyToManyField('Cliente', related_name='notas_fiscais') + + def __str__(self) -> str: + return f'Nota Fiscal {self.id} - {self.fornecedor}' + +class Boleto(models.Model): + """ + Modelo que representa um boleto. Cada boleto possui um valor, uma data de vencimento e uma nota fiscal. + """ + valor = models.DecimalField(max_digits=10, decimal_places=2) + data_vencimento = models.DateField() + nota_fiscal = models.ForeignKey(NotaFiscal, on_delete=models.CASCADE) + + def __str__(self) -> str: + return f'Boleto {self.valor} - {self.data_vencimento}' + +class Endereco(models.Model): + """ + Modelo que representa um endereço. Cada endereço possui um logradouro, um número, um bairro, uma cidade, um estado, um CEP, um país e um telefone. + """ + logradouro = models.CharField(max_length=100) + numero = models.CharField(max_length=10) + bairro = models.CharField(max_length=50) + cidade = models.CharField(max_length=50) + estado = models.CharField(max_length=2) + cep = models.CharField(max_length=8) + pais = models.CharField(max_length=50) + telefone = models.CharField(max_length=15) + + def __str__(self) -> str: + return self.logradouro + +class Cliente(models.Model): + """ + Modelo que representa um cliente. Cada cliente possui um nome, um tipo de documento (CPF ou CNPJ), um documento (CPF ou CNPJ) e um endereço. + """ + TIPO_DOCUMENTO = ( + ('CPF', 'CPF'), + ('CNPJ', 'CNPJ'), + ) + + nome = models.CharField(max_length=100) + tipo_documento = models.CharField(max_length=4, choices=TIPO_DOCUMENTO) + documento = models.CharField(max_length=14, unique=True) # cpf ou cnpj + endereco = models.ForeignKey(Endereco, on_delete=models.CASCADE) + + def __str__(self) -> str: + return self.nome diff --git a/venhapararecomb/notafiscal/tests.py b/venhapararecomb/notafiscal/tests.py new file mode 100644 index 0000000..5b61083 --- /dev/null +++ b/venhapararecomb/notafiscal/tests.py @@ -0,0 +1,93 @@ +from django.test import TestCase +from django.urls import reverse +from .models import Fornecedor, NotaFiscal, Cliente, Boleto, Endereco + +FORNECEDOR_NOME = 'Fornecedor Test' +FORNECEDOR_CNPJ = '12345678901234' +NF_IDENTIFICADOR = 'NF001' +CLIENTE_NOME = 'Cliente Test' +CLIENTE_TIPO_DOCUMENTO = 'CPF' +CLIENTE_DOCUMENTO = '12345678901' +BOLETO_VALOR = 100.00 +BOLETO_DATA_VENCIMENTO = '2024-01-01' + +class ModelTestCase(TestCase): + def setUp(self): + self.fornecedor = Fornecedor.objects.create(nome=FORNECEDOR_NOME, cnpj=FORNECEDOR_CNPJ) + self.endereco = Endereco.objects.create(logradouro='Rua Test', numero='123', bairro='Bairro Test', + cidade='Cidade Test', estado='TS', cep='12345678', + pais='País Test', telefone='123456789') + self.cliente = Cliente.objects.create(nome=CLIENTE_NOME, tipo_documento=CLIENTE_TIPO_DOCUMENTO, documento=CLIENTE_DOCUMENTO, + endereco=self.endereco) + self.nf = NotaFiscal.objects.create(identificador=NF_IDENTIFICADOR, fornecedor=self.fornecedor) + self.boleto = Boleto.objects.create(valor=BOLETO_VALOR, data_vencimento=BOLETO_DATA_VENCIMENTO, nota_fiscal=self.nf) + + def test_fornecedor_creation(self): + self.assertEqual(self.fornecedor.nome, FORNECEDOR_NOME) + self.assertEqual(self.fornecedor.cnpj, FORNECEDOR_CNPJ) + + def test_nota_fiscal_creation(self): + self.assertEqual(self.nf.identificador, NF_IDENTIFICADOR) + self.assertEqual(self.nf.fornecedor, self.fornecedor) + + def test_cliente_creation(self): + self.assertEqual(self.cliente.nome, CLIENTE_NOME) + self.assertEqual(self.cliente.tipo_documento, CLIENTE_TIPO_DOCUMENTO) + self.assertEqual(self.cliente.documento, CLIENTE_DOCUMENTO) + self.assertEqual(self.cliente.endereco, self.endereco) + + def test_boleto_creation(self): + self.assertEqual(self.boleto.valor, BOLETO_VALOR) + self.assertEqual(str(self.boleto.data_vencimento), BOLETO_DATA_VENCIMENTO) + self.assertEqual(self.boleto.nota_fiscal, self.nf) + + +class ViewTestCase(TestCase): + def setUp(self) : + self.fornecedor = Fornecedor.objects.create(nome=FORNECEDOR_NOME, cnpj=FORNECEDOR_CNPJ) + + def test_index_view(self): + response = self.client.get(reverse('index')) + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, 'index.html') + + def test_list_nfs_view(self): + response = self.client.get(reverse('list_nfs')) + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, 'list_nfs.html') + + def test_detail_nf_view(self): + nf = NotaFiscal.objects.create(identificador=NF_IDENTIFICADOR, fornecedor=self.fornecedor) + response = self.client.get(reverse('detail_nf', args=(nf.id,))) + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, 'detail_nf.html') + + def test_delete_nf_view(self): + nf = NotaFiscal.objects.create(identificador=NF_IDENTIFICADOR, fornecedor=self.fornecedor) + response = self.client.post(reverse('delete_nf', args=(nf.id,))) + self.assertEqual(response.status_code, 302) + + def test_list_clientes_view(self): + response = self.client.get(reverse('list_clientes')) + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, 'list_clientes.html') + + def test_list_forncedores_view(self): + response = self.client.get(reverse('list_fornecedores')) + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, 'list_fornecedores.html') + + def test_delete_fornecedor_view(self): + response = self.client.post(reverse('delete_fornecedor', args=(self.fornecedor.id,))) + self.assertEqual(response.status_code, 302) + + def test_delete_cliente_view(self): + cliente = Cliente.objects.create(nome=CLIENTE_NOME, tipo_documento=CLIENTE_TIPO_DOCUMENTO, documento=CLIENTE_DOCUMENTO, + endereco=Endereco.objects.create(logradouro='Rua Test', numero='123', bairro='Bairro Test', + cidade='Cidade Test', estado='TS', cep='12345678', + pais='País Test', telefone='123456789')) + response = self.client.post(reverse('delete_cliente', args=(cliente.id,))) + self.assertEqual(response.status_code, 302) + + + diff --git a/venhapararecomb/notafiscal/urls.py b/venhapararecomb/notafiscal/urls.py new file mode 100644 index 0000000..a6a00ea --- /dev/null +++ b/venhapararecomb/notafiscal/urls.py @@ -0,0 +1,13 @@ +from django.urls import path +from . import views + +urlpatterns = [ + path('', views.index, name='index'), + path('nfs/', views.list_nfs, name='list_nfs'), + path('nf//', views.detail_nf, name='detail_nf'), + path('nf//delete/', views.delete_nf, name='delete_nf'), + path('fornecedores/', views.list_fornecedores, name='list_fornecedores'), + path('fornecedor//delete/', views.delete_fornecedor, name='delete_fornecedor'), + path('clientes/', views.list_clientes, name='list_clientes'), + path('cliente//delete/', views.delete_cliente, name='delete_cliente'), +] diff --git a/venhapararecomb/notafiscal/views.py b/venhapararecomb/notafiscal/views.py new file mode 100644 index 0000000..6ec4fa7 --- /dev/null +++ b/venhapararecomb/notafiscal/views.py @@ -0,0 +1,238 @@ +from django.shortcuts import render, redirect +import xml.etree.ElementTree as ET +from .models import Fornecedor, Cliente, Boleto, NotaFiscal, Endereco +from django.urls import reverse +from django.views.decorators.http import require_POST + + +def parse_xml(xml_file): + """ + Esta função recebe um arquivo XML e extrai informações relevantes para o sistema de notas fiscais. + + Args: + xml_file: O arquivo XML enviado pelo usuário. + + Returns: + dict: Um dicionário contendo informações extraídas do XML, incluindo ID da nota fiscal, fornecedor, + clientes e boletos. + """ + + xml = ET.parse(xml_file) + root = xml.getroot() + nsNFe = {'ns': 'http://www.portalfiscal.inf.br/nfe'} + nf_id = root.find('.//ns:infNFe', nsNFe).attrib['Id'] + + # Extraindo informações do fornecedor da nota fiscal (emitente) + xNome = root.find('ns:NFe/ns:infNFe/ns:emit/ns:xNome', nsNFe).text + cnpj = root.find('ns:NFe/ns:infNFe/ns:emit/ns:CNPJ', nsNFe).text + fornecedor = {'nome': xNome, 'cnpj': cnpj} + + # Extraindo informações dos clientes da nota fiscal + clientes = [] + for dest in root.findall('ns:NFe/ns:infNFe/ns:dest', nsNFe): + xNome = dest.find('ns:xNome', nsNFe).text + cpf = dest.find('ns:CPF', nsNFe) + cnpj = dest.find('ns:CNPJ', nsNFe) + + # Extraindo informações do endereço do cliente + endereco = dest.find('ns:enderDest', nsNFe) + logradouro = endereco.find('ns:xLgr', nsNFe).text + numero = endereco.find('ns:nro', nsNFe).text + bairro = endereco.find('ns:xBairro', nsNFe).text + cidade = endereco.find('ns:xMun', nsNFe).text + estado = endereco.find('ns:UF', nsNFe).text + cep = endereco.find('ns:CEP', nsNFe).text + pais = endereco.find('ns:xPais', nsNFe).text + telefone = endereco.find('ns:fone', nsNFe).text + + documento = cpf.text if cpf is not None else cnpj.text + tipo_documento = 'CPF' if cpf is not None else 'CNPJ' + + endereco_json = { + 'logradouro': logradouro, 'numero': numero, 'bairro': bairro, + 'cidade': cidade, 'estado': estado, 'cep': cep, 'pais': pais, 'telefone': telefone + } + + clientes.append({'nome': xNome, 'documento': documento, 'tipo_documento': tipo_documento, 'endereco': endereco_json}) + + # Extraindo informações dos boletos da nota fiscal + boletos = [] + for det in root.findall('ns:NFe/ns:infNFe/ns:cobr/ns:dup', nsNFe): + valor = det.find('ns:vDup', nsNFe).text + data_vencimento = det.find('ns:dVenc', nsNFe).text + boletos.append({'valor': valor, 'data_vencimento': data_vencimento}) # Adicionando informações do boleto à lista de boletos + + return {'nf_id': nf_id, 'fornecedor': fornecedor, 'clientes': clientes, 'boletos': boletos} + + + +def index(request): + """ + Esta função é responsável por renderizar a página inicial do sistema de notas fiscais. + Permite aos usuários enviar arquivos XML para processamento e salvar as informações da nota fiscal no banco de dados. + + Returns: + HttpResponse: Uma resposta HTTP renderizada com base na solicitação do usuário. + """ + context = {} + if request.method == 'POST': + # Verificando se o usuário deseja ler um arquivo XML + if 'read_xml' in request.POST: + xml_data = parse_xml(request.FILES['xml_file']) + request.session['xml_data'] = xml_data + context['xml_data'] = xml_data + + # Verificando se o usuário deseja salvar a nota fiscal lida + elif 'save_nf' in request.POST: + xml_data = request.session.pop('xml_data', {}) + fornecedor, _ = Fornecedor.objects.get_or_create(nome=xml_data['fornecedor']['nome'], cnpj=xml_data['fornecedor']['cnpj']) + nf, created = NotaFiscal.objects.get_or_create(identificador=xml_data['nf_id'], fornecedor=fornecedor) + + # Verificando se a nota fiscal já foi cadastrada + if not created: + context['error'] = 'Nota Fiscal já cadastrada' + context['xml_data'] = xml_data + return render(request, 'index.html', context) + + # Adicionando clientes à nota fiscal + for cliente_data in xml_data['clientes']: + documento = cliente_data['documento'] + try: + cliente_obj = Cliente.objects.get(documento=documento) + except Cliente.DoesNotExist: + endereco_obj = Endereco.objects.create(**cliente_data['endereco']) + cliente_obj = Cliente.objects.create(documento=documento, nome=cliente_data['nome'], tipo_documento=cliente_data['tipo_documento'], endereco=endereco_obj) + + nf.clientes.add(cliente_obj) + + # Adicionando boletos à nota fiscal + for boleto_data in xml_data['boletos']: + Boleto.objects.create(valor=boleto_data['valor'], data_vencimento=boleto_data['data_vencimento'], nota_fiscal=nf) + + context['success'] = 'Nota Fiscal cadastrada com sucesso' + + return render(request, 'index.html', context) + +@require_POST +def delete_nf(request, id): + """ + Esta função é responsável por deletar uma nota fiscal do banco de dados. + + Args: + id: O ID da nota fiscal a ser deletada. + + Returns: + HttpResponseRedirect: Redireciona o usuário para a página de listagem de notas fiscais após a exclusão. + """ + try: + nf = NotaFiscal.objects.get(id=id) + nf.delete() + except NotaFiscal.DoesNotExist: + pass + return redirect(reverse('list_nfs')) + + +def list_nfs(request): + """ + Esta função é responsável por listar todas as notas fiscais cadastradas no sistema. + + Returns: + HttpResponse: Uma resposta HTTP renderizada com base na solicitação do usuário, listando todas as notas fiscais. + """ + context = { + 'nfs': NotaFiscal.objects.all() + } + return render(request, 'list_nfs.html', context) + + +def detail_nf(request, id): + """ + Esta função é responsável por renderizar a página de detalhes de uma nota fiscal. + + Args: + id: O ID da nota fiscal a ser visualizada. + + Returns: + HttpResponse: Uma resposta HTTP renderizada com base na solicitação do usuário, exibindo os detalhes da nota fiscal. + """ + + nf = NotaFiscal.objects.get(id=id) + clientes = nf.clientes.all() + fornecedor = nf.fornecedor + boletos = Boleto.objects.filter(nota_fiscal=nf) + + context = { + 'nf': nf, + 'clientes': clientes, + 'boletos': boletos, + 'fornecedor': fornecedor + } + + return render(request, 'detail_nf.html', context) + +@require_POST +def delete_fornecedor(request, id): + """ + Esta função é responsável por deletar um fornecedor do banco de dados. + + Args: + id: O ID do fornecedor a ser deletado. + + Returns: + HttpResponseRedirect: Redireciona o usuário para a página de listagem de fornecedores após a exclusão. + """ + try: + fornecedor = Fornecedor.objects.get(id=id) + fornecedor.delete() + except Fornecedor.DoesNotExist: + pass + return redirect(reverse('list_fornecedores')) + +def list_fornecedores(request): + """ + Esta função é responsável por listar todos os fornecedores cadastrados no sistema. + + Returns: + HttpResponse: Uma resposta HTTP renderizada com base na solicitação do usuário, listando todos os fornecedores. + """ + context = { + 'fornecedores': Fornecedor.objects.all() + } + return render(request, 'list_fornecedores.html', context) + +@require_POST +def delete_cliente(request, id): + """ + Esta função é responsável por deletar um cliente do banco de dados. + + Args: + id: O ID do cliente a ser deletado. + + Returns: + HttpResponseRedirect: Redireciona o usuário para a página de listagem de clientes após a exclusão. + """ + try: + cliente = Cliente.objects.get(id=id) + # deletar todas as notas fiscais relacionadas ao cliente + notas = cliente.notas_fiscais.all() + for nota in notas: + nota.delete() + cliente.delete() + except Cliente.DoesNotExist: + pass + return redirect(reverse('list_clientes')) + +def list_clientes(request): + """ + Esta função é responsável por listar todos os clientes cadastrados no sistema. + + Returns: + HttpResponse: Uma resposta HTTP renderizada com base na solicitação do usuário, listando todos os clientes. + """ + context = { + 'clientes': Cliente.objects.all() + } + + return render(request, 'list_clientes.html', context) + + diff --git a/venhapararecomb/requirements.txt b/venhapararecomb/requirements.txt new file mode 100644 index 0000000..c4805a2 Binary files /dev/null and b/venhapararecomb/requirements.txt differ diff --git a/venhapararecomb/templates/base.html b/venhapararecomb/templates/base.html new file mode 100644 index 0000000..6be0930 --- /dev/null +++ b/venhapararecomb/templates/base.html @@ -0,0 +1,45 @@ + + + + + + {% block title %}{% endblock %} + + + + + + + + + + +
+ {% block content %} + {% endblock %} +
+ + + + diff --git a/venhapararecomb/templates/detail_nf.html b/venhapararecomb/templates/detail_nf.html new file mode 100644 index 0000000..16c4e15 --- /dev/null +++ b/venhapararecomb/templates/detail_nf.html @@ -0,0 +1,64 @@ +{% extends 'base.html' %} + +{% block title %} +Informações da nota fiscal {{ nf.identificador }} +{% endblock %} + + +{% block content %} + +
+

Nota Fiscal

+
+
+
    + +
  • + Fornecedor:
    + Nome - {{ fornecedor.nome }} | + CNPJ - {{ fornecedor.cnpj }} +
  • + +
  • + Clientes: +
      + {% for cliente in clientes %} +
    • + Nome: {{ cliente.nome }} | + {{ cliente.tipo_documento }}: {{ cliente.documento }} + +
        +
      • Endereço: {{ cliente.endereco.logradouro }} {{ cliente.endereco.numero }}
      • +
      • CEP: {{ cliente.endereco.cep }}
      • +
      • Cidade: {{ cliente.endereco.cidade }}
      • +
      • Estado: {{ cliente.endereco.estado }}
      • +
      • País: {{ cliente.endereco.pais }}
      • +
      • Telefone: {{ cliente.endereco.telefone }}
      • +
      +
    • + {% endfor %} +
    +
  • + +
  • + Boletos: +
      + {% for boleto in boletos %} +
    • + Valor: {{ boleto.valor }} | + Vencimento: {{ boleto.data_vencimento }} +
    • + {% endfor %} +
    + +
  • +
+
+
+
+ +
+ Voltar +
+ +{% endblock %} \ No newline at end of file diff --git a/venhapararecomb/templates/index.html b/venhapararecomb/templates/index.html new file mode 100644 index 0000000..9151e04 --- /dev/null +++ b/venhapararecomb/templates/index.html @@ -0,0 +1,98 @@ + +{% extends 'base.html' %} + +{% block title %} +Gerenciamento de Notas Fiscais +{% endblock %} + +{% block content %} + +
+

Olá, seja bem vindo!

+
+

Este é um sistema de gerenciamento de notas fiscais. Envie um arquivo XML para começar:

+
+
+ {% csrf_token %} + + +
+
+
+
+ + +{% if error %} + +{% elif success %} + +{% endif %} + + +{% if xml_data and not error %} +
+ +
+

Nota Fiscal

+
+
+ {% csrf_token %} + +
+
+
+ + +
+
+
    + +
  • + Fornecedor:
    + Nome - {{ xml_data.fornecedor.nome }} | + CNPJ - {{ xml_data.fornecedor.cnpj }} +
  • + +
  • + Clientes: +
      + {% for cliente in xml_data.clientes %} +
    • + Nome: {{ cliente.nome }} | + {{ cliente.tipo_documento }}: {{ cliente.documento }} + +
        +
      • Endereço: {{ cliente.endereco.logradouro }} {{ cliente.endereco.numero }}
      • +
      • CEP: {{ cliente.endereco.cep }}
      • +
      • Cidade: {{ cliente.endereco.cidade }}
      • +
      • Estado: {{ cliente.endereco.estado }}
      • +
      • País: {{ cliente.endereco.pais }}
      • +
      • Telefone: {{ cliente.endereco.telefone }}
      • +
      +
    • + {% endfor %} +
    +
  • + +
  • + Boletos: +
      + {% for boleto in xml_data.boletos %} +
    • + Valor: {{ boleto.valor }} | + Vencimento: {{ boleto.data_vencimento }} +
    • + {% endfor %} +
    +
  • +
+
+
+
+{% endif %} + +{% endblock %} diff --git a/venhapararecomb/templates/list_clientes.html b/venhapararecomb/templates/list_clientes.html new file mode 100644 index 0000000..7766ae3 --- /dev/null +++ b/venhapararecomb/templates/list_clientes.html @@ -0,0 +1,35 @@ +{% extends 'base.html' %} + +{% block title %} +Lista de Clientes +{% endblock %} + +{% block content %} + +
+

Clientes

+ + + + {% if clientes %} +
    + {% for cliente in clientes %} +
  • + + {{ cliente }} + +
    + {% csrf_token %} + +
    +
  • + {% endfor %} +
+ {% endif %} +
+
+ Voltar +
+{% endblock %} diff --git a/venhapararecomb/templates/list_fornecedores.html b/venhapararecomb/templates/list_fornecedores.html new file mode 100644 index 0000000..4e0b5f7 --- /dev/null +++ b/venhapararecomb/templates/list_fornecedores.html @@ -0,0 +1,35 @@ +{% extends 'base.html' %} + +{% block title %} +Lista de Fornecedores +{% endblock %} + +{% block content %} + +
+

Fornecedores

+ + + + {% if fornecedores %} +
    + {% for fornecedor in fornecedores %} +
  • + + {{ fornecedor }} + +
    + {% csrf_token %} + +
    +
  • + {% endfor %} +
+ {% endif %} +
+
+ Voltar +
+{% endblock %} diff --git a/venhapararecomb/templates/list_nfs.html b/venhapararecomb/templates/list_nfs.html new file mode 100644 index 0000000..16651f7 --- /dev/null +++ b/venhapararecomb/templates/list_nfs.html @@ -0,0 +1,30 @@ +{% extends 'base.html' %} + +{% block title %} +Lista de Notas Fiscais +{% endblock %} + +{% block content %} + +
+

Notas Fiscais

+ {% if nfs %} +
    + {% for nf in nfs %} +
  • + + {{ nf }} + +
    + {% csrf_token %} + +
    +
  • + {% endfor %} +
+ {% endif %} +
+
+ Voltar +
+{% endblock %} diff --git a/venhapararecomb/venhapararecomb/__init__.py b/venhapararecomb/venhapararecomb/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venhapararecomb/venhapararecomb/__pycache__/__init__.cpython-310.pyc b/venhapararecomb/venhapararecomb/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..57b4c59 Binary files /dev/null and b/venhapararecomb/venhapararecomb/__pycache__/__init__.cpython-310.pyc differ diff --git a/venhapararecomb/venhapararecomb/__pycache__/__init__.cpython-311.pyc b/venhapararecomb/venhapararecomb/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..d55a950 Binary files /dev/null and b/venhapararecomb/venhapararecomb/__pycache__/__init__.cpython-311.pyc differ diff --git a/venhapararecomb/venhapararecomb/__pycache__/__init__.cpython-312.pyc b/venhapararecomb/venhapararecomb/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..66d5e14 Binary files /dev/null and b/venhapararecomb/venhapararecomb/__pycache__/__init__.cpython-312.pyc differ diff --git a/venhapararecomb/venhapararecomb/__pycache__/settings.cpython-310.pyc b/venhapararecomb/venhapararecomb/__pycache__/settings.cpython-310.pyc new file mode 100644 index 0000000..57107b6 Binary files /dev/null and b/venhapararecomb/venhapararecomb/__pycache__/settings.cpython-310.pyc differ diff --git a/venhapararecomb/venhapararecomb/__pycache__/settings.cpython-311.pyc b/venhapararecomb/venhapararecomb/__pycache__/settings.cpython-311.pyc new file mode 100644 index 0000000..b3a4ddf Binary files /dev/null and b/venhapararecomb/venhapararecomb/__pycache__/settings.cpython-311.pyc differ diff --git a/venhapararecomb/venhapararecomb/__pycache__/settings.cpython-312.pyc b/venhapararecomb/venhapararecomb/__pycache__/settings.cpython-312.pyc new file mode 100644 index 0000000..4e94464 Binary files /dev/null and b/venhapararecomb/venhapararecomb/__pycache__/settings.cpython-312.pyc differ diff --git a/venhapararecomb/venhapararecomb/__pycache__/urls.cpython-310.pyc b/venhapararecomb/venhapararecomb/__pycache__/urls.cpython-310.pyc new file mode 100644 index 0000000..d8adf70 Binary files /dev/null and b/venhapararecomb/venhapararecomb/__pycache__/urls.cpython-310.pyc differ diff --git a/venhapararecomb/venhapararecomb/__pycache__/urls.cpython-311.pyc b/venhapararecomb/venhapararecomb/__pycache__/urls.cpython-311.pyc new file mode 100644 index 0000000..3e0c0c7 Binary files /dev/null and b/venhapararecomb/venhapararecomb/__pycache__/urls.cpython-311.pyc differ diff --git a/venhapararecomb/venhapararecomb/__pycache__/urls.cpython-312.pyc b/venhapararecomb/venhapararecomb/__pycache__/urls.cpython-312.pyc new file mode 100644 index 0000000..5657d33 Binary files /dev/null and b/venhapararecomb/venhapararecomb/__pycache__/urls.cpython-312.pyc differ diff --git a/venhapararecomb/venhapararecomb/__pycache__/wsgi.cpython-310.pyc b/venhapararecomb/venhapararecomb/__pycache__/wsgi.cpython-310.pyc new file mode 100644 index 0000000..c98c509 Binary files /dev/null and b/venhapararecomb/venhapararecomb/__pycache__/wsgi.cpython-310.pyc differ diff --git a/venhapararecomb/venhapararecomb/__pycache__/wsgi.cpython-311.pyc b/venhapararecomb/venhapararecomb/__pycache__/wsgi.cpython-311.pyc new file mode 100644 index 0000000..fe0a8c7 Binary files /dev/null and b/venhapararecomb/venhapararecomb/__pycache__/wsgi.cpython-311.pyc differ diff --git a/venhapararecomb/venhapararecomb/__pycache__/wsgi.cpython-312.pyc b/venhapararecomb/venhapararecomb/__pycache__/wsgi.cpython-312.pyc new file mode 100644 index 0000000..7bcebfc Binary files /dev/null and b/venhapararecomb/venhapararecomb/__pycache__/wsgi.cpython-312.pyc differ diff --git a/venhapararecomb/venhapararecomb/asgi.py b/venhapararecomb/venhapararecomb/asgi.py new file mode 100644 index 0000000..1117c7b --- /dev/null +++ b/venhapararecomb/venhapararecomb/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for venhapararecomb project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'venhapararecomb.settings') + +application = get_asgi_application() diff --git a/venhapararecomb/venhapararecomb/settings.py b/venhapararecomb/venhapararecomb/settings.py new file mode 100644 index 0000000..0ec2a6d --- /dev/null +++ b/venhapararecomb/venhapararecomb/settings.py @@ -0,0 +1,136 @@ +""" +Django settings for venhapararecomb project. + +Generated by 'django-admin startproject' using Django 5.0.3. + +For more information on this file, see +https://docs.djangoproject.com/en/5.0/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.0/ref/settings/ +""" + +from pathlib import Path +import os + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure--okz#m@yr*2dh72v&hf420%djgsnt457yxdcqe$&1hjcoc#yhl' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +#ALLOWED_HOSTS = ['trumpet.db.elephantsql.com', '127.0.0.1'] +ALLOWED_HOSTS = [] + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'notafiscal', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'venhapararecomb.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [os.path.join(BASE_DIR, 'templates')], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'venhapararecomb.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/5.0/ref/settings/#databases + +# DATABASES = { +# 'default': { +# 'ENGINE': 'django.db.backends.postgresql', +# 'NAME': 'azixfhyp', +# 'USER': 'azixfhyp', +# 'PASSWORD': 'mx7x20d6m-3JM4MVisx8sicxwyg0NVTI', +# 'HOST': 'trumpet.db.elephantsql.com', +# 'PORT': '5432', +# } +# } + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + +# Password validation +# https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/5.0/topics/i18n/ + +LANGUAGE_CODE = 'pt-br' + +TIME_ZONE = 'America/Sao_Paulo' + +USE_I18N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/5.0/howto/static-files/ + +STATIC_URL = '/static/' + + +# Default primary key field type +# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' diff --git a/venhapararecomb/venhapararecomb/urls.py b/venhapararecomb/venhapararecomb/urls.py new file mode 100644 index 0000000..15e4a89 --- /dev/null +++ b/venhapararecomb/venhapararecomb/urls.py @@ -0,0 +1,23 @@ +""" +URL configuration for venhapararecomb project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/5.0/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('notafiscal.urls')), +] diff --git a/venhapararecomb/venhapararecomb/wsgi.py b/venhapararecomb/venhapararecomb/wsgi.py new file mode 100644 index 0000000..6c218a6 --- /dev/null +++ b/venhapararecomb/venhapararecomb/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for venhapararecomb project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'venhapararecomb.settings') + +application = get_wsgi_application()