Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Catalog · How the catalog works

Random project

Delphi-PedidoVenda

Omie - Pedido de Venda

View on GitHub

Anyone may press Interesting, signed in or not. It helps others find this project.

Member rating

No ratings yet.

Sign in to rate this project.

README

Delphi — Pedido de Venda

Teste técnico para a vaga de Analista Desenvolvedor Delphi.

Aplicação desktop desenvolvida em Delphi com persistência em Firebird 4.0 via FireDAC, organizada em camadas (Repository/Service), seguindo Clean Code e queries 100% parametrizadas.

Links para ferramentas utilizadas:

Detalhes extras

  • [x] Arquivos SQLs para criação da base dados
  • [x] Sem utilização de componentes de terceiros
  • [x] Utilização de componentes mais simples do Delphi (TStringGrid ao invés de TDBGrid, por exemplo)
  • [x] Lisagem de pedidos com total geral
  • [x] Botão de cancelar pedido
  • [x] Testes unitários com DUnitX
  • [x] Commits detalhados no Github com criação de PR para exemplificar processo de desenvolvimento
  • [x] Documentação completa

Índice


Pré-requisitos

Ferramenta Versão mínima
Delphi 10.4 Sydney ou superior
Firebird Server 4.0
fbclient.dll 4.0 (incluída em /bin)

Estrutura do projeto

pascal
Delphi-PedidoVenda/
???
????????? bin/
???   ????????? fbclient.dll               # Client library Firebird 4.0
???   ????????? config.ini.example         # Modelo de configura????o
???
????????? database/
???   ????????? create-database.sql        # Cria o arquivo .fdb
???   ????????? db.sql                     # DDL completo + carga de dados
???
????????? src/
    ????????? app/
    ???   ????????? UMain                  # Tela principal (View)
    ????????? connection/
    ???   ????????? UConfigINI             # Leitura do config.ini
    ???   ????????? UDM                    # DataModule com TFDConnection
    ????????? entities/
    ???   ????????? UEntityBase            # Classe base das entidades
    ???   ????????? UCliente
    ???   ????????? UProduto
    ???   ????????? UPedido                # Agrega TObjectList<TPedidoItem>
    ???   ????????? UPedidoItem            # Auto-calcula VlrTotal nos setters
    ????????? repositories/
    ???   ????????? URepositoryBase        # Base gen??rica com ObterPorCodigo/ValidarSeExiste
    ???   ????????? UClienteRepository
    ???   ????????? UProdutoRepository
    ???   ????????? UPedidoRepository      # Inserir/Atualizar/Carregar/Excluir/Listar com transa????o
    ????????? services/
    ???   ????????? UClienteService
    ???   ????????? UProdutoService
    ???   ????????? UPedidoService         # Valida????es e orquestra????o
    ????????? tests/
        ????????? UPedidoVendaTests      # Testes unit??rios com DUnitX

Criando o banco de dados

1. Criar o arquivo .fdb

Execute via isql, FlameRobin ou IBExpert, ajustando o caminho conforme seu ambiente:

sql
CREATE DATABASE 'C:\Delphi-PedidoVenda\database.fdb'
  USER 'SYSDBA' PASSWORD 'masterkey'
  PAGE_SIZE = 4096
  DEFAULT CHARACTER SET UTF8;

Ou use o arquivo pronto:

pascal
database/create-database.sql

2. Rodar o script DDL + carga

Com o banco criado, conecte nele e execute:

pascal
database/db.sql

O script cria:

  • Sequences SEQ_PEDIDO e SEQ_PEDIDO_ITEM
  • Tabelas CLIENTE, PRODUTO, PEDIDO, PEDIDO_ITEM
  • Triggers de auto-incremento para PEDIDO.NUMERO_PEDIDO e PEDIDO_ITEM.NUMERO_ITEM
  • Índices e chaves estrangeiras
  • 10 clientes e 10 produtos para teste

