Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,11 @@ Uma ressalva que vale para qualquer instalação: o ponteiro de NSU pertence ao
aplicação. Se outro sistema fiscal já consome a fila daquele CNPJ, a carga inicial não traz histórico —
os NSUs anteriores já foram entregues a ele. Não é defeito, é como a SEFAZ define a fila.

A manifestação de ciência também já foi exercitada em produção: o evento 210210 foi aceito pela SEFAZ e
o protocolo ficou gravado no documento.

As pendências conhecidas — todas registradas como decisão, não esquecimento — estão em
[`RELEASE.md`](RELEASE.md). A principal: a manifestação de ciência ainda não foi exercitada contra a
SEFAZ de produção.
[`RELEASE.md`](RELEASE.md).

### Fluxo mínimo para testar de ponta a ponta

Expand Down
1 change: 0 additions & 1 deletion RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ daqui só criaria referência que ninguém consegue abrir.
|---|---|
| Imagem da API com 375 MB contra os 250 MB do NFR | Deploy mais lento e mais banda por release; sem impacto em execução |
| Comando de rotação da chave mestra não implementado | Rotacionar `ECONTABIL_CRYPTO_KEY` exige o procedimento manual do `RUNBOOK.md`, com janela de parada |
| Manifestação não exercitada contra a SEFAZ de produção | O caminho de ciência só foi provado por teste; a primeira execução real pode revelar rejeição não prevista |
| Consulta avulsa por chave (`consChNFe`) | Nota conhecida por chave só entra no acervo se aparecer na fila de NSU |
| E2E de navegador e teste de carga | Regressão de fluxo completo e limite de carga dependem de verificação manual |
| Sem tela de usuários no frontend | Criar, editar e desativar operador só por API — `curl` ou Swagger |
Expand Down
14 changes: 12 additions & 2 deletions src/eContabil.Infrastructure/Sefaz/ZeusFiscalService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,11 @@ public async Task<Result<RetornoManifestacaoDto>> ManifestarCienciaAsync(
chavesNFe: [.. manifestacao.Chaves],
nFeTipoEventoManifestacaoDestinatario: NFeTipoEvento.TeMdCienciaDaOperacao,
cpfcnpj: manifestacao.Certificado.CnpjTitular,
justificativa: string.Empty,

// Nulo, e não string vazia: a justificativa é do evento de operação não realizada, e o
// schema da ciência não admite o campo. Vazio vira `<xJust></xJust>` no XML, que a SEFAZ
// recusa com cStat 493 — "evento não atende o schema XML específico".
justificativa: null,
dhEvento: null);

var retorno = TradutorDeEventoSefaz.Traduzir(resposta.Retorno);
Expand Down Expand Up @@ -166,8 +170,14 @@ public async Task<Result<RetornoManifestacaoDto>> ManifestarCienciaAsync(
// Deixá-lo no padrão faz o serviço ser reportado como "não disponível para a UF".
ModeloDocumento = ModeloDocumento.NFe,

// A Distribuição DF-e só existe em 1.00: é a versão única do serviço, não um padrão herdado.
VersaoNFeDistribuicaoDFe = VersaoServico.Versao100,
VersaoRecepcaoEventoManifestacaoDestinatario = VersaoServico.Versao100,

// O evento de manifestação, ao contrário, precisa de 4.00. A biblioteca implementa o
// `RecepcaoEvento` 1.00 apenas no .NET Framework e, sob .NET, a chamada morria antes de sair da
// máquina com "RecepcaoEvento 1.0 não está implementado para .net standard". Quem tem
// implementação aqui é o `RecepcaoEventoManifestacaoDestinatario4`, do layout nacional vigente.
VersaoRecepcaoEventoManifestacaoDestinatario = VersaoServico.Versao400,
TimeOut = _opcoes.TimeoutMs,
ValidarSchemas = _opcoes.ValidarSchemas
};
Expand Down
7 changes: 5 additions & 2 deletions src/econtabil-web/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# EcontabilWeb
# eContabil — Notas Fiscais

This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 21.2.19.
Frontend da plataforma. A documentação do produto, do fluxo de captura e da operação está no
[`README.md`](../../README.md) e no [`RUNBOOK.md`](../../RUNBOOK.md) da raiz.

