# ENG-1398 — Reconciliação de aprovação tardia de requisições

## Contexto

Ao criar uma requisição no Rex, o sistema a exporta para o Senior e executa uma sincronização imediata. O ajuste atual ignora retornos com `qtdApr = 0`, evitando a criação de uma saída que poderia ser classificada incorretamente como cancelada.

Esse ajuste deixou uma lacuna: quando o Senior aprova a requisição mais tarde, o sincronizador periódico pode receber o retorno aprovado, mas não consegue identificar a requisição local que o originou. O número externo `numEme` retornado na exportação não é preservado na requisição local.

## Regra de negócio aprovada

- Se `qtdApr = 0`, a requisição local permanece pendente, mesmo que exista quantidade cancelada no retorno do Senior.
- Nessa condição, não são criados `stock_ios`, `stock_io_products` ou vínculos de itens.
- O Rex não cancela automaticamente a requisição a partir das quantidades retornadas pelo Senior.
- Uma saída só é criada ou vinculada quando uma sincronização posterior retornar `qtdApr > 0`.

## Desenho recomendado

### Correlação de integração

Adicionar a relação polimórfica `integration()` à entidade `Request`. Depois que `SeniorRequestExport` retornar o `numEme`, `RequestStoreService` gravará uma integração da requisição com, no mínimo, `request_number`, `company_code` e `branch_code`.

Esses atributos pertencem ao Senior e devem permanecer em `integrations.parameters`, sem criar colunas específicas do ERP em `requests`.

### Reconciliação no sincronizador

`SeniorSyncRequestsJob` resolverá uma requisição local pela integração que contém o `request_number` retornado pelo Senior quando não recebeu uma requisição diretamente no construtor.

Para cada item retornado:

1. Com `qtdApr = 0`, preservar a requisição e seus itens locais como pendentes e registrar que a aprovação está aguardada.
2. Com `qtdApr > 0`, criar ou atualizar a saída e seus produtos, vincular a requisição a `stock_io_id` e vincular os itens locais aos respectivos `stock_io_products`.
3. Para uma requisição local identificada pelo sincronizador periódico, usar o motivo `REQUEST`; o motivo `SYNCED_REQUEST` permanece exclusivo de retornos do Senior que não possuem uma requisição local correspondente.

O vínculo deverá ser idempotente: execuções repetidas não podem criar saídas, produtos ou ligações duplicadas, nem substituir alterações locais mais recentes já protegidas pelo mecanismo de sincronização.

### Observabilidade e recuperação

O fluxo deve registrar nos logs de integração quando uma requisição local estiver aguardando aprovação e quando for reconciliada. Requisições criadas antes desta mudança não têm o identificador externo persistido; a recuperação delas exige associação manual ao `numEme` conhecido e uma nova sincronização.

## Testes de aceite

1. Criar requisição local com `qtdApr = 0`: persistir a correlação externa, manter requisição e itens pendentes e não criar saída.
2. Executar sincronização posterior com `qtdApr > 0`: criar exatamente uma saída local, ligar `request.stock_io_id` e os `request_items` aos produtos da saída.
3. Reexecutar a sincronização aprovada: não duplicar registros nem modificar estado local protegido.
4. Receber `qtdApr = 0` com quantidade cancelada: manter a requisição pendente, sem cancelamento automático.
5. Importar uma requisição existente apenas no Senior: manter o comportamento atual de saída `SYNCED_REQUEST`, sem criar associação a uma requisição local.

## Arquivos previstos

- `app/Models/Request/Request.php`
- `Domain/Request/Services/RequestStoreService.php`
- `app/Jobs/Senior/SeniorSyncRequestsJob.php`
- `tests/Unit/Request/BackfillOutputSeniorSyncRequestsJobTest.php`
- testes de feature de criação de requisição, se necessários para cobrir a persistência da correlação.
