Commit 7960068e authored by anas jegoual's avatar anas jegoual

Merge branch 'anas' into 'master'

Schedule&Filter

See merge request !2
parents 128740d4 5b9938d3
File added
package bmci.esign.backendend.config;
import bmci.esign.backendend.services.DemandeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Component
@EnableAsync
@EnableScheduling
@Slf4j
public class ScheduleService {
private final DemandeService demandeService;
private static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");
public ScheduleService(DemandeService demandeService) {
this.demandeService = demandeService;
}
@Scheduled(cron = "0 0 10 * * *", zone = "Africa/Casablanca")
public void scheduleTaskWithFixedDelay(){
log.info("Fixed Task :: Execution Time - {}", dateTimeFormatter.format(LocalDateTime.now()));
// demandeService.findDemandesByExpirationDateBeforeAndStatut
demandeService.cancelExpiredDm();
}
}
package bmci.esign.backendend.controllers;
import bmci.esign.backendend.dto.DemandeDto;
import bmci.esign.backendend.dto.request.FilterDto;
import bmci.esign.backendend.dto.request.GlobaleRequestDto;
import bmci.esign.backendend.dto.response.DashboardChart;
import bmci.esign.backendend.dto.response.TableDto;
import bmci.esign.backendend.models.ResponseModelStandard;
import bmci.esign.backendend.models.enums.EStatut;
import bmci.esign.backendend.services.DemandeService;
......@@ -12,19 +13,26 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@RestController
@RequestMapping("/demande")
@Slf4j
public class DemandeController {
private final DemandeService demandeService;
public DemandeController(DemandeService demandeService) {
this.demandeService = demandeService;
}
@Autowired
private DemandeService demandeService;
@PostMapping("/add")
@PostMapping("/add")
public ResponseModelStandard<Long> addDemande(@RequestBody DemandeDto demandeDto){
log.info("NEW°DM.... {}",demandeDto.getTypeDocument());
try {
......@@ -123,4 +131,22 @@ public class DemandeController {
return new ResponseModelStandard<>("099");
}
}
@PostMapping("/global")
public ResponseModelStandard<Page<TableDto>> loadGlobalFilteredDm(@RequestBody GlobaleRequestDto dto){
try {
if(dto.getPage() == null || dto.getSize() == null || dto.getPage() < 0 || dto.getSize() <= 0){
return new ResponseModelStandard<>("099","Page or Size cannot be negative or Null");
}
return new ResponseModelStandard<>("000", demandeService.loadGlobalFiltered(dto));
}catch (Exception e){
return new ResponseModelStandard<>("099");
}
}
@PostMapping("/check")
public ResponseModelStandard<?> loadGlobalFilteredDm(){
return new ResponseModelStandard<>("000", demandeService.cancelExpiredDm());
}
}
......@@ -3,6 +3,7 @@ package bmci.esign.backendend.controllers;
import bmci.esign.backendend.dto.DemandeDto;
import bmci.esign.backendend.dto.DestinataireDto;
import bmci.esign.backendend.dto.request.FilterDto;
import bmci.esign.backendend.dto.request.RejectRequestDto;
import bmci.esign.backendend.dto.response.DashboardChart;
import bmci.esign.backendend.models.ResponseModelStandard;
import bmci.esign.backendend.services.DestinataireService;
......@@ -60,4 +61,9 @@ public class DestinataireController {
return new ResponseModelStandard<>("099");
}
}
@PostMapping("/reject")
public ResponseModelStandard<?> rejectDm(@RequestBody RejectRequestDto dto){
return new ResponseModelStandard<>("000", destinataireService.rejectDemandByDestinataire(dto));
}
}
\ No newline at end of file
package bmci.esign.backendend.dto;
import bmci.esign.backendend.models.User;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AllArgsConstructor;
......@@ -22,6 +23,10 @@ public class DestinataireDto {
private int place;
@JsonIgnore
private DemandeDto demande;
@JsonIgnore
private User recipient;
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
private Date creationDate;
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
......
package bmci.esign.backendend.dto;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@AllArgsConstructor
public class RecipientDto {
private Long id;
private String name;
private String email;
private String role;
private String statut;
}
......@@ -4,8 +4,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.Date;
import java.time.LocalDate;
@Getter
@Setter
......@@ -15,9 +14,10 @@ public class FilterDto {
private int page;
private int size;
private String email;
private Date createdDate;
private LocalDate createdDate;
private String demandeType;
private String priority;
private String statut;
@Override
public String toString() {
......@@ -27,7 +27,6 @@ public class FilterDto {
", email='" + email + '\'' +
", createdDate=" + createdDate +
", demandeType='" + demandeType + '\'' +
", priority='" + priority + '\'' +
'}';
}
}
\ No newline at end of file
package bmci.esign.backendend.dto.request;
import bmci.esign.backendend.models.enums.EStatut;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class GlobaleRequestDto {
private String email;
private Integer page;
private Integer size;
private String creationDate;
private EStatut statut;
private String type;
}
package bmci.esign.backendend.dto.request;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class RejectRequestDto {
private Long demandId;
private String email;
}
\ No newline at end of file
package bmci.esign.backendend.dto.response;
import bmci.esign.backendend.models.enums.EStatut;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.Date;
@Getter
@Setter
@AllArgsConstructor
public class TableDto implements Serializable {
private Long id;
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
private Date creationDate;
private String demandeType;
private String typeDocument;
// private List<RecipientDto> destinataires;
private int destinataires;
private String statut;
public String getStatut() {
return EStatut.valueOf(statut).getDisplayName();
}
}
package bmci.esign.backendend.dto.response;
import camundajar.impl.com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class TableResponseDto {
@SerializedName("data")
private TableDto data;
private int totalElements;
private int totalPages;
}
......@@ -20,12 +20,10 @@ public abstract class AuditorEntity {
protected Long id;
@CreationTimestamp
// @Column(name = "creationDate", columnDefinition = "TIMESTAMP", nullable = false, updatable = false)
@Temporal(TemporalType.TIMESTAMP)
protected Date creationDate;
@UpdateTimestamp
// @Column(name = "modificationDate", columnDefinition = "TIMESTAMP", nullable = false)
@Temporal(TemporalType.TIMESTAMP)
protected Date modificationDate;
}
\ No newline at end of file
......@@ -21,22 +21,30 @@ public class Destinataire {
private String name;
private String email;
private String role;
@Enumerated(EnumType.STRING)
@Column(length = 50)
private EStatut statut;
private String envoie;
private int place;
@ManyToOne
@JoinColumn(name = "demande_id")
@JsonIgnore
// @JsonBackReference
private Demande demande;
@ManyToOne
@JoinColumn(name = "user_id")
private User recipient;
@CreationTimestamp
@Temporal(TemporalType.TIMESTAMP)
private Date creationDate;
@UpdateTimestamp
@Temporal(TemporalType.TIMESTAMP)
private Date modificationDate;
@OneToMany(mappedBy = "destinataire")
private List<Position> positions;
}
......@@ -25,17 +25,24 @@ public class User extends AuditorEntity implements Serializable {
private String email;
@Column(length = 60)
private String password;
/*
@OneToMany(mappedBy = "sender")
@JsonIgnore
private List<Demande> sentDemandes = new ArrayList<>();
@OneToMany(mappedBy = "user") @JsonIgnore
private List<Demande> demandes = new ArrayList<>();
@OneToMany(mappedBy = "user") @JsonIgnore
@OneToMany(mappedBy = "recipient")
@JsonIgnore
private List<Destinataire> receivedDemandes = new ArrayList<>();
*/
@OneToMany(mappedBy = "user")
@JsonIgnore
private List<Signature> signatures = new ArrayList<>();
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable( name = "user_authority",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "authority_id")
@JoinTable(
name = "user_authority",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "authority_id")
)
private Set<Authority> authorities;
}
......@@ -4,6 +4,7 @@ public enum EStatut {
WAITING("En attente"),
CANCELED("Expiré"),
COMPLETE("Signé");
// REJECTED("Rejeté");
private final String displayName;
EStatut(String displayName) {
......
......@@ -2,20 +2,25 @@ package bmci.esign.backendend.repositories;
import bmci.esign.backendend.dto.response.DashboardChart;
import bmci.esign.backendend.models.Demande;
import bmci.esign.backendend.models.enums.EStatut;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.Date;
import java.util.List;
@Repository
public interface DemandeRepository extends JpaRepository<Demande, Long>, JpaSpecificationExecutor<Demande> {
List<Demande> findAllByUserId(Long id);
@Query(value = "SELECT count(d.id) as count, d.statut as statut FROM Demande d WHERE d.user.email= :email GROUP BY d.statut")
List<DashboardChart> loadSignaturesChart(@Param("email") String email);
List<Demande> findAllByExpirationDateBeforeAndStatut(Date date, EStatut eStatut);
@Modifying
@Query("UPDATE Demande d set d.statut = :newStatut WHERE d.id = :id")
int updateExpiredById(@Param("id") Long id, @Param("newStatut") EStatut newStatut);
}
/*
SELECT statut as statut, SUM(count) as total
......
......@@ -18,4 +18,5 @@ public interface DestinataireRepository extends JpaRepository<Destinataire, Long
@Query(value = "SELECT count(d.id) as count, d.statut as statut FROM Destinataire d WHERE d.email= :email GROUP BY d.statut")
List<DashboardChart> loadSignDm(@Param("email") String email);
Optional<Destinataire> findByEmail(String email);
Destinataire findByDemandeIdAndEmail(Long id, String email);
}
......@@ -2,7 +2,9 @@ package bmci.esign.backendend.services;
import bmci.esign.backendend.dto.DemandeDto;
import bmci.esign.backendend.dto.request.FilterDto;
import bmci.esign.backendend.dto.request.GlobaleRequestDto;
import bmci.esign.backendend.dto.response.DashboardChart;
import bmci.esign.backendend.dto.response.TableDto;
import bmci.esign.backendend.models.Demande;
import org.springframework.data.domain.Page;
......@@ -25,4 +27,6 @@ public interface DemandeService {
Page<DemandeDto> findDemandesByUser(FilterDto filterDto);
List<DashboardChart> loadReceivedChart(String email);
List<DashboardChart> loadGlobalData(String email);
Page<TableDto> loadGlobalFiltered(GlobaleRequestDto globaleRequestDto);
int cancelExpiredDm();
}
......@@ -3,6 +3,7 @@ package bmci.esign.backendend.services;
import bmci.esign.backendend.dto.DemandeDto;
import bmci.esign.backendend.dto.DestinataireDto;
import bmci.esign.backendend.dto.request.FilterDto;
import bmci.esign.backendend.dto.request.RejectRequestDto;
import bmci.esign.backendend.dto.response.DashboardChart;
import bmci.esign.backendend.models.Destinataire;
import org.springframework.data.domain.Page;
......@@ -18,4 +19,5 @@ public interface DestinataireService {
List<DestinataireDto> findAllByDemandeId(Long id);
Page<DemandeDto> findAllDemandesToSigne(FilterDto destinataireFilterDto);
List<DashboardChart> loadSignDmChart(String email);
String rejectDemandByDestinataire(RejectRequestDto dto);
}
......@@ -23,13 +23,12 @@ public class CamundaUserService {
public void updateUser(String userId, String newFirstName, String newLastName, String newEmail) {
User user = identityService.createUserQuery().userId(userId).singleResult();
if (user != null) {
user.setFirstName(newFirstName);
user.setLastName(newLastName);
user.setEmail(newEmail);
if (user != null) {
user.setFirstName(newFirstName);
user.setLastName(newLastName);
user.setEmail(newEmail);
identityService.saveUser(user);
identityService.saveUser(user);
}
}
}
}
}
\ No newline at end of file
package bmci.esign.backendend.services.impl;
import bmci.esign.backendend.models.Demande;
import bmci.esign.backendend.models.Destinataire;
import bmci.esign.backendend.models.User;
import bmci.esign.backendend.models.enums.EStatut;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.jpa.domain.Specification;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
@Slf4j
public class DemandeSpecification {
private static final String date_pattern ="yyyy-MM-dd"; // "dd-MM-yyyy"
public static Specification<Demande> isSentBy(User user) {
return (root, query, criteriaBuilder) ->
criteriaBuilder.equal(root.get("user"), user);
}
public static Specification<Demande> isReceivedBy(User user) {
return (root, query, criteriaBuilder) -> {
Join<Demande, Destinataire> join = root.join("destinataires", JoinType.INNER);
return criteriaBuilder.equal(join.get("recipient"), user);
};
}
public static Specification<Demande> hasStatus(EStatut statut) {
return (root, query, criteriaBuilder) ->
criteriaBuilder.equal(root.get("statut"), statut);
}
public static Specification<Demande> withDate(String creationDate) {
try {
Date date = new SimpleDateFormat(date_pattern).parse(creationDate);
log.info("creationDate_string: {} -> parse_date {}", creationDate, date);
return (root, query, criteriaBuilder) ->
criteriaBuilder.equal(
criteriaBuilder.function("DATE", Date.class, root.get("creationDate")),
date);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
\ No newline at end of file
......@@ -3,11 +3,14 @@ package bmci.esign.backendend.services.impl;
import bmci.esign.backendend.dto.DemandeDto;
import bmci.esign.backendend.dto.DestinataireDto;
import bmci.esign.backendend.dto.request.FilterDto;
import bmci.esign.backendend.dto.request.RejectRequestDto;
import bmci.esign.backendend.dto.response.DashboardChart;
import bmci.esign.backendend.dto.services.IMapClassWithDto;
import bmci.esign.backendend.models.Demande;
import bmci.esign.backendend.models.Destinataire;
import bmci.esign.backendend.models.enums.EDemande;
import bmci.esign.backendend.models.enums.EStatut;
import bmci.esign.backendend.repositories.DemandeRepository;
import bmci.esign.backendend.repositories.DestinataireRepository;
import bmci.esign.backendend.services.DestinataireService;
import lombok.extern.slf4j.Slf4j;
......@@ -17,21 +20,27 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
@Service
@Slf4j
public class DestinataireServiceImpl implements DestinataireService {
private final DestinataireRepository destinataireRepository;
private final DemandeRepository demandeRepository;
private final IMapClassWithDto<Destinataire, DestinataireDto> destinataireMapping;
private final IMapClassWithDto<Demande, DemandeDto> demandeMapping;
public DestinataireServiceImpl(DestinataireRepository destinataireRepository, IMapClassWithDto<Destinataire, DestinataireDto> destinataireMapping, IMapClassWithDto<Demande, DemandeDto> demandeMapping) {
public DestinataireServiceImpl(DestinataireRepository destinataireRepository, DemandeRepository demandeRepository, IMapClassWithDto<Destinataire, DestinataireDto> destinataireMapping, IMapClassWithDto<Demande, DemandeDto> demandeMapping) {
this.destinataireRepository = destinataireRepository;
this.demandeRepository = demandeRepository;
this.destinataireMapping = destinataireMapping;
this.demandeMapping = demandeMapping;
}
......@@ -98,14 +107,19 @@ public class DestinataireServiceImpl implements DestinataireService {
return (root, query, criteriaBuilder) -> {
List<Predicate> predicates = new ArrayList<>();
if (dto.getCreatedDate() != null) {
log.info("creation_date: {}",dto.getCreatedDate());
predicates.add(criteriaBuilder.equal(root.get("creation_date"), dto.getCreatedDate()));
Expression<LocalDate> creationDateExpression = criteriaBuilder.function(
"date", LocalDate.class, root.get("creationDate"));
predicates.add(criteriaBuilder.equal(creationDateExpression, dto.getCreatedDate()));
}
if (dto.getDemandeType() != null) {
log.info("envoie: {}",dto.getDemandeType());
predicates.add(criteriaBuilder.equal(root.get("envoie"), EDemande.fromString(dto.getDemandeType())));
}
if(dto.getPriority() != null){
log.info("priority: {}",dto.getPriority());
predicates.add(criteriaBuilder.equal(root.get("demande").get("priority"), dto.getPriority()));
if(dto.getStatut() != null){
log.info("statut: {}",dto.getStatut());
predicates.add(criteriaBuilder.equal(root.get("statut"), EStatut.fromString(dto.getStatut())));
}
predicates.add(criteriaBuilder.equal(root.get("statut"), EStatut.WAITING));
// predicates.add(criteriaBuilder.equal(root.get("statut"), EStatut.WAITING));
predicates.add(criteriaBuilder.equal(root.get("email"), dto.getEmail()));
return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
......@@ -125,9 +139,48 @@ public class DestinataireServiceImpl implements DestinataireService {
return null;
}
return destinataireMapping.mappingData(destinataireRepository.loadSignDm(email));
}catch (Exception e){
} catch (Exception e){
log.error("EXCEPTION<>loadSignaturesChart: {}", e.getMessage(), e);
return Collections.emptyList();
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public String rejectDemandByDestinataire(RejectRequestDto dto) {
log.info("PROCESSING.... rejectDemandByDestinataire ID {}", dto.getDemandId());
try {
if(dto.getEmail() == null){
log.warn("Email cannot be null");
return "failed";
}
Optional<Demande> demande=demandeRepository.findById(dto.getDemandId());
if(demande.isEmpty()){
log.error("Demand NotFound With id: {}",dto.getDemandId());
return "failed";
}
Destinataire userAction=destinataireRepository.findByDemandeIdAndEmail(dto.getDemandId(), dto.getEmail());
List<Destinataire> destinataireList= destinataireRepository.findAllByDemandeId(dto.getDemandId());
log.warn("destinataireList SIZE {}",destinataireList.size());
log.info("Destinataire {} email {} statut {}",userAction.getId(), userAction.getEmail(), userAction.getStatut());
if(demande.get().getEdemande().equals(EDemande.SEQUENCE)){
log.warn("DM_TYPE {} PLACE {}",demande.get().getEdemande(), userAction.getPlace());
destinataireList.forEach(destinataire1 -> {
if (destinataire1.getPlace() > userAction.getPlace()){
destinataire1.setStatut(EStatut.CANCELED);
destinataireRepository.save(destinataire1);
}
});
}
userAction.setStatut(EStatut.CANCELED);
destinataireRepository.save(userAction);
demande.get().setStatut(EStatut.CANCELED);
demandeRepository.save(demande.get());
return "success";
} catch (Exception e){
log.error("Exception<rejectDemandByDestinataire> message: {} class {}",e.getMessage(),e.getClass(),e);
return "failed";
}
}
}
......@@ -19,6 +19,10 @@ import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
......@@ -37,7 +41,8 @@ public class EmailServiceImpl implements EmailService {
private String senderMail;
private static final String CHARACTERS = "0123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
private static final int CODE_LENGTH = 16;
// private static final String TEMPLATE_NAME="sendDoc.ftl";
private static final String TEMPLATE_NAME="test.ftl";
@Override
public String generateVerificationCode() {
Random random = new Random();
......@@ -58,21 +63,22 @@ public class EmailServiceImpl implements EmailService {
log.info("PROCESSING<>{sendEmail} REQUEST {}", req.toString());
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = null;
String template_name = "";
String subject = "" ;
String url_sign = "";
Template template = null;
try {
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withLocale(Locale.FRANCE);
// File footerfile = ResourceUtils.getFile("classpath:" + Utils.staticImgFolder + "file_footer.png");
helper = new MimeMessageHelper( mimeMessage, true);
if(req.getEmail_type().equals("bmci_t1")) {
template_name="sendDoc.ftl" ;
subject=model.get("objet") ;
url_sign= generateVerificationCode();
model.put("url_sign", environment.getProperty("url.esign.acess")+":"+url_sign);
model.put("day_date", LocalDateTime.now().format(formatter));
model.put("message", model.get("message"));
}
template = config.getTemplate(template_name);
template = config.getTemplate(TEMPLATE_NAME);
String HtmlMsg = FreeMarkerTemplateUtils.processTemplateIntoString(template,model) ;
req.setToken(url_sign);
......
spring.application.name=backend-esign
# App Properties
spring.mvc.converters.preferred-json-mapper=gson
server.address=localhost
server.address=192.168.1.23
server.servlet.context-path=/esignback
#server.address=192.168.11.106
#server.servlet-path=/*
......@@ -45,4 +45,3 @@ file.upload-dir.access=/Users/anace/Desktop/InDataCore/bmsi/Documents/SIGNATURES
url.esign.acess=http://localhost:4200/#/online-signature/
#url.esign.acess=https://skyanalytics.indatacore.com/esign/#/online-signature/
<!doctype html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Simple Transactional Email</title>
<style media="all">
body {
font-family: Helvetica, sans-serif;
-webkit-font-smoothing: antialiased;
font-size: 16px;
line-height: 1.3;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
table {
border-collapse: separate;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
width: 100%;
}
table td {
font-family: Helvetica, sans-serif;
font-size: 16px;
vertical-align: top;
}
body {
background-color: #f4f5f6;
margin: 0;
padding: 0;
}
.body {
background-color: #f4f5f6;
width: 100%;
}
.container {
margin: 0 auto !important;
max-width: 600px;
padding: 0;
padding-top: 24px;
width: 600px;
}
.content {
box-sizing: border-box;
display: block;
margin: 0 auto;
max-width: 600px;
padding: 0;
}
.main {
background: #ffffff;
border: 1px solid #eaebed;
border-radius: 16px;
width: 100%;
}
.wrapper {
box-sizing: border-box;
padding: 24px;
}
.footer {
clear: both;
padding-top: 24px;
text-align: center;
width: 100%;
}
.footer td,
.footer p,
.footer span,
.footer a {
color: #9a9ea6;
font-size: 16px;
text-align: center;
}
p {
font-family: Helvetica, sans-serif;
font-size: 16px;
font-weight: normal;
margin: 0;
margin-bottom: 16px;
}
a {
color: #0867ec;
text-decoration: underline;
}
.btn {
box-sizing: border-box;
min-width: 100% !important;
width: 100%;
}
.btn > tbody > tr > td {
padding-bottom: 16px;
}
.btn table {
width: auto;
}
.btn table td {
background-color: #ffffff;
border-radius: 4px;
text-align: center;
}
.btn a {
background-color: #ffffff;
border: solid 1px #28a745;
border-radius: 2px;
box-sizing: border-box;
color: #28a745;
cursor: pointer;
display: inline-block;
font-size: 14px;
font-weight: bold;
margin: 0;
padding: 8px 18px;
text-decoration: none;
text-transform: capitalize;
}
.btn-primary table td {
background: linear-gradient(45deg, #07674D, #0ECD99);
}
.btn-primary a {
background: linear-gradient(45deg, #07674D, #0ECD99);
border-color: #07674D;
color: #ffffff;
text-decoration: none;
display: inline-block;
padding: 10px 20px;
border-radius: 5px;
}
@media all {
.btn-primary table td:hover {
background-color: #218838 !important;
}
.btn-primary a:hover {
background-color: #218838 !important;
border-color: #218838 !important;
}
}
.powered-by a {
text-decoration: none;
}
@media only screen and (max-width: 640px) {
.main p,
.main td,
.main span {
font-size: 16px !important;
}
.wrapper {
padding: 8px !important;
}
.content {
padding: 0 !important;
}
.container {
padding: 0 !important;
padding-top: 8px !important;
width: 100% !important;
}
.btn table {
max-width: 100% !important;
width: 100% !important;
}
.btn a {
font-size: 16px !important;
max-width: 100% !important;
width: 100% !important;
}
}
@media all {
.apple-link a {
color: inherit !important;
font-family: inherit !important;
font-size: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
text-decoration: none !important;
}
#MessageViewBody a {
color: inherit;
text-decoration: none;
font-size: inherit;
font-family: inherit;
font-weight: inherit;
line-height: inherit;
}
}
</style>
</head>
<body>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="body">
<tr>
<td>&nbsp;</td>
<td class="container">
<div class="content">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td class="wrapper">
<p>Bonjour ${name},</p>
<p>${message}</p>
<p>Veuillez cliquer sur le lien ci-dessous pour procéder à la signature :</p>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="btn btn-primary">
<tbody>
<tr>
<td align="left">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td> <a href="${url_sign}" target="_blank">Cliquez ici pour signer</a> </td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</table>
<div class="footer">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td class="content-block">
<span class="apple-link">BANQUE MAROCAINE POUR LE COMMERCE ET L'INDUSTRIE (BMCI)</span>
</td>
</tr>
<tr>
<td class="content-block powered-by">
Fait à <b> Casablanca </b> le &nbsp;<span>${day_date}</span>
</td>
</tr>
</table>
</div>
</div>
</td>
<td>&nbsp;</td>
</tr>
</table>
</body>
</html>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment