# Ações Internas — Arquitetura > Para devs. Explica como adicionar reações automáticas a eventos de OS por cliente. --- ## Problema que resolve O PostSchedule já dispara webhooks externos (ERPs, clientes). Precisávamos de uma camada equivalente para **ações internas** — lógica específica por cliente que roda após o mesmo evento, sem poluir o core do Servico. --- ## Localização no código ``` Api/Integracoes/ Core/ IAcaoInternaService.cs ← contrato AcaoInternaFactory.cs ← dispatcher Clientes/ SipolattiService.cs ← implementação da Sipolatti Erps/ MMS/ Models/ MmsModels.cs Services/ MmsHttpService.cs MmsWebhookServico.cs ``` --- ## Como funciona ``` Servico processa PostSchedule item 1. HTTP POST externo (webhook normal) — inalterado 2. AcaoInternaFactory.ProcessarAsync(item.Json) → deserializa WebHookJobs → SELECT ContratoSaasId FROM Pedido JOIN Saida WHERE Pedido.Id = payload.JobId → _servicos.TryGetValue(contratoSaasId) → IAcaoInternaService → servico.ExecutarAsync(payload, logger) ``` A chamada da factory é isolada em try/catch — falha interna **não afeta** o resultado do PostSchedule. --- ## Interface ```csharp public interface IAcaoInternaService { Task ExecutarAsync(WebHookJobs payload, TextWriter logger); } ``` O `payload` é o `WebHookJobs` já existente do PostSchedule. Campos mais usados: | Campo | Tipo | Descrição | |-------|------|-----------| | `JobId` | int | ID do Pedido | | `UltimoStatusId` | int | StatusCalculadoId atual | | `ProfissionalId` | int | ID do profissional da Saida | | `ParceiroId` | int | ID do parceiro | | `CodigoJob` | string | Código da OS | --- ## Adicionar nova integração por cliente **1. Criar o serviço do cliente em `Api/Integracoes/Clientes/`:** ```csharp public class NomeClienteService : IAcaoInternaService { public async Task ExecutarAsync(WebHookJobs payload, TextWriter logger) { if (payload.UltimoStatusId == 1700) // Cancelado { // lógica específica do cliente } } } ``` **2. Registrar no factory em `AcaoInternaFactory.cs`:** ```csharp private static readonly Dictionary _servicos = new Dictionary { { 1082, new SipolattiService() }, // Sipolatti { 9999, new NomeClienteService() }, // ← nova linha }; ``` Só isso. Zero mudança no Servico ou no core. --- ## Clientes configurados | ContratoSaasId | Cliente | Serviço | Ações | |---------------|---------|---------|-------| | 1082 | Sipolatti | `SipolattiService` | Cancelado (1700) → `DELETE /api/erp/cancelar-mms` se profissional = `mms@sipolatti.com.br` | --- ## ERP MMS Os serviços do ERP MMS ficam em `Api/Integracoes/Erps/MMS/`: - **`MmsWebhookServico`** — envia adesão, retorno improdutivo e cancelamento para a MMS - **`MmsHttpService`** — cliente HTTP puro: token OAuth2, POST adesão, DELETE cancelamento, GET ocorrências, GET capacity - **`MmsModels`** — modelos de request/response e payloads de webhook recebidos Namespace: `Api.Integracoes.Erps.MMS.Services` / `Api.Integracoes.Erps.MMS.Models` --- ## Endpoints WebHubDonc relacionados | Endpoint | Descrição | |----------|-----------| | `POST /api/erp/encaminhar-mms` | Envia OS para MMS (adesão normal ou retorno improdutivo se Saida.StatusId=2000) | | `DELETE /api/erp/cancelar-mms` | Cancela OS na MMS + registra PedidoStatus com resultado | | `POST /api/integracoes/mms/ocorrencia` | Recebe webhook de ocorrência da MMS → processa improdutivo | | `POST /api/integracoes/mms/checklist` | Recebe webhook de checklist da MMS (processamento pendente) |