# Seleção do fornecedor de integração por empresa interna — plano

## Problema

O Cegid é hoje o único destino de integração suportado, mas o código está escrito
como se fosse o único que alguma vez existirá: o formulário de **Empresas
internas** (`Companies.razor`) mostra sempre o cabeçalho "Cegid" e o botão
"Configurar Cegid" para qualquer empresa interna, tenha ou não essa integração
ativa. Não existe hoje nenhum campo que diga "esta empresa usa X" — a única
forma de saber é a existência (ou não) de uma linha em `CegidCompanyConnections`.

Isto passa a ser um problema à medida que se equaciona outro ERP/software de
faturação (ex.: Moloni, `https://www.moloni.pt/dev/endpoints/`). É preciso que
a configuração da empresa diga explicitamente qual o software de integração
(Nenhum / Cegid / Moloni / ...) e que a UI mostre apenas os campos relevantes.

## Âmbito da Fase 1 (este plano)

Confirmado com o utilizador: âmbito mínimo e de baixo risco.

- Adicionar à configuração da empresa interna um seletor **"Software de
  integração"** com as opções `Nenhum`, `Cegid`, `Moloni`.
- A secção Cegid do formulário só aparece quando o valor selecionado for
  `Cegid` — deixa de aparecer por omissão para empresas sem integração.
- `Moloni` fica registado como opção selecionável, mas sem integração
  funcional: ao escolher Moloni mostra-se uma nota "integração ainda não
  implementada", sem formulário de configuração.
- Não inclui: abstrair o motor de sincronização (`CegidCommit`,
  `CegidOperation`, `CegidSalesDocument`, `CegidReconciliationService`,
  `CegidSalesSyncService`, `FinancialWorkbookProjector`, etc.) para um
  provider genérico. Esse código permanece 100% específico do Cegid. Se um
  dia se avançar com a integração real do Moloni, esse desenho de
  abstração terá de ser feito nessa altura — este plano não o antecipa.

## Modelo de dados

Novo agregado, paralelo ao `CegidCompanyConnection` mas genérico e sem
dependências do Cegid:

`Sibyla.Domain/Companies/CompanyIntegrationSettings.cs`

```csharp
public enum IntegrationProvider
{
    None = 0,
    Cegid = 1,
    Moloni = 2
}

public sealed class CompanyIntegrationSettings
{
    public Guid Id { get; set; } = Guid.NewGuid();
    public Guid CompanyEntityId { get; set; }
    public IntegrationProvider Provider { get; set; } = IntegrationProvider.None;
    public long Version { get; set; } = 1;
    public DateTimeOffset UpdatedAt { get; set; }
    public string UpdatedBy { get; set; } = "system";

    public BusinessEntity CompanyEntity { get; set; } = null!;
}
```

- Índice único em `CompanyEntityId` (uma linha por empresa).
- Sem linha = `None` (não é necessário pré-criar linhas para todas as
  empresas).
- Campo `Version` para concorrência otimista, igual ao padrão já usado em
  `CegidCompanyConnection`.

### Migração e retrocompatibilidade

- Migração EF Core cria a tabela `CompanyIntegrationSettings`.
- Passo de *backfill* de dados na própria migração: para cada
  `CompanyEntityId` distinto em `CegidCompanyConnections`, inserir uma linha
  com `Provider = Cegid`. Isto garante que nenhuma empresa já configurada com
  Cegid perde a secção Cegid ao atualizar — o comportamento visível não muda
  para quem já tem Cegid ligado.
- Empresas sem linha em `CegidCompanyConnections` ficam sem linha em
  `CompanyIntegrationSettings`, logo tratadas como `None` — é precisamente o
  que corrige o problema reportado.

## Backend

- `ICompanyIntegrationSettingsService` (novo, em
  `Sibyla.Infrastructure/Companies/`): `GetAsync(companyId)`,
  `SetProviderAsync(companyId, provider, expectedVersion, actor,
  correlationId)`.
- Regra de negócio na alteração: se o valor atual for `Cegid` e existir uma
  `CegidCompanyConnection` com `Enabled = true`, bloquear a mudança para
  `None`/`Moloni` com um erro claro ("desative a ligação Cegid antes de
  mudar de fornecedor"). Evita desligar silenciosamente uma integração ativa
  ao trocar o seletor. Sem efeitos automáticos em cascata — mais simples de
  implementar e testar do que um auto-disable.
- Novo endpoint em `Sibyla.Api/Companies/` (mesmo padrão de
  `CompanyAccountEndpoints.cs`): `GET /api/admin/companies/{id}/integration-provider`
  e `PUT /api/admin/companies/{id}/integration-provider`.
- Nenhuma alteração aos serviços de sincronização/jobs do Cegid
  (`CegidSalesPollingHostedService`, `IntegrateDocumentJobHandler`, etc.):
  continuam a decidir se atuam sobre uma empresa apenas com base em existir
  uma `CegidCompanyConnection` testada e ativa — comportamento documentado em
  `docs/cegid-integration.md` e que não muda neste plano.

## UI (`Companies.razor`)

- Novo campo `<select>` "Software de integração" no `entity-form` principal,
  junto aos restantes campos da empresa (código, nome, país, NIF, estado).
- A secção `Cegid` (título "Cegid", botão "Configurar Cegid" e todo o bloco
  `showCegidEditor`) passa a estar dentro de
  `@if (integrationProvider == IntegrationProvider.Cegid) { ... }`.
- Quando `integrationProvider == IntegrationProvider.Moloni`: mostrar um
  aviso simples "Integração Moloni ainda não disponível" em vez de qualquer
  formulário.
- Quando `integrationProvider == IntegrationProvider.None`: não mostrar
  nenhuma secção de integração.
- Coluna "Cegid" da tabela de listagem passa a coluna "Integração":
  mostra o nome do fornecedor escolhido e, só quando for Cegid, o estado
  atual (Não configurado / Pronto a ativar / Ativo / Inativo) tal como hoje.
- `Save()` passa a gravar também `CompanyIntegrationSettings` quando o
  seletor for alterado, reaproveitando a mesma transação já usada para
  gravar a empresa e (opcionalmente) o Cegid.
- Mensagens de erro novas a mapear em `LocalizeError` para o código de
  conflito "não é possível mudar de fornecedor com uma ligação Cegid ativa".

## Passos de implementação sugeridos

1. Domínio: `IntegrationProvider` enum + `CompanyIntegrationSettings`.
2. Persistência: `IEntityTypeConfiguration`, registo no `SibylaDbContext`,
   migração EF Core com o passo de backfill.
3. Infraestrutura: `ICompanyIntegrationSettingsService` +
   implementação com a regra de bloqueio descrita acima.
4. API: endpoints GET/PUT em `Sibyla.Api/Companies/`.
5. UI: seletor, condicional em torno da secção Cegid, placeholder Moloni,
   coluna da tabela, mensagens de erro, textos PT/EN.
6. Testes (ver secção seguinte).
7. Atualizar `docs/cegid-integration.md` com uma nota a apontar para este
   novo seletor (a secção Cegid só aparece com o fornecedor certo
   selecionado).

## Testes a cobrir

- Empresa nova → fornecedor por omissão `None`, sem secção Cegid visível.
- Empresa existente com `CegidCompanyConnection` (antes da migração) →
  após a migração, fornecedor = `Cegid`, secção continua visível, nenhum
  dado perdido.
- Mudar de `None`/`Moloni` para `Cegid` → secção Cegid aparece vazia, fluxo
  de configuração igual ao atual.
- Tentar mudar de `Cegid` para outro valor com a ligação Cegid `Enabled` →
  bloqueado com mensagem clara.
- Tentar mudar de `Cegid` para outro valor com a ligação Cegid desativada
  (ou inexistente) → permitido, dados do Cegid preservados na base de dados
  (não apagados), apenas deixam de aparecer.
- Conflito de concorrência otimista no `PUT` do seletor (dois utilizadores a
  editar a mesma empresa).

## Em aberto / a validar com o utilizador antes de implementar

- Nome definitivo a mostrar no seletor para "Nenhum" (ex.: "Sem integração"
  vs "Nenhum").
- Se, no futuro, a lista de fornecedores crescer, considerar mover de enum
  fixo para uma tabela de referência — não necessário para 2–3 opções.
