diff --git a/README.md b/README.md index 0b00914..cf7d1c8 100644 --- a/README.md +++ b/README.md @@ -27,8 +27,18 @@ No Windows, confirme que o Java está disponível no `PATH` e execute | `GET` | `/ordens?cliente=nome&page=0&size=20` | Filtra ordens pelo cliente e mantém a paginação | | `GET` | `/ordens/{id}` | Consulta uma ordem pelo ID | | `PUT` | `/ordens/{id}` | Atualiza uma ordem existente | +| `PATCH` | `/ordens/{id}/status` | Atualiza o status da ordem | | `DELETE` | `/ordens/{id}` | Exclui uma ordem existente | +Os status disponíveis são `ABERTA`, `EM_ANDAMENTO`, `CONCLUIDA` e +`CANCELADA`. Para atualizar, envie por exemplo: + +```json +{ + "status": "CONCLUIDA" +} +``` + ## Respostas de erro Erros de validação retornam `400 Bad Request` no formato Problem Details, diff --git a/src/main/java/com/exemplo/ordem_servico/controller/OrdemServicoController.java b/src/main/java/com/exemplo/ordem_servico/controller/OrdemServicoController.java index 5a7af6b..6b85131 100644 --- a/src/main/java/com/exemplo/ordem_servico/controller/OrdemServicoController.java +++ b/src/main/java/com/exemplo/ordem_servico/controller/OrdemServicoController.java @@ -7,6 +7,7 @@ import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -15,6 +16,7 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; +import com.exemplo.ordem_servico.dto.AtualizarStatusRequest; import com.exemplo.ordem_servico.model.OrdemServico; import com.exemplo.ordem_servico.service.OrdemServicoService; @@ -59,4 +61,11 @@ public OrdemServico atualizar( @Valid @RequestBody OrdemServico ordem) { return service.atualizar(id, ordem); } + + @PatchMapping("/{id}/status") + public OrdemServico atualizarStatus( + @PathVariable Long id, + @Valid @RequestBody AtualizarStatusRequest requisicao) { + return service.atualizarStatus(id, requisicao.status()); + } } diff --git a/src/main/java/com/exemplo/ordem_servico/dto/AtualizarStatusRequest.java b/src/main/java/com/exemplo/ordem_servico/dto/AtualizarStatusRequest.java new file mode 100644 index 0000000..efbebb8 --- /dev/null +++ b/src/main/java/com/exemplo/ordem_servico/dto/AtualizarStatusRequest.java @@ -0,0 +1,10 @@ +package com.exemplo.ordem_servico.dto; + +import com.exemplo.ordem_servico.model.StatusOrdemServico; + +import jakarta.validation.constraints.NotNull; + +public record AtualizarStatusRequest( + @NotNull(message = "O status é obrigatório") + StatusOrdemServico status) { +} diff --git a/src/main/java/com/exemplo/ordem_servico/model/OrdemServico.java b/src/main/java/com/exemplo/ordem_servico/model/OrdemServico.java index 9fcc5ef..1d89cd5 100644 --- a/src/main/java/com/exemplo/ordem_servico/model/OrdemServico.java +++ b/src/main/java/com/exemplo/ordem_servico/model/OrdemServico.java @@ -4,10 +4,13 @@ import java.math.RoundingMode; import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Positive; import jakarta.validation.constraints.PositiveOrZero; import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; @@ -38,6 +41,11 @@ public class OrdemServico { @PositiveOrZero(message = "O custo dos materiais não pode ser negativo") @Column(precision = 12, scale = 2) private BigDecimal custoMateriais; + + @NotNull(message = "O status é obrigatório") + @Enumerated(EnumType.STRING) + @Column(length = 20) + private StatusOrdemServico status = StatusOrdemServico.ABERTA; public Long getId() { @@ -83,6 +91,14 @@ public void setCustoMateriais(BigDecimal custoMateriais) { this.custoMateriais = custoMateriais; } + public StatusOrdemServico getStatus() { + return status == null ? StatusOrdemServico.ABERTA : status; + } + + public void setStatus(StatusOrdemServico status) { + this.status = status; + } + public BigDecimal getValorMaoDeObra() { return horasServico.multiply(VALOR_HORA) .setScale(ESCALA_MONETARIA, RoundingMode.HALF_UP); diff --git a/src/main/java/com/exemplo/ordem_servico/model/StatusOrdemServico.java b/src/main/java/com/exemplo/ordem_servico/model/StatusOrdemServico.java new file mode 100644 index 0000000..4993491 --- /dev/null +++ b/src/main/java/com/exemplo/ordem_servico/model/StatusOrdemServico.java @@ -0,0 +1,8 @@ +package com.exemplo.ordem_servico.model; + +public enum StatusOrdemServico { + ABERTA, + EM_ANDAMENTO, + CONCLUIDA, + CANCELADA +} diff --git a/src/main/java/com/exemplo/ordem_servico/service/OrdemServicoService.java b/src/main/java/com/exemplo/ordem_servico/service/OrdemServicoService.java index 4d4a763..dc50964 100644 --- a/src/main/java/com/exemplo/ordem_servico/service/OrdemServicoService.java +++ b/src/main/java/com/exemplo/ordem_servico/service/OrdemServicoService.java @@ -6,6 +6,7 @@ import com.exemplo.ordem_servico.exception.OrdemServicoNaoEncontradaException; import com.exemplo.ordem_servico.model.OrdemServico; +import com.exemplo.ordem_servico.model.StatusOrdemServico; import com.exemplo.ordem_servico.repository.OrdemServicoRepository; @Service @@ -49,4 +50,10 @@ public OrdemServico atualizar(Long id, OrdemServico novosDados) { ordem.setCustoMateriais(novosDados.getCustoMateriais()); return repository.save(ordem); } + + public OrdemServico atualizarStatus(Long id, StatusOrdemServico status) { + OrdemServico ordem = buscarPorId(id); + ordem.setStatus(status); + return repository.save(ordem); + } } diff --git a/src/test/java/com/exemplo/ordem_servico/model/OrdemServicoTests.java b/src/test/java/com/exemplo/ordem_servico/model/OrdemServicoTests.java index 1cf1cc4..50e1a48 100644 --- a/src/test/java/com/exemplo/ordem_servico/model/OrdemServicoTests.java +++ b/src/test/java/com/exemplo/ordem_servico/model/OrdemServicoTests.java @@ -8,6 +8,13 @@ class OrdemServicoTests { + @Test + void deveIniciarOrdemComStatusAberta() { + OrdemServico ordem = new OrdemServico(); + + assertEquals(StatusOrdemServico.ABERTA, ordem.getStatus()); + } + @Test void deveCalcularValoresMonetariosComPrecisaoDecimal() { OrdemServico ordem = new OrdemServico(); diff --git a/src/test/java/com/exemplo/ordem_servico/service/OrdemServicoServiceTests.java b/src/test/java/com/exemplo/ordem_servico/service/OrdemServicoServiceTests.java index f08dcae..60d00bb 100644 --- a/src/test/java/com/exemplo/ordem_servico/service/OrdemServicoServiceTests.java +++ b/src/test/java/com/exemplo/ordem_servico/service/OrdemServicoServiceTests.java @@ -20,6 +20,7 @@ import com.exemplo.ordem_servico.exception.OrdemServicoNaoEncontradaException; import com.exemplo.ordem_servico.model.OrdemServico; +import com.exemplo.ordem_servico.model.StatusOrdemServico; import com.exemplo.ordem_servico.repository.OrdemServicoRepository; @ExtendWith(MockitoExtension.class) @@ -104,6 +105,21 @@ void deveRetornarNaoEncontradoAoAtualizarOrdemInexistente() { () -> service.atualizar(99L, novosDados)); } + @Test + void deveAtualizarStatusDaOrdem() { + OrdemServico ordem = novaOrdem("Cliente", "Servico", "1", "0"); + ordem.setId(1L); + when(repository.findById(1L)).thenReturn(Optional.of(ordem)); + when(repository.save(ordem)).thenReturn(ordem); + + OrdemServico atualizada = service.atualizarStatus( + 1L, + StatusOrdemServico.CONCLUIDA); + + assertEquals(StatusOrdemServico.CONCLUIDA, atualizada.getStatus()); + verify(repository).save(ordem); + } + private OrdemServico novaOrdem( String cliente, String descricao,