> ⚠️ **Aviso:** Este documento tem caráter apenas de apoio e referência técnica. As informações aqui descritas — incluindo entradas, saídas, estruturas de dados, fluxos e validações — não são definitivas e podem ser alteradas conforme evolução do entendimento do negócio, ajustes da arquitetura, revisões de API ou decisões de implementação. # Documento de Design: PreAtendimentoEtapa ## Visão Geral Este documento descreve o design para implementação da funcionalidade `PreAtendimentoEtapa`, que rastreia checkpoints de progresso para um `PreAtendimento`. **Decisão de Design Principal:** O modelo de domínio `PreAtendimentoEtapa` contém `PreAtendimento` dentro dele. Esta abordagem evita modificar a classe `PreAtendimento` existente. ## Tabela do Banco de Dados ```sql PreAtendimentoEtapa { Long id (PK) Long PreAtendimentoId (FK) String Etapa (PATIENT, MEDICAL_REQUEST, OVERVIEW) } ``` ## Link Diagrama completo https://drive.google.com/file/d/1sCmmch8ntIbNZ7In2FHymMVKulHrxgbg/view?usp=sharing --- ## Componentes da Implementação ### 1. Enum de Checkpoint **Arquivo:** `core/domain/model/EtapaEnum.java` Enum que representa os possíveis checkpoints de progresso do pré-atendimento: ```java package br.com.shift.preatendimento.core.domain.model; import lombok.Getter; import lombok.RequiredArgsConstructor; @Getter @RequiredArgsConstructor public enum EtapaEnum { PATIENT, MEDICAL_REQUEST, OVERVIEW } ``` --- ### 2. Modelo de Domínio **Arquivo:** `core/domain/model/PreAtendimentoEtapa.java` O `PreAtendimentoEtapa` contém `PreAtendimento` dentro: ```java package br.com.shift.preatendimento.core.domain.model; @Data @Builder public class PreAtendimentoEtapa { Long id; EtapaEnum etapa; // PreAtendimento está contido dentro de PreAtendimentoEtapa PreAtendimento preAtendimento; } ``` --- ### 3. Camada de Entidade **Arquivo:** `core/adapter/out/db/entity/PreAtendimentoEtapaEntity.java` ```java package br.com.shift.preatendimento.core.adapter.out.db.entity; @Getter @Setter @Builder @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(onlyExplicitlyIncluded = true) @Entity(name = "PreAtendimentoEtapa") @Table(schema = "preatendimento", name = "PreAtendimentoEtapa") public class PreAtendimentoEtapaEntity { @Id @Column(name = "ID") @EqualsAndHashCode.Include @GeneratedValue(strategy = GenerationType.UUID) private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "PreAtendimentoId", foreignKey = @ForeignKey(name = "FkPreAtendimentoId")) private PreAtendimentoEntity preAtendimento; @Column(name = "Checkpoint") private Integer checkpoint; public static PreAtendimentoEtapaEntity fromDomain( PreAtendimentoEtapa progresso, PreAtendimentoEntity preAtendimentoEntity) { return PreAtendimentoEtapaEntity.builder() .id(progresso.getId()) .preAtendimento(preAtendimentoEntity) .checkpoint(progresso.getCheckpoint() != null ? progresso.getCheckpoint().getCodigo() : null) .build(); } public PreAtendimentoEtapa toDomain() { return PreAtendimentoEtapa.builder() .id(getId()) .checkpoint(getCheckpoint() != null ? CheckpointEtapa.fromCodigo(getCheckpoint()) : null) .preAtendimento(getPreAtendimento() != null ? getPreAtendimento().toDomain() : null) .build(); } } ``` --- ### 4. Repository Port (Porta de Saída) **Arquivo:** `core/application/port/out/PreAtendimentoEtapaRepositoryPort.java` Criar uma nova porta de repositório para `PreAtendimentoEtapa`: ```java package br.com.shift.preatendimento.core.application.port.out; import br.com.shift.preatendimento.core.domain.model.PreAtendimentoEtapa; import java.util.Optional; public interface PreAtendimentoEtapaRepositoryPort { // não considerar esse salvar, caso nao esteja na parte de salvar de fato o passo void salvar(PreAtendimentoEtapa progresso); Optional<PreAtendimentoEtapa> buscarPorPreAtendimentoId(Long preAtendimentoId); } ``` --- ### 5. Implementação do Adapter de Banco de Dados **Arquivo:** `core/adapter/out/db/PreAtendimentoEtapaDbAdapter.java` ```java package br.com.shift.preatendimento.core.adapter.out.db; @ApplicationScoped public class PreAtendimentoEtapaDbAdapter implements PreAtendimentoEtapaRepositoryPort, PanacheRepositoryBase<PreAtendimentoEtapaEntity, UUID> { @WithSpan @Override @Transactional public void salvar(PreAtendimentoEtapa progresso) { PreAtendimentoEtapaEntity entity = PreAtendimentoEtapaEntity.builder() .id(progresso.getId()) .checkpoint(progresso.getCheckpoint() != null ? progresso.getCheckpoint().getCodigo() : null) .build(); persist(entity); } @WithSpan @Override public Optional<PreAtendimentoEtapa> buscarPorPreAtendimentoId(Long preAtendimentoId) { // alguma query... } } ``` --- ### 6. Use Case Port (Porta de Entrada) **Arquivo:** `core/application/port/in/BuscarPreAtendimentoEtapaUseCase.java` ```java package br.com.shift.preatendimento.core.application.port.in; import br.com.shift.preatendimento.core.domain.model.PreAtendimentoEtapa; public interface BuscarPreAtendimentoEtapaUseCase { PreAtendimentoEtapa buscarPorPreAtendimentoId(Long preAtendimentoId); } ``` --- ### 7. Implementação do Service **Arquivo:** `core/application/service/PreAtendimentoEtapaService.java` Criar um novo service para `PreAtendimentoEtapa`: ```java package br.com.shift.preatendimento.core.application.service; @Slf4j @ApplicationScoped public class PreAtendimentoEtapaService implements BuscarPreAtendimentoEtapaUseCase { @Inject PreAtendimentoEtapaRepositoryPort preAtendimentoEtapaRepositoryPort; @Override @WithSpan public PreAtendimentoEtapa buscarPorPreAtendimentoId(Long preAtendimentoId) { return preAtendimentoEtapaRepositoryPort .buscarPorPreAtendimentoId(preAtendimentoId) .orElseThrow(() -> { log.error("Etapa não encontrado para o pré-atendimento id: {}", preAtendimentoId); return new PreAtendimentoEtapaInexistenteException(); }); } } ``` --- ### 8. Exceção (Opcional) **Arquivo:** `core/domain/exception/PreAtendimentoEtapaInexistenteException.java` ```java package br.com.shift.preatendimento.core.domain.exception; public class PreAtendimentoEtapaInexistenteException extends RuntimeException { public PreAtendimentoEtapaInexistenteException() { super("Etapa do pré-atendimento não encontrado"); } } ``` --- ### 9. REST Resource (Opcional) **Arquivo:** `core/adapter/in/rest/resource/PreAtendimentoEtapaResource.java` ```java package br.com.shift.preatendimento.core.adapter.in.rest.resource; @Path("steps") public class PreAtendimentoEtapaResource { @Inject BuscarPreAtendimentoEtapaUseCase buscarPreAtendimentoEtapaUseCase; @GET @Path("/pre-services/{preAtendimentoId}") @Produces(MediaType.APPLICATION_JSON) public Response buscarPorPreAtendimentoId(@PathParam("preAtendimentoId") Long preAtendimentoId) { PreAtendimentoEtapa progresso = buscarPreAtendimentoEtapaUseCase.buscarPorPreAtendimentoId(preAtendimentoId); return Response.ok(progresso).build(); } } ``` --- ## Auditoria Implementação manual de auditoria para registrar alterações no `PreAtendimentoEtapa`. ### Tabelas ```sql PreAtendimentoEtapaAuditoria { Long ID (PK) Long REV (FK -> Revisao) Long PreAtendimentoId (FK) String Checkpoint (PATIENT, MEDICAL_REQUESTS, OVERVIEW) String TipoOperacao (INSERT, UPDATE, DELETE) } Revisao { Long ID (PK) DateTime DataHora String Usuario } ``` ### Enum **Arquivo:** `core/domain/model/TipoOperacaoAuditoria.java` ```java public enum TipoOperacaoAuditoria { INSERT, UPDATE, DELETE } ``` ### Modelo de Domínio **Arquivo:** `core/domain/model/PreAtendimentoEtapaAuditoria.java` ```java @Data @Builder public class PreAtendimentoEtapaAuditoria { private Long id; private Long preAtendimentoEtapaId; private Long preAtendimentoId; private CheckpointEtapa checkpoint; private TipoOperacaoAuditoria tipoOperacao; private Revisao revisao; } ``` **Arquivo:** `core/domain/model/Revisao.java` ```java @Data @Builder public class Revisao { private Long id; private LocalDateTime dataHora; private String usuario; } ``` ### Entidades **Arquivo:** `core/adapter/out/db/entity/PreAtendimentoEtapaAuditoriaEntity.java` ```java @Entity @Table(schema = "preatendimento", name = "PreAtendimentoEtapaAuditoria") public class PreAtendimentoEtapaAuditoriaEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "REV") private RevisaoEntity revisao; @Column(name = "PreAtendimentoId") private Long preAtendimentoId; @Column(name = "Checkpoint") private Integer checkpoint; @Enumerated(EnumType.STRING) @Column(name = "TipoOperacao") private TipoOperacaoAuditoria tipoOperacao; // fromDomain e toDomain... } ``` **Arquivo:** `core/adapter/out/db/entity/RevisaoEntity.java` ```java @Entity @Table(schema = "preatendimento", name = "Revisao") public class RevisaoEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "DataHora") private LocalDateTime dataHora; @Column(name = "Usuario") private String usuario; // fromDomain e toDomain... } ``` ### Port e Adapter **Arquivo:** `core/application/port/out/PreAtendimentoEtapaAuditoriaRepositoryPort.java` ```java public interface PreAtendimentoEtapaAuditoriaRepositoryPort { void registrar(PreAtendimentoEtapaAuditoria auditoria); List<PreAtendimentoEtapaAuditoria> buscarPorPreAtendimentoId(Long preAtendimentoId); } ``` **Arquivo:** `core/adapter/out/db/PreAtendimentoEtapaAuditoriaDbAdapter.java` e `RevisaoDbAdapter.java` > Implementações seguem o mesmo padrão dos demais adapters do projeto. --- ## Exemplo de Resposta Ao chamar `GET /pre-service-progress/pre-service/{preAtendimentoId}`, a resposta será: ```json { "step": "PATIENT", "preAtendimento": { "id": 1, "idExterno": "abc-123", "status": "UNDER_REVIEW", "pacienteId": 100, "telefoneOrigem": "11999999999", "telefoneLaboratorio": "1133333333", "dataCriacao": "2025-12-17T10:00:00", "dataAtualizacao": "2025-12-17T10:30:00", "visualizado": true, "codigo": "PA001" } } ``` --- ## Resumo dos Arquivos | Camada | Arquivo | Descrição | |--------|---------|-----------| | Domain | `CheckpointEtapa.java` | Enum dos checkpoints de progresso | | Domain | `TipoOperacaoAuditoria.java` | Enum dos tipos de operação de auditoria | | Domain | `PreAtendimentoEtapa.java` | Modelo de domínio do progresso | | Domain | `PreAtendimentoEtapaAuditoria.java` | Modelo de domínio da auditoria | | Domain | `Revisao.java` | Modelo de domínio da revisão | | Domain | `PreAtendimentoEtapaInexistenteException.java` | Exceção customizada | | Entity | `PreAtendimentoEtapaEntity.java` | Entidade JPA do progresso | | Entity | `PreAtendimentoEtapaAuditoriaEntity.java` | Entidade JPA da auditoria | | Entity | `RevisaoEntity.java` | Entidade JPA da revisão | | Port Out | `PreAtendimentoEtapaRepositoryPort.java` | Interface do repositório de progresso | | Port Out | `PreAtendimentoEtapaAuditoriaRepositoryPort.java` | Interface do repositório de auditoria | | Adapter Out | `PreAtendimentoEtapaDbAdapter.java` | Implementação do repositório de progresso | | Adapter Out | `PreAtendimentoEtapaAuditoriaDbAdapter.java` | Implementação do repositório de auditoria | | Adapter Out | `RevisaoDbAdapter.java` | Implementação do repositório de revisão | | Port In | `BuscarPreAtendimentoEtapaUseCase.java` | Interface do caso de uso | | Service | `PreAtendimentoEtapaService.java` | Implementação do caso de uso | | Adapter In | `PreAtendimentoEtapaResource.java` | Endpoint REST |