# Documentação técnica — Catálogo padrão do sistema

Este documento descreve o **catálogo padrão multi-tenant**: cadastros marcados no **tenant mestre** que são replicados para todas as instâncias, com regras de **proteção por uso**, **exclusão lógica no tenant** e **sincronização** que não sobrescreve dados já utilizados ou removidos localmente.

Documentos relacionados: **`Doc_Modulo_Tenant.md`** (provisionamento ao criar tenant), **`Doc_Modulo_Financeiro.md`** (NF, parcelas, formas de pagamento), **`Doc_Modulo_Produto_Servico.md`** (hierarquia contábil e `prodserv`), **`Doc_Seeders_e_Dados_Iniciais.md`**.

---

## 1. Conceito

| Conceito | Descrição |
|----------|-----------|
| **Registro origem** | Linha criada/editada no tenant mestre (ex.: finalidade fiscal no tenant `1`). |
| **`tabela_padrao`** | Tabela central com `tabela`, `tabela_id`, `snapshot` (campos espelhados), `ativo`, `protegido`, `permite_edicao`, `ordem`. |
| **Réplica no tenant** | Mesma entidade no tenant destino com **`tabela_padrao_id`** apontando para o catálogo; **PK local próprio** (`idfinalidade_fiscal`, etc.). |
| **Molde** | Registro origem + snapshot do catálogo; base para criar/atualizar réplicas. |

Fluxo resumido:

```text
[Mestre] marca "Padrão do sistema"
    → INSERT/UPDATE em tabela_padrao
    → origem.tabela_padrao_id = catálogo.id
    → upsert réplica em cada tenant (ordem por sync_order)

[Mestre] edita catálogo (Admin → Catálogo padrão) ou altera campos sincronizados na origem
    → atualiza snapshot + origem + réplicas (respeitando preservação — § 5)

[Tenant] usa o cadastro em NF, produto, etc.
    → réplica preservada em sync e ao desmarcar padrão (§ 5)

[Tenant] "exclui" item do catálogo (com campo status)
    → status EXCLUIDO; some da listagem; sync não reativa
```

---

## 2. Quem pode gerenciar

| Regra | Implementação |
|-------|----------------|
| Tenants autorizados | `.env` **`CATALOGO_PADRAO_MASTER_TENANTS`** (padrão `1,17`) → `config/catalogo_padrao.php` → `master_tenant_ids`. |
| Checagem em código | `CatalogoPadraoSistema::podeGerenciar()` compara `session('selectedTenant')` ou `auth()->user()->idtenant`. |
| Rotas admin do catálogo | Middleware **`catalogo.padrao.master`** + `role:ADMIN` — `admin/tabela-padrao` (index, edit, update). |
| UI nos cadastros | Switch **Padrão do sistema** e botão **Sincronizar tenants** só aparecem se `podeGerenciar()`. |

Tenants que **não** são mestre veem aviso informativo quando o registro tem `tabela_padrao_id`, mas não marcam/desmarcam padrão nem disparam sync em massa.

---

## 3. Entidades cobertas

Configuração única: **`config/catalogo_padrao.php`** (`entidades`).

| Chave | Tabela | Escopo tenant | Global | Ordem sync |
|-------|--------|---------------|--------|------------|
| `fluxo` | `fluxo` | `idtenant` | não | 5 |
| `grupoconta` | `grupoconta` | `idtenant` | não | 10 |
| `grupoitem` | `grupoitem` | via `idempresa` | não | 20 |
| `item` | `item` | via `idempresa` | não | 30 |
| `prodservtipo` | `prodservtipo` | via `idempresa` | não | 40 |
| `prodserv` | `prodserv` | via `idempresa` | não | 45 |
| `finalidade_fiscal` | `finalidade_fiscal` | `idtenant` | não | 48 |
| `natureza_operacao` | `natureza_operacao` | `idtenant` | não | 50 |
| `formapagamento` | `formapagamento` | `idtenant` | não | 60 |
| `codigo_tributacao_nacional` | `codigos_tributacao_nacional` | — | **sim** | 70 |

Campos replicados: lista **`fields`** por entidade. FKs entre entidades do catálogo usam **`fk_resolvers`** (ex.: `grupoconta`, `grupoitem`, `item`, `prodservtipo`, `linhadre_global`).

**Chave natural no tenant:** `unique_per_tenant` (ex.: `codigo` em `finalidade_fiscal`) evita duplicata ao sincronizar se o seed já criou o mesmo código.

---

## 4. Interface (admin)

### 4.1 Formulários das entidades

| Partial | Uso |
|---------|-----|
| `partials/catalogo-padrao-sistema-switch` | Checkbox `eh_padrao_sistema` no **formulário** (create/edit). |
| `partials/catalogo-padrao-sync-btn` | Botão **Sincronizar tenants** na **listagem** (`variant`: `toolbar` ou `inline`). |

Models usam o trait **`HasCatalogoPadraoSistema`** (hook `saved` / `deleting` / bloqueio de campos no `saving`).

### 4.2 Módulo Catálogo padrão

- Menu sidebar (mestre): **Catálogo padrão** → `TabelaPadraoController`.
- Edição: metadados (`ativo`, `protegido`, `permite_edicao`, `ordem`) + campos do **snapshot**.
- Toggle de status na listagem (AJAX), alinhado aos demais módulos.

### 4.3 Edição bloqueada no tenant

Com catálogo **ativo** e **`permite_edicao` = false** (padrão), campos listados em `fields` **não** podem ser alterados na tela da entidade — exceto no mestre com permissão explícita no catálogo ou edição via **Admin → Catálogo padrão**.

---

## 5. Regras de preservação (uso, exclusão, desmarcação)

### 5.1 Tabela de comportamentos

| Ação | Quem | Comportamento |
|------|------|----------------|
| **Marcar padrão** | Mestre | Cria/atualiza `tabela_padrao`, vincula origem, replica em todos os tenants (ou atualiza registro global). |
| **Desmarcar padrão** | Mestre | Desativa entrada no catálogo (`ativo`/`protegido` false). Em cada tenant: **`tabela_padrao_id = null` só se o registro não estiver em uso** (§ 5.2). |
| **Sincronizar** (`catalogo:sync-padrao` ou botão) | Mestre / CLI | Atualiza réplicas com o molde; **não** altera réplicas **EXCLUIDO** nem **em uso** (apenas garante vínculo se `tabela_padrao_id` estiver vazio). |
| **Provisionar tenant** | Observer / CLI | `provisionarTenant($idtenant)` — mesmo upsert por tenant novo. |
| **Excluir no tenant** | Qualquer tenant | Se tem `status` no catálogo: vira **`EXCLUIDO`** (exclusão lógica). Se **em uso**: erro, não exclui. |
| **Excluir físico** | — | Bloqueado para catálogo protegido/ativo sem status; mensagem no trait. |

### 5.2 Verificação de uso (`usage_checks`)

Em **`config/catalogo_padrao.php`**, cada entidade pode declarar referências:

```php
'usage_checks' => [
    ['table' => 'prodserv', 'column' => 'idfinalidade_fiscal', 'scope' => 'empresa'],
],
```

| `scope` | Significado |
|---------|-------------|
| **`empresa`** | Conta referências onde `idempresa` = do registro, ou, se só há tenant, onde `idempresa` ∈ empresas do tenant. Usado em `nf`, `nfparcela`, `prodserv`, etc. |
| **`tenant`** | Filtra por `idtenant` (coluna configurável em `tenant_column` do check, padrão `idtenant`). |
| **`fluxo_tenant`** | `fluxostatus` + join `fluxo` com mesmo `idtenant`. |

Implementação: **`CatalogoPadraoSistemaService::registroEmUsoNoTenant()`** e **`existeReferenciaUso()`**.

**Entidade global** (`codigo_tributacao_nacional`): ao desvincular, se **qualquer** `prodserv` referenciar o código, o vínculo com o catálogo **permanece**.

### 5.3 Mapa atual de uso (referência)

| Entidade | Tabelas / colunas verificadas |
|----------|------------------------------|
| `finalidade_fiscal` | `prodserv.idfinalidade_fiscal` |
| `natureza_operacao` | `nf.idnatureza_operacao` |
| `formapagamento` | `nf`, `nfparcela`, `contrato` → `idformapagamento` |
| `grupoconta` | `grupoitem.idgrupoconta` |
| `grupoitem` | `item.idgrupoitem` |
| `item` | `prodservtipo.iditem` |
| `prodservtipo` | `prodserv`, `nf` → `idprodservtipo` |
| `prodserv` | `nfitem.idprodserv` |
| `fluxo` | `fluxostatus` (via `fluxo.idtenant`) |
| `codigo_tributacao_nacional` | `prodserv.id_codigo_tributacao_nacional` |

Para incluir nova dependência: adicionar entrada em **`usage_checks`** e testar desmarcação + sync + exclusão no tenant.

### 5.4 Status `EXCLUIDO` e listagens

| Config | Valor padrão |
|--------|----------------|
| `status_excluido` | `EXCLUIDO` |
| `status_inativo` | `INATIVO` |

- Listagens admin das entidades do catálogo: **`CatalogoPadraoSistema::aplicarFiltroStatusListagem()`** oculta `INATIVO` e `EXCLUIDO`; filtro `?status=` exibe sob demanda.
- Réplica com `EXCLUIDO`: sync **não** reaplica snapshot nem reativa; pode apenas preencher `tabela_padrao_id` se estiver nulo.

---

## 6. Operações técnicas

### 6.1 Artisan

```bash
# Replica todos os catálogos ativos em todos os tenants
php artisan catalogo:sync-padrao

# Provisiona apenas um tenant (ex.: após criar instância manualmente)
php artisan catalogo:sync-padrao --tenant=42
```

### 6.2 Novo tenant

**`TenantObserver`** (após paleta e seeders de fluxo/finalidade):

1. `FluxoStatusSeeder::runForTenant`
2. `FinalidadeFiscalSeeder::runForTenant`
3. **`CatalogoPadraoSistemaService::provisionarTenant($idtenant)`** — aplica catálogos já ativos em `tabela_padrao`.

Ordem de sync entre entidades respeita **`sync_order`** (FKs resolvidas na ordem crescente).

### 6.3 Serviço principal

| Método | Função |
|--------|--------|
| `definirPadrao($model, $ehPadrao)` | Marca/desmarca padrão; desmarcação chama `desvincularReplicasAoRemoverPadrao`. |
| `sincronizarTodos()` | Loop catálogos ativos × tenants. |
| `provisionarTenant($idtenant)` | Upsert para um tenant. |
| `atualizarEntradaCatalogo($catalogo, $meta, $snapshot)` | Edição central + propagação. |
| `aplicarExclusaoLogicaCatalogo($model)` | `EXCLUIDO` no tenant; falha se em uso. |
| `replicaIgnoradaNaSincronizacao($existente, $cfg)` | `EXCLUIDO` **ou** em uso. |
| `registroEmUsoNoTenant($model)` | Consulta `usage_checks`. |
| `permiteEditarCamposNaEntidade($tabelaPadraoId)` | Respeita `permite_edicao` no catálogo. |

---

## 7. Schema e migrations

- **`tabela_padrao`**: migration `2026_06_03_140000_create_tabela_padrao_and_refactor_catalogo.php`.
- Coluna **`tabela_padrao_id`** nas tabelas das entidades: `2026_06_03_120000_add_catalogo_padrao_sistema_columns.php`.
- **`permite_edicao`**: `2026_06_03_160000_add_permite_edicao_to_tabela_padrao.php`.

---

## 8. Referência de arquivos

| Arquivo | Função |
|---------|--------|
| `config/catalogo_padrao.php` | Entidades, campos, FKs, `usage_checks`, tenants mestre. |
| `app/Services/CatalogoPadraoSistemaService.php` | Sync, desvinculação, uso, exclusão lógica. |
| `app/Support/CatalogoPadraoSistema.php` | Helpers, filtro listagem, `podeGerenciar()`. |
| `app/Traits/HasCatalogoPadraoSistema.php` | Hooks Eloquent nos models. |
| `app/Http/Middleware/CatalogoPadraoMasterMiddleware.php` | Protege rotas do catálogo. |
| `app/Http/Controllers/Admin/TabelaPadraoController.php` | CRUD metadados + snapshot. |
| `app/Http/Controllers/Admin/CatalogoPadraoSistemaController.php` | Sync HTTP (se usado pelas rotas de entidade). |
| `app/Console/Commands/SincronizarCatalogoPadraoCommand.php` | CLI `catalogo:sync-padrao`. |
| `app/Observers/TenantObserver.php` | `provisionarTenant` no `created`. |
| `resources/views/partials/catalogo-padrao-*.blade.php` | Switch, sync, status. |
| `.cursor/rules/ajuda-modal-global.mdc` | Padrão de ajuda contextual nas telas (incl. catálogo). |

Models com trait (exemplos): `FinalidadeFiscal`, `NaturezaOperacao`, `FormaPagamento`, `GrupoConta`, `GrupoItem`, `Item`, `TipoProdutoServico`, `ProdutoServico`, `Fluxo`, `CodigoTributacaoNacional`.

---

## 9. Cenários de teste sugeridos

1. **Desmarcar padrão** com finalidade usada em `prodserv` no tenant A: registro em A mantém `tabela_padrao_id` e dados; tenant B sem uso perde vínculo.
2. **Sync** após tenant alterar descrição localmente (sem uso): descrição volta ao molde.
3. **Sync** com réplica em uso: campos locais **não** mudam; vínculo mantido.
4. **Excluir** finalidade em uso no tenant: mensagem de erro; sem uso → `EXCLUIDO`, some da lista, sync não reativa.
5. **Novo tenant**: após observer, catálogos ativos presentes com `tabela_padrao_id` preenchido.
6. **`permite_edicao`**: habilitar no catálogo e editar campo na tela da entidade no mestre.

---

## 10. Evolução do módulo

Ao adicionar entidade ao catálogo:

1. Migration: `tabela_padrao_id` na tabela.
2. Entrada em **`config/catalogo_padrao.php`** (`fields`, `sync_order`, `tenant_column` / `tenant_via`, `fk_resolvers`, `usage_checks`).
3. Trait **`HasCatalogoPadraoSistema`** no model.
4. Partials de switch (form) e sync (index); **`aplicarFiltroStatusListagem`** no controller se houver `status`.
5. Documentar **`usage_checks`** neste arquivo (§ 5.3).

---

*Documento alinhado ao código em `CatalogoPadraoSistemaService` e `config/catalogo_padrao.php`. Atualize ao alterar regras de preservação ou novas entidades.*
