# Documentação técnica — Módulo de Tags (ativos / retiradas)

O módulo trata de **tipos de tag** (modelo de ativo com campos opcionais), **tags** (identificadores por empresa, com numeração automática), **retiradas/reservas** (`tagretira`: quem pegou qual tag, período e status) e um **dashboard** com calendário e indicadores. A rota **`/dashboard/tags`**: **`Doc_Modulo_Dashboards.md`** § 9. Não há vínculo direto com **eventos** ou **NF** no model `Evento`; o model `Tag` possui `idnf` no `$fillable` para extensão futura ou uso pontual.

---

## 1. Visão geral do fluxo de dados

```mermaid
flowchart LR
  TT[tagtipo por empresa]
  T[tag numerada]
  TR[tagretira]
  TT -->|idtagtipo| T
  T -->|idtag| TR
  TR --> P[pessoa colaborador]
  TR --> E[empresa]
```

1. Cadastra-se um **tipo** (`tagtipo`) com nome e “parâmetros” habilitados (marca, modelo, dimensões, TI, manutenção, etc.) como flags **0/1**.
2. Cadastra-se a **tag** (`tag`): empresa, tipo, observação, status; o **código legível** (`tag`) é gerado automaticamente se vier nulo.
3. Registra-se **retirada** (`tagretira`): pessoa, empresa, tag, datas (`datainicio`, `datafim`, `datadevolucao`), status, observação — com regras para **RESERVADA** e **CONCLUÍDO**.

---

## 2. Tabelas e models

### 2.1 `tagtipo` — `App\Models\TagTipo`

| Aspecto | Detalhe |
|---------|---------|
| PK | `idtagtipo` |
| Tenant | `TenantScope` |
| Campos centrais | `idempresa`, `tagtipo` (nome do tipo), `status` (`ATIVO` / `INATIVO`) |
| “Parâmetros” | Colunas `marca`, `modelo`, `anofabricacao`, `numeroserie`, `altura`, `largura`, `comprimento`, `peso`, `material`, `combustivel`, `datamanutencao`, `dataproximamanutencao`, `garantia`, `voltagem`, `processador`, `memoriaram`, `cor`, `sistemaoperacional` — no controller são normalizadas como **booleanas 0/1** a partir de checkboxes `on` |

**Relações:** `empresa()`, `criador()` → `User` via `criadopor` (**atenção:** em `TagTipoController::store`, `criadopor` recebe `auth()->user()->name`, enquanto `criador()` espera **id** de usuário — risco de relacionamento quebrado ou exibição incorreta na listagem).

### 2.2 `tag` — `App\Models\Tag`

| Aspecto | Detalhe |
|---------|---------|
| PK | `idtag` |
| Tenant | `TenantScope` |
| FKs | `idtagtipo`, `idempresa`; opcional `idnf` (nota fiscal) no fillable |
| `tag` (string) | Identificador exibido; formato típico **`{sigla_empresa}-{número}`** via `TagService::generateTagNumber` |

**Hooks `creating`:**

- Se `tag` for nulo, `TagService` busca a última tag da empresa, extrai parte numérica, incrementa e prefixa com **`Empresa::find($idempresa)->sigla`**.
- Se `criadopor` for nulo, recebe **`Auth::user()->id`**.

**Relações:** `tagTipo()` (`belongsTo` com `withDefault()`), `empresa()`, `pessoa()` (campo `idpessoa` não está no `$fillable` atual — relação pode ficar sem uso no CRUD padrão).

**Método `filter()`:** busca com `with('empresa', 'tagtipo')` — o nome do relacionamento correto é `tagTipo`; uso de `'tagtipo'` em string pode falhar conforme versão do Eloquent.

### 2.3 `tagretira` — `App\Models\TagRetira`

| Aspecto | Detalhe |
|---------|---------|
| PK | `idtagretira` |
| Tenant | `TenantScope` |
| Campos | `idpessoa`, `idempresa`, `idtag`, `datainicio`, `datafim`, `datadevolucao`, `status`, `observacao`, auditoria |

