💻 Desafio Técnico – Desenvolvedor Fullstack Júnior
O Instituto Senai de Inovação está em busca de desenvolvedores com perfil versátil, capazes de atuar tanto no backend quanto no frontend, para resolver desafios reais e relevantes.
Este desafio faz parte do nosso processo seletivo para a vaga de Desenvolvedor Fullstack Júnior.
O objetivo é avaliar sua habilidade técnica, clareza de raciocínio, organização de código e capacidade de entregar uma aplicação funcional com base em requisitos enxutos, algo que acontece com frequência em projetos de inovação.
Mais do que domínio técnico, valorizamos a capacidade de pensar de forma estruturada, escrever código limpo, seguir boas práticas e tomar decisões conscientes durante o desenvolvimento.
✅ O que esperamos ver no seu projeto
- Organização do projeto com estrutura clara e lógica
- Capacidade de construir uma aplicação funcional, mesmo com requisitos limitados
- Uso consistente de boas práticas no frontend e backend
- Uso de Git com histórico coerente de commits
🌟 Diferenciais técnicos que contam pontos
- Código limpo e legível, seguindo os princípios do Clean Code (nomes significativos, pequenas funções, baixo acoplamento, alta coesão)
- Arquitetura consistente, com separação clara entre camadas da aplicação (ex: MVC, DDD)
- Tratamento de erros e respostas HTTP padronizadas (mensagens claras e status codes corretos)
- Testes automatizados (unitários ou de integração ou E2E) com cobertura mínima dos fluxos principais – não são obrigatórios, mas contam como diferencial
- Documentação técnica clara no
README.md explicando o setup, execução e decisões técnicas
- Interface com responsividade básica, priorizando usabilidade
- Uso de Docker (
Dockerfile e/ou docker-compose) para facilitar o deploy e garantir portabilidade do ambiente, não é obrigatório, mas será considerado um diferencial
- Uso consciente de bibliotecas externas com explicações, quando necessário, das escolhas de dependência
O que será avaliado
| Critério | Peso |
|---|
| Estrutura e organização do projeto | ★★★★★ |
| Aplicação correta das regras de negócio | ★★★★☆ |
| Clareza e limpeza do código | ★★★★☆ |
| Tratamento de erros | ★★★☆☆ |
| README técnico completo | ★★★★☆ |
| Git com granularidade e histórico limpo | ★★★☆☆ |
| Aderência a padrões REST e boas práticas HTTP | ★★★☆☆ |
| Experiência do Usuário (Frontend) | ★★★★☆ |
🎯 Objetivo
Este desafio técnico tem como propósito simular um fluxo real de vendas dentro de um ambiente corporativo, focando no cadastro, listagem, edição e gerenciamento de produtos, bem como na aplicação de descontos com regras de negócio rigorosas e realistas. A ideia é proporcionar uma experiência próxima da realidade de sistemas de e-commerce ou ERPs modernos, exigindo atenção aos detalhes, domínio de boas práticas de desenvolvimento e compreensão sólida de integrações e processos de validação.
Você será responsável por desenvolver uma aplicação web fullstack, contemplando as seguintes funcionalidades principais:
- Cadastro de produtos com controle de preço, estoque e unicidade de nome
- Listagem de produtos com filtros avançados e paginação
- Aplicação e remoção de descontos percentuais ou cupons promocionais, seguindo regras específicas de negócio
A proposta visa não apenas testar a sua capacidade técnica e organização de projeto, mas também avaliar sua sensibilidade às regras de negócio, tratamento de exceções e comportamento frente a requisitos ambíguos ou propensos a falhas. Essa simulação aproxima-se dos desafios enfrentados por times de desenvolvimento que lidam com fluxos reais de negócio em empresas que prezam pela confiabilidade e manutenção da lógica da aplicação ao longo do tempo.
🧭 Stack Mínima Sugerida
Backend
- NestJS: framework moderno e escalável que utiliza TypeScript por padrão e favorece uma arquitetura modular.
- Express.js: framework web minimalista e flexível, bastante difundido para criação de APIs REST com Node.js.
Observação: Também é permitida a utilização de outras linguagens, como Java com Spring Boot, desde que a arquitetura web REST seja mantida e os requisitos sejam atendidos.
Frontend
-
Biblioteca Base: ReactJS
Preferencialmente, utilize ReactJS, com ou sem frameworks adicionais. Esperamos a construção de componentes reutilizáveis, aplicação de um controle de estado simples com useState, useEffect, e, se necessário, Context API para compartilhamento de estado global.
A integração com a API backend deve ser clara, funcional e bem organizada (ex.: fetch/axios com tratamento de loading e erro).
-
Liberdade de Framework:
Você tem liberdade para utilizar frameworks baseados em React, como:
- Next.js: oferece roteamento baseado em arquivos, SSR, SSG e ótimo suporte a SEO.
- Remix: traz uma abordagem centrada em rotas, com carregamento de dados no servidor, ideal para experiências rápidas e declarativas.
Ambos são bem-vindos e aceitos neste desafio, desde que o projeto mantenha clareza arquitetural, organização e cobertura dos requisitos funcionais.
-
Liberdade de Biblioteca de Estado:
Também é permitido utilizar a biblioteca de gerenciamento de estado de sua preferência, como:
O mais importante é que a implementação seja bem estruturada, compreensível e adequada à complexidade da aplicação.
-
Outras Bibliotecas/Frameworks:
Frameworks modernos como Vue.js ou Angular também são aceitos, desde que respeitem a arquitetura proposta e cumpram todos os requisitos funcionais com clareza.
Banco de Dados
- Tipo: Relacional em memória ou Relacional
- Exemplo: SQLite utilizando
':memory:' como caminho para rodar totalmente em memória.
Alternativas Aceitas:
- H2 ou HSQLDB (para implementações em Java)
better-sqlite3 no Node.js (com suporte a ':memory:')
- Qualquer outro banco relacional leve, desde que mantenha a persistência temporária ou fixa (Postgres, MySQL) e seja fácil de configurar para fins de teste e demonstração
Backend
Módulo: Produtos e Descontos
Você deverá criar:
-
Backend com API RESTful para produtos e cupons, incluindo:
- Endpoints para criação, edição, inativação (soft delete) e listagem paginada de produtos
- Endpoints para aplicar e remover descontos percentuais e cupons promocionais
- Validações de unicidade, integridade referencial e regras específicas de negócio
-
Frontend funcional, contendo:
- Listagem de produtos com paginação, busca e filtros (nome, faixa de preço, com ou sem desconto)
- Formulário de cadastro e edição de produtos (com suporte a atualização via patch)
- Interface para aplicar e remover cupons/descontos, com feedback visual claro
- Destaques visuais para produtos com estoque zerado ou com desconto ativo
-
Validações robustas, cobrindo:
- Formatos de preço, normalização de nome e restrições de valor
- Prevenção à aplicação múltipla de descontos no mesmo produto
- Rejeição de cupons inválidos, expirados ou que resultem em valor final abaixo de R$ 0,01
- Retorno de códigos HTTP apropriados para erros esperados (
422, 409, 412, entre outros)
🚨 Funcionalidades Obrigatórias
Listagem de Produtos
Deve ser possível:
- Visualizar uma tabela com as colunas:
- Nome
- Descrição
- Estoque atual
- Preço original
- Preço com desconto (se aplicável)
- Exibir badges ou indicadores visuais para:
- Produtos com desconto ativo
- Produtos com estoque zerado
- Filtrar produtos por:
- Nome (busca textual)
- Faixa de preço (mínimo e máximo)
- Com ou sem desconto ativo (booleano)
- Paginar os resultados com paginação padrão de 10 por página
🧾 Query Params Aceitos
Os seguintes parâmetros podem ser utilizados para refinar a listagem de produtos:
page (integer ≥ 1): número da página atual.
limit (integer, entre 1 e 50): quantidade de itens por página.
search (string): busca textual no nome ou descrição do produto.
minPrice / maxPrice (decimal): filtro por faixa de preço mínima e máxima.
hasDiscount (boolean): true ou false para filtrar produtos com ou sem desconto.
sortBy (string): campo para ordenação. Valores possíveis: name, price, created_at, stock.
sortOrder (string): direção da ordenação. Pode ser asc ou desc.
includeDeleted (boolean): se true, inclui produtos inativos (soft deleted). Recomendado apenas para administradores.
onlyOutOfStock (boolean): se true, retorna apenas produtos com estoque igual a zero.
withCouponApplied (boolean): se true, retorna apenas produtos que possuem cupom promocional aplicado.
Requisitos Adicionais
- Garantir que a ordenação por nome, preço e estoque seja suportada em ambas as direções (
asc e desc).
- Retornar resposta
200 OK com uma lista vazia caso nenhuma correspondência seja encontrada.
- Adotar comportamento consistente de paginação, mesmo quando não houver resultados.
Exemplo: se page=10 não possui itens, ainda assim deve retornar um array vazio com os metadados corretos (page, limit, totalItems, totalPages).
Cadastro de Produto
O cadastro de produtos deve ser feito com especial atenção às validações de regras de negócio, estrutura dos campos e consistência dos dados. A aplicação deverá ser robusta o suficiente para impedir erros simples e respeitar todas as regras de domínio.
Campos obrigatórios
-
name (string, obrigatório)
- Deve ser único após normalização (remover espaços duplicados)
- Mínimo: 3 caracteres
- Máximo: 100 caracteres
- Regex recomendado:
^[a-zA-Z0-9\s\-_,.]+$
-
description (string, opcional)
-
stock (integer, obrigatório)
- Valor mínimo: 0
- Valor máximo: 999999
-
price (decimal, obrigatório)
- Mínimo: 0.01
- Máximo: 1.000.000,00
- Deve aceitar formatos brasileiros (ex: "1.234,56") e internacionais (ex: 1234.56), mas ser persistido corretamente como decimal
-
created_at (ISODate, obrigatório)
- Deve ser preenchido com a data/hora atual no momento do cadastro
- Deve ser imutável após criação
- Deve estar no passado ou presente (nunca no futuro)
Regras obrigatórias
- O campo
name deve ser único no banco mesmo após normalização.
- Produtos com
stock == 0 devem ser destacados na listagem com um badge visual "Esgotado".
- O valor original nunca deve ser alterado por descontos. Os descontos devem ser armazenados separadamente.
- O valor com desconto (se houver) deve ser sempre recalculado dinamicamente e não salvo de forma persistente no banco.
- É proibido criar produtos com o preço com desconto menor que R$ 0,01.
- O campo
created_at deve refletir corretamente a data/hora da criação e não pode ser editado posteriormente.
- Adicionar o campo
updated_at para rastrear modificações (opcional, mas recomendado).
Aplicação de Descontos
Tipos permitidos