Created
March 23, 2026 13:59
-
-
Save maykonmeier/51ef8291d1de154b8d592252755ce590 to your computer and use it in GitHub Desktop.
Cenários de Teste — Portal do Cedente (Opera Capital) — 272 cenários
We can make this file beautiful and searchable if this error is corrected: Illegal quoting in line 2.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Nº;Bloco;Módulo;Sub-módulo;Cenário;Passos;Resultado Esperado;Tipo;Prioridade;Status | |
| 1;Bloco 1 — Autenticação;Login;Usuário Existente;Login com credenciais válidas (usuário existente);Acessar /login → Preencher user_name e password válidos → Clicar "Entrar";Token gerado (access_token), redirecionado para Dashboard (user) ou /operacoes (admin). Response com token_type: "Bearer" e expires_at;Funcional;Alta;✅ Validado | |
| 2;Bloco 1 — Autenticação;Login;Usuário Existente;Login com senha incorreta;Preencher user_name válido + senha errada → Clicar "Entrar";Erro 422: "As credenciais informadas estão incorretas." Banner vermelho no frontend;Funcional;Alta;✅ Validado | |
| 3;Bloco 1 — Autenticação;Login;Usuário Existente;Login com usuário inexistente no Opera Capital;Preencher user_name que não existe na API externa → Clicar "Entrar";Erro 403: API Opera Capital retorna exceção, tratada como UserNotActiveException;Funcional;Alta;✅ Validado | |
| 4;Bloco 1 — Autenticação;Login;Usuário Existente;Login com usuário inativo no Opera Capital;Preencher credenciais de usuário com situacaoUsuario = "I" (inativo);Erro 403: "Verifique sua situação com a Opera Capital... e-mail de suporte";Funcional;Alta;✅ Validado | |
| 5;Bloco 1 — Autenticação;Login;Validação;Login com campos vazios;Deixar user_name e/ou password em branco → Clicar "Entrar";Frontend: "Usuário é obrigatório" / "Senha é obrigatória". Backend: 422 com user_name.required / password.required;Validação;Alta;✅ Validado | |
| 6;Bloco 1 — Autenticação;Login;Validação;Login com user_name < 3 caracteres;Preencher user_name com 2 chars → Clicar "Entrar";Frontend (Zod): "Usuário deve ter no mínimo 3 caracteres". Backend aceita (sem min no LoginRequest);Validação;Média;✅ Validado | |
| 7;Bloco 1 — Autenticação;Login;Validação;Login com senha < 6 caracteres;Preencher senha com 5 chars → Clicar "Entrar";Frontend (Zod): "Senha deve ter no mínimo 6 caracteres". Backend aceita (sem min no LoginRequest);Validação;Média;✅ Validado | |
| 8;Bloco 1 — Autenticação;Pré-Registro;Novo Usuário;Login com usuário Opera sem cadastro local;Preencher credenciais de usuário ativo no Opera Capital mas sem cadastro local;Response 200: action: "pre_registration", pre_registration_id, message: "Código de autorização enviado para o e-mail cadastrado." E-mail AuthorizationCodeMail enviado;Funcional;Alta;✅ Validado | |
| 9;Bloco 1 — Autenticação;Verificação de Conta;Token;Verificação de conta com token válido;POST /verify-token com token válido;Response 200: "Token verificado com sucesso." + dados do pré-registro. Status muda para VERIFIED. Frontend redireciona para /redefinicao-senha;Funcional;Alta;✅ Validado | |
| 10;Bloco 1 — Autenticação;Verificação de Conta;Token;Verificação com token expirado;POST /verify-token após 15min (config authorization_code.expiry_minutes);Erro 422: "O código de autorização expirou. Solicite um novo código.";Funcional;Alta;✅ Validado | |
| 11;Bloco 1 — Autenticação;Verificação de Conta;Token;Verificação com token inexistente;POST /verify-token com token=invalido;Erro 404: "Código de autorização não encontrado.";Funcional;Média;✅ Validado | |
| 12;Bloco 1 — Autenticação;Verificação de Conta;Token;Verificação sem token na URL;Acessar /verificar-conta sem query param token;Erro 422: validação token.required. Frontend: "Token não encontrado...", redirect /login;Funcional;Média;✅ Validado | |
| 13;Bloco 1 — Autenticação;Registro;Senha;Registro com senha válida (todas as regras);POST /register com token válido + senha ≥8 chars completa + confirmação;Response 201: access_token, user. Usuário criado, role atribuída, pré-registro deletado;Funcional;Alta;✅ Validado | |
| 14;Bloco 1 — Autenticação;Registro;Validação;Registro com senhas não coincidentes;password ≠ password_confirmation;Erro 422: "A confirmação de senha não confere." Frontend: botão desabilitado;Validação;Alta;✅ Validado | |
| 15;Bloco 1 — Autenticação;Registro;Validação;Registro com senha sem caractere especial;Senha sem !@#$%...;Frontend: indicador vermelho, botão desabilitado. Backend aceita (RegisterRequest exige apenas min:8 e confirmed);Validação;Média;✅ Validado | |
| 16;Bloco 1 — Autenticação;Registro;Validação;Registro com senha sem maiúscula;Senha toda minúscula;Frontend: indicador vermelho, botão desabilitado. Backend aceita;Validação;Média;✅ Validado | |
| 17;Bloco 1 — Autenticação;Registro;Navegação;Acesso direto a /redefinicao-senha sem token;Navegar manualmente para a rota sem state;Frontend: warning notification, redirect /login pelo router guard;Navegação;Média;✅ Validado | |
| 18;Bloco 1 — Autenticação;Sessão;Proteção de Rotas;Acessar rota protegida sem token;Navegar para /dashboard sem autenticação;API: 401 Unauthenticated. Frontend: router guard redireciona para /login;Segurança;Alta;✅ Validado | |
| 19;Bloco 1 — Autenticação;Sessão;Token Expirado;Token expirado durante navegação;Request com token expirado (sanctum.expiration = 120min);Response 401 → Axios interceptor remove cookie → Reload → Redirect /login;Segurança;Alta;✅ Validado | |
| 20;Bloco 1 — Autenticação;Sessão;Logout;Logout;Clicar em logout → POST /logout;Response 200: "Logout realizado com sucesso." Token deletado, store resetado, cookie removido, redirect /login;Funcional;Alta;✅ Validado | |
| 21;Bloco 1 — Autenticação;Sessão;Navegação;Usuário autenticado acessa /login;Navegar para /login estando logado;Router guard detecta token → Valida via GET /me → Redirect para home ou /operacoes se admin;Navegação;Média;✅ Validado | |
| 22;Bloco 1 — Autenticação;Sessão;Rate Limiting;Rate limiting no login;Enviar 6+ requests em 1 minuto para POST /login;Erro 429 (Too Many Requests). Throttle: 5,1;Segurança;Alta;✅ Validado | |
| 23;Bloco 2 — Dashboard;Carregamento;Estados;Carregamento inicial do Dashboard;Acessar / (usuário comum);GET /dashboard/ com CNPJ do usuário. Spinner → DashboardResource renderizada;Funcional;Alta;✅ Validado | |
| 24;Bloco 2 — Dashboard;Carregamento;Erro;Erro ao carregar Dashboard;API Opera Capital retorna erro/timeout;Ícone de erro + "Erro ao carregar dashboard" + botão "Tentar novamente";Funcional;Alta;✅ Validado | |
| 25;Bloco 2 — Dashboard;Carregamento;Retry;Retry após erro;Clicar "Tentar novamente";TanStack Query refetch() disparado, spinner, dados recarregam;Funcional;Média;✅ Validado | |
| 26;Bloco 2 — Dashboard;Carregamento;Vazio;Dashboard sem dados (204);CNPJ sem dados ou inválido pelo CnpjHelper;Response 204 No Content. Frontend: tratamento de vazio;Funcional;Média;✅ Validado | |
| 27;Bloco 2 — Dashboard;Métricas Perfil;Exibição;Exibição das 5 métricas de perfil;Dashboard carregado com dados;CNPJ, Cliente Desde, Última Operação, Primeira Operação, Vencimento do Contrato — formatados dd/MM/yyyy;Funcional;Alta;✅ Validado | |
| 28;Bloco 2 — Dashboard;Métricas Perfil;Nulos;Métricas com datas nulas;Alguma data retorna null da API;Campo exibe string vazia (não "Invalid Date");Funcional;Média;✅ Validado | |
| 29;Bloco 2 — Dashboard;Cards;Operações e Limites;Cards de Operações, Limite Aprovado, Limite Disponível;Dashboard com dados;3 cards com valores em R$ formatados, sparklines de 14 pontos;Funcional;Alta;✅ Validado | |
| 30;Bloco 2 — Dashboard;Cards;Tranche;Cards secundários (Tranche);Dashboard com dados;Limite Tranche, Tranche Disponível + card Última Confirmação;Funcional;Alta;✅ Validado | |
| 31;Bloco 2 — Dashboard;Taxas;Exibição;Card de Taxas;Dashboard com dados;4 taxas visíveis (Deságio FIDC/SEC/Especial, Cobrança Trustee em %). 4 ocultas;Funcional;Média;✅ Validado | |
| 32;Bloco 2 — Dashboard;Títulos Negociados;Tabela;Tabela de Títulos Negociados;Dashboard com dados;Total geral + tabela com 4 tipos: Duplicata, Confissão de dívida, Cheque, Cartão de Crédito;Funcional;Alta;✅ Validado | |
| 33;Bloco 2 — Dashboard;Títulos Abertos;Colapsada;Tabela de Títulos Abertos (colapsada);Dashboard com dados;Total + 2 linhas: "A Vencer" e "Vencidos" com chevron para expandir;Funcional;Alta;✅ Validado | |
| 34;Bloco 2 — Dashboard;Títulos Abertos;Expandida;Expandir detalhamento de Títulos Abertos;Clicar no chevron;Sub-linhas: Até 5/15/30 dias, Acima de 30 dias — quantidade, valor, %;Funcional;Média;✅ Validado | |
| 35;Bloco 2 — Dashboard;Títulos Liquidados;Mini-cards;Mini-cards de Títulos Liquidados;Dashboard com dados;7 mini-cards coloridos com quantidade, valor e %;Funcional;Média;✅ Validado | |
| 36;Bloco 2 — Dashboard;Controladoria;Tabela;Tabela de Controladoria;Dashboard com dados;7 linhas com Descrição, Quantia, %, Valor, Tranche;Funcional;Média;✅ Validado | |
| 37;Bloco 2 — Dashboard;Concentração;Sacados;Tabela de Concentração de Sacados;Dashboard com dados;Top sacados: Sacado, CNPJ/CPF, Valor, % (barra de progresso);Funcional;Média;✅ Validado | |
| 38;Bloco 2 — Dashboard;Concentração;Grupos Econômicos;Tabela de Grupos Econômicos Sacados;Dashboard com dados;Tabela dinâmica: Grupo, Valor;Funcional;Média;✅ Validado | |
| 39;Bloco 2 — Dashboard;Grupo Econômico;Ativar;Ativar Grupo Econômico;Clicar botão "Grupo Econômico";Banner, query com grupo_economico=1, dados agregados;Funcional;Média;✅ Validado | |
| 40;Bloco 2 — Dashboard;Grupo Econômico;Desativar;Desativar Grupo Econômico;Clicar novamente no botão;Banner some, query sem grupo_economico, dados individuais;Funcional;Média;✅ Validado | |
| 41;Bloco 3 — Kanban;Carregamento;Inicial;Carga inicial da página de Operações;Acessar /operacoes;5 colunas carregam em paralelo (5 requests). Range: 30 dias. Cores: Digitando #64DCFF, Em análise #FFDC50, Assinatura #7200CA, Pago #00FF96, Reprovadas #FF7C62;Funcional;Alta;✅ Validado | |
| 42;Bloco 3 — Kanban;Carregamento;Loading;Loading state durante carga;Acessar /operacoes com API lenta;Spinner/loading em cada coluna;Funcional;Média;✅ Validado | |
| 43;Bloco 3 — Kanban;Carregamento;Vazio;Kanban sem operações (período vazio);Filtrar período sem dados;5 colunas com estado vazio;Funcional;Média;✅ Validado | |
| 44;Bloco 3 — Kanban;Carregamento;Badges;Badges de contagem nas colunas;Página carregada;Cada coluna exibe badge "N OP" com total (meta.total);Funcional;Média;✅ Validado | |
| 45;Bloco 3 — Kanban;Cards;Digitando;Card na coluna Digitando;Visualizar card em "Digitando";Data de criação, Qnt Títulos, Valor Total. Sem opera_id (null em EM_DIGITACAO);Funcional;Alta;✅ Validado | |
| 46;Bloco 3 — Kanban;Cards;Outras Colunas;Card em colunas não-Digitando;Visualizar card nas demais colunas;"Operação [num_aditivo ou opera_id]", data importação, Qnt Títulos, Valor Total;Funcional;Alta;✅ Validado | |
| 47;Bloco 3 — Kanban;Cards;Processando;Card com substatus "Processando";Card em "Em análise" com substatus;Badge amarelo "Processando" + ícone info. Valores podem estar zerados;Funcional;Média;✅ Validado | |
| 48;Bloco 3 — Kanban;Cards;Formatação;Formatação de valores monetários;Qualquer card;Valor em R$ com separador de milhares pt-BR (R$ 1.500,00);Funcional;Média;✅ Validado | |
| 49;Bloco 3 — Kanban;Navegação;Digitando;Clicar card em "Digitando";Clicar em card da coluna Digitando;Navega para /operacoes/{id} (página de edição);Navegação;Alta;✅ Validado | |
| 50;Bloco 3 — Kanban;Navegação;Em Análise;Clicar card em "Em análise" (não processando);Clicar em card sem substatus Processando;Navega para /operacoes/{id}/detalhamento;Navegação;Alta;✅ Validado | |
| 51;Bloco 3 — Kanban;Navegação;Processando;Clicar card "Processando";Clicar em card com badge Processando;Dialog de aviso. Não navega;Navegação;Média;✅ Validado | |
| 52;Bloco 3 — Kanban;Navegação;Outras Colunas;Clicar card em Assinatura/Pago/Reprovadas;Clicar em card nessas colunas;Navega para /operacoes/{id}/detalhamento;Navegação;Alta;✅ Validado | |
| 53;Bloco 3 — Kanban;Paginação;Ver Mais Visível;Coluna com mais de 10 operações;Coluna com total > 10;Botão "VER MAIS" visível (ITEMS_PER_PAGE = 10);Funcional;Média;✅ Validado | |
| 54;Bloco 3 — Kanban;Paginação;Carregar Mais;Clicar "Ver Mais";Clicar no botão;Loading → Próxima página adicionada (append) à coluna;Funcional;Média;✅ Validado | |
| 55;Bloco 3 — Kanban;Paginação;Sem Mais Páginas;Coluna sem mais páginas;Todas carregadas (page >= total_pages);Botão desabilitado com tooltip informativo;Funcional;Baixa;✅ Validado | |
| 56;Bloco 3 — Kanban;Paginação;Independente;Ver Mais em múltiplas colunas;Clicar "Ver Mais" em colunas diferentes;Cada coluna pagina independentemente;Funcional;Média;✅ Validado | |
| 57;Bloco 3 — Kanban;Filtros;Status;Filtrar por status específico;Selecionar "Digitando" → Clicar filtrar;Apenas dados do status selecionado recarregam;Funcional;Alta;✅ Validado | |
| 58;Bloco 3 — Kanban;Filtros;Todos;Filtrar por "Todos";Selecionar "Todos" → Filtrar;Todas as 5 colunas recarregam;Funcional;Média;✅ Validado | |
| 59;Bloco 3 — Kanban;Filtros;Datas Válidas;Filtrar por intervalo de datas válido;start_date e end_date ≤ 60 dias → Filtrar;Operações recarregadas para o período;Funcional;Alta;✅ Validado | |
| 60;Bloco 3 — Kanban;Filtros;> 60 dias Frontend;Filtrar com intervalo > 60 dias (frontend);Período > 60 dias → Filtrar;Notificação de erro frontend: período excede 60 dias;Validação;Média;✅ Validado | |
| 61;Bloco 3 — Kanban;Filtros;> 90 dias Backend;Filtrar com intervalo > 90 dias (backend);Request direto com período > 90 dias;Erro 422: "O período de consulta não pode ser maior que 90 dias...";Validação;Alta;✅ Validado | |
| 62;Bloco 3 — Kanban;Filtros;Mesmo Dia;Filtro com mesma data início e fim;Mesmo dia para ambos → Filtrar;Operações daquele dia. Validação before_or_equal/after_or_equal passa;Funcional;Baixa;✅ Validado | |
| 63;Bloco 3 — Kanban;Filtros;Tooltip;Tooltip informativo dos filtros;Hover no ícone de info;Tooltip: "Os registros referem-se ao período selecionado (padrão: 30 dias)...";UI;Baixa;✅ Validado | |
| 64;Bloco 3 — Kanban;Admin;Seletor Visível;Seletor de Cedente visível para admin;Acessar /operacoes como admin;AdminCedenteSelector exibido. CNPJ obrigatório;Funcional;Alta;✅ Validado | |
| 65;Bloco 3 — Kanban;Admin;Selecionar Cedente;Selecionar cedente;Escolher CNPJ no seletor;Filtro cnpj aplicado, operações recarregadas;Funcional;Alta;✅ Validado | |
| 66;Bloco 3 — Kanban;Admin;Limpar Cedente;Limpar cedente;Clicar botão limpar;Filtro cnpj removido, página recarrega;Funcional;Média;✅ Validado | |
| 67;Bloco 3 — Kanban;Admin;Oculto p/ User;Seletor oculto para usuário comum;Acessar /operacoes como user;AdminCedenteSelector não renderizado. CNPJ via user.resolveCnpj();Funcional;Média;✅ Validado | |
| 68;Bloco 3 — Kanban;Criação;Modal;Abrir modal de nova operação;Clicar "Adicionar Operação";Modal AdicionarOperacaoModal com seleção de tipo (Duplicata, Cheque, XML);Funcional;Alta;✅ Validado | |
| 69;Bloco 3 — Kanban;Criação;Sucesso;Criar operação com sucesso;Preencher dados → Confirmar;POST /operations/ → 201. Redirect para /operacoes/{id};Funcional;Alta;✅ Validado | |
| 70;Bloco 3 — Kanban;Responsividade;Desktop;Desktop (1920px+);Tela grande;5 colunas visíveis, base 220px, max 260px;UI;Baixa;✅ Validado | |
| 71;Bloco 3 — Kanban;Responsividade;Laptop;Laptop (1440px);Notebook;5 colunas com espaçamento ajustado;UI;Baixa;✅ Validado | |
| 72;Bloco 3 — Kanban;Responsividade;Mobile;Tablet/Mobile (<1024px);Tela menor;Scroll horizontal, min-width 180px;UI;Baixa;✅ Validado | |
| 73;Bloco 4 — Detalhe Operação;Edição;Carregamento;Carregar operação em digitação;Clicar card "Digitando" → /operacoes/{id};GET /operations/{id} → OperationResource com invoices, checks, files, endorser;Funcional;Alta;✅ Validado | |
| 74;Bloco 4 — Detalhe Operação;Edição;Loading;Loading state da operação;Acessar /operacoes/{id};Spinner durante carregamento;Funcional;Média;✅ Validado | |
| 75;Bloco 4 — Detalhe Operação;Edição;404;Operação não encontrada;/operacoes/{id} com ID inexistente;API: 404 "Operação não encontrada";Funcional;Alta;✅ Validado | |
| 76;Bloco 4 — Detalhe Operação;Títulos;Adicionar;Adicionar título manualmente;Modal → Preencher número, NF, valor, vencimento, sacado, tipo, chave NF-e;POST /invoices/ → 201. Título na tabela;Funcional;Alta;✅ Validado | |
| 77;Bloco 4 — Detalhe Operação;Títulos;Validação Obrigatórios;Validação de campos obrigatórios do título;Submeter vazio;Erros 422: operation_id, payer_id, number, number_nf, value, due_date, type;Validação;Alta;✅ Validado | |
| 78;Bloco 4 — Detalhe Operação;Títulos;NF-e Max Chars;Validação de chave NF-e (máx 44 chars);nfe_key > 44 chars;Erro 422: "O campo chave da NF-e não pode ter mais de 44 caracteres.";Validação;Média;✅ Validado | |
| 79;Bloco 4 — Detalhe Operação;Títulos;NF-e Duplicada;Chave NF-e duplicada;nfe_key já existente (unique whereNull deleted_at);Erro 422: "Esta chave de NF-e já está cadastrada no sistema.";Validação;Alta;✅ Validado | |
| 80;Bloco 4 — Detalhe Operação;Títulos;Editar;Editar título existente;Modal EditarNotaModal → Alterar valor/data → Salvar;PUT /invoices/{id} → 200. Dados atualizados;Funcional;Alta;✅ Validado | |
| 81;Bloco 4 — Detalhe Operação;Títulos;Atualização Parcial;Atualização parcial de título;PUT com apenas 1 campo;UpdateInvoiceRequest usa sometimes — apenas campos enviados validados;Funcional;Média;✅ Validado | |
| 82;Bloco 4 — Detalhe Operação;Títulos;Excluir;Excluir título;Excluir → Confirmar;DELETE /invoices/{id} → 200 "Nota fiscal excluída com sucesso". Soft delete;Funcional;Alta;✅ Validado | |
| 83;Bloco 4 — Detalhe Operação;Títulos;Valor Negativo;Valor do título < 0;Valor negativo;Erro 422: "O campo valor deve ser maior ou igual a zero." (min:0);Validação;Média;✅ Validado | |
| 84;Bloco 4 — Detalhe Operação;Cheques;Adicionar;Adicionar cheque;Modal AdicionarChequeModal → CMC7, agência, conta, valor;POST /checks/ → 201;Funcional;Alta;✅ Validado | |
| 85;Bloco 4 — Detalhe Operação;Cheques;CMC7 Inválido;Validação de CMC7 inválido;CMC7 fora do formato;Erro 422: Cmc7Rule — CMC7 inválido;Validação;Alta;✅ Validado | |
| 86;Bloco 4 — Detalhe Operação;Cheques;Obrigatórios;Campos obrigatórios do cheque;Submeter vazio;Erros 422: operation_id, payer_id, cmc7, agency, account, value;Validação;Alta;✅ Validado | |
| 87;Bloco 4 — Detalhe Operação;Cheques;Editar;Editar cheque existente;Alterar valor/conta → Salvar;PUT /checks/{id} → 200;Funcional;Alta;✅ Validado | |
| 88;Bloco 4 — Detalhe Operação;Cheques;Excluir;Excluir cheque;Excluir → Confirmar;DELETE /checks/{id} → 200 "Cheque excluído com sucesso". Soft delete;Funcional;Alta;✅ Validado | |
| 89;Bloco 4 — Detalhe Operação;Sacados;Criar;Criar sacado manualmente;Preencher CNPJ/CPF, razão social, CEP, estado, cidade, endereço, e-mail;POST /payers/ → 201;Funcional;Alta;✅ Validado | |
| 90;Bloco 4 — Detalhe Operação;Sacados;CNPJ/CPF Inválido;Validação de CNPJ/CPF inválido;Dígitos incorretos;Erro 422: CnpjCpfRule — documento inválido;Validação;Alta;✅ Validado | |
| 91;Bloco 4 — Detalhe Operação;Sacados;Obrigatórios;Campos obrigatórios do sacado;Submeter vazio;Erros 422: cnpj_cpf, company_name, zip_code, state, city, address, email;Validação;Alta;✅ Validado | |
| 92;Bloco 4 — Detalhe Operação;Sacados;Editar;Editar sacado existente;Alterar endereço → Salvar;PUT /payers/{id} → 200. UpdatePayerRequest usa sometimes;Funcional;Média;✅ Validado | |
| 93;Bloco 4 — Detalhe Operação;Sacados;Excluir c/ Invoices;Excluir sacado com títulos vinculados;DELETE sacado que tem invoices;Erro 422: "Não é possível deletar o sacado pois existem notas fiscais vinculadas.";Funcional;Alta;✅ Validado | |
| 93b;Bloco 4 — Detalhe Operação;Sacados;Excluir c/ Checks;Excluir sacado com cheques vinculados;DELETE sacado que tem checks;Erro 422: "Não é possível deletar o sacado pois existem cheques vinculados.";Funcional;Alta;✅ Validado | |
| 94;Bloco 4 — Detalhe Operação;Sacados;Excluir Livre;Excluir sacado sem vínculos;DELETE sacado sem invoices/checks;200: "Sacado excluído com sucesso.";Funcional;Média;✅ Validado | |
| 95;Bloco 4 — Detalhe Operação;Operação;Excluir;Excluir operação em digitação;DELETE /operations/{id} → Confirmar;200: "Operação excluída com sucesso". Soft delete cascata (invoices + checks). Nota: backend NÃO valida se a operação já foi submetida;Funcional;Alta;✅ Validado | |
| 96;Bloco 4 — Detalhe Operação;Operação;Excluir Outro User;Tentar excluir operação de outro usuário;DELETE operação que pertence a outro user;404: "Operação não encontrada" (getOperation() filtra por user_id);Segurança;Alta;✅ Validado | |
| 97;Bloco 4 — Detalhe Operação;Detalhamento;Carregar;Carregar detalhamento de operação;Card não-Digitando → /operacoes/{id}/detalhamento;GET /consulta-detalhes-operacao/ com cnpj_cedente + num_aditivo;Funcional;Alta;✅ Validado | |
| 98;Bloco 4 — Detalhe Operação;Detalhamento;Loading;Loading state do detalhamento;Acessar página;Spinner "Carregando detalhes da operação...";Funcional;Média;✅ Validado | |
| 99;Bloco 4 — Detalhe Operação;Detalhamento;Erro;Erro ao carregar detalhamento;API erro/timeout;Ícone de erro + "Erro ao carregar detalhes da operação" + botão voltar;Funcional;Alta;✅ Validado | |
| 100;Bloco 4 — Detalhe Operação;Detalhamento;Processando;Operação em processamento (substatus);Substatus "processando";Tooltip info: dados serão atualizados após processamento;Funcional;Média;✅ Validado | |
| 101;Bloco 4 — Detalhe Operação;Detalhamento;Métricas Cedente;Métricas do cedente no topo;Página carregada;5 métricas: Limite, Limite Tranche, Tranche disponível, Limite disponível, Última confirmação;Funcional;Alta;✅ Validado | |
| 102;Bloco 4 — Detalhe Operação;Detalhamento;Dados Lateral;Card "Dados da Operação" lateral;Página carregada;Valor de face, Abatimento, Deságio, Desconto, Ad.Valorem, Recompras, Valor a pagar, Tax, Taxa, Prazo médio;Funcional;Alta;✅ Validado | |
| 103;Bloco 4 — Detalhe Operação;Detalhamento;Responsivo;Layout responsivo (< 1280px);Viewport < 1280px;Card lateral move para baixo do card principal;UI;Baixa;✅ Validado | |
| 104;Bloco 4 — Detalhe Operação;Tabela Sacados;Colapsada;Tabela de sacados colapsada;Página carregada;Colunas: CPF/CNPJ, Sacado, Valor, Nr títulos;Funcional;Alta;✅ Validado | |
| 105;Bloco 4 — Detalhe Operação;Tabela Sacados;Expandir;Expandir sacado para ver títulos;Clicar na linha de um sacado;Sub-tabela: Nº NF, Nr Doc, T Doc, Vencimento, Prazo médio, Deságio, Desconto, Valor face, Status;Funcional;Alta;✅ Validado | |
| 106;Bloco 4 — Detalhe Operação;Tabela Sacados;Status Pills;Status pills nos títulos;Expandir sacado;Pills: Aprovado (verde), Pendente (laranja), Reprovado (cinza), Info (azul);UI;Média;✅ Validado | |
| 107;Bloco 4 — Detalhe Operação;Tabela Sacados;Tooltip NF;Tooltip de NF truncado;NF com número longo;Últimos 8 dígitos na tabela, tooltip mostra completo;UI;Baixa;✅ Validado | |
| 108;Bloco 4 — Detalhe Operação;Filtros Detalhe;Por Status;Filtrar títulos por status;Selecionar "Aprovado";Apenas títulos aprovados. Sacados sem títulos filtrados ocultados;Funcional;Média;✅ Validado | |
| 109;Bloco 4 — Detalhe Operação;Filtros Detalhe;Por Período;Filtrar por período/ano;Selecionar ano (gerado dinamicamente);Apenas títulos com vencimento naquele ano;Funcional;Média;✅ Validado | |
| 110;Bloco 4 — Detalhe Operação;Filtros Detalhe;Combinado;Filtrar status + período combinados;Ambos os filtros;Interseção: títulos que atendem ambos;Funcional;Média;✅ Validado | |
| 111;Bloco 4 — Detalhe Operação;Filtros Detalhe;Sem Resultado;Filtro sem resultados;Filtro sem dados;"Nenhum sacado encontrado";Funcional;Baixa;✅ Validado | |
| 112;Bloco 4 — Detalhe Operação;Filtros Detalhe;Reset Período;Reset de filtro de período;Opções mudam após filtro status;Dropdown reseta para "Todos" se opção indisponível;Funcional;Baixa;✅ Validado | |
| 113;Bloco 4 — Detalhe Operação;Favorecidos;Tabela;Tabela de favorecidos;Página carregada;Tabela: CPF/CNPJ, Favorecido, Valor, Tipo pagto;Funcional;Média;✅ Validado | |
| 114;Bloco 4 — Detalhe Operação;Favorecidos;Vazio;Sem favorecidos;Operação sem favorecidos;"Nenhum favorecido encontrado";Funcional;Baixa;✅ Validado | |
| 115;Bloco 4 — Detalhe Operação;Extras;Download REM;Download arquivo .REM;Clicar botão download (se arquivo existe);Arquivo .REM baixado via Blob, loading state;Funcional;Média;✅ Validado | |
| 116;Bloco 4 — Detalhe Operação;Extras;REM Oculto;Botão .REM oculto;Operação sem arquivo .REM;Botão não renderizado;UI;Baixa;✅ Validado | |
| 117;Bloco 4 — Detalhe Operação;Extras;Erro Download;Erro ao baixar .REM;Falha no download;Toast: "Erro ao baixar arquivo .rem";Funcional;Média;✅ Validado | |
| 118;Bloco 4 — Detalhe Operação;Extras;Imprimir;Imprimir operação;Clicar "Imprimir";window.print(). CSS @media print formata layout;Funcional;Baixa;✅ Validado | |
| 119;Bloco 4 — Detalhe Operação;Admin;Detalhamento;Admin acessa detalhamento;Admin com cedente selecionado;CNPJ via cedenteStore;Funcional;Média;✅ Validado | |
| 120;Bloco 4 — Detalhe Operação;CNPJ;Fallback;Fallback de CNPJ;Usuário sem CNPJ direto;Chain: authLocal.cnpj → user.cnpj → perfil.cnpj_digits → perfil.cnpj;Funcional;Média;✅ Validado | |
| 121;Bloco 5 — Submissão;Resumo;Carregar;Carregar resumo da operação;"Avançar" → /operacoes/{id}/resumo;GET /operations/{id}/summary → operation, fee, beneficiaries;Funcional;Alta;✅ Validado | |
| 122;Bloco 5 — Submissão;Resumo;Loading;Loading state do resumo;Acessar página;Spinner durante carregamento;Funcional;Média;✅ Validado | |
| 123;Bloco 5 — Submissão;Resumo;404;Operação não encontrada no resumo;ID inexistente;API: 404 "Operação não encontrada";Funcional;Alta;✅ Validado | |
| 124;Bloco 5 — Submissão;Resumo;Métricas;Exibição de métricas do resumo;Página carregada;Quantidade de títulos, Valor Face total, Taxa de deságio (%);Funcional;Alta;✅ Validado | |
| 125;Bloco 5 — Submissão;Favorecidos;Listagem;Listagem de contas bancárias;Página carregada;Grid de cards com contas (Banco, Tipo, Agência, Conta, Dígito). Radio button;Funcional;Alta;✅ Validado | |
| 126;Bloco 5 — Submissão;Favorecidos;Conta Única;Selecionar conta única;Radio button em uma conta;Conta selecionada, valor preenchido com total da operação;Funcional;Alta;✅ Validado | |
| 127;Bloco 5 — Submissão;Favorecidos;Split;Split de pagamento (múltiplas contas);Selecionar mais de uma conta;Campos de valor para cada conta. Soma deve igualar total;Funcional;Alta;✅ Validado | |
| 128;Bloco 5 — Submissão;Favorecidos;Soma Incorreta;Validação de soma dos valores;Soma ≠ total;Botão "Aceitar" desabilitado. Mensagem de aviso;Validação;Alta;✅ Validado | |
| 129;Bloco 5 — Submissão;Favorecidos;Sem Contas;Sem contas bancárias;Cedente sem favorecidos;Lista vazia. Botão "Aceitar" desabilitado;Funcional;Média;✅ Validado | |
| 130;Bloco 5 — Submissão;Observações;Adicionar;Adicionar observação;Modal AdicionarObservacaoModal → Texto → Confirmar;Texto salvo. Máximo 1000 chars (backend obs: max:1000);Funcional;Baixa;✅ Validado | |
| 131;Bloco 5 — Submissão;Observações;Vazia;Observação vazia;Não preencher;Envio sem obs — campo opcional (nullable);Funcional;Baixa;✅ Validado | |
| 132;Bloco 5 — Submissão;Envio;Sucesso;Submeter operação com sucesso;Conta(s) + valores → "Aceitar" → Confirmar;POST /operations/{id}/submit com fee + beneficiaries[]. opera_id atribuído, status → PROCESSANDO. Redirect /operacoes;Funcional;Alta;✅ Validado | |
| 133;Bloco 5 — Submissão;Envio;Sem Beneficiários;Validação de beneficiários obrigatórios;Sem contas selecionadas;Erro 422: "É necessário informar pelo menos um favorecido." (beneficiaries: required, min:1);Validação;Alta;✅ Validado | |
| 134;Bloco 5 — Submissão;Envio;Valor < 0.01;Validação de valor do beneficiário < 0.01;Valor = 0;Erro 422: "O valor do favorecido deve ser maior que zero." (beneficiaries.*.value: min:0.01);Validação;Média;✅ Validado | |
| 135;Bloco 5 — Submissão;Envio;Payment Method;Validação de método de pagamento;payment_method inválido;Erro 422: "A forma de pagamento deve ser 1 (TED), 2 (DOC) ou 3 (PIX).";Validação;Média;✅ Validado | |
| 136;Bloco 5 — Submissão;Envio;Indicator;Validação de indicador;indicator inválido;Erro 422: "O indicador do favorecido deve ser P (Próprio) ou T (Terceiro).";Validação;Média;✅ Validado | |
| 137;Bloco 5 — Submissão;Envio;Soma Diverge;Soma dos beneficiários ≠ total da operação;Total diverge;Erro 422: "A soma dos valores dos favorecidos (R$ X) não corresponde ao total da operação (R$ Y).";Validação;Alta;✅ Validado | |
| 138;Bloco 5 — Submissão;Envio;Já Submetida;Operação já submetida;Status ≠ EM_DIGITACAO;Erro 422: "A operação já foi submetida." (OperationSubmitException::operationAlreadySubmitted);Funcional;Alta;✅ Validado | |
| 139;Bloco 5 — Submissão;Envio;Erro API;Erro na API Opera Capital durante envio;enviarOperacao() retorna erro;Erro tratado pelo OperationSubmitException. Operação permanece EM_DIGITACAO;Funcional;Alta;✅ Validado | |
| 140;Bloco 5 — Submissão;Envio;XML ZIP;Envio com arquivos XML (ZIP);Invoices com media collection 'xml';ZIP criado automaticamente, enviado multipart, deletado no finally;Funcional;Média;✅ Validado | |
| 141;Bloco 5 — Submissão;Importação;XML Upload;Upload de XML (NF-e/CT-e);Arrastar .xml para zona de upload;POST /operations/import com FormData. ImportSummaryResource retornada. Max 10MB por arquivo;Funcional;Alta;✅ Validado | |
| 142;Bloco 5 — Submissão;Importação;CNAB Upload;Upload de CNAB 240/400 (.rem);Selecionar .rem;Detectado via ImportFileType::fromExtension(). Job ImportFromRem enfileirado;Funcional;Alta;✅ Validado | |
| 143;Bloco 5 — Submissão;Importação;Tracking;Import batch tracking;Acompanhar progresso;GET /operations/import/{batchKey}/summary → total_files, processed_files;Funcional;Média;✅ Validado | |
| 144;Bloco 5 — Submissão;Importação;Sucesso;Resultado da importação (sucesso);Processada com sucesso;Toast: X títulos importados. Títulos na tabela;Funcional;Alta;✅ Validado | |
| 145;Bloco 5 — Submissão;Importação;Erro;Resultado da importação (erro);Formato inválido ou extensão não suportada;Erro 422: "Apenas arquivos xml, rem são permitidos." ou ImportLog com status erro;Funcional;Alta;✅ Validado | |
| 146;Bloco 6 — Relatórios;Página;Carregamento;Carregamento da página de relatórios;Acessar /relatorios;Grid 3x2 com 6 cards: Posição Abertos, Posição Liquidados, Borderô, Status Aceite, Termo Cessão, Demonstrativo Financeiro;Funcional;Alta;✅ Validado | |
| 147;Bloco 6 — Relatórios;Página;Admin Bloqueado;Admin não acessa relatórios;/relatorios como admin;Menu desabilitado (disabled: isAdmin). Tooltip: "Área ainda não habilitada para admin";Funcional;Média;✅ Validado | |
| 148;Bloco 6 — Relatórios;Página;Responsividade;Responsividade da grid;Reduzir viewport;3 cols > 1400px, 2 cols 900-1400px, 1 col < 900px;UI;Baixa;✅ Validado | |
| 149;Bloco 6 — Relatórios;Com Datas;Modal;Abrir modal relatório com datas;Clicar "Gerar" em Posição Abertos/Liquidados;Modal GerarRelatorioModal: CNPJ sacado (masked), Data início, Data fim;Funcional;Alta;✅ Validado | |
| 150;Bloco 6 — Relatórios;Com Datas;Gerar Sucesso;Gerar relatório com dados válidos;Preencher tudo → Gerar;POST /gerar-relatorio/ com codigo_relatorio 1 ou 2. Response: RelatorioBase64. PDF em iframe;Funcional;Alta;✅ Validado | |
| 151;Bloco 6 — Relatórios;Com Datas;CNPJ Cedente;CNPJ do cedente indisponível;Sem CNPJ no localStorage;Toast: "CNPJ/CPF do cedente (usuário) indisponível";Validação;Média;✅ Validado | |
| 152;Bloco 6 — Relatórios;Com Datas;Sem Sacado;CNPJ do sacado não informado;Gerar sem CNPJ sacado;Toast: "Informe o CNPJ do sacado";Validação;Média;✅ Validado | |
| 153;Bloco 6 — Relatórios;Com Datas;Datas Ausentes;Datas obrigatórias ausentes;Request sem data_de ou data_ate;Erro 422: "A data de início/fim é obrigatória para este relatório.";Validação;Alta;✅ Validado | |
| 154;Bloco 6 — Relatórios;Com Datas;Formato Data;Formato de data inválido;Data fora de AAAA-MM-DD;Erro 422: "A data deve estar no formato AAAA-MM-DD.";Validação;Média;✅ Validado | |
| 155;Bloco 6 — Relatórios;Com Datas;Sem PDF;PDF não retornado pela API;Response sem RelatorioBase64;Toast: "PDF não retornado pela API";Funcional;Média;✅ Validado | |
| 156;Bloco 6 — Relatórios;Com Aditivo;Modal;Abrir modal relatório com aditivo;Clicar "Gerar" em Borderô/Status Aceite/Termo/Demonstrativo;Modal GerarRelatorioAditivoModal: Sequencial Aditivo (inteiro);Funcional;Alta;✅ Validado | |
| 157;Bloco 6 — Relatórios;Com Aditivo;Gerar Sucesso;Gerar relatório por aditivo;Preencher aditivo → Gerar;POST /gerar-relatorio/ com codigo_relatorio 3-6 + sequencial_aditivo. PDF em iframe;Funcional;Alta;✅ Validado | |
| 158;Bloco 6 — Relatórios;Com Aditivo;Sem Aditivo;Aditivo não informado;Request sem sequencial_aditivo;Erro 422: "O sequencial do aditivo é obrigatório para este relatório.";Validação;Alta;✅ Validado | |
| 159;Bloco 6 — Relatórios;Com Aditivo;Aditivo Texto;Aditivo não numérico;Texto no campo;Erro 422: "O sequencial do aditivo deve ser um número inteiro.";Validação;Média;✅ Validado | |
| 160;Bloco 6 — Relatórios;Validações;Código Inválido;Código de relatório inválido;codigo_relatorio fora de 1-6;Erro 422: "O código do relatório deve ser entre 1 e 6.";Validação;Média;✅ Validado | |
| 161;Bloco 6 — Relatórios;Validações;Empresa;Código da empresa obrigatório;Sem codigo_empresa;Erro 422: "O código da empresa é obrigatório.";Validação;Média;✅ Validado | |
| 162;Bloco 6 — Relatórios;Validações;Filial;Código da filial obrigatório;Sem codigo_filial;Erro 422: "O código da filial é obrigatório.";Validação;Média;✅ Validado | |
| 163;Bloco 6 — Relatórios;Erros API;400;Erro 400 da API QProf;API retorna 400;"Dados inválidos. Verifique os campos obrigatórios para este tipo de relatório.";Funcional;Alta;✅ Validado | |
| 164;Bloco 6 — Relatórios;Erros API;502;Erro 502 da API QProf;Serviço indisponível;"Falha ao consultar o QProf. Serviço temporariamente indisponível.";Funcional;Alta;✅ Validado | |
| 165;Bloco 6 — Relatórios;Erros API;500;Erro 500 interno;Erro configuração/interno;"Erro interno ao gerar relatório. Tente novamente.";Funcional;Alta;✅ Validado | |
| 166;Bloco 6 — Relatórios;Erros API;Loading;Loading state durante geração;Clicar "Gerar" e aguardar;Botão com loading (isGenerating=true), desabilitado durante processamento;Funcional;Média;✅ Validado | |
| 167;Bloco 7 — Cedentes;Admin Selector;Visível;AdminCedenteSelector visível para admin;Qualquer página como admin;Barra roxa com seletor. Nome e CNPJ formatado do cedente;Funcional;Alta;✅ Validado | |
| 168;Bloco 7 — Cedentes;Busca;Buscar;Buscar cedente por nome/CNPJ;≥4 chars no campo;Debounce 350ms → GET /assignors?q=texto → AssignorResource collection;Funcional;Alta;✅ Validado | |
| 169;Bloco 7 — Cedentes;Busca;< 4 chars;Busca com < 4 caracteres;3 chars;Erro 422: "O parâmetro de busca deve ter no mínimo 4 caracteres.";Validação;Média;✅ Validado | |
| 170;Bloco 7 — Cedentes;Busca;Sem Resultado;Busca sem resultados;Texto sem correspondência;Dropdown vazio ou "Nenhum cedente encontrado";Funcional;Média;✅ Validado | |
| 171;Bloco 7 — Cedentes;Seleção;Selecionar;Selecionar cedente;Clicar em resultado;Salvo no cedenteStore (code, cnpj, name). sessionStorage. CNPJ formatado XX.XXX.XXX/XXXX-XX;Funcional;Alta;✅ Validado | |
| 172;Bloco 7 — Cedentes;Seleção;Limpar;Limpar cedente selecionado;Clicar "X";cedenteStore resetado. Dados recarregam sem filtro;Funcional;Média;✅ Validado | |
| 173;Bloco 7 — Cedentes;Persistência;Navegação;Persistência entre navegação;Selecionar → Navegar → Voltar;Cedente mantido (sessionStorage);Funcional;Média;✅ Validado | |
| 174;Bloco 7 — Cedentes;Persistência;Fechar Aba;Cedente perdido ao fechar aba;Fechar aba → Reabrir;Cedente resetado (sessionStorage limpa);Funcional;Baixa;✅ Validado | |
| 175;Bloco 7 — Cedentes;Favorecidos;User;Consultar favorecidos como usuário;GET /beneficiaries/;CNPJ via user.resolveCnpj(). BeneficiaryResource retornada;Funcional;Alta;✅ Validado | |
| 176;Bloco 7 — Cedentes;Favorecidos;Admin s/ CNPJ;Consultar favorecidos admin sem CNPJ;GET /beneficiaries/ como admin sem cnpj;Erro 422: "O campo CNPJ é obrigatório para administradores.";Validação;Alta;✅ Validado | |
| 177;Bloco 7 — Cedentes;Favorecidos;Admin c/ CNPJ;Consultar favorecidos admin com CNPJ;GET /beneficiaries/?cnpj=xxx;Favorecidos do CNPJ retornados;Funcional;Alta;✅ Validado | |
| 178;Bloco 7 — Cedentes;Favorecidos;Vazio;Sem favorecidos cadastrados;CNPJ sem contas na API;Response 204 No Content;Funcional;Média;✅ Validado | |
| 179;Bloco 7 — Cedentes;Detalhes API;Válido;Consultar detalhes com dados válidos;GET /consulta-detalhes-operacao/ válido;DetalhesOperacaoResource com sacados, títulos, favorecidos;Funcional;Alta;✅ Validado | |
| 180;Bloco 7 — Cedentes;Detalhes API;Inválido;Consultar detalhes com borderô/aditivo inválido;Parâmetros inválidos;"Esta operação não possui detalhamento disponível. Operações em digitação devem ser acessadas pela tela de edição.";Funcional;Alta;✅ Validado | |
| 181;Bloco 7 — Cedentes;Detalhes API;Não Autorizado;CNPJ não autorizado;CNPJ de outro usuário;Erro 403: "Detalhes não encontrados ou CNPJ não autorizado.";Segurança;Alta;✅ Validado | |
| 182;Bloco 7 — Cedentes;Detalhes API;Erro Interno;Erro interno na consulta;API erro inesperado;"Erro interno ao consultar detalhes da operação. Tente novamente.";Funcional;Alta;✅ Validado | |
| 183;Bloco 8 — Layout;Sidebar;Menu;Menu lateral renderizado após login;Login com sucesso;Sidebar roxo #221C42. Logo, 3 itens: Dashboard, Operações, Relatórios. "Sair" no rodapé;Funcional;Alta;✅ Validado | |
| 184;Bloco 8 — Layout;Sidebar;Navegação;Navegação via menu;Clicar itens do menu;Router navega. Item ativo com fundo #6359E9;Navegação;Alta;✅ Validado | |
| 185;Bloco 8 — Layout;Sidebar;Dashboard Admin;Dashboard desabilitado para admin;Login como admin;opacity: 0.5, cursor: not-allowed. Tooltip: "Área ainda não habilitada para admin";Funcional;Média;✅ Validado | |
| 186;Bloco 8 — Layout;Sidebar;Relatórios Admin;Relatórios desabilitado para admin;Login como admin;Mesmo comportamento desabilitado;Funcional;Média;✅ Validado | |
| 187;Bloco 8 — Layout;Sidebar;Tela Pequena;Menu em tela pequena (< md);Viewport < 1024px;Sidebar overlay (drawer). Fecha após navegação;UI;Média;✅ Validado | |
| 188;Bloco 8 — Layout;Sidebar;Logo Fallback;Logo com fallback;Logo não carrega (404);Fallback texto "opera CAPITAL" branco;UI;Baixa;✅ Validado | |
| 189;Bloco 8 — Layout;Logout;Dialog;Fluxo de logout;Clicar "Sair";Dialog: "Deseja realmente sair?" com "Cancelar" / "Sair";Funcional;Alta;✅ Validado | |
| 190;Bloco 8 — Layout;Logout;Confirmar;Confirmar logout;Clicar "Sair" no dialog;POST /logout → Cookie removido → Store reset → PostHog reset → Redirect /login;Funcional;Alta;✅ Validado | |
| 191;Bloco 8 — Layout;Logout;Cancelar;Cancelar logout;Clicar "Cancelar";Dialog fecha. Nenhuma ação. Permanece na página;Funcional;Média;✅ Validado | |
| 192;Bloco 8 — Layout;Interceptors;Token;Token automaticamente injetado;Qualquer request autenticado;Authorization: Bearer {token} do cookie "authorization";Segurança;Alta;✅ Validado | |
| 193;Bloco 8 — Layout;Interceptors;Toast Sucesso;Toast de sucesso em mutations;POST/PUT/DELETE com sucesso;Toast verde: mensagem da API ou "Operação realizada com sucesso!" (12s);Funcional;Média;✅ Validado | |
| 194;Bloco 8 — Layout;Interceptors;Toast Erro;Toast de erro em requests;Request falha (4xx/5xx);Toast vermelho. Login: timeout infinito + botão fechar. Outros: 12s;Funcional;Média;✅ Validado | |
| 195;Bloco 8 — Layout;Interceptors;401 Global;401 global — sessão expirada;Request retorna 401 (exceto /login e /logout);PostHog reset → Cookie removido → reload() após 100ms → Redirect /login;Segurança;Alta;✅ Validado | |
| 196;Bloco 8 — Layout;Interceptors;FormData;FormData handling;Upload de arquivos;Content-Type removido para browser definir multipart/form-data;Funcional;Média;✅ Validado | |
| 197;Bloco 8 — Layout;Preferências;Tema Auto;Tema padrão (auto);Primeiro acesso;theme = 'auto'. Quasar Dark.set('auto');Funcional;Baixa;✅ Validado | |
| 198;Bloco 8 — Layout;Preferências;Toggle Tema;Alternar tema;Toggle light ↔ dark;setTheme() atualiza store e Quasar Dark. Persistido localStorage;Funcional;Baixa;✅ Validado | |
| 199;Bloco 8 — Layout;Preferências;Idioma;Idioma (pt padrão);Primeiro acesso;language = 'pt'. Reservado para futura i18n;Funcional;Baixa;✅ Validado | |
| 200;Bloco 8 — Layout;Preferências;Sidebar;Sidebar colapsada;Toggle sidebar;sidebarCollapsed atualizado. Persistido localStorage;Funcional;Baixa;✅ Validado | |
| 201;Bloco 8 — Layout;Chatbot;Inicialização;Inicialização do chatbot;Primeiro carregamento MainLayout;Script Typebot injetado (check data-typebot-injected). Bubble verde #5c8a2f;Funcional;Baixa;✅ Validado | |
| 202;Bloco 8 — Layout;Chatbot;Não Duplica;Chatbot não duplica;Navegar entre páginas;querySelector impede reinjeção do script;Funcional;Baixa;✅ Validado | |
| 203;Bloco 8 — Layout;404;Rota Inexistente;Rota inexistente;URL que não existe;ErrorNotFound.vue via /:catchAll(.*)*;Funcional;Média;✅ Validado | |
| 204;Bloco 9 — Complementares;Download Mídia;Owner CNAB;Download de arquivo CNAB (owner);GET /media/{media}/download como dono;Middleware EnsureMediaOwnership valida collection 'cnab' → user_id match. Download OK;Funcional;Alta;✅ Validado | |
| 205;Bloco 9 — Complementares;Download Mídia;Owner XML;Download de arquivo XML de invoice (owner);GET /media/{media}/download para XML de invoice;Middleware valida collection 'xml' → operation.user_id match. Download OK;Funcional;Alta;✅ Validado | |
| 206;Bloco 9 — Complementares;Download Mídia;Outro Usuário;Download de arquivo de outro usuário;GET /media/{media}/download como usuário diferente;Erro 403: "Acesso não autorizado." via EnsureMediaOwnership;Segurança;Alta;✅ Validado | |
| 207;Bloco 9 — Complementares;Download Mídia;Collection Desconhecida;Download com collection desconhecida;Arquivo com collection não mapeada;userId = null → 403 "Acesso não autorizado.";Segurança;Média;✅ Validado | |
| 208;Bloco 9 — Complementares;Rate Limiting;Verify Token;Rate limiting no verify-token;4+ requests em 1 min para POST /verify-token;Erro 429. Throttle: 3,1;Segurança;Alta;✅ Validado | |
| 209;Bloco 9 — Complementares;Rate Limiting;Preview;Rate limiting no pre-registration-preview;11+ requests em 1 min para POST /pre-registration-preview;Erro 429. Throttle: 10,1;Segurança;Média;✅ Validado | |
| 210;Bloco 9 — Complementares;Validação CMC7;< 30 dígitos;CMC7 com menos de 30 dígitos;Cheque com CMC7 de 29 dígitos;Erro 422: "O campo CMC7 informado é inválido. Verifique o código e tente novamente.";Validação;Alta;✅ Validado | |
| 211;Bloco 9 — Complementares;Validação CMC7;> 30 dígitos;CMC7 com mais de 30 dígitos;Cheque com CMC7 de 31 dígitos;Mesmo erro 422 da Cmc7Rule;Validação;Média;✅ Validado | |
| 212;Bloco 9 — Complementares;Validação CMC7;Repetidos;CMC7 com 30 dígitos repetidos;CMC7 = "111111111111111111111111111111";Erro 422: regex detecta repetição. CMC7 inválido;Validação;Média;✅ Validado | |
| 213;Bloco 9 — Complementares;Validação CPF;Dígitos Incorretos;CPF com dígitos verificadores incorretos;Sacado com CPF que falha validação algorítmica;Erro 422: "O campo cnpj_cpf deve ser um CPF ou CNPJ válido." (CnpjCpfRule);Validação;Alta;✅ Validado | |
| 214;Bloco 9 — Complementares;Validação CPF;Repetidos;CPF com 11 dígitos repetidos;CPF = "11111111111";Erro 422: regex rejeita. CPF inválido;Validação;Média;✅ Validado | |
| 215;Bloco 9 — Complementares;Validação CNPJ;Inválido;CNPJ inválido via CnpjHelper;CNPJ com dígitos incorretos;Erro 422: "O campo cnpj deve ser um CNPJ válido." (CnpjRule);Validação;Alta;✅ Validado | |
| 216;Bloco 9 — Complementares;Validação CPF/CNPJ;CPF no campo;Documento que é CPF válido mas não CNPJ;CPF válido no campo cnpj_cpf;Aceito — CnpjCpfRule testa CPF e CNPJ. Basta um ser válido;Validação;Média;✅ Validado | |
| 217;Bloco 9 — Complementares;Importação;Extensão Inválida;Upload de arquivo com extensão não suportada;Enviar .pdf ou .txt via import;Erro 422: "Apenas arquivos xml, rem são permitidos." (ImportFileType::fromExtension);Validação;Alta;✅ Validado | |
| 218;Bloco 9 — Complementares;Importação;> 10MB;Upload de arquivo > 10MB;Arquivo XML > 10MB;Erro 422: "Cada arquivo não pode exceder o tamanho máximo de 10 MB." (max:10240);Validação;Média;✅ Validado | |
| 219;Bloco 9 — Complementares;Importação;Sem Arquivos;Import sem arquivos;POST /operations/import sem campo files;Erro 422: "É necessário enviar pelo menos um arquivo para importação.";Validação;Alta;✅ Validado | |
| 220;Bloco 9 — Complementares;Importação;Op Inexistente;Import com operation_id inexistente;operation_id que não existe;Erro 422: "A operação especificada não existe." (exists:operations,id);Validação;Média;✅ Validado | |
| 221;Bloco 9 — Complementares;Importação;Banco Não Suportado;Import CNAB com banco não suportado;CNAB 400 com código de banco não mapeado;UnsupportedBankException: "Banco com código 'XXX' não é suportado para importação CNAB 400." ImportLog: ERROR;Funcional;Alta;✅ Validado | |
| 222;Bloco 9 — Complementares;Importação;Título Duplicado;Import com título duplicado (mesma NF-e);XML com NF-e já existente;updateOrCreateByBankTitle() faz upsert — atualiza existente. ImportLog: IMPORTED;Funcional;Média;✅ Validado | |
| 223;Bloco 9 — Complementares;Importação;Batch Inexistente;Import batch não encontrado;GET /operations/import/{batchKey}/summary inexistente;404: "Lote de importação não encontrado.";Funcional;Média;✅ Validado | |
| 224;Bloco 9 — Complementares;Importação;Logs Operação;Import logs de operação;GET /operations/{id}/import-logs;Lista de ImportBatch com ImportSummaryResource;Funcional;Média;✅ Validado | |
| 225;Bloco 9 — Complementares;CNPJ;Sem CNPJ Store;Criar operação sem CNPJ disponível;POST /operations/ como user sem CNPJ;Erro 422: "CNPJ não disponível." (controller verifica resolveCnpj);Funcional;Alta;✅ Validado | |
| 226;Bloco 9 — Complementares;CNPJ;Import s/ CNPJ;Import sem CNPJ disponível;POST /operations/import como user sem CNPJ;Erro 422: "CNPJ não disponível.";Funcional;Alta;✅ Validado | |
| 227;Bloco 9 — Complementares;Admin;Ops s/ CNPJ;Admin lista operações sem CNPJ;GET /operations/?status=DIGITANDO como admin sem cnpj;Erro 422: "O campo CNPJ é obrigatório para usuários Opera.";Validação;Alta;✅ Validado | |
| 228;Bloco 9 — Complementares;Rotas;GET /user;GET /user (rota inline);GET /user autenticado;Retorna request->user() — dados do user sem UserResource wrapper;Funcional;Baixa;✅ Validado | |
| 229;Bloco 9 — Complementares;Isolamento;Invoice Outro User;Usuário visualiza invoice de outro usuário;GET /invoices/{id} com invoice de outro user;404: "Nota fiscal não encontrada" (findUserInvoice filtra por user);Segurança;Alta;✅ Validado | |
| 230;Bloco 9 — Complementares;Isolamento;Check Outro User;Usuário visualiza cheque de outro usuário;GET /checks/{id} com check de outro user;404: "Cheque não encontrado";Segurança;Alta;✅ Validado | |
| 231;Bloco 9 — Complementares;Isolamento;Payer Outro User;Usuário visualiza sacado de outro usuário;GET /payers/{id} com payer de outro user;404: "Sacado não encontrado." (getPayer filtra por user_id);Segurança;Alta;✅ Validado | |
| 232;Bloco 9 — Complementares;Op Submetida;Criar Invoice;Criar invoice em operação submetida;POST /invoices/ com operation_id de op PROCESSANDO;422: "Operação não encontrada ou já submetida." (canModifyOperation);Funcional;Alta;✅ Validado | |
| 233;Bloco 9 — Complementares;Op Submetida;Editar Invoice;Editar invoice em operação submetida;PUT /invoices/{id} de op submetida;404: "Nota fiscal não encontrada" (updateInvoice retorna null);Funcional;Alta;✅ Validado | |
| 234;Bloco 9 — Complementares;Op Submetida;Excluir Invoice;Excluir invoice em operação submetida;DELETE /invoices/{id} de op submetida;404: "Nota fiscal não encontrada" (deleteInvoice retorna false);Funcional;Alta;✅ Validado | |
| 235;Bloco 9 — Complementares;Op Submetida;Criar Check;Criar check em operação submetida;POST /checks/ com operation_id de op PROCESSANDO;422: "Operação não encontrada ou já submetida.";Funcional;Alta;✅ Validado | |
| 236;Bloco 9 — Complementares;Op Submetida;Editar Check;Editar check em operação submetida;PUT /checks/{id} de op submetida;404: "Cheque não encontrado";Funcional;Alta;✅ Validado | |
| 237;Bloco 9 — Complementares;Op Submetida;Excluir Check;Excluir check em operação submetida;DELETE /checks/{id} de op submetida;404: "Cheque não encontrado";Funcional;Alta;✅ Validado | |
| 238;Bloco 9 — Complementares;API Opera;Timeout;Timeout na API Opera Capital;Request excede 30s;Retry 3x com 100ms delay. Se falhar: OperaCapitalException;Funcional;Alta;✅ Validado | |
| 239;Bloco 9 — Complementares;API Opera;Token Expirado;Token JWT expirado durante operação;Cache de token expira entre requests;OperaCapitalClient reauthentifica automaticamente (cache 55min);Funcional;Média;✅ Validado | |
| 240;Bloco 9 — Complementares;API Opera;Erro Desconhecido;API retorna erro desconhecido;Response com formato inesperado;OperaCapitalException::fromResponse() extrai 'detail' ou 'error' ou fallback;Funcional;Média;✅ Validado | |
| 241;Bloco 9 — Complementares;NF-e/NFS-e;Sem Nenhuma Chave;Criar título sem nfe_key NEM nfs_e_key;POST /invoices/ com ambos nulos (tipo DUPLICATA/XML);Erro 422: "O campo chave da NF-e é obrigatório quando a chave da NFS-e não for informada.";Validação;Alta;✅ Validado | |
| 242;Bloco 9 — Complementares;NF-e/NFS-e;Apenas NFS-e;Criar título com apenas nfs_e_key;POST /invoices/ com nfs_e_key válida e nfe_key nulo;201 Created — requiredIf(empty nfe_key) satisfeito;Funcional;Média;✅ Validado | |
| 243;Bloco 9 — Complementares;NF-e/NFS-e;NFS-e > 50 chars;NFS-e key > 50 caracteres;nfs_e_key com 51 chars;Erro 422: "O campo chave da NFS-e não pode ter mais de 50 caracteres.";Validação;Média;✅ Validado | |
| 244;Bloco 9 — Complementares;NF-e/NFS-e;Duplicata Standalone;NF-e key duplicada em StoreInvoiceRequest;POST /invoices/ com nfe_key existente;Aceita — StoreInvoiceRequest NÃO tem unique constraint (potencial duplicata);Validação;Alta;✅ Validado | |
| 245;Bloco 9 — Complementares;NF-e/NFS-e;Duplicata Operação;NF-e key duplicada ao criar operação;POST /operations/ com invoice.nfe_key existente;Erro 422: "Esta chave de NF-e já está cadastrada no sistema." (unique whereNull deleted_at);Validação;Alta;✅ Validado | |
| 246;Bloco 9 — Complementares;Filtros Listagem;Payer por CNPJ;Filtrar sacados por cnpj_cpf;GET /payers/?cnpj_cpf=12345678000190;Retorna sacados com CNPJ/CPF correspondente (service limpa máscara);Funcional;Média;✅ Validado | |
| 247;Bloco 9 — Complementares;Filtros Listagem;Payer por Nome;Filtrar sacados por razão social (parcial);GET /payers/?company_name=empresa;Busca LIKE retorna matches parciais;Funcional;Média;✅ Validado | |
| 248;Bloco 9 — Complementares;Filtros Listagem;Payer por Cidade;Filtrar sacados por cidade;GET /payers/?city=São Paulo;Retorna sacados da cidade;Funcional;Baixa;✅ Validado | |
| 249;Bloco 9 — Complementares;Filtros Listagem;Payer por Estado;Filtrar sacados por estado;GET /payers/?state=SP;Retorna sacados do estado (max:2 chars);Funcional;Baixa;✅ Validado | |
| 250;Bloco 9 — Complementares;Filtros Listagem;Payer por Email;Filtrar sacados por e-mail;GET /payers/?email=teste@empresa.com;Match exato do e-mail;Funcional;Baixa;✅ Validado | |
| 251;Bloco 9 — Complementares;Filtros Listagem;Payer Multi-filtro;Filtrar sacados com múltiplos filtros;GET /payers/?state=SP&city=São Paulo;AND lógico — ambos critérios aplicados;Funcional;Média;✅ Validado | |
| 252;Bloco 9 — Complementares;Filtros Listagem;Payer Sem Filtro;Filtrar sacados sem parâmetros;GET /payers/ (sem filtros);Retorna todos os sacados do usuário;Funcional;Baixa;✅ Validado | |
| 253;Bloco 9 — Complementares;Filtros Listagem;Invoice por Op;Filtrar invoices por operation_id;GET /invoices/?operation_id={id};Retorna invoices da operação;Funcional;Média;✅ Validado | |
| 254;Bloco 9 — Complementares;Filtros Listagem;Invoice por Número;Filtrar invoices por número (parcial);GET /invoices/?number=001;LIKE retorna matches parciais;Funcional;Média;✅ Validado | |
| 255;Bloco 9 — Complementares;Filtros Listagem;Check por CMC7;Filtrar checks por cmc7 (parcial);GET /checks/?cmc7=12345;LIKE retorna matches parciais;Funcional;Média;✅ Validado | |
| 256;Bloco 9 — Complementares;Detalhes Params;Snake Case;Parâmetros em snake_case;GET /consulta-detalhes-operacao/?cnpj_cedente=XXX&num_bordero=123;prepareForValidation() converte para camelCase. Request aceita;Funcional;Média;✅ Validado | |
| 257;Bloco 9 — Complementares;Detalhes Params;Camel Case;Parâmetros em camelCase;GET /consulta-detalhes-operacao/?CNPJCedente=XXX&NumBordero=123;Aceita diretamente;Funcional;Média;✅ Validado | |
| 258;Bloco 9 — Complementares;Detalhes Params;Sem Borderô/Aditivo;Sem borderô nem aditivo;GET /consulta-detalhes-operacao/?CNPJCedente=XXX;Erro 422: "Informe o número do borderô ou do aditivo." (required_without);Validação;Alta;✅ Validado | |
| 259;Bloco 9 — Complementares;Detalhes Params;Ambos;Com borderô e aditivo;GET ?CNPJCedente=XXX&NumBordero=1&NumAditivo=2;Ambos aceitos (required_without permite ter os dois);Funcional;Baixa;✅ Validado | |
| 260;Bloco 9 — Complementares;Detalhes Params;CNPJ Inválido;CNPJ do cedente inválido na consulta;GET ?CNPJCedente=invalido&NumBordero=1;Erro 422: "O CNPJ do cedente informado é inválido." (CnpjHelper);Validação;Alta;✅ Validado | |
| 261;Bloco 9 — Complementares;Multi-Upload;2 XMLs;Upload de 2 XMLs em um request;POST /operations/import com files[]=[file1.xml, file2.xml];Ambos processados. ImportBatch total_files=2;Funcional;Média;✅ Validado | |
| 262;Bloco 9 — Complementares;Multi-Upload;XML + CNAB;Upload de XML + CNAB no mesmo request;files[]=[file.xml, file.rem];Cada arquivo roteado para job correto;Funcional;Média;✅ Validado | |
| 263;Bloco 9 — Complementares;Multi-Upload;Parcial Falha;Upload parcial: 1 falha, 2 sucedem;3 arquivos, 1 malformado;ImportLog: 2 IMPORTED, 1 ERROR. processed_files=3;Funcional;Alta;✅ Validado | |
| 264;Bloco 9 — Complementares;Modal Readonly;Nota Submetida;EditarNotaModal em operação submetida;Clicar título em op EM_ANALISE/ASSINATURA/PAGO;Modal readonly: campos desabilitados, botão salvar oculto;UI;Média;✅ Validado | |
| 265;Bloco 9 — Complementares;Modal Readonly;Cheque Submetido;EditarChequeModal em operação submetida;Clicar cheque em op submetida;Modal readonly: campos desabilitados, botão salvar oculto;UI;Média;✅ Validado | |
| 266;Bloco 9 — Complementares;Submissão;Fee Zero;Fee = 0 na submissão;POST /operations/{id}/submit com fee=0;Aceito — fee nullable, numeric, min:0. Zero é válido;Funcional;Média;✅ Validado | |
| 267;Bloco 9 — Complementares;Submissão;Fee Negativa;Fee negativa na submissão;POST /operations/{id}/submit com fee=-1;Erro 422: "O campo taxa de deságio não pode ser menor que zero.";Validação;Média;✅ Validado | |
| 268;Bloco 9 — Complementares;Submissão;Obs Beneficiário;Observação do beneficiário > 255 chars;beneficiaries[0].observation com 256 chars;Erro 422: "A observação do favorecido não pode ter mais de 255 caracteres.";Validação;Baixa;✅ Validado | |
| 269;Bloco 9 — Complementares;Admin;Criar Op s/ CNPJ;Admin cria operação sem CNPJ;POST /operations/ como admin sem cnpj;Erro 422: "O campo CNPJ é obrigatório para administradores.";Validação;Alta;✅ Validado | |
| 270;Bloco 9 — Complementares;Rotas;GET /me;GET /me retorna UserResource;GET /me autenticado;Response formatada via UserResource (id, name, user_name, email, cnpj, role);Funcional;Média;✅ Validado | |
| 271;Bloco 9 — Complementares;Rotas;GET /user Raw;GET /user retorna objeto raw;GET /user autenticado;Response com objeto User direto sem wrapper Resource;Funcional;Baixa;✅ Validado |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment