# Documentação técnica — Cadastro de Produto/Serviço e plano de categorias (DRE)

Este documento descreve o **plano hierárquico** usado para classificar produtos e serviços, os **controllers** e **models** envolvidos, e a integração com **estoque**, **NF** e **fiscal**. Baseado em `GrupoContaController`, `GrupoItemController`, `ItemController`, `TipoProdutoServicoController`, `ProdutoServicoController` e models correlatos. O **PDV** (`/PDV`) consome **`ProdutoServico`** ativo por nome, **código** e **código de barras** — ver **`Doc_Modulo_PDV.md`**. A hierarquia **`grupoconta` → `grupoitem` → `item` → `prodservtipo` → `prodserv`** pode participar do **catálogo padrão multi-tenant** — ver **`Doc_Modulo_Catalogo_Padrao.md`**.

---

## 1. Hierarquia de classificação (visão de negócio)

O sistema modela quatro níveis “contábeis” abaixo do **Grupo Conta** (DRE / nível 1), alinhados aos rótulos usados nas telas de produto/serviço:

| Nível | Tabela | Model | Nome na UI (exemplos) |
|-------|--------|-------|------------------------|
| **1** | `grupoconta` | `GrupoConta` | Grupo Conta (DRE) |
| **2** | `grupoitem` | `GrupoItem` | Conta nível 2 / “Grupo Conta (DRE)” no contexto do item |
| **3** | `item` | `Item` | Categoria (sintética) / “Conta Sintética” |
| **4** | `prodservtipo` | `TipoProdutoServico` | Subcategoria / **Conta analítica** (`prodservtipo`) |
| **Registro final** | `prodserv` | `ProdutoServico` | Produto (`tipo = 'p'`) ou Serviço (`tipo = 's'`) |

**Relação principal do cadastro de produto:** cada `ProdutoServico` possui **`idprodservtipo`** → um único `TipoProdutoServico` (conta analítica), que por sua vez aponta para **`iditem`** (categoria), que aponta para **`idgrupoitem`**, que aponta para **`idgrupoconta`**.

O model `ProdutoServico` também expõe relação N:N **`tipos()`** via tabela pivô **`prodserv_prodservtipo`** (`belongsToMany`); o fluxo administrativo padrão usa sobretudo **`prodservtipo()`** (`belongsTo` em `idprodservtipo`).

```mermaid
flowchart TB
  GC[GrupoConta nivel 1 DRE]
  GI[GrupoItem nivel 2]
  IT[Item categoria sintetica]
  TPS[TipoProdutoServico prodservtipo]
  PS[ProdutoServico prodserv]
  GC --> GI
  GI --> IT
  IT --> TPS
  TPS --> PS
```

---

## 2. Models e tabelas

### 2.1 `GrupoConta` (`grupoconta`)

| Aspecto | Detalhe |
|---------|---------|
| Escopo | `TenantScope` — ligado ao **`idtenant`** (não por `idempresa`) |
| PK | `idgrupoconta` |
| Campos relevantes | `ordem`, `nome`, **`tipo`**: `I` = item detalhável, `N` = total não detalhável (constantes `TIPO_ITEM` / `TIPO_TOTAL`) |
| **DRE gerencial** | **`idlinhadre`** → `linhadre` (linha do demonstrativo de resultado); **`natureza_dre`** (código curto legado, alinhado à linha) |
| **DFC** | **`tipo_fluxo`**: `FCO` (operacional), `FCI` (investimentos), `FCF` (financiamento) — campo **“Fluxo de caixa (DFC)”** no formulário admin |
| Flags | `mostrar_forecast_compra`, `mostrar_forecast_venda` (boolean) |
| `status` | `ATIVO` / `INATIVO` |
| Relação | `contasNivel2()` → `GrupoItem`, `linhaDre()` |

**Controller:** `GrupoContaController` — **não** filtra por empresa; ao criar, preenche `idtenant` com `session('selectedTenant')` ou `auth()->user()->tenant`. Valores sugeridos de DRE/DFC podem vir de **`ClassificacaoContabilService`** (por nome do grupo).

### 2.1.1 Catálogo global `linhadre` e parâmetros `classificacao_contabil_padrao`

| Tabela / model | Escopo | Uso |
|----------------|--------|-----|
| **`linhadre`** (`LinhaDre`) | Global (todos os tenants) | Catálogo de linhas do DRE gerencial: receita bruta, deduções, custos variáveis, despesas fixas, excluir, etc. (`LinhaDreSeeder`) |
| **`classificacao_contabil_padrao`** (`ClassificacaoContabilPadrao`) | Global | Parâmetros por **nome** de grupo conta (`nivel = grupo_conta`: `idlinhadre`, `tipo_fluxo`) e exceções por subcategoria (`ClassificacaoContabilPadraoSeeder`) |

**Serviço:** `App\Services\ClassificacaoContabilService` — resolve padrões por nome, **`sincronizarCadastros()`** propaga para `grupoconta` e `prodservtipo` do tenant.

**Comando manual:** `php artisan contabilidade:sincronizar-classificacao` (opção `--sem-sobrescrever` preserva `idlinhadre` já definido em subcategorias).

**Impacto nas telas:** **`/dashboard/dre`** agrupa por `idlinhadre`; **`/dashboard/dfc`** usa `grupoconta.tipo_fluxo` (FCO/FCI/FCF). Ver **`Doc_Modulo_Dashboards.md`** § 4–5.

**Distinção:** `EstruturaContabilSeeder` cria a **árvore de produtos** (4 níveis); a **classificação gerencial** DRE/DFC é camada adicional sobre `grupoconta` / `prodservtipo` — ver **`Doc_Seeders_e_Dados_Iniciais.md`**.

### 2.2 `GrupoItem` (`grupoitem`)

| Aspecto | Detalhe |
|---------|---------|
| Escopo | `TenantScope` + **`idempresa`** |
| PK | `idgrupoitem` |
| Campos | `grupoitem` (nome), `idgrupoconta`, `cor`, `ordem`, **`classificacao`**: `C` crédito / `D` débito (`CLASSIFICACAO_*`), `status` |
| Relações | `grupoConta()`, `empresa()` |

**Controller:** `GrupoItemController` — mensagens de sucesso referem “Conta Nível 2”; `create` lista `GrupoConta::active()` para vínculo.

### 2.3 `Item` (`item`)

| Aspecto | Detalhe |
|---------|---------|
| Escopo | `TenantScope` + `idempresa` |
| PK | `iditem` |
| Campos | `item` (nome da categoria), `idgrupoitem`, `ordem`, `cor`, `status` |
| Relações | `grupoitem()`, `subcategorias()` → `hasMany(TipoProdutoServico)` |

**Controller:** `ItemController` — “Conta Sintética criada”; listagem mostra Grupo Conta (via `grupoitem.grupoConta`), conta nível 2 e categoria.

### 2.4 `TipoProdutoServico` (`prodservtipo`)

| Aspecto | Detalhe |
|---------|---------|
| Escopo | `TenantScope` |
| PK | `idprodservtipo` |
| Campos | `idempresa`, **`iditem`** (categoria pai), `prodservtipo` (nome da subcategoria/analítica), **`idlinhadre`** (exceção de linha DRE por subcategoria), `padrao`, `status`, auditoria |
| Relações | `item()`, `empresa()`, `produtos()` N:N em `prodserv` |
| Scope | `active()` → `status = ATIVO` |

**Controller:** `TipoProdutoServicoController` — CRUD “Subcategoria”; `store`/`update` usam apenas `idempresa`, `iditem`, `prodservtipo`, `status` (**`padrao` não** é atribuído no `store` do controller; se necessário, vem do banco default ou outra rota).

### 2.5 `ProdutoServico` (`prodserv`)

| Aspecto | Detalhe |
|---------|---------|
| Escopo | `TenantScope` |
| PK | `idprodserv` |
| `tipo` | `'p'` produto / `'s'` serviço (convenção usada nas views e listagens) |
| Campos principais | `idprodservtipo`, `idfinalidade_fiscal`, `idempresa`, `prodserv`, `codigo`, `codigobarras`, `valorcompra`, `valorvenda`, `unidade`, `estoque`, `estoqueminimo`, `status`, flags **`eh_vendivel`**, **`eh_compravel`**, **`eh_solicitavel`** (casts boolean), NFS-e: `id_codigo_tributacao_nacional`, `codigo_tributacao_municipal` |
| Relações | `prodservtipo()`, `finalidadeFiscal()`, `empresa()`, `tipos()` (N:N) |

**Estoque exibido na lista:** calculado por **`EstoqueService::calcularEstoqueAtual`** (entradas − saídas em `nfitem` com NF `CONCLUÍDO`, tipo `D` entrada / `C` saída), **não** necessariamente o campo `estoque` persistido na tabela.

---

## 3. Fluxo de cadastro recomendado (ordem operacional)

1. **Grupo Conta** (`admin/grupo-conta`) — estrutura DRE do tenant.  
2. **Grupo Item** (`admin/grupoitens`) — conta nível 2 por **empresa**, vínculo ao grupo conta.  
3. **Item** (`admin/itens`) — categoria sintética, vínculo ao grupo item.  
4. **Tipo produto/serviço** (`admin/tipo-produto-servico`) — subcategoria (`prodservtipo`), vínculo ao item.  
5. **Produto/serviço** (`admin/produto-servico`) — registro final com preços, unidade, flags de uso em venda/compra/pedido.

Sem os níveis superiores, o `ProdutoServicoController` ainda pode montar select: se **não** existir `Item` com `subcategorias`, cai no fallback **`TipoProdutoServico::where('status','ATIVO')`** plano (sem agrupamento por categoria).

---

## 4. Controllers — responsabilidades resumidas

### 4.1 `GrupoContaController`

- CRUD + `fetch` (JSON para datatable), `search`.
- `store`: injeta `idtenant` a partir da sessão/usuário.

### 4.2 `GrupoItemController`

- CRUD + `fetch`, `search`.
- `create`/`edit`: empresas ativas + grupos conta ativos ordenados por `ordem`, `nome`.
- `update`: suporte a `redirect=false` → JSON com `status`.
- **Detalhe:** mensagem de sucesso no `update` diz “Evento atualizado!” (provável cópia incorreta); `destroy` id de parâmetro nomeado `$idEvento`.

### 4.3 `ItemController`

- CRUD + `fetch`, `search`.
- `create`/`edit`: lista `GrupoItem` (sem filtrar só ativos no `create`).
- Eager load na listagem: `grupoitem.grupoConta`.

### 4.4 `TipoProdutoServicoController`

- CRUD + `fetch`, `search`.
- `create`/`edit`: `Item::with('grupoitem')` para montar selects.
- Listagem/fetch: colunas DRE completas via `item.grupoitem.grupoConta`.

### 4.5 `ProdutoServicoController`

- **`index` / `search` / `fetch`:** `with(['prodservtipo.item', 'empresa'])`, estoque atual via `EstoqueService` para produtos (`tipo == 'p'` na UI).
- **`create` / `edit`:**  
  - Categorias com subcategorias ativas: `Item::with(subcategorias)->has('subcategorias')->orderBy(ordem,item)`.  
  - `FinalidadeFiscal::active()`, `CodigoTributacaoNacional` (tabela global NFS-e), `UnidadeDeMedida::all()`.  
- **`store`:**  
  - Form normal: `create` + redirect para `edit`.  
  - **`Accept: application/json` (`wantsJson`):** após criar produto, opcionalmente cria **`ProdutoFornecedorMap`** (mapeamento XML ↔ produto) e **`NfItem`** na NF informada (`idnf`, `idpessoa`, quantidade a partir de `estoque` do request — campo usado no JSON embora não esteja no `only` do create; depende de mass assignment ou atributo no model). Fluxo típico de **importação/cadastro rápido a partir de compra**.  
- **`update`:** com `redirect=true`, `only([...])` whitelist; com `redirect=false`, `update($request->all())` (cuidado: superfície maior de atributos).  
- **`destroy`:** delete direto.

---

## 5. Regras e flags de uso do produto/serviço

| Flag / campo | Uso no código (referência) |
|--------------|----------------------------|
| `eh_vendivel` | `VendaController`: listagem de produtos para venda (`eh_vendivel` true ou null) |
| `eh_compravel` | `NfController` (compras): idem para itens compráveis |
| `eh_solicitavel` | `PedidoController`: itens solicitáveis em pedido |
| `tipo` `p` / `s` | Colunas estoque / estoque mínimo na listagem; serviço sem movimentação de estoque na grade |
| `idprodservtipo` | Classificação em NF (compras, vendas, pedidos); relatórios e selects agrupados |

---

## 6. Integrações

| Módulo | Ligação |
|--------|---------|
| **NF / `nfitem`** | Itens de nota referenciam `idprodserv`; compras podem atualizar `valorcompra` ao editar item |
| **Estoque** | `EstoqueService` deriva quantidade de `nfitem` + NF concluída |
| **Evento** | `EventoTipo.idprodserv` → produto/serviço padrão do tipo de evento |
| **ProdutoFornecedorMap** | Criação em `ProdutoServicoController::store` (JSON) para NFe/XML |
| **Fiscal** | `FinalidadeFiscal`, códigos tributação nacional/municipal no cadastro de produto |

---

## 7. Helper e unidades

**`App\Helpers\UnidadeDeMedida`:** lista estática de códigos/descrições para select no cadastro de produto/serviço (alinhado conceitualmente às unidades usadas em `NfController` para compras).

---

## 8. Multi-tenant

- `GrupoConta`: por **`idtenant`**.  
- `GrupoItem`, `Item`, `TipoProdutoServico`, `ProdutoServico`: **`TenantScope`** (e `idempresa` onde aplicável nos níveis 2–5).

Evitar misturar empresa de um tenant com `GrupoConta` de outro ao vincular `GrupoItem` (validação de consistência, se existir, é no front ou no banco).

---

## 9. Referência rápida de arquivos

| Arquivo | Função |
|---------|--------|
| `GrupoContaController.php` | Nível 1 DRE por tenant |
| `GrupoItemController.php` | Nível 2 por empresa |
| `ItemController.php` | Categoria (nível 3) |
| `TipoProdutoServicoController.php` | Subcategoria / `prodservtipo` (nível 4) |
| `ProdutoServicoController.php` | Produto/serviço + estoque calculado + fluxo JSON/NF |
| `GrupoConta.php`, `GrupoItem.php`, `Item.php`, `TipoProdutoServico.php`, `ProdutoServico.php` | Models e relações |
| `EstoqueService.php` | `calcularEstoqueAtual` a partir de NF concluídas |
| `UnidadeDeMedida.php` | Opções de unidade de medida |

**Rotas (prefixo admin):** `grupo-conta`, `grupoitens`, `itens`, `tipo-produto-servico`, `produto-servico` (ver `routes/web.php`).

---

*Documento gerado a partir da leitura do código. Constraints de FK e exclusões em cascata devem ser confirmadas nas migrations.*