Atenção: execute os scripts na ordem indicada. O db.sql pressupõe que o banco já existe.


Configurando o INI

Copie o arquivo de exemplo e renomeie:

pascal
bin/config.ini.example  ???  bin/config.ini

Edite com os dados do seu ambiente:

ini
[DATABASE]
Server=localhost
Port=3050
Database=C:\Delphi-PedidoVenda\database.fdb
Username=SYSDBA
Password=masterkey
ClientLibrary=.\fbclient.dll
Chave Descrição
Server IP ou hostname do servidor Firebird
Port Porta TCP (padrão: 3050)
Database Caminho completo do arquivo .fdb
Username Usuário do banco
Password Senha do usuário
ClientLibrary Caminho para o fbclient.dll

O fbclient.dll do Firebird 4.0 está incluído em /bin. Se preferir usar o instalado localmente, aponte para C:\Program Files\Firebird\Firebird_4_0\fbclient.dll.

O config.ini deve estar na mesma pasta do executável.


Executando o projeto

Via Delphi IDE

  1. Abra o group project: src/grpPedidoVenda.groupproj
  2. Defina PedidoVenda como projeto ativo
  3. Certifique-se de que o config.ini está no diretório de saída (ex: src/Win32/Debug/)
  4. Compile e execute (F9)

Via executável compilado

  1. Reúna em uma mesma pasta: PedidoVenda.exe, fbclient.dll e config.ini
  2. Execute o PedidoVenda.exe

Roteiro de testes manuais

A tela é dividida em dois painéis: à esquerda a listagem de todos os pedidos com o total geral, à direita o formulário de pedido.


1. Listagem inicial

  1. Ao abrir a aplicação, o grid à esquerda exibe todos os pedidos gravados com número, cliente e valor total
  2. O rodapé do painel esquerdo exibe o Valor Total Geral (soma de todos os pedidos)
  3. Esperado: grid vazio se nenhum pedido foi gravado ainda

2. Cliente inválido

  1. No campo Cód. Cliente, informe um código inexistente (ex: 999) e pressione TAB
  2. Esperado: mensagem "Cliente não encontrado", campos de cliente permanecem vazios

3. Novo pedido completo

  1. Clique em Novo Pedido
  2. Informe 1 em Cód. Cliente e pressione TAB
  3. Esperado: Nome, Cidade e UF preenchidos automaticamente (somente leitura)
  4. Informe 1 em Cód. Produto e pressione TAB
  5. Esperado: Descrição e Valor Unitário preenchidos automaticamente
  6. Informe 2 em Quantidade e pressione TAB — o Valor Total do item é calculado automaticamente
  7. Clique em Inserir/Atualizar Item
  8. Esperado: item inserido no grid de itens, total do pedido atualizado no rodapé
  9. Preencha o campo Observação com algum texto
  10. Clique em Gravar Pedido
  11. Esperado: mensagem de sucesso com o número do pedido gerado; grid de pedidos atualizado à esquerda — anote o número gerado

4. Produtos repetidos

  1. Com um pedido aberto, informe o mesmo código de produto duas vezes com quantidades diferentes
  2. Esperado: dois itens distintos no grid (linhas separadas), totais somados corretamente

5. Editar item via teclado (ENTER)

  1. Com itens no grid de itens, posicione o cursor sobre um item e pressione ENTER
  2. Esperado: campos de produto/quantidade/valor preenchidos para edição
  3. Altere a quantidade e clique em Inserir/Atualizar Item
  4. Esperado: linha atualizada no grid, total do pedido recalculado

O duplo clique no item também aciona a edição.


6. Excluir item via teclado (DEL)

  1. Com itens no grid de itens, selecione um item e pressione DEL
  2. Confirme a exclusão
  3. Esperado: item removido do grid e total do pedido recalculado imediatamente

7. Validações ao gravar