**Status usados no sistema:** `PENDENTE`, `EM ANDAMENTO`, `CONCLUÍDO`, `RESERVADA`, `CANCELADO` (listagens costumam excluir `CANCELADO`).

**Relações:** `pessoa()`, `empresa()`, `tag()` → inclui `tag.tagTipo` nas consultas do calendário.

---

## 3. Controllers admin

### 3.1 `TagTipoController` — `admin/tagtipos`

| Ação | Comportamento |
|------|----------------|
| `index` / `fetch` | Lista com `empresa`, `criador` |
| `store` | Normaliza checkboxes dos parâmetros para 0/1; define `criadopor` e `criadoem`; **redirect pós-create usa `$tagTipoModel->idtagtipo`** após `create()` — o ID correto seria o **modelo retornado** por `create`; comportamento possivelmente incorreto |
| `update` | Se existirem **tags** com `status = ATIVO` vinculadas ao tipo, **impede** mudar o tipo para `INATIVO` (redirect ou JSON de erro); normaliza checkboxes quando `redirect=true`; com `redirect=false` atualiza com `$request->all()` |
| `destroy` | Delete do registro |

**Busca (`search`):** contém `orderBy('tagtipo.tagtipo')` — possível erro de sintaxe (alias de tabela); validar em runtime.

### 3.2 `TagController` — `admin/tags`

| Ação | Comportamento |
|------|----------------|
| `index` / `fetch` | Tags com `status != INATIVO`; status na UI: `ATIVO`, `MANUTENCAO`, `INATIVO` |
| `store` | Apenas `idempresa`, `idtagtipo`, `observacao`, `status` — **não** envia `tag` (geração automática) |
| `update` | Whitelist inclui `tag`, `nome`, `descricao`, etc. — alinhamento com colunas reais do banco depende das migrations posteriores |
| `edit` | **Bug:** cor de status usa `$tagModel->status` em vez de `$tag->status` |
| `destroy` | Redirect para **`admin.tag.index`** — nome de rota provavelmente incorreto (`admin.tags.index`) |
| `search` | Encadeia `where` + dois `whereHas` com **AND** entre si (empresa e tipo devem **simultaneamente** casar com o mesmo termo + tag LIKE) — tende a retornar poucos resultados |

**`fetch` — bug:** coluna STATUS usa `id` => `$item->idformapagamento` (cópia de outro módulo); deveria ser `idtag`.

### 3.3 `TagRetiraController` — `admin/tagsretira`

| Ação | Comportamento |
|------|----------------|
| `index` / `fetch` | Exclui `CANCELADO`; eager `tag`, `empresa`, `pessoa` |
| `store` | Se status ≠ `RESERVADA`, `create` e volta; se `RESERVADA`, valida se **já existe** outro `tagretira` com mesmo `idtag` e `RESERVADA` — se sim, erro; senão `create`. **Bug:** redirect `route('admin.tagsretira.edit', $tagRetira)` usa variável não definida após `create` (deveria ser o modelo criado) |
| `update` | Se status atual é `CONCLUÍDO`, tenta limitar alterações (lógica mistura observação e status); valida unicidade de `RESERVADA` por `idtag` excluindo o registro atual |
| `getTagReservas` | Rota `GET .../tagsretira/gettagreservadas/{idtag}` → `TagRetiraService::get` — JSON com reservas/pendentes da tag |

**`fetch`:** STATUS com `id` => `idnf` — possível erro (deveria ser `idtagretira`).

**`edit`:** `bg_status` baseado em `$tagModel->status` (model injetado) em vez de `$tagRetira->status`.

---

## 4. Serviços

### 4.1 `TagService::generateTagNumber($idempresa)`

- Última `tag` da empresa ordenada desc; extrai dígitos; +1; formato **`{sigla}-{número}`**.
- Colisão: se houver tags não numéricas misturadas, o `preg_replace` pode gerar sequências inesperadas.

### 4.2 `TagRetiraService::get($idtag)`

- Retorna JSON com registros `TagRetira` do `idtag` onde `status` ∈ `RESERVADA`, `PENDENTE`, com `pessoa`, ordenados por `criadoem`.

---

## 5. Dashboard — `GET /dashboard/tags`

- View `resources/views/dashboard/tags.blade.php`.
- **Calendário:** `@livewire('calendar-tag-component')` — eventos no mês corrente, status `PENDENTE` ou `RESERVADA`, intervalo `datainicio`–`datafim`; cores por status; link para `admin/tagsretira/{id}/edit`; query `?visualizacao=inicio|termino|duracao` (igual ideia ao calendário de eventos).
- **Painel:** `@livewire('tag-component')` — métricas sobre `TagRetira` (mês atual vs anterior, abertas, reservadas, pendentes, em execução, a vencer em 3 dias, vencidas).

### 5.1 `TagComponent` (lógica)

- Filtra `TagRetira` com `status != CANCELADO`.
- Janelas por **`datainicio`** (`whereBetween` / comparadores).
- **“Aberto”:** status literal `'aberto'` — na prática o método recebe `'aberto'` mas a query usa `where('status', 'aberto')`; **não** corresponde aos status reais (`PENDENTE`, etc.) — possível bug de KPI.
- **“Reservada”:** `where('status', 'reservada')` vs valor **`RESERVADA`** — **case mismatch**, contagem pode zerar.
- **A vencer / vencidas:** filtros em coleção com `datafim` e status `EM ANDAMENTO` / `RESERVADA`.

### 5.2 `CalendarTagComponent`

- Apenas mês atual; não aplica `TenantScope` explicitamente além do model.

---

## 6. Livewire auxiliar — `TagtipoModal`

- Modal para criar **TagTipo** com validação Livewire (`idempresa`, `tagtipo`, `status` e flags de parâmetros).
- Útil em telas que embutem cadastro rápido de tipo sem ir ao CRUD completo.

---

## 7. Front específico

- `public/assets/js/tagsretira.js` — interações da tela de retiradas (ex.: reservas via API `gettagreservadas`).

---

## 8. Rotas admin (prefixo típico)

| Recurso | Rotas |
|---------|--------|
| Tipos | `tagtipos` + `search`, `fetch` |
| Tags | `tags` + `search`, `fetch` |
| Retiradas | `tagsretira` + `search`, `fetch`, `gettagreservadas/{idtag}` |

---

## 9. Integração com outros módulos

| Módulo | Ligação |
|--------|---------|
| **Evento** | Nenhuma FK ou controller referenciando `Tag` / `TagRetira` nos models de evento analisados |
| **NF** | Campo `idnf` no fillable de `Tag`; não documentado fluxo automático no `TagController` |
| **Pessoa** | Retiradas usam `idpessoa` (funcionário ou cliente conforme `funcionarioOuCliente` no create) |
| **Empresa** | Todas as entidades são por empresa + tenant |

---

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

| Arquivo | Função |
|---------|--------|
| `TagTipoController.php` | CRUD tipos + flags de parâmetros + bloqueio de inativação |
| `TagController.php` | CRUD tags + numeração implícita |
| `TagRetiraController.php` | CRUD retiradas/reservas + API de reservas |
| `Tag.php`, `TagTipo.php`, `TagRetira.php` | Models |
| `TagService.php`, `TagRetiraService.php` | Numeração e JSON de reservas |
| `TagComponent.php`, `CalendarTagComponent.php` | Dashboard |
| `TagtipoModal.php` | Modal de tipo |
| `dashboard/tags.blade.php` | Página do dashboard |

---

## 11. Inconsistências úteis para correção futura

- Rotas/nomes em `TagController::destroy` (`admin.tag.index`).
- IDs errados em partials de status nos `fetch` de `TagController` e `TagRetiraController`.
- `TagTipoController::store` redirect com ID após `create`.
- `TagRetiraController::store` variável `$tagRetira` no redirect após `create`.
- `TagComponent` status `'aberto'` / `'reservada'` vs valores reais em maiúsculas.
- `TagTipo` `criadopor` string (nome) vs relação `User` por id.
- `TagController::search` lógica AND entre `whereHas`.

---

*Documento baseado na leitura do código e migrations iniciais; migrações posteriores (`update_tags_table`, etc.) podem ter alterado colunas.*
