diff --git a/src/main/java/sic/modelo/EnvioDeCorreoGrupal.java b/src/main/java/sic/modelo/EnvioDeCorreoGrupal.java new file mode 100644 index 00000000..5be2f3c2 --- /dev/null +++ b/src/main/java/sic/modelo/EnvioDeCorreoGrupal.java @@ -0,0 +1,60 @@ +package sic.modelo; + +import com.fasterxml.jackson.annotation.JsonView; +import lombok.*; +import org.hibernate.Hibernate; +import sic.controller.Views; + +import javax.persistence.*; +import javax.validation.constraints.NotEmpty; +import java.io.Serializable; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; + +@Entity +@Table(name = "envioDeCorreoGrupal") +@Getter +@Setter +@RequiredArgsConstructor +@AllArgsConstructor +@ToString +@JsonView(Views.Encargado.class) +@Builder +public class EnvioDeCorreoGrupal implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long idEnvioDeCorreoGrupal; + + private LocalDateTime fecha; + + @ElementCollection(targetClass = Rol.class, fetch = FetchType.EAGER) + @CollectionTable(name = "rol", joinColumns = @JoinColumn(name = "idEnvioDeCorreoGrupal")) + @Enumerated(EnumType.STRING) + @Column(name = "nombre") + @NotEmpty(message = "{mensaje_usuario_no_selecciono_rol}") + private List roles; + + private String asunto; + + private String mensaje; + + private String descripcionAdjunto; + + @Lob + private byte[] reporteAdjunto; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false; + EnvioDeCorreoGrupal that = (EnvioDeCorreoGrupal) o; + return idEnvioDeCorreoGrupal != 0L && Objects.equals(idEnvioDeCorreoGrupal, that.idEnvioDeCorreoGrupal); + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } +} diff --git a/src/main/java/sic/modelo/dto/EnvioDeCorreoGrupalDTO.java b/src/main/java/sic/modelo/dto/EnvioDeCorreoGrupalDTO.java new file mode 100644 index 00000000..405e75d0 --- /dev/null +++ b/src/main/java/sic/modelo/dto/EnvioDeCorreoGrupalDTO.java @@ -0,0 +1,24 @@ +package sic.modelo.dto; + +import lombok.*; +import sic.modelo.Rol; +import java.time.LocalDateTime; +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@EqualsAndHashCode +@Builder +public class EnvioDeCorreoGrupalDTO { + + private LocalDateTime fecha; + + private List roles; + + private String asunto; + + private String mensaje; + + private byte[] reporteAdjunto; +} diff --git a/src/main/java/sic/repository/EnvioDeCorreoGrupalRepository.java b/src/main/java/sic/repository/EnvioDeCorreoGrupalRepository.java new file mode 100644 index 00000000..7ad1717d --- /dev/null +++ b/src/main/java/sic/repository/EnvioDeCorreoGrupalRepository.java @@ -0,0 +1,9 @@ +package sic.repository; + +import org.springframework.data.querydsl.QuerydslPredicateExecutor; +import org.springframework.data.repository.PagingAndSortingRepository; +import sic.modelo.EnvioDeCorreoGrupal; + +public interface EnvioDeCorreoGrupalRepository extends PagingAndSortingRepository, QuerydslPredicateExecutor { + +} diff --git a/src/main/java/sic/service/IEmailService.java b/src/main/java/sic/service/IEmailService.java index c642ecb4..ed2de9eb 100644 --- a/src/main/java/sic/service/IEmailService.java +++ b/src/main/java/sic/service/IEmailService.java @@ -1,12 +1,25 @@ package sic.service; +import sic.modelo.EnvioDeCorreoGrupal; +import sic.modelo.dto.EnvioDeCorreoGrupalDTO; + public interface IEmailService { void enviarEmail( - String toEmail, + String[] toEmail, String bcc, String subject, String mensaje, byte[] byteArray, String attachmentDescription); + + void enviarEmail( + String toEmail, + String bcc, + String subject, + String mensaje, + byte[] byteArray, + String attachmentDescription); + + EnvioDeCorreoGrupal enviarCorreoGrupal(EnvioDeCorreoGrupalDTO envioDeCorreoGrupal); } diff --git a/src/main/java/sic/service/IProductoService.java b/src/main/java/sic/service/IProductoService.java index 8201f19f..4879a333 100644 --- a/src/main/java/sic/service/IProductoService.java +++ b/src/main/java/sic/service/IProductoService.java @@ -85,7 +85,11 @@ BigDecimal calcularGananciaPorcentaje( void getListaDePreciosEnPdf(BusquedaProductoCriteria criteria, long idSucursal); - void enviarListaDeProductosPorEmail(String mailTo, byte[] listaDeProductos, String formato); + void enviarListaDeProductosPorEmail(String mailTo, byte[] listaDeProductos, String formato, String mensaje); + + void enviarListaDeProductosParaUsuariosSegunRol(Rol rol, BusquedaProductoCriteria criteria, String formato); + + void enviarCatalogoParaViajantes(); Producto guardar(NuevoProductoDTO producto, long idMedida, long idRubro, long idProveedor); diff --git a/src/main/java/sic/service/impl/GmailEmailServiceImpl.java b/src/main/java/sic/service/impl/GmailEmailServiceImpl.java index 9408dfc9..21bc0578 100644 --- a/src/main/java/sic/service/impl/GmailEmailServiceImpl.java +++ b/src/main/java/sic/service/impl/GmailEmailServiceImpl.java @@ -17,6 +17,16 @@ import javax.mail.PasswordAuthentication; import javax.mail.Transport; import sic.exception.BusinessServiceException; +import sic.modelo.EnvioDeCorreoGrupal; +import sic.modelo.Rol; +import sic.modelo.Usuario; +import sic.modelo.dto.EnvioDeCorreoGrupalDTO; +import sic.repository.EnvioDeCorreoGrupalRepository; +import sic.service.IUsuarioService; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; import sic.service.IEmailService; import java.util.Locale; import java.util.Properties; @@ -35,16 +45,21 @@ public class GmailEmailServiceImpl implements IEmailService { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final MessageSource messageSource; + private final EnvioDeCorreoGrupalRepository envioDeCorreoGrupalRepository; + private final IUsuarioService usuarioService; @Autowired - public GmailEmailServiceImpl(MessageSource messageSource) { + public GmailEmailServiceImpl(MessageSource messageSource, EnvioDeCorreoGrupalRepository envioDeCorreoGrupalRepository, + IUsuarioService usuarioService) { this.messageSource = messageSource; + this.envioDeCorreoGrupalRepository = envioDeCorreoGrupalRepository; + this.usuarioService = usuarioService; } @Override @Async public void enviarEmail( - String toEmail, + String[] toEmails, String bcc, String subject, String mensaje, @@ -69,7 +84,7 @@ protected PasswordAuthentication getPasswordAuthentication() { MimeMessage message = new MimeMessage(Session.getInstance(props, auth)); MimeMessageHelper helper = new MimeMessageHelper(message, true); helper.setFrom(emailUsername); - helper.setTo(toEmail); + helper.setTo(toEmails); if (bcc != null && !bcc.isEmpty()) helper.setBcc(bcc); helper.setSubject(subject); helper.setText(mensaje); @@ -86,4 +101,54 @@ protected PasswordAuthentication getPasswordAuthentication() { logger.error("Mail environment = {}, el mail NO se envió.", mailEnv); } } + + @Override + @Async + public void enviarEmail( + String toEmail, + String bcc, + String subject, + String mensaje, + byte[] byteArray, + String attachmentDescription) { + List correosDeUsuarios = new ArrayList<>(); + correosDeUsuarios.add(toEmail); + this.enviarEmail(correosDeUsuarios.toArray(String[]::new), bcc, subject, mensaje, byteArray, attachmentDescription); + } + + @Override + @Async + public EnvioDeCorreoGrupal enviarCorreoGrupal(EnvioDeCorreoGrupalDTO envioDeCorreoGrupalDTO) { + EnvioDeCorreoGrupal envioDeCorreoGrupal = this.crearEnvioDeCorreoGrupal(envioDeCorreoGrupalDTO); + List usuariosParaEnviarReporte = this.getUsuariosParaEnviaEmail(envioDeCorreoGrupalDTO.getRoles()); + List correosDeUsuarios = new ArrayList<>(); + usuariosParaEnviarReporte.stream().filter(usuario -> usuario.getEmail() != null) + .forEach(usuario -> correosDeUsuarios.add(usuario.getEmail())); + this.enviarEmail( + correosDeUsuarios.toArray(String[]::new), + emailUsername, + envioDeCorreoGrupalDTO.getAsunto(), + envioDeCorreoGrupalDTO.getMensaje(), + envioDeCorreoGrupal.getReporteAdjunto(), + envioDeCorreoGrupal.getDescripcionAdjunto()); + return envioDeCorreoGrupalRepository.save(this.crearEnvioDeCorreoGrupal(envioDeCorreoGrupalDTO)); + } + + private EnvioDeCorreoGrupal crearEnvioDeCorreoGrupal(EnvioDeCorreoGrupalDTO envioDeCorreoGrupalDTO) { + return EnvioDeCorreoGrupal.builder() + .fecha(LocalDateTime.now()) + .asunto(envioDeCorreoGrupalDTO.getAsunto()) + .roles(envioDeCorreoGrupalDTO.getRoles()) + .mensaje(envioDeCorreoGrupalDTO.getMensaje()) + .reporteAdjunto(envioDeCorreoGrupalDTO.getReporteAdjunto()) + .build(); + } + + private List getUsuariosParaEnviaEmail(List roles) { + List usuarios = new ArrayList<>(); + roles.forEach(rol -> { + usuarios.addAll(usuarioService.getUsuariosPorRol(rol).getContent()); + }); + return usuarios; + } } diff --git a/src/main/java/sic/service/impl/ProductoServiceImpl.java b/src/main/java/sic/service/impl/ProductoServiceImpl.java index 5287e4ed..ba7d9d48 100644 --- a/src/main/java/sic/service/impl/ProductoServiceImpl.java +++ b/src/main/java/sic/service/impl/ProductoServiceImpl.java @@ -11,6 +11,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.Scheduled; import sic.modelo.*; import java.math.BigDecimal; @@ -33,6 +34,7 @@ import sic.exception.BusinessServiceException; import sic.exception.ServiceException; import sic.modelo.criteria.BusquedaProductoCriteria; +import sic.modelo.criteria.BusquedaUsuarioCriteria; import sic.modelo.dto.*; import sic.modelo.embeddable.CantidadProductoEmbeddable; import sic.modelo.embeddable.PrecioProductoEmbeddable; @@ -1126,7 +1128,7 @@ public BigDecimal calcularPrecioLista(BigDecimal pvp, BigDecimal ivaPorcentaje) public void getListaDePreciosEnXls(BusquedaProductoCriteria criteria, long idSucursal) { List productos = this.buscarProductosParaReporte(criteria); this.enviarListaDeProductosPorEmail(sucursalService.getSucursalPorId(idSucursal).getEmail(), - this.getListaDePrecios(productos, FORMATO_XLSX), FORMATO_XLSX); + this.getListaDePrecios(productos, FORMATO_XLSX), FORMATO_XLSX, ""); } @Override @@ -1134,20 +1136,43 @@ public void getListaDePreciosEnXls(BusquedaProductoCriteria criteria, long idSuc public void getListaDePreciosEnPdf(BusquedaProductoCriteria criteria, long idSucursal) { List productos = this.buscarProductosParaReporte(criteria); this.enviarListaDeProductosPorEmail(sucursalService.getSucursalPorId(idSucursal).getEmail(), - this.getListaDePrecios(productos, FORMATO_PDF), FORMATO_PDF); + this.getListaDePrecios(productos, FORMATO_PDF), FORMATO_PDF, ""); } + @Async @Override - public void enviarListaDeProductosPorEmail(String mailTo, byte[] listaDeProductos, String formato) { + public void enviarListaDeProductosPorEmail(String mailTo, byte[] listaDeProductos, String formato, String mensaje) { emailService.enviarEmail( mailTo, "", "Listado de productos", - "", + mensaje, listaDeProductos, "ListaDeProductos." + formato); } + @Override + public void enviarListaDeProductosParaUsuariosSegunRol(Rol rol, BusquedaProductoCriteria criteria, String formato) { + Page usuariosParaEnviarReporte = usuarioService.getUsuariosPorRol(rol); + byte[] listaDeProductos = this.getListaDePrecios(this.buscarProductosParaReporte(criteria), formato); + usuariosParaEnviarReporte.get().filter(usuario -> usuario.getEmail() != null) + .forEach(usuario -> { + String mensaje = messageSource.getMessage( + "mensaje_producto_reporte_viajantes", new Object[]{usuario.getApellido() + usuario.getNombre()}, Locale.getDefault()); + this.enviarListaDeProductosPorEmail(usuario.getEmail(), listaDeProductos, formato, mensaje); + }); + } + + @Scheduled(cron = "50 0 0 ? * MON") // Todos los lunes 00:00:50 + @Override + public void enviarCatalogoParaViajantes() { + logger.warn( + messageSource.getMessage( + "mensaje_producto_reporte_catalogo", new Object[]{Rol.VIAJANTE}, Locale.getDefault())); + this.enviarListaDeProductosParaUsuariosSegunRol(Rol.VIAJANTE, BusquedaProductoCriteria.builder() + .listarSoloParaCatalogo(true).build(), FORMATO_PDF); + } + public byte[] getListaDePrecios(List productos, String formato) { Map params = new HashMap<>(); Sucursal sucursalPredeterminada = sucursalService.getSucursalPredeterminada(); diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index 553dbb63..95f5c1ca 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -51,6 +51,8 @@ mensaje_producto_oferta_sin_imagen=Para poder marcarlo como Oferta, debe tener i mensaje_producto_oferta_inferior_0=El % de oferta no puede ser 0% o inferior mensaje_producto_consulta_stock_sin_sucursal=Para poder consultar stock debe indicar una sucursal mensaje_producto_error_actualizar_cantidad_reservada=El estado del pedido no corresponde con uno permitido para actualizar la cantidad reservada +mensaje_producto_reporte_catalogo=Se envía catalogo a usuarios con rol: {0} +mensaje_producto_reporte_viajantes=Estimado {0}, se adjunta el catálogo de productos.\n Cualquier duda o sugerencia por favor contactenos. mensaje_producto_error_sorting_busqueda=El criterio de ordenamiento no es valido #ProductoFavorito