Cenário Esperado
Gravar sem informar cliente Mensagem "Informe o cliente"
Gravar sem nenhum item Mensagem "Pedido sem itens"
Gravar com valor total zero Mensagem "Valor total inválido"

8. Carregar pedido pela listagem

  1. No grid de pedidos à esquerda, selecione um pedido e clique em Carregar Pedido
  2. Esperado: cabeçalho, observação e itens do pedido carregados no formulário à direita

9. Editar pedido existente

  1. Carregue um pedido existente conforme o teste 8
  2. Altere a observação ou adicione um novo item
  3. Clique em Gravar Pedido
  4. Esperado: pedido atualizado, grid de pedidos à esquerda reflete o novo valor total

10. Cancelar pedido

  1. Com um pedido carregado no formulário, clique em Cancelar Pedido e confirme
  2. Esperado: mensagem de sucesso, formulário limpo, pedido removido do grid à esquerda
  3. Tente carregar o mesmo número novamente pelo campo de número
  4. Esperado: mensagem "Pedido não encontrado"

11. Total geral atualizado

  1. Grave dois pedidos com valores distintos
  2. Esperado: campo Valor Total Geral no rodapé do painel esquerdo reflete a soma correta
  3. Cancele um dos pedidos
  4. Esperado: total geral recalculado automaticamente após o cancelamento

Executando os testes unitários

  1. No Delphi IDE, defina PedidoVendaTests como projeto ativo no group project
  2. Compile e execute (F9)
  3. O runner do DUnitX exibe os resultados no console

Cobertura:

Grupo Casos
Item Cálculo do total; recálculo ao alterar quantidade; recálculo ao alterar valor unitário; item com valor zero
Pedido Total com múltiplos itens; recálculo após exclusão de item; produtos repetidos permitidos; total zero sem itens; 10 itens acumulados; valores fracionados

Decisões técnicas relevantes

Listagem de pedidos com ListarPedidos O TPedidoRepository.ListarPedidos busca os números dos pedidos ordenados por data e número decrescentes, e para cada um chama Carregar — que já faz o JOIN com CLIENTE e carrega os itens com JOIN em PRODUTO. Essa abordagem reutiliza o mapeamento completo já existente sem duplicar código. Para volumes maiores, uma query única com agregação seria mais performática, mas para o escopo do teste a clareza tem prioridade.

TRepositoryBase<T> com generics Base genérica que centraliza ObterPorCodigo e ValidarSeExiste, evitando duplicação de código entre TClienteRepository e TProdutoRepository. O ValidarSeExiste reutiliza ObterPorCodigo intencionalmente — o custo é idêntico ao de um SELECT COUNT(1) para buscas por PK com retorno de 0 ou 1 linha, e elimina a necessidade de uma segunda query escrita manualmente.

TPedidoItem com self-calculation Os setters de Quantidade e VlrUnitario recalculam VlrTotal automaticamente via RecalcularTotal, garantindo que a entidade nunca fique em estado inconsistente independentemente de quem a manipule.

Delete/insert dos itens no Atualizar Na operação de atualização do pedido, todos os itens existentes são excluídos e reinseridos dentro da mesma transação. Simplifica o controle de estado em tela sem abrir mão de atomicidade — em caso de falha, rollback garante consistência.

TConfigINI separado do DataModule A leitura do config.ini foi isolada em TConfigINI retornando um TDatabaseConfig (record), separando a responsabilidade de configuração da de conexão. O TfDM consome o record e configura o TFDConnection dinamicamente — sem nenhuma credencial hardcoded no código ou no DFM.

Produtos repetidos Digitar um código de produto manualmente sempre insere uma nova linha no grid. A atualização de linha existente só ocorre quando o item foi carregado via ENTER (ou duplo clique) no grid. Comportamento documentado pois o requisito é ambíguo nesse ponto.


Tela de Pedido de Venda final

Tela de Pedido de Venda