# ClientFlow v3.3 — HTMX manual e operação Jasmin mais estável

Esta versão é incremental sobre a v3.2 e foca-se em remover o comportamento visual estranho causado pelo auto-refresh do cartão **Documentos Jasmin**.

## Alterações principais

### 1. Documentos Jasmin sem auto-refresh

Foi removido o polling HTMX automático do cartão de Documentos Jasmin.

Antes:

```html
hx-trigger="every 10s"
```

Agora:

- o cartão não se reconstrói sozinho;
- existe botão **Atualizar estado**;
- os botões **Criar orçamento** e **Converter em fatura** continuam a atualizar o cartão uma vez após o clique;
- o operador controla quando quer atualizar o estado.

Fluxo esperado:

```text
[Criar orçamento]
→ cria item na outbox
→ mostra feedback imediato
→ timer/worker processa
→ operador clica [Atualizar estado]
→ vê orçamento criado ou erro
```

### 2. Feedback visível após ações Jasmin

Os botões continuam a devolver mensagens visíveis no cartão:

- Pedido de orçamento enviado para a outbox Jasmin.
- Pedido de fatura enviado para a outbox Jasmin.
- Erros de validação antes de criar a outbox.

### 3. Outbox Jasmin visível na oportunidade

O cartão de Documentos Jasmin continua a mostrar as ações da outbox associadas à oportunidade:

- action type;
- estado;
- erro resumido;
- botão **Reprocessar** para itens pendentes/falhados.

### 4. Validação antes de criar orçamento

Mantém-se a validação preventiva:

- cliente associado;
- NIF válido;
- nome fiscal;
- morada/código postal/cidade quando o cliente ainda não existe no Jasmin;
- pelo menos uma linha de produto;
- todas as linhas com `jasmin_sales_item`;
- preço unitário maior que zero.

### 5. SKU/Odoo separado de artigo Jasmin

Mantém-se a regra introduzida na v3.1/v3.2:

```text
products.sku = código interno/Odoo
products.jasmin_sales_item = artigo Jasmin
opportunity_items.sku = código interno/Odoo
opportunity_items.jasmin_sales_item = artigo Jasmin usado no orçamento
```

A criação de orçamento usa `jasmin_sales_item`, não o SKU Odoo.

## Deploy

Aplicar como nas versões anteriores:

```bash
rsync -avz --delete \
  --exclude ".env" \
  --exclude ".venv/" \
  --exclude "venv/" \
  --exclude "__pycache__/" \
  --exclude ".git/" \
  --exclude "*.db" \
  --exclude "*.log" \
  --exclude "uploads/" \
  ./ plx@alarmsys:/mnt/ssd/home/plx/clientflow_backend/
```

Depois no remoto:

```bash
cd /mnt/ssd/home/plx/clientflow_backend
source .venv/bin/activate
python -m py_compile app/*.py scripts/*.py
sudo systemctl restart clientflow-api
```

## Nota operacional

O botão **Atualizar estado** não processa a outbox. Ele apenas recarrega o cartão.

Para processar automaticamente, manter ativo o timer systemd da outbox Jasmin:

```bash
systemctl list-timers | grep clientflow-outbox-jasmin
```

Ou processar manualmente:

```bash
JASMIN_OUTBOX_ENABLED=true \
OUTBOX_TARGET_SYSTEM=jasmin \
OUTBOX_DRY_RUN=false \
python scripts/process_outbox.py
```