Gerado com [Angular CLI](https://github.com/angular/angular-cli) 21.2.19.

## Development server

Expand Down
6 changes: 5 additions & 1 deletion src/econtabil-web/angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
}
],
"styles": [
"@fontsource/roboto/300.css",
"@fontsource/roboto/400.css",
"@fontsource/roboto/500.css",
"material-icons/iconfont/filled.css",
"src/styles.scss"
]
},
Expand All @@ -38,7 +42,7 @@
"budgets": [
{
"type": "initial",
"maximumWarning": "500kB",
"maximumWarning": "600kB",
"maximumError": "1MB"
},
{
Expand Down
17 changes: 17 additions & 0 deletions src/econtabil-web/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/econtabil-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
"@angular/material": "^21.2.14",
"@angular/platform-browser": "^21.2.0",
"@angular/router": "^21.2.0",
"@fontsource/roboto": "^5.3.0",
"@ngrx/signals": "^21.1.1",
"material-icons": "^1.13.14",
"rxjs": "~7.8.0",
"tslib": "^2.3.0"
},
Expand Down
53 changes: 53 additions & 0 deletions src/econtabil-web/public/login-fundo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
84 changes: 81 additions & 3 deletions src/econtabil-web/src/app/core/layout/shell.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,17 @@ const MENU: readonly ItemDeMenu[] = [
<mat-icon>menu</mat-icon>
</button>

<span class="titulo">eContabil</span>
<span class="marca">
<mat-icon>receipt_long</mat-icon>
<span class="titulo">eContabil</span>
</span>

<span class="espacador"></span>

<span class="usuario">{{ store.usuario()?.nome }}</span>
<span class="usuario">
<span class="nome">{{ store.usuario()?.nome }}</span>
<span class="perfil">{{ store.usuario()?.role }}</span>
</span>

<button matIconButton type="button" aria-label="Sair" (click)="sair()">
<mat-icon>logout</mat-icon>
Expand All @@ -88,26 +95,97 @@ const MENU: readonly ItemDeMenu[] = [
</mat-sidenav-container>
`,
styles: `
/*
* O azul da marca é fixo, e não o primary do tema: a barra identifica o produto e precisa do mesmo
* tom em toda tela, inclusive na de login, onde o tema do Material não chega.
*/
mat-toolbar {
background: var(--ec-marca);
color: #fff;
position: sticky;
top: 0;
z-index: 2;
box-shadow: 0 1px 3px rgb(15 23 42 / 18%);
}

.espacador {
flex: 1 1 auto;
}

.marca {
display: flex;
align-items: center;
gap: 0.5rem;
margin-left: 0.25rem;
}

.titulo {
margin-left: 0.5rem;
font-weight: 500;
letter-spacing: 0.01em;
}

.usuario {
display: flex;
flex-direction: column;
align-items: flex-end;
line-height: 1.2;
margin-right: 0.75rem;
}

.usuario .nome {
font-size: 0.875rem;
}

.usuario .perfil {
font-size: 0.6875rem;
text-transform: uppercase;
letter-spacing: 0.06em;
color: rgb(255 255 255 / 70%);
}

.conteudo {
height: calc(100vh - 64px);
background: var(--ec-fundo);
}

mat-sidenav {
width: 15rem;
border-right: 1px solid var(--ec-borda);
background: #fff;
padding-top: 0.5rem;
}

/*
* O item ativo ganha fundo e barra à esquerda. Só a cor do texto não bastaria: no menu vertical, o
* olho procura a linha destacada, não o tom da fonte.
*/
a.ativo {
background: var(--ec-marca-fundo);
color: var(--ec-marca);
font-weight: 500;
box-shadow: inset 3px 0 0 var(--ec-marca);
}

a.ativo mat-icon {
color: var(--ec-marca);
}

.pagina {
padding: 1.5rem;
max-width: 90rem;
}

@media (width < 48rem) {
.pagina {
padding: 1rem;
}

.usuario .nome {
max-width: 8rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
`,
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ const TAMANHO_MAXIMO_BYTES = 5 * 1024 * 1024;
}

.erro {
color: #b3261e;
color: var(--ec-erro);
margin: 0;
}

Expand Down Expand Up @@ -187,26 +187,6 @@ const TAMANHO_MAXIMO_BYTES = 5 * 1024 * 1024;
mat-card {
margin-bottom: 1rem;
}

.grade {
width: 100%;
border-collapse: collapse;
}

.grade th,
.grade td {
text-align: left;
padding: 0.5rem;
border-bottom: 1px solid rgb(0 0 0 / 12%);
}

.oculto {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
}
`,
})
export class CertificadosComponent implements OnInit {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,33 +190,21 @@ const ROTULOS_DE_RESULTADO: Readonly<Record<ResultadoExecucao, string>> = {

.rotulo {
margin: 0;
color: rgb(0 0 0 / 60%);
color: var(--ec-texto-secundario);
}

mat-card {
margin-bottom: 1rem;
}

.grade {
width: 100%;
border-collapse: collapse;
}

.grade th,
.grade td {
text-align: left;
padding: 0.5rem;
border-bottom: 1px solid rgb(0 0 0 / 12%);
}

.numero-celula {
text-align: right;
}

.numero-celula .secundario {
display: block;
font-size: 0.75rem;
color: rgb(0 0 0 / 55%);
color: var(--ec-texto-terciario);
}

.documento {
Expand All @@ -225,17 +213,9 @@ const ROTULOS_DE_RESULTADO: Readonly<Record<ResultadoExecucao, string>> = {
}

.pendente {
color: #78350f;
color: var(--ec-aviso);
font-weight: 500;
}

.oculto {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
}
`,
})
export class DashboardComponent implements OnInit, OnDestroy {
Expand Down
Loading
Loading