diff --git a/pom.xml b/pom.xml index acd7cc0eb..60441ac4c 100644 --- a/pom.xml +++ b/pom.xml @@ -28,6 +28,7 @@ 1.46 2.7 1.5.2 + 6.14.0 1.33.0 8.5.0 2.1.4 @@ -169,6 +170,11 @@ gson ${google-gson.version} + + org.javers + javers-spring-boot-starter-sql + ${javers.version} + diff --git a/src/main/java/sic/controller/PedidoController.java b/src/main/java/sic/controller/PedidoController.java index a0d9b771e..44365b399 100644 --- a/src/main/java/sic/controller/PedidoController.java +++ b/src/main/java/sic/controller/PedidoController.java @@ -3,6 +3,7 @@ import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; +import java.util.Map; import io.jsonwebtoken.Claims; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; @@ -14,23 +15,21 @@ import sic.aspect.AccesoRolesPermitidos; import sic.modelo.*; import sic.modelo.criteria.BusquedaPedidoCriteria; -import sic.modelo.dto.NuevosResultadosComprobanteDTO; +import sic.modelo.dto.*; import sic.modelo.Resultados; -import sic.modelo.dto.PedidoDTO; -import sic.modelo.dto.NuevoRenglonPedidoDTO; import sic.service.*; @RestController @RequestMapping("/api/v1") public class PedidoController { - private final IPedidoService pedidoService; - private final IUsuarioService usuarioService; - private final ISucursalService sucursalService; - private final IClienteService clienteService; - private final IReciboService reciboService; - private final IAuthService authService; - private static final String ID_USUARIO = "idUsuario"; + private final IPedidoService pedidoService; + private final IUsuarioService usuarioService; + private final ISucursalService sucursalService; + private final IClienteService clienteService; + private final IReciboService reciboService; + private final IAuthService authService; + private static final String ID_USUARIO = "idUsuario"; @Autowired public PedidoController( @@ -48,21 +47,20 @@ public PedidoController( this.authService = authService; } - @GetMapping("/pedidos/{idPedido}") - public Pedido getPedidoPorId(@PathVariable long idPedido) { - return pedidoService.getPedidoNoEliminadoPorId(idPedido); - } + @GetMapping("/pedidos/{idPedido}") + public Pedido getPedidoPorId(@PathVariable long idPedido) { + return pedidoService.getPedidoNoEliminadoPorId(idPedido); + } - @GetMapping("/pedidos/{idPedido}/renglones") - public List getRenglonesDelPedido(@PathVariable long idPedido, - @RequestParam(required = false) boolean clonar) { - return pedidoService.getRenglonesDelPedidoOrdenadorPorIdRenglonSegunEstadoOrClonar(idPedido, clonar); - } + @GetMapping("/pedidos/{idPedido}/renglones") + public List getRenglonesDelPedido(@PathVariable long idPedido, + @RequestParam(required = false) boolean clonar) { + return pedidoService.getRenglonesDelPedidoOrdenadorPorIdRenglonSegunEstadoOrClonar(idPedido, clonar); + } @PostMapping("/pedidos/renglones/clientes/{idCliente}") @AccesoRolesPermitidos({Rol.ADMINISTRADOR, Rol.ENCARGADO, Rol.VENDEDOR, Rol.VIAJANTE}) - public List calcularRenglonesPedido( - @RequestBody List nuevosRenglonesPedidoDTO) { + public List calcularRenglonesPedido(@RequestBody List nuevosRenglonesPedidoDTO) { return pedidoService.calcularRenglonesPedido( pedidoService.getArrayDeIdProducto(nuevosRenglonesPedidoDTO), pedidoService.getArrayDeCantidadesProducto(nuevosRenglonesPedidoDTO)); @@ -79,14 +77,10 @@ public void actualizar(@RequestBody PedidoDTO pedidoDTO) { pedido.setRecargoPorcentaje(pedidoDTO.getRecargoPorcentaje()); if (pedidoDTO.getDescuentoPorcentaje() != null) pedido.setDescuentoPorcentaje(pedidoDTO.getDescuentoPorcentaje()); - List renglonesAnteriores = new ArrayList<>(pedido.getRenglones()); - pedido.getRenglones().clear(); - pedido - .getRenglones() - .addAll( - pedidoService.calcularRenglonesPedido( - pedidoService.getArrayDeIdProducto(pedidoDTO.getRenglones()), - pedidoService.getArrayDeCantidadesProducto(pedidoDTO.getRenglones()))); + List renglonesAnteriores = new ArrayList<>(); + pedido.getRenglones().forEach(renglonPedido -> renglonesAnteriores.add(CantidadProductoDTO.builder() + .idProductoItem(renglonPedido.getIdProductoItem()).cantidad(renglonPedido.getCantidad()).build())); + pedido.setRenglones(this.pedidoService.actualizarRenglonesPedido(pedido.getRenglones(), pedidoDTO.getRenglones())); pedidoService.actualizar( pedido, renglonesAnteriores, @@ -144,18 +138,30 @@ public void cancelar(@PathVariable long idPedido) { pedidoService.cancelar(pedidoService.getPedidoNoEliminadoPorId(idPedido)); } - @GetMapping("/pedidos/{idPedido}/reporte") - public ResponseEntity getReportePedido(@PathVariable long idPedido) { - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_PDF); - headers.add("content-disposition", "inline; filename=Pedido.pdf"); - headers.setCacheControl("must-revalidate, post-check=0, pre-check=0"); - byte[] reportePDF = pedidoService.getReportePedido(idPedido); - return new ResponseEntity<>(reportePDF, headers, HttpStatus.OK); - } + @GetMapping("/pedidos/{idPedido}/reporte") + public ResponseEntity getReportePedido(@PathVariable long idPedido) { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_PDF); + headers.add("content-disposition", "inline; filename=Pedido.pdf"); + headers.setCacheControl("must-revalidate, post-check=0, pre-check=0"); + byte[] reportePDF = pedidoService.getReportePedido(idPedido); + return new ResponseEntity<>(reportePDF, headers, HttpStatus.OK); + } @PostMapping("/pedidos/calculo-pedido") public Resultados calcularResultadosPedido(@RequestBody NuevosResultadosComprobanteDTO nuevosResultadosComprobanteDTO) { return pedidoService.calcularResultadosPedido(nuevosResultadosComprobanteDTO); } + + @GetMapping("/pedidos/{idPedido}/cambios") + @AccesoRolesPermitidos({Rol.ADMINISTRADOR, Rol.ENCARGADO}) + public List getCambios(@PathVariable long idPedido) { + return pedidoService.getCambiosPedido(idPedido); + } + + @GetMapping("/pedidos/{idPedido}/renglones/cambios") + @AccesoRolesPermitidos({Rol.ADMINISTRADOR, Rol.ENCARGADO}) + public List getCambiosRenglones(@PathVariable long idPedido) { + return pedidoService.getCambiosRenglonesPedido(idPedido); + } } diff --git a/src/main/java/sic/interceptor/JwtInterceptor.java b/src/main/java/sic/interceptor/JwtInterceptor.java index a52eb5c36..d1c5fb475 100644 --- a/src/main/java/sic/interceptor/JwtInterceptor.java +++ b/src/main/java/sic/interceptor/JwtInterceptor.java @@ -29,6 +29,7 @@ public boolean preHandle( } long idUsuario = authService.getClaimsDelToken(authorizationHeader).get("idUsuario", Long.class); + authService.setActiveUserId(authorizationHeader); if (!usuarioService.esUsuarioHabilitado(idUsuario)) { throw new UnauthorizedException( messageSource.getMessage("mensaje_usuario_no_habilitado", null, Locale.getDefault())); diff --git a/src/main/java/sic/modelo/dto/CambioDTO.java b/src/main/java/sic/modelo/dto/CambioDTO.java new file mode 100644 index 000000000..5dba9d8a7 --- /dev/null +++ b/src/main/java/sic/modelo/dto/CambioDTO.java @@ -0,0 +1,21 @@ +package sic.modelo.dto; + + +import com.fasterxml.jackson.annotation.JsonView; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import sic.controller.Views; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@JsonView(Views.Encargado.class) +public class CambioDTO { + + private String atributo; + private String valorAnterior; + private String valorSiguiente; +} diff --git a/src/main/java/sic/modelo/dto/NuevoRenglonPedidoDTO.java b/src/main/java/sic/modelo/dto/CantidadProductoDTO.java similarity index 88% rename from src/main/java/sic/modelo/dto/NuevoRenglonPedidoDTO.java rename to src/main/java/sic/modelo/dto/CantidadProductoDTO.java index 57ef2841f..442ad3836 100644 --- a/src/main/java/sic/modelo/dto/NuevoRenglonPedidoDTO.java +++ b/src/main/java/sic/modelo/dto/CantidadProductoDTO.java @@ -11,7 +11,7 @@ @AllArgsConstructor @NoArgsConstructor @Builder -public class NuevoRenglonPedidoDTO { +public class CantidadProductoDTO { private long idProductoItem; private BigDecimal cantidad; diff --git a/src/main/java/sic/modelo/dto/CommitDTO.java b/src/main/java/sic/modelo/dto/CommitDTO.java new file mode 100644 index 000000000..aa5a67ab6 --- /dev/null +++ b/src/main/java/sic/modelo/dto/CommitDTO.java @@ -0,0 +1,27 @@ +package sic.modelo.dto; + +import com.fasterxml.jackson.annotation.JsonView; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import sic.controller.Views; + +import java.time.LocalDateTime; +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@JsonView(Views.Encargado.class) +public class CommitDTO { + + private String idCommit; + private String idCommitRelacionado; + private LocalDateTime fecha; + private String usuario; + private String tipoDeOperacion; + private List cambios; + +} diff --git a/src/main/java/sic/modelo/dto/PedidoDTO.java b/src/main/java/sic/modelo/dto/PedidoDTO.java index 844380a90..0400fcb38 100644 --- a/src/main/java/sic/modelo/dto/PedidoDTO.java +++ b/src/main/java/sic/modelo/dto/PedidoDTO.java @@ -20,7 +20,7 @@ public class PedidoDTO { private String observaciones; private Long idCliente; private TipoDeEnvio tipoDeEnvio; - private List renglones; + private List renglones; private Long[] idsFormaDePago; private BigDecimal[] montos; private BigDecimal recargoPorcentaje; diff --git a/src/main/java/sic/service/IAuditService.java b/src/main/java/sic/service/IAuditService.java new file mode 100644 index 000000000..3f0d5cef4 --- /dev/null +++ b/src/main/java/sic/service/IAuditService.java @@ -0,0 +1,15 @@ +package sic.service; + +import sic.modelo.dto.CommitDTO; +import java.util.List; +import java.util.Map; + +public interface IAuditService { + + String auditar(String idUsuario, Object objeto, Map propiedades); + + List getCambios(T objeto); + + List getCambios(String idCommit); + +} diff --git a/src/main/java/sic/service/IAuthService.java b/src/main/java/sic/service/IAuthService.java index 58e4102ef..c98e31345 100644 --- a/src/main/java/sic/service/IAuthService.java +++ b/src/main/java/sic/service/IAuthService.java @@ -2,6 +2,7 @@ import io.jsonwebtoken.Claims; import sic.modelo.Rol; + import java.util.List; public interface IAuthService { @@ -19,4 +20,8 @@ public interface IAuthService { void validarRecaptcha(String recaptcha); void excluirTokenAcceso(String authorizationHeader); + + void setActiveUserId(String token); + + long getActiveUserId(); } diff --git a/src/main/java/sic/service/IPedidoService.java b/src/main/java/sic/service/IPedidoService.java index 271cdb5a9..1ca5ffe6d 100644 --- a/src/main/java/sic/service/IPedidoService.java +++ b/src/main/java/sic/service/IPedidoService.java @@ -2,12 +2,14 @@ import java.math.BigDecimal; import java.util.List; +import java.util.Map; import com.querydsl.core.BooleanBuilder; import org.springframework.data.domain.Page; import sic.modelo.*; import sic.modelo.criteria.BusquedaPedidoCriteria; -import sic.modelo.dto.NuevoRenglonPedidoDTO; +import sic.modelo.dto.CantidadProductoDTO; +import sic.modelo.dto.CommitDTO; import sic.modelo.dto.NuevosResultadosComprobanteDTO; import sic.modelo.Resultados; @@ -19,7 +21,8 @@ public interface IPedidoService { Pedido getPedidoPorNumeroAndSucursal(long nroPedido, Sucursal sucursal); - void actualizar(Pedido pedido, List renglonesAnteriores, Long idSucursal, List recibos); + void actualizar(Pedido pedido, List renglonesAnteriores, Long idSucursal, List recibos); + void actualizarFacturasDelPedido(Pedido pedido, List facturas); @@ -49,11 +52,20 @@ public interface IPedidoService { Resultados calcularResultadosPedido(NuevosResultadosComprobanteDTO calculoPedido); - long[] getArrayDeIdProducto(List nuevosRenglones); + long[] getArrayDeIdProducto(List nuevosRenglones); + + BigDecimal[] getArrayDeCantidadesProducto(List nuevosRenglones); + + void actualizarCantidadReservadaDeProductosPorCambioDeEstado(Pedido pedido); + + void actualizarCantidadReservadaDeProductosPorModificacion(Pedido pedido, List renglonesAnteriores); + + List actualizarRenglonesPedido(List renglonesDelPedido, List renglonesParaActualizar); + + RenglonPedido actualizarCantidadRenglonPedido(RenglonPedido renglonPedido, BigDecimal cantidadNueva); - BigDecimal[] getArrayDeCantidadesProducto(List nuevosRenglones); + List getCambiosPedido(long idPedido); - void actualizarCantidadReservadaDeProductosPorCambioDeEstado(Pedido pedido); + List getCambiosRenglonesPedido(long idCommitPedido); - void actualizarCantidadReservadaDeProductosPorModificacion(Pedido pedido, List renglonesAnteriores); } diff --git a/src/main/java/sic/service/IProductoService.java b/src/main/java/sic/service/IProductoService.java index 25cf551cd..44de49fa3 100644 --- a/src/main/java/sic/service/IProductoService.java +++ b/src/main/java/sic/service/IProductoService.java @@ -18,7 +18,7 @@ public interface IProductoService { void actualizar(Producto productoPorActualizar, Producto productoPersistido, byte[] imagen); void devolverStockPedido( - Pedido pedido, TipoDeOperacion tipoDeOperacion, List renglonesAnteriores, Long idSucursalOrigen); + Pedido pedido, TipoDeOperacion tipoDeOperacion, List renglonesAnteriores, Long idSucursalOrigen); void actualizarStockPedido(Pedido pedido, TipoDeOperacion tipoDeOperacion); diff --git a/src/main/java/sic/service/impl/AuthServiceImpl.java b/src/main/java/sic/service/impl/AuthServiceImpl.java index c29fbfe26..f109347fe 100644 --- a/src/main/java/sic/service/impl/AuthServiceImpl.java +++ b/src/main/java/sic/service/impl/AuthServiceImpl.java @@ -31,6 +31,8 @@ public class AuthServiceImpl implements IAuthService { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private static final String URL_RECAPTCHA = "https://www.google.com/recaptcha/api/siteverify"; private static final String BEARER_TOKEN_PREFIX = "Bearer"; + + private long activeUserId; private final MessageSource messageSource; @Value("${RECAPTCHA_SECRET_KEY}") @@ -131,4 +133,14 @@ public void excluirTokenAcceso(String authorizationHeader) { tokenAccesoExcluidoRepository.save(new TokenAccesoExcluido(0, token)); } } + + @Override + public void setActiveUserId(String token) { + activeUserId = this.getClaimsDelToken(token).get("idUsuario", Integer.class); + } + + @Override + public long getActiveUserId() { + return activeUserId; + } } diff --git a/src/main/java/sic/service/impl/CarritoCompraServiceImpl.java b/src/main/java/sic/service/impl/CarritoCompraServiceImpl.java index 2b13254ef..8b03ab760 100644 --- a/src/main/java/sic/service/impl/CarritoCompraServiceImpl.java +++ b/src/main/java/sic/service/impl/CarritoCompraServiceImpl.java @@ -3,6 +3,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Locale; @@ -201,7 +202,7 @@ public Pedido crearPedido(NuevaOrdenDePagoDTO nuevaOrdenDePagoDTO, Long idUsuari i.getProducto().getIdProducto(), i.getCantidad()))); pedido.setRenglones(renglonesPedido); pedido.setTipoDeEnvio(nuevaOrdenDePagoDTO.getTipoDeEnvio()); - Pedido p = pedidoService.guardar(pedido, null); + Pedido p = pedidoService.guardar(pedido, Collections.emptyList()); this.eliminarTodosLosItemsDelUsuario(idUsuario); return p; } diff --git a/src/main/java/sic/service/impl/JaversAuditServiceImpl.java b/src/main/java/sic/service/impl/JaversAuditServiceImpl.java new file mode 100644 index 000000000..5a0da95f1 --- /dev/null +++ b/src/main/java/sic/service/impl/JaversAuditServiceImpl.java @@ -0,0 +1,178 @@ +package sic.service.impl; + +import com.google.gson.internal.LinkedTreeMap; +import org.javers.core.Javers; +import org.javers.core.commit.CommitId; +import org.javers.core.diff.Change; +import org.javers.core.diff.changetype.InitialValueChange; +import org.javers.core.diff.changetype.ObjectRemoved; +import org.javers.core.diff.changetype.ReferenceChange; +import org.javers.core.diff.changetype.ValueChange; +import org.javers.core.diff.changetype.container.ListChange; +import org.javers.core.metamodel.object.InstanceId; +import org.javers.repository.jql.QueryBuilder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.MessageSource; +import org.springframework.stereotype.Service; +import sic.modelo.TipoDeOperacion; +import sic.modelo.dto.CambioDTO; +import sic.modelo.dto.CommitDTO; +import sic.service.IAuditService; +import sic.service.IUsuarioService; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +@Service +public class JaversAuditServiceImpl implements IAuditService { + + private final IUsuarioService usuarioService; + private final Javers javers; + private final MessageSource messageSource; + private static final String ID_COMMIT_RELACIONADO = "idCommitRelacionado"; + private static final String INITIAL_VALUE_CHANGE = "InitialValueChange"; + private static final String LIST_CHANGE = "ListChange"; + private static final String COLLECTION_CHANGE = "CollectionChange"; + private static final String REFERENCE_CHANGE = "ReferenceChange"; + private static final String OBJECT_REMOVED = "ObjectRemoved"; + private static final String VALUE_CHANGE = "ValueChange"; + private static final String PROPERTY_RENGLONES="renglones"; + + @Autowired + public JaversAuditServiceImpl(IUsuarioService usuarioService, Javers javers, MessageSource messageSource) { + this.usuarioService = usuarioService; + this.javers = javers; + this.messageSource = messageSource; + } + + @Override + public String auditar(String idUsuario, Object objeto, Map propiedades) { + return javers.commit(idUsuario, objeto, propiedades).getId().value(); + } + + @Override + public List getCambios(T objeto) { + var changesDTO = new ArrayList(); + var changes = javers.findChanges(QueryBuilder.byInstance(objeto).build()); + changes.groupByCommit().forEach(changesByCommit -> { + var author = usuarioService.getUsuarioNoEliminadoPorId(Long.parseLong(changesByCommit.getCommit().getAuthor())); + changesDTO.add(CommitDTO.builder() + .idCommit(changesByCommit.getCommit().getId().value()) + .idCommitRelacionado(changesByCommit.getCommit().getProperties().get(ID_COMMIT_RELACIONADO)) + .fecha(changesByCommit.getCommit().getCommitDate()) + .usuario(author.getApellido() + " " + author.getNombre() + " (" + author.getUsername() + ")") + .cambios(this.getDetallesCambios(changesByCommit.get())) + .tipoDeOperacion(changesByCommit.getCommit().getProperties().get(TipoDeOperacion.class.getSimpleName())) + .build()); + }); + return changesDTO; + } + + @Override + public List getCambios(String idCommit) { + var changesDTO = new ArrayList(); + var query = QueryBuilder.anyDomainObject().withCommitId(CommitId.valueOf(idCommit)).build(); + var changes = javers.findChanges(query).groupByCommit(); + changes.forEach(changesByCommit -> { + var author = usuarioService.getUsuarioNoEliminadoPorId(Long.parseLong(changesByCommit.getCommit().getAuthor())); + changesDTO.add(CommitDTO.builder() + .idCommit(changesByCommit.getCommit().getId().value()) + .fecha(changesByCommit.getCommit().getCommitDate()) + .usuario(author.getApellido() + " " + author.getNombre() + " (" + author.getUsername() + ")") + .cambios(this.getDetallesCambios(changesByCommit.get())) + .tipoDeOperacion(changesByCommit.getCommit().getProperties().get(TipoDeOperacion.class.getSimpleName())) + .build()); + }); + return changesDTO; + } + + private List getDetallesCambios(List changes) { + var valuesChanges = new ArrayList(); + changes.forEach(change -> { + switch (change.getClass().getSimpleName()) { + case VALUE_CHANGE -> { + var valueChange = (ValueChange) change; + valuesChanges.add(CambioDTO.builder() + .valorSiguiente(valueChange.getRight() == null ? "" : valueChange.getRight().toString()) + .valorAnterior(valueChange.getLeft() == null ? "" : valueChange.getLeft().toString()) + .atributo(valueChange.getPropertyName()) + .build()); + } + case OBJECT_REMOVED -> { + var objectRemoved = (ObjectRemoved) change; + valuesChanges.add(CambioDTO.builder() + .atributo(objectRemoved.getAffectedObject().getClass().getSimpleName()) + .build()); + } + case REFERENCE_CHANGE -> { + var referenceChange = (ReferenceChange) change; + valuesChanges.add(CambioDTO.builder() + .valorSiguiente(referenceChange.getRight() == null ? "" : referenceChange.getRight().toString()) + .valorAnterior(referenceChange.getLeft() == null ? "" : referenceChange.getLeft().toString()) + .atributo(referenceChange.getPropertyName()) + .build()); + } + case COLLECTION_CHANGE -> { + var collectionChange = (ListChange) change; + valuesChanges.add(CambioDTO.builder() + .valorSiguiente(collectionChange.getRight() == null ? "" : collectionChange.getRight().toString()) + .valorAnterior(collectionChange.getLeft() == null ? "" : collectionChange.getLeft().toString()) + .atributo(collectionChange.getPropertyName()) + .build()); + } + case LIST_CHANGE -> valuesChanges.addAll(this.procesarCambiosDeListas((ListChange) change)); + case INITIAL_VALUE_CHANGE -> { + var initialValueChange = (InitialValueChange) change; + valuesChanges.add(CambioDTO.builder() + .atributo(initialValueChange.getPropertyName()) + .valorAnterior("") + .valorSiguiente(initialValueChange.getRight().toString()) + .build()); + } + //default -> throw new BusinessServiceException( + // messageSource.getMessage("mensaje_tipo_de_cambio_no_valido", null, Locale.getDefault())); + } + }); + return valuesChanges; + } + + + private CambioDTO buildCambioDTO(String atributo, String valorAnterior, String valorSiguiente) { + return CambioDTO.builder() + .atributo(atributo) + .valorAnterior(valorAnterior) + .valorSiguiente(valorSiguiente) + .build(); + } + + public List procesarCambiosDeListas(ListChange listChange) { + List valuesChanges = new ArrayList<>(); + if (Objects.equals(listChange.getPropertyName(), PROPERTY_RENGLONES)) { + this.procesarElementoDeLista(listChange.getRight().get(0), listChange, valuesChanges); + } else { + listChange.getRight().forEach(right -> this.procesarElementoDeLista(right, listChange, valuesChanges)); + } + return valuesChanges; + } + + public void procesarElementoDeLista(Object right, ListChange listChange, List valuesChanges) { + if (right instanceof InstanceId) { + valuesChanges.add(this.buildCambioDTO(listChange.getPropertyName(), + String.valueOf(listChange.getLeft().size()), String.valueOf(listChange.getRight().size()))); + } + if (right instanceof LinkedTreeMap mapRight) { + var mapLeft = listChange.getLeft() != null && !listChange.getLeft().isEmpty() ? + (LinkedTreeMap) listChange.getLeft().get(0) : new LinkedTreeMap<>(); + var keySet = mapRight.keySet(); + keySet.forEach(key -> { + var valorSiguiente = mapRight.get(key); + var valorAnterior = mapLeft.get(key); + valuesChanges.add(this.buildCambioDTO(key.toString(), + valorAnterior != null ? valorAnterior.toString() : "", + valorSiguiente != null ? valorSiguiente.toString() : "")); + }); + } + } + +} diff --git a/src/main/java/sic/service/impl/PedidoServiceImpl.java b/src/main/java/sic/service/impl/PedidoServiceImpl.java index bb8615ec1..3cc27fbab 100644 --- a/src/main/java/sic/service/impl/PedidoServiceImpl.java +++ b/src/main/java/sic/service/impl/PedidoServiceImpl.java @@ -24,8 +24,6 @@ import org.springframework.transaction.annotation.Transactional; import sic.modelo.*; import sic.modelo.criteria.BusquedaPedidoCriteria; -import sic.modelo.dto.NuevosResultadosComprobanteDTO; -import sic.modelo.Resultados; import sic.modelo.dto.*; import sic.repository.RenglonPedidoRepository; import sic.service.*; @@ -48,10 +46,13 @@ public class PedidoServiceImpl implements IPedidoService { private final IEmailService emailService; private final IReciboService reciboService; private final ICuentaCorrienteService cuentaCorrienteService; + private final IAuthService authService; + private final IAuditService auditService; private final ModelMapper modelMapper; private static final BigDecimal CIEN = new BigDecimal("100"); private final Logger logger = LoggerFactory.getLogger(this.getClass()); private static final int TAMANIO_PAGINA_DEFAULT = 25; + private static final String ID_COMMIT_RELACIONADO = "idCommitRelacionado"; private final MessageSource messageSource; private final CustomValidator customValidator; private final JasperReportsHandler jasperReportsHandler; @@ -66,6 +67,8 @@ public PedidoServiceImpl( IEmailService emailService, IReciboService reciboService, ICuentaCorrienteService cuentaCorrienteService, + IAuditService auditService, + IAuthService authService, ModelMapper modelMapper, MessageSource messageSource, CustomValidator customValidator, @@ -78,6 +81,8 @@ public PedidoServiceImpl( this.emailService = emailService; this.reciboService = reciboService; this.cuentaCorrienteService = cuentaCorrienteService; + this.auditService = auditService; + this.authService = authService; this.modelMapper = modelMapper; this.messageSource = messageSource; this.customValidator = customValidator; @@ -229,6 +234,11 @@ public Pedido guardar(Pedido pedido, List recibos) { "Reporte.pdf"); logger.warn("El mail del pedido nro {} se envió.", pedido.getNroPedido()); } + var properties = new HashMap(); + properties.put("TipoDeOperacion", TipoDeOperacion.ALTA.name()); + var idCommit = auditService.auditar(String.valueOf(authService.getActiveUserId()), pedido.getRenglones(), properties); + properties.put(ID_COMMIT_RELACIONADO, idCommit); + auditService.auditar(String.valueOf(authService.getActiveUserId()), pedido, properties); return pedido; } @@ -393,7 +403,7 @@ private Pageable getPageable(Integer pagina, String ordenarPor, String sentido) @Override @Transactional - public void actualizar(Pedido pedido, List renglonesAnteriores, Long idSucursalOrigen, List recibos) { + public void actualizar(Pedido pedido, List renglonesAnteriores, Long idSucursalOrigen, List recibos) { //de los renglones, sacar ids y cantidades, array de nuevosResultadosPedido BigDecimal[] importesDeRenglones = new BigDecimal[pedido.getRenglones().size()]; int i = 0; @@ -427,6 +437,11 @@ public void actualizar(Pedido pedido, List renglonesAnteriores, L productoService.devolverStockPedido(pedido, TipoDeOperacion.ACTUALIZACION, renglonesAnteriores, idSucursalOrigen); productoService.actualizarStockPedido(pedido, TipoDeOperacion.ACTUALIZACION); pedidoRepository.save(pedido); + var properties = new HashMap(); + properties.put("TipoDeOperacion", TipoDeOperacion.ACTUALIZACION.name()); + var idCommit = auditService.auditar(String.valueOf(authService.getActiveUserId()), pedido.getRenglones(), properties); + properties.put(ID_COMMIT_RELACIONADO, idCommit); + auditService.auditar(String.valueOf(authService.getActiveUserId()), pedido, properties); this.actualizarCantidadReservadaDeProductosPorModificacion(pedido, renglonesAnteriores); } @@ -657,7 +672,7 @@ public void cancelarPedidosAbiertos() { } @Override - public long[] getArrayDeIdProducto(List nuevosRenglones) { + public long[] getArrayDeIdProducto(List nuevosRenglones) { long[] idProductoItem = new long[nuevosRenglones.size()]; for (int i = 0; i < nuevosRenglones.size(); ++i) { idProductoItem[i] = nuevosRenglones.get(i).getIdProductoItem(); @@ -666,7 +681,7 @@ public long[] getArrayDeIdProducto(List nuevosRenglones) } @Override - public BigDecimal[] getArrayDeCantidadesProducto(List nuevosRenglones) { + public BigDecimal[] getArrayDeCantidadesProducto(List nuevosRenglones) { BigDecimal[] cantidades = new BigDecimal[nuevosRenglones.size()]; for (int i = 0; i < nuevosRenglones.size(); ++i) { cantidades[i] = nuevosRenglones.get(i).getCantidad(); @@ -687,7 +702,7 @@ public void actualizarCantidadReservadaDeProductosPorCambioDeEstado(Pedido pedid } @Override - public void actualizarCantidadReservadaDeProductosPorModificacion(Pedido pedido, List renglonesAnteriores) { + public void actualizarCantidadReservadaDeProductosPorModificacion(Pedido pedido, List renglonesAnteriores) { if (pedido.getEstado() == EstadoPedido.ABIERTO) { renglonesAnteriores.forEach(renglonPedido -> productoService.quitarCantidadReservada(renglonPedido.getIdProductoItem(), renglonPedido.getCantidad())); pedido.getRenglones().forEach(renglonPedido -> @@ -697,4 +712,82 @@ public void actualizarCantidadReservadaDeProductosPorModificacion(Pedido pedido, messageSource.getMessage("mensaje_producto_error_actualizar_cantidad_reservada", null, Locale.getDefault())); } } + + @Override + public List actualizarRenglonesPedido(List renglonesDelPedido, List nuevosRenglones) { + List renglonesParaAgregar = new ArrayList<>(); + List idsProductos = new ArrayList<>(); + nuevosRenglones.forEach(renglon -> idsProductos.add(renglon.getIdProductoItem())); + renglonesDelPedido.forEach(renglonPedido -> {// marca para eliminar los renglones seteando la cantidad a cero + if (!idsProductos.contains(renglonPedido.getIdProductoItem())){ + renglonPedido.setIdProductoItem(0); + }}); + renglonesDelPedido.removeIf(renglonPedido -> renglonPedido.getIdProductoItem() == 0); //elimina los renglones + nuevosRenglones.forEach(nuevoRenglon -> renglonesDelPedido.stream().filter(renglonPedido -> nuevoRenglon.getIdProductoItem() == renglonPedido.getIdProductoItem()) + .forEach(renglonPedido -> { + this.actualizarCantidadRenglonPedido(renglonPedido, nuevoRenglon.getCantidad()); + nuevoRenglon.setIdProductoItem(0L); + })); + nuevosRenglones.removeIf(nuevoRenglon -> nuevoRenglon.getIdProductoItem() == 0); + nuevosRenglones.forEach(nuevoRenglon -> renglonesParaAgregar.add(this.calcularRenglonPedido(nuevoRenglon.getIdProductoItem(), nuevoRenglon.getCantidad()))); + renglonesDelPedido.addAll(renglonesParaAgregar); + return renglonesDelPedido; + } + + @Override + public RenglonPedido actualizarCantidadRenglonPedido(RenglonPedido renglonPedido, BigDecimal cantidad) { + if (cantidad.compareTo(BigDecimal.ZERO) <= 0) { + throw new BusinessServiceException( + messageSource.getMessage( + "mensaje_producto_cantidad_igual_menor_cero", null, Locale.getDefault())); + } + Producto producto = productoService.getProductoNoEliminadoPorId(renglonPedido.getIdProductoItem()); + renglonPedido.setCantidad(cantidad); + renglonPedido.setPrecioUnitario(producto.getPrecioProducto().getPrecioLista()); + if (producto.getPrecioProducto().isOferta() + && renglonPedido.getCantidad().compareTo(producto.getCantidadProducto().getCantMinima()) >= 0 + && producto.getPrecioProducto().getPorcentajeBonificacionOferta() != null) { + renglonPedido.setBonificacionPorcentaje(producto.getPrecioProducto().getPorcentajeBonificacionOferta()); + renglonPedido.setBonificacionNeta( + CalculosComprobante.calcularProporcion( + renglonPedido.getPrecioUnitario(), producto.getPrecioProducto().getPorcentajeBonificacionOferta())); + } else if (renglonPedido.getCantidad().compareTo(producto.getCantidadProducto().getCantMinima()) >= 0) { + renglonPedido.setBonificacionPorcentaje(producto.getPrecioProducto().getPorcentajeBonificacionPrecio()); + renglonPedido.setBonificacionNeta( + CalculosComprobante.calcularProporcion( + renglonPedido.getPrecioUnitario(), producto.getPrecioProducto().getPorcentajeBonificacionPrecio())); + } else { + renglonPedido.setBonificacionPorcentaje(BigDecimal.ZERO); + renglonPedido.setBonificacionNeta(BigDecimal.ZERO); + } + renglonPedido.setImporteAnterior( + CalculosComprobante.calcularImporte( + renglonPedido.getCantidad(), producto.getPrecioProducto().getPrecioLista(), BigDecimal.ZERO)); + renglonPedido.setImporte( + CalculosComprobante.calcularImporte( + renglonPedido.getCantidad(), + producto.getPrecioProducto().getPrecioLista(), + renglonPedido.getBonificacionNeta())); + return renglonPedido; + } + + @Override + public List getCambiosPedido(long idPedido) { + return auditService.getCambios(this.getPedidoNoEliminadoPorId(idPedido)); + } + + @Override + public List getCambiosRenglonesPedido(long idPedido) { + var commitsPedido = auditService.getCambios(this.getPedidoNoEliminadoPorId(idPedido)); + var cambiosRenglones = new ArrayList(); + if (!commitsPedido.isEmpty()) { + commitsPedido.forEach(commitPedido -> { + var idCommitRenglones = commitPedido.getIdCommitRelacionado(); + var cambios = auditService.getCambios(idCommitRenglones); + cambiosRenglones.addAll(cambios); + }); + } + return cambiosRenglones; + } + } diff --git a/src/main/java/sic/service/impl/ProductoServiceImpl.java b/src/main/java/sic/service/impl/ProductoServiceImpl.java index 42ee7ee98..aee928dba 100644 --- a/src/main/java/sic/service/impl/ProductoServiceImpl.java +++ b/src/main/java/sic/service/impl/ProductoServiceImpl.java @@ -500,7 +500,7 @@ private void calcularPrecioBonificado(Producto producto) { @Override public void devolverStockPedido( - Pedido pedido, TipoDeOperacion tipoDeOperacion, List renglonesAnteriores, Long idSucursalOrigen) { + Pedido pedido, TipoDeOperacion tipoDeOperacion, List renglonesAnteriores, Long idSucursalOrigen) { if (tipoDeOperacion == TipoDeOperacion.ACTUALIZACION && pedido.getEstado() == EstadoPedido.ABIERTO && renglonesAnteriores != null diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 1f6e98a85..de9234e68 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -21,6 +21,7 @@ mensaje_error_al_encriptar=Ocurrio un error al encriptar mensaje_error_al_desencriptar=Ocurrio un error al desencriptar mensaje_operacion_no_soportada=El tipo de operación solicitado no está disponible mensaje_recurso_no_encontrado=No se pudo obtener el recurso solicitado +mensaje_tipo_de_cambio_no_valido=El tipo de cambio no es valido #AFIP mensaje_no_es_comprobanteAFIP=No es un comprobante autorizable de AFIP diff --git a/src/test/java/sic/controller/PedidoControllerTest.java b/src/test/java/sic/controller/PedidoControllerTest.java index 40b5b8561..263c47c7c 100644 --- a/src/test/java/sic/controller/PedidoControllerTest.java +++ b/src/test/java/sic/controller/PedidoControllerTest.java @@ -6,7 +6,7 @@ import org.mockito.Mock; import org.springframework.test.context.junit.jupiter.SpringExtension; import sic.modelo.*; -import sic.modelo.dto.NuevoRenglonPedidoDTO; +import sic.modelo.dto.CantidadProductoDTO; import sic.modelo.dto.NuevosResultadosComprobanteDTO; import sic.service.impl.PedidoServiceImpl; @@ -34,11 +34,11 @@ void shouldGetPedidoPorId() { @Test void shouldCalcularRenglonesPedido() { - List nuevoRenglonPedido = new ArrayList<>(); + List nuevoRenglonPedido = new ArrayList<>(); nuevoRenglonPedido.add( - NuevoRenglonPedidoDTO.builder().idProductoItem(1L).cantidad(BigDecimal.TEN).build()); + CantidadProductoDTO.builder().idProductoItem(1L).cantidad(BigDecimal.TEN).build()); nuevoRenglonPedido.add( - NuevoRenglonPedidoDTO.builder().idProductoItem(2L).cantidad(BigDecimal.ONE).build()); + CantidadProductoDTO.builder().idProductoItem(2L).cantidad(BigDecimal.ONE).build()); List renglones = new ArrayList<>(); long[] idsProducto = {1L, 2L}; BigDecimal[] cantidades = {BigDecimal.TEN, BigDecimal.ONE}; diff --git a/src/test/java/sic/integration/AppIntegrationTest.java b/src/test/java/sic/integration/AppIntegrationTest.java index 1e6e59ac5..ad0993131 100644 --- a/src/test/java/sic/integration/AppIntegrationTest.java +++ b/src/test/java/sic/integration/AppIntegrationTest.java @@ -9,10 +9,7 @@ import org.springframework.context.MessageSource; import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.io.ClassPathResource; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpRequest; -import org.springframework.http.HttpStatus; +import org.springframework.http.*; import org.springframework.http.client.ClientHttpRequestExecution; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpResponse; @@ -807,7 +804,7 @@ void testEscenarioAltaDeProducto() throws IOException { } @Test - @DisplayName("Dar de alta un cliente y levantar un pedido con reserva, verificar stock") + @DisplayName("Dar de alta un cliente y levantar un pedido con reserva, verificar stock y consultar su historico de cambios") @Order(7) void testEscenarioAltaClienteYPedido() { this.iniciarSesionComoAdministrador(); @@ -844,14 +841,14 @@ void testEscenarioAltaClienteYPedido() { Producto productoDos = restTemplate.getForObject(apiPrefix + "/productos/2/sucursales/1", Producto.class); assertEquals(new BigDecimal("13.000000000000000"), productoUno.getCantidadTotalEnSucursales()); assertEquals(new BigDecimal("12.000000000000000"), productoDos.getCantidadTotalEnSucursales()); - List renglonesPedidoDTO = new ArrayList<>(); + List renglonesPedidoDTO = new ArrayList<>(); renglonesPedidoDTO.add( - NuevoRenglonPedidoDTO.builder() + CantidadProductoDTO.builder() .idProductoItem(1L) .cantidad(new BigDecimal("5.000000000000000")) .build()); renglonesPedidoDTO.add( - NuevoRenglonPedidoDTO.builder() + CantidadProductoDTO.builder() .idProductoItem(2L) .cantidad(new BigDecimal("2.000000000000000")) .build()); @@ -912,10 +909,30 @@ void testEscenarioAltaClienteYPedido() { assertEquals( new BigDecimal("1768.000000000000000000000000000000"), renglonesDelPedido.get(1).getImporte()); + List cambios = + Arrays.asList(restTemplate.getForObject( + apiPrefix + "/pedidos/" + pedidoRecuperado.getIdPedido() + "/cambios", + CommitDTO[].class)); + assertFalse(cambios.isEmpty()); + assertEquals("2.00", cambios.get(0).getIdCommit()); + assertEquals("1.00", cambios.get(0).getIdCommitRelacionado()); + assertEquals("Power Max (dueño)", cambios.get(0).getUsuario()); + assertEquals("ALTA", cambios.get(0).getTipoDeOperacion()); + assertEquals(17, cambios.get(0).getCambios().size()); + List> cambiosRenglones = + restTemplate.getForObject( + apiPrefix + "/pedidos/" + pedidoRecuperado.getIdPedido() + "/renglones/cambios", + List.class); + assertFalse(cambiosRenglones.isEmpty()); + assertEquals("1.00", cambiosRenglones.get(0).get("idCommit")); + assertNull(cambiosRenglones.get(0).get("idCommitRelacionado")); + assertEquals("Power Max (dueño)", cambiosRenglones.get(0).get("usuario")); + assertEquals(TipoDeOperacion.ALTA.name() ,cambiosRenglones.get(0).get("tipoDeOperacion")); + assertNotNull(cambiosRenglones.get(0).get("cambios")); } @Test - @DisplayName("Modificar el pedido agregando un nuevo producto y cambiando la cantidad de uno ya existente, reservando y verificando stock") + @DisplayName("Modificar el pedido agregando un nuevo producto y cambiando la cantidad de uno ya existente, reservando, verificando stock y su historico de cambios") @Order(8) void testEscenarioModificacionPedido() { this.iniciarSesionComoAdministrador(); @@ -939,17 +956,17 @@ void testEscenarioModificacionPedido() { sic.model.RenglonPedido[].class)); assertNotNull(renglonesPedidos); assertEquals(2, renglonesPedidos.size()); - List renglonesPedidoDTO = new ArrayList<>(); + List renglonesPedidoDTO = new ArrayList<>(); renglonesPedidos.forEach( renglonPedido -> renglonesPedidoDTO.add( - NuevoRenglonPedidoDTO.builder() + CantidadProductoDTO.builder() .idProductoItem(renglonPedido.getIdProductoItem()) .cantidad(renglonPedido.getCantidad()) .build())); renglonesPedidoDTO.get(1).setCantidad(new BigDecimal("3")); renglonesPedidoDTO.add( - NuevoRenglonPedidoDTO.builder().idProductoItem(3L).cantidad(BigDecimal.TEN).build()); + CantidadProductoDTO.builder().idProductoItem(3L).cantidad(BigDecimal.TEN).build()); PedidoDTO pedidoDTO = PedidoDTO.builder() .idPedido(pedidosRecuperados.get(0).getIdPedido()) @@ -1032,6 +1049,37 @@ void testEscenarioModificacionPedido() { assertEquals( new BigDecimal("120279.618000000000000000000000000000"), renglonesDelPedido.get(2).getImporte()); + List cambios = + Arrays.asList(restTemplate.getForObject( + apiPrefix + "/pedidos/" + pedidosRecuperados.get(0).getIdPedido() + "/cambios", + CommitDTO[].class)); + assertFalse(cambios.isEmpty()); + assertEquals(2, cambios.size()); + assertEquals("4.00", cambios.get(0).getIdCommit()); + assertEquals("3.00", cambios.get(0).getIdCommitRelacionado()); + assertEquals("Power Max (dueño)", cambios.get(0).getUsuario()); + assertEquals("ACTUALIZACION", cambios.get(0).getTipoDeOperacion()); + assertEquals(8, cambios.get(0).getCambios().size()); + assertEquals("2.00", cambios.get(1).getIdCommit()); + assertEquals("1.00", cambios.get(1).getIdCommitRelacionado()); + assertEquals("Power Max (dueño)", cambios.get(1).getUsuario()); + assertEquals("ALTA", cambios.get(1).getTipoDeOperacion()); + assertEquals(17, cambios.get(1).getCambios().size()); + List> cambiosRenglones = + restTemplate.getForObject( + apiPrefix + "/pedidos/" + pedidosRecuperados.get(0).getIdPedido() + "/renglones/cambios", + List.class); + assertFalse(cambiosRenglones.isEmpty()); + assertEquals("3.00", cambiosRenglones.get(0).get("idCommit")); + assertNull(cambiosRenglones.get(0).get("idCommitRelacionado")); + assertEquals("Power Max (dueño)", cambiosRenglones.get(0).get("usuario")); + assertEquals(TipoDeOperacion.ACTUALIZACION.name() ,cambiosRenglones.get(0).get("tipoDeOperacion")); + assertNotNull(cambiosRenglones.get(0).get("cambios")); + assertEquals("1.00", cambiosRenglones.get(1).get("idCommit")); + assertNull(cambiosRenglones.get(1).get("idCommitRelacionado")); + assertEquals("Power Max (dueño)", cambiosRenglones.get(1).get("usuario")); + assertEquals(TipoDeOperacion.ALTA.name() ,cambiosRenglones.get(1).get("tipoDeOperacion")); + assertNotNull(cambiosRenglones.get(1).get("cambios")); } @Test diff --git a/src/test/java/sic/service/impl/PedidoServiceImplTest.java b/src/test/java/sic/service/impl/PedidoServiceImplTest.java index a8c1f2e33..c25d57021 100644 --- a/src/test/java/sic/service/impl/PedidoServiceImplTest.java +++ b/src/test/java/sic/service/impl/PedidoServiceImplTest.java @@ -1,5 +1,6 @@ package sic.service.impl; +import org.javers.core.Javers; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.modelmapper.ModelMapper; @@ -12,12 +13,15 @@ import sic.exception.ServiceException; import sic.modelo.*; import sic.modelo.criteria.BusquedaPedidoCriteria; -import sic.modelo.dto.NuevoRenglonPedidoDTO; +import sic.modelo.dto.CantidadProductoDTO; import sic.modelo.dto.ProductoFaltanteDTO; import sic.modelo.dto.UbicacionDTO; import sic.modelo.embeddable.CantidadProductoEmbeddable; +import sic.modelo.embeddable.PrecioProductoEmbeddable; import sic.repository.PedidoRepository; import sic.repository.RenglonPedidoRepository; +import sic.service.IAuditService; +import sic.service.IAuthService; import sic.service.IEmailService; import sic.util.CustomValidator; import sic.util.JasperReportsHandler; @@ -47,9 +51,50 @@ class PedidoServiceImplTest { @MockBean ReciboServiceImpl reciboService; @MockBean MessageSource messageSource; @MockBean ModelMapper modelMapper; + @MockBean IAuthService authService; + @MockBean Javers javers; + @MockBean IAuditService auditService; @Autowired PedidoServiceImpl pedidoService; + private Producto construirProducto() { + Producto producto = new Producto(); + producto.setIdProducto(1L); + producto.setCodigo("1"); + producto.setDescripcion("Cinta adhesiva doble faz 3M"); + producto.setMedida(new Medida()); + producto.setPrecioProducto(new PrecioProductoEmbeddable()); + producto.getPrecioProducto().setPrecioCosto(new BigDecimal("89.35")); + producto.getPrecioProducto().setGananciaPorcentaje(new BigDecimal("38.74")); + producto.getPrecioProducto().setGananciaNeto(new BigDecimal("34.614")); + producto.getPrecioProducto().setPrecioVentaPublico(new BigDecimal("123.964")); + producto.getPrecioProducto().setIvaPorcentaje(new BigDecimal("21")); + producto.getPrecioProducto().setIvaNeto(new BigDecimal("26.032")); + producto.getPrecioProducto().setPrecioLista(new BigDecimal("150")); + producto.getPrecioProducto().setPorcentajeBonificacionPrecio(new BigDecimal("10")); + producto.getPrecioProducto().setPrecioBonificado(new BigDecimal("135")); + producto.getPrecioProducto().setPorcentajeBonificacionOferta(BigDecimal.ZERO); + producto.setCantidadProducto(new CantidadProductoEmbeddable()); + producto.getCantidadProducto().setCantMinima(new BigDecimal("5")); + producto.setFechaAlta(LocalDateTime.now()); + producto.setFechaUltimaModificacion(LocalDateTime.now()); + Sucursal sucursal = new Sucursal(); + Rubro rubro = new Rubro(); + Proveedor proveedor = new Proveedor(); + Set cantidadEnSucursales = new HashSet<>(); + CantidadEnSucursal cantidadEnSucursal = new CantidadEnSucursal(); + cantidadEnSucursal.setCantidad(BigDecimal.TEN); + cantidadEnSucursal.setSucursal(sucursal); + cantidadEnSucursales.add(cantidadEnSucursal); + cantidadEnSucursal.setSucursal(sucursal); + producto.getCantidadProducto().setCantidadEnSucursales(cantidadEnSucursales); + producto.getCantidadProducto().setCantidadTotalEnSucursales(BigDecimal.TEN); + producto.getCantidadProducto().setCantidadReservada(BigDecimal.ZERO); + producto.setRubro(rubro); + producto.setProveedor(proveedor); + return producto; + } + @Test void shouldCancelarPedidoAbierto() { Pedido pedido = new Pedido(); @@ -86,13 +131,13 @@ void shouldNotCancelarPedidoCerrado() { @Test void shouldGetArrayDeIdProducto() { - List nuevosRenglonesPedido = new ArrayList<>(); - NuevoRenglonPedidoDTO nuevoRenglonPedidoDTO1 = new NuevoRenglonPedidoDTO(); - nuevoRenglonPedidoDTO1.setIdProductoItem(1L); - NuevoRenglonPedidoDTO nuevoRenglonPedidoDTO2 = new NuevoRenglonPedidoDTO(); - nuevoRenglonPedidoDTO2.setIdProductoItem(5L); - nuevosRenglonesPedido.add(nuevoRenglonPedidoDTO1); - nuevosRenglonesPedido.add(nuevoRenglonPedidoDTO2); + List nuevosRenglonesPedido = new ArrayList<>(); + CantidadProductoDTO cantidadProductoDTO1 = new CantidadProductoDTO(); + cantidadProductoDTO1.setIdProductoItem(1L); + CantidadProductoDTO cantidadProductoDTO2 = new CantidadProductoDTO(); + cantidadProductoDTO2.setIdProductoItem(5L); + nuevosRenglonesPedido.add(cantidadProductoDTO1); + nuevosRenglonesPedido.add(cantidadProductoDTO2); long[] idsProductoEsperado = new long[] {1L, 5L}; long[] idsProductoResultado = pedidoService.getArrayDeIdProducto(nuevosRenglonesPedido); assertEquals(idsProductoEsperado.length, idsProductoResultado.length); @@ -102,13 +147,13 @@ void shouldGetArrayDeIdProducto() { @Test void shouldGetArrayDeCantidadesProducto() { - List nuevosRenglonesPedido = new ArrayList<>(); - NuevoRenglonPedidoDTO nuevoRenglonPedidoDTO1 = new NuevoRenglonPedidoDTO(); - nuevoRenglonPedidoDTO1.setCantidad(BigDecimal.TEN); - NuevoRenglonPedidoDTO nuevoRenglonPedidoDTO2 = new NuevoRenglonPedidoDTO(); - nuevoRenglonPedidoDTO2.setCantidad(BigDecimal.ONE); - nuevosRenglonesPedido.add(nuevoRenglonPedidoDTO1); - nuevosRenglonesPedido.add(nuevoRenglonPedidoDTO2); + List nuevosRenglonesPedido = new ArrayList<>(); + CantidadProductoDTO cantidadProductoDTO1 = new CantidadProductoDTO(); + cantidadProductoDTO1.setCantidad(BigDecimal.TEN); + CantidadProductoDTO cantidadProductoDTO2 = new CantidadProductoDTO(); + cantidadProductoDTO2.setCantidad(BigDecimal.ONE); + nuevosRenglonesPedido.add(cantidadProductoDTO1); + nuevosRenglonesPedido.add(cantidadProductoDTO2); BigDecimal[] idsProductoEsperado = new BigDecimal[] {BigDecimal.TEN, BigDecimal.ONE}; BigDecimal[] idsProductoResultado = pedidoService.getArrayDeCantidadesProducto(nuevosRenglonesPedido); @@ -174,6 +219,7 @@ void shouldGuardarPedido() { clienteDeUsuario.setNombreFiscal("nombre fiscal"); when(clienteService.getClientePorIdUsuario(1L)).thenReturn(clienteDeUsuario); pedido.setDescuentoPorcentaje(BigDecimal.ZERO); + when(auditService.auditar(anyString(),any(),any())).thenReturn("1"); assertThrows( BusinessServiceException.class, () -> pedidoService.guardar(pedido, new ArrayList<>())); verify(messageSource).getMessage(eq("mensaje_pedido_detalle_envio_vacio"), any(), any()); @@ -389,11 +435,8 @@ void shouldActualizarCantidadReservadaDeProductosPorModificacion() { renglonPedido.setCantidad(BigDecimal.TEN); renglonesPedido.add(renglonPedido); pedido.setRenglones(renglonesPedido); - List renglonesAnterioresPedido = new ArrayList<>(); - RenglonPedido renglonAnteriorPedido = new RenglonPedido(); - renglonAnteriorPedido.setIdProductoItem(5L); - renglonAnteriorPedido.setCantidad(BigDecimal.ONE); - renglonesAnterioresPedido.add(renglonAnteriorPedido); + List renglonesAnterioresPedido = new ArrayList<>(); + renglonesAnterioresPedido.add(CantidadProductoDTO.builder().idProductoItem(5L).cantidad(BigDecimal.ONE).build()); pedidoService.actualizarCantidadReservadaDeProductosPorModificacion(pedido, renglonesAnterioresPedido); verify(productoService).quitarCantidadReservada(5L, BigDecimal.ONE); verify(productoService).agregarCantidadReservada(1L, BigDecimal.TEN); @@ -403,15 +446,60 @@ void shouldActualizarCantidadReservadaDeProductosPorModificacion() { void shouldThrowsServiceExceptionActualizarCantidadReservadaDeProductosPorModificacion() { Pedido pedido = new Pedido(); pedido.setEstado(EstadoPedido.CANCELADO); - List renglonesAnterioresPedido = new ArrayList<>(); - RenglonPedido renglonAnteriorPedido = new RenglonPedido(); - renglonAnteriorPedido.setIdProductoItem(5L); - renglonAnteriorPedido.setCantidad(BigDecimal.ONE); - renglonesAnterioresPedido.add(renglonAnteriorPedido); + List renglonesAnterioresPedido = new ArrayList<>(); + renglonesAnterioresPedido.add(CantidadProductoDTO.builder().idProductoItem(5L).cantidad(BigDecimal.ONE).build()); assertThrows( ServiceException.class, () -> pedidoService.actualizarCantidadReservadaDeProductosPorModificacion(pedido, renglonesAnterioresPedido)); verify(messageSource) .getMessage(eq("mensaje_producto_error_actualizar_cantidad_reservada"), any(), any()); } + + @Test + void shouldActualizarRenglonesPedido() { + Producto productoUno = this.construirProducto(); + Producto productoDos = this.construirProducto(); + productoDos.setIdProducto(2L); + Producto productoTres = this.construirProducto(); + productoTres.setIdProducto(3L); + when(productoService.getProductoNoEliminadoPorId(1L)).thenReturn(productoUno); + when(productoService.getProductoNoEliminadoPorId(2L)).thenReturn(productoDos); + when(productoService.getProductoNoEliminadoPorId(3L)).thenReturn(productoTres); + List renglones = new ArrayList<>(); + RenglonPedido renglonPedido1 = new RenglonPedido(); + renglonPedido1.setIdRenglonPedido(1L); + renglonPedido1.setIdProductoItem(1L); + renglonPedido1.setCantidad(BigDecimal.TEN); + RenglonPedido renglonPedido2 = new RenglonPedido(); + renglonPedido2.setIdRenglonPedido(2L); + renglonPedido2.setIdProductoItem(2L); + renglonPedido2.setCantidad(BigDecimal.ONE); + renglones.add(renglonPedido1); + renglones.add(renglonPedido2); + List nuevosRenglonesPedido = new ArrayList<>(); + CantidadProductoDTO cantidadProductoDTO = new CantidadProductoDTO(); + cantidadProductoDTO.setIdProductoItem(1L); + cantidadProductoDTO.setCantidad(BigDecimal.ONE); + nuevosRenglonesPedido.add(cantidadProductoDTO); + CantidadProductoDTO nuevoRenglonPedido2DTO = new CantidadProductoDTO(); + nuevoRenglonPedido2DTO.setIdProductoItem(3L); + nuevoRenglonPedido2DTO.setCantidad(BigDecimal.TEN); + nuevosRenglonesPedido.add(nuevoRenglonPedido2DTO); + pedidoService.actualizarRenglonesPedido(renglones, nuevosRenglonesPedido); + assertEquals(1L, renglones.get(0).getIdProductoItem()); + assertEquals(3L, renglones.get(1).getIdProductoItem()); + assertEquals(BigDecimal.ONE, renglones.get(0).getCantidad()); + assertEquals(1L, renglones.get(0).getIdProductoItem()); + assertEquals(BigDecimal.TEN, renglones.get(1).getCantidad()); + assertEquals(3L, renglones.get(1).getIdProductoItem()); + } + + @Test + void shouldActualizarRenglon() { + Producto productoUno = this.construirProducto(); + when(productoService.getProductoNoEliminadoPorId(1L)).thenReturn(productoUno); + RenglonPedido renglonPedido1 = pedidoService.calcularRenglonPedido(productoUno.getIdProducto(), BigDecimal.TEN); + pedidoService.actualizarCantidadRenglonPedido(renglonPedido1, BigDecimal.ONE); + assertEquals(BigDecimal.ONE, renglonPedido1.getCantidad()); + } } diff --git a/src/test/java/sic/service/impl/ProductoServiceImplTest.java b/src/test/java/sic/service/impl/ProductoServiceImplTest.java index c85fd7284..660e3cc54 100644 --- a/src/test/java/sic/service/impl/ProductoServiceImplTest.java +++ b/src/test/java/sic/service/impl/ProductoServiceImplTest.java @@ -22,10 +22,7 @@ import sic.exception.ServiceException; import sic.modelo.*; import sic.modelo.criteria.BusquedaProductoCriteria; -import sic.modelo.dto.NuevoProductoDTO; -import sic.modelo.dto.ProductoFaltanteDTO; -import sic.modelo.dto.ProductosParaActualizarDTO; -import sic.modelo.dto.ProductosParaVerificarStockDTO; +import sic.modelo.dto.*; import sic.modelo.embeddable.CantidadProductoEmbeddable; import sic.modelo.embeddable.PrecioProductoEmbeddable; import sic.repository.ProductoFavoritoRepository; @@ -638,10 +635,8 @@ void shouldDevolverStockPedido() { Sucursal sucursal = new Sucursal(); sucursal.setIdSucursal(1L); pedido.setSucursal(sucursal); - List renglonesAnteriores = new ArrayList<>(); - RenglonPedido renglonPedidoAnterior = new RenglonPedido(); - renglonPedidoAnterior.setIdProductoItem(1L); - renglonesAnteriores.add(renglonPedido); + List renglonesAnteriores = new ArrayList<>(); + renglonesAnteriores.add(CantidadProductoDTO.builder().idProductoItem(1L).build()); productoService.devolverStockPedido( pedido, TipoDeOperacion.ACTUALIZACION, renglonesAnteriores, 1L); verify(messageSource)