Skip to content
Snippets Groups Projects
Commit d9a17a20 authored by CHERIF Maram's avatar CHERIF Maram
Browse files

new_feat

parent efaa68d0
No related branches found
No related tags found
No related merge requests found
Showing
with 210 additions and 81 deletions
package fr.atlantique.imt.inf211.jobmngt.controller; package fr.atlantique.imt.inf211.jobmngt.controller;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
...@@ -17,7 +18,9 @@ import org.springframework.web.bind.annotation.RequestMapping; ...@@ -17,7 +18,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes; import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import fr.atlantique.imt.inf211.jobmngt.entity.Company;
import fr.atlantique.imt.inf211.jobmngt.entity.JobOffer; import fr.atlantique.imt.inf211.jobmngt.entity.JobOffer;
import fr.atlantique.imt.inf211.jobmngt.entity.QualificationLevel;
import fr.atlantique.imt.inf211.jobmngt.entity.Sector; import fr.atlantique.imt.inf211.jobmngt.entity.Sector;
import fr.atlantique.imt.inf211.jobmngt.service.CompanyService; import fr.atlantique.imt.inf211.jobmngt.service.CompanyService;
import fr.atlantique.imt.inf211.jobmngt.service.JobOfferService; import fr.atlantique.imt.inf211.jobmngt.service.JobOfferService;
...@@ -28,12 +31,13 @@ import fr.atlantique.imt.inf211.jobmngt.service.SectorService; ...@@ -28,12 +31,13 @@ import fr.atlantique.imt.inf211.jobmngt.service.SectorService;
@RequestMapping("/jobs") @RequestMapping("/jobs")
public class JobOfferController { public class JobOfferController {
private static final Logger log = LoggerFactory.getLogger(JobOfferController.class); // ✅ Ajout du logger
private final JobOfferService jobOfferService; private final JobOfferService jobOfferService;
private final CompanyService companyService; private final CompanyService companyService;
private final QualificationLevelService qualificationLevelService; private final QualificationLevelService qualificationLevelService;
private final SectorService sectorService; private final SectorService sectorService;
@Autowired @Autowired
public JobOfferController(JobOfferService jobOfferService, public JobOfferController(JobOfferService jobOfferService,
CompanyService companyService, CompanyService companyService,
...@@ -49,7 +53,7 @@ public class JobOfferController { ...@@ -49,7 +53,7 @@ public class JobOfferController {
@GetMapping @GetMapping
public String listJobOffers(Model model) { public String listJobOffers(Model model) {
List<JobOffer> jobOffers = jobOfferService.getAllJobOffers(); List<JobOffer> jobOffers = jobOfferService.getAllJobOffers();
System.out.println("🔎 Nombre d'offres récupérées: " + jobOffers.size()); log.info("🔎 Nombre d'offres récupérées: {}", jobOffers.size());
model.addAttribute("jobOffers", jobOffers); model.addAttribute("jobOffers", jobOffers);
return "jobOffer/jobOfferList"; return "jobOffer/jobOfferList";
...@@ -68,28 +72,32 @@ public class JobOfferController { ...@@ -68,28 +72,32 @@ public class JobOfferController {
} }
} }
// ✅ Affiche le formulaire de création avec sélection des secteurs // ✅ Affiche le formulaire de création
@GetMapping("/create") @GetMapping("/create")
public String showCreateForm(Model model) { public String showCreateForm(Model model) {
JobOffer jobOffer = new JobOffer(); List<QualificationLevel> levels = qualificationLevelService.listOfQualificationLevels();
jobOffer.setPublicationDate(new Date()); List<Company> companies = companyService.getAllCompanies();
List<Sector> sectors = sectorService.listOfSectors();
model.addAttribute("jobOffer", jobOffer);
model.addAttribute("companies", companyService.getAllCompanies()); // Ajout des logs pour voir si les listes sont vides
model.addAttribute("qualificationLevels", qualificationLevelService.listOfQualificationLevels()); log.info("Loaded Qualification Levels: {}", levels.size());
model.addAttribute("sectors", sectorService.listOfSectors()); log.info("Loaded Companies: {}", companies.size());
log.info("Loaded Sectors: {}", sectors.size());
model.addAttribute("jobOffer", new JobOffer());
model.addAttribute("qualificationLevels", levels);
model.addAttribute("companies", companies);
model.addAttribute("sectors", sectors);
return "jobOffer/jobOfferForm"; return "jobOffer/jobOfferForm";
} }
// ✅ Enregistre une offre avec gestion des secteurs et des erreurs // ✅ Enregistre une offre avec gestion des secteurs et des erreurs
@PostMapping("/save") @PostMapping("/save")
public String saveJobOffer(@ModelAttribute JobOffer jobOffer, public String saveJobOffer(@ModelAttribute JobOffer jobOffer,
@RequestParam(value = "sectorIds", required = false) List<Integer> sectorIds, @RequestParam(value = "sectorIds", required = false) List<Integer> sectorIds,
RedirectAttributes redirectAttributes) { RedirectAttributes redirectAttributes) {
try { try {
System.out.println("🔹 Tentative d'enregistrement: " + jobOffer); log.info("🔹 Tentative d'enregistrement: {}", jobOffer);
// Associer les secteurs sélectionnés à l'offre d'emploi // Associer les secteurs sélectionnés à l'offre d'emploi
if (sectorIds != null && !sectorIds.isEmpty()) { if (sectorIds != null && !sectorIds.isEmpty()) {
...@@ -97,23 +105,22 @@ public String saveJobOffer(@ModelAttribute JobOffer jobOffer, ...@@ -97,23 +105,22 @@ public String saveJobOffer(@ModelAttribute JobOffer jobOffer,
.map(sectorService::findById) .map(sectorService::findById)
.filter(Optional::isPresent) .filter(Optional::isPresent)
.map(Optional::get) .map(Optional::get)
.collect(Collectors.toSet()); // Convertir la liste en Set .collect(Collectors.toSet());
jobOffer.setSectors(selectedSectors); // Affectation corrigée jobOffer.setSectors(selectedSectors);
} }
jobOfferService.saveJobOffer(jobOffer); jobOfferService.saveJobOffer(jobOffer);
System.out.println("✅ Enregistrement réussi !"); log.info("✅ Enregistrement réussi !");
redirectAttributes.addFlashAttribute("successMessage", "✅ Offre d'emploi créée avec succès !"); redirectAttributes.addFlashAttribute("successMessage", "✅ Offre d'emploi créée avec succès !");
return "redirect:/jobs"; return "redirect:/jobs";
} catch (Exception e) { } catch (Exception e) {
System.err.println("❌ Erreur lors de l'enregistrement: " + e.getMessage()); log.error("❌ Erreur lors de l'enregistrement: {}", e.getMessage());
redirectAttributes.addFlashAttribute("errorMessage", "❌ Erreur lors de la création de l'offre !"); redirectAttributes.addFlashAttribute("errorMessage", "❌ Erreur lors de la création de l'offre !");
return "redirect:/jobs/create"; return "redirect:/jobs/create";
} }
} }
// ✅ Supprime une offre d'emploi // ✅ Supprime une offre d'emploi
@GetMapping("/delete/{id}") @GetMapping("/delete/{id}")
public String deleteJobOffer(@PathVariable("id") int id, RedirectAttributes redirectAttributes) { public String deleteJobOffer(@PathVariable("id") int id, RedirectAttributes redirectAttributes) {
...@@ -124,6 +131,7 @@ public String deleteJobOffer(@PathVariable("id") int id, RedirectAttributes redi ...@@ -124,6 +131,7 @@ public String deleteJobOffer(@PathVariable("id") int id, RedirectAttributes redi
jobOfferService.deleteJobOffer(id); jobOfferService.deleteJobOffer(id);
redirectAttributes.addFlashAttribute("successMessage", "✅ Offre d'emploi supprimée avec succès !"); redirectAttributes.addFlashAttribute("successMessage", "✅ Offre d'emploi supprimée avec succès !");
} catch (Exception e) { } catch (Exception e) {
log.error("❌ Erreur lors de la suppression de l'offre: {}", e.getMessage());
redirectAttributes.addFlashAttribute("errorMessage", "❌ Erreur lors de la suppression de l'offre !"); redirectAttributes.addFlashAttribute("errorMessage", "❌ Erreur lors de la suppression de l'offre !");
} }
} else { } else {
...@@ -133,10 +141,6 @@ public String deleteJobOffer(@PathVariable("id") int id, RedirectAttributes redi ...@@ -133,10 +141,6 @@ public String deleteJobOffer(@PathVariable("id") int id, RedirectAttributes redi
return "redirect:/jobs"; return "redirect:/jobs";
} }
// ✅ Affiche le formulaire de modification // ✅ Affiche le formulaire de modification
@GetMapping("/{id}/edit") @GetMapping("/{id}/edit")
public String showEditForm(@PathVariable("id") int id, Model model, RedirectAttributes redirectAttributes) { public String showEditForm(@PathVariable("id") int id, Model model, RedirectAttributes redirectAttributes) {
...@@ -153,7 +157,3 @@ public String deleteJobOffer(@PathVariable("id") int id, RedirectAttributes redi ...@@ -153,7 +157,3 @@ public String deleteJobOffer(@PathVariable("id") int id, RedirectAttributes redi
} }
} }
} }
...@@ -8,6 +8,7 @@ import org.springframework.format.annotation.DateTimeFormat; ...@@ -8,6 +8,7 @@ import org.springframework.format.annotation.DateTimeFormat;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
import jakarta.persistence.FetchType; import jakarta.persistence.FetchType;
...@@ -33,14 +34,14 @@ public class JobOffer implements java.io.Serializable { ...@@ -33,14 +34,14 @@ public class JobOffer implements java.io.Serializable {
@SequenceGenerator(name = "JOBOFFER_ID_GENERATOR", sequenceName = "JOBOFFER_ID_SEQ", allocationSize = 1) @SequenceGenerator(name = "JOBOFFER_ID_GENERATOR", sequenceName = "JOBOFFER_ID_SEQ", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "JOBOFFER_ID_GENERATOR") @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "JOBOFFER_ID_GENERATOR")
@Column(name="id", unique = true, nullable = false) @Column(name="id", unique = true, nullable = false)
private int id; private Integer id; // 🔹 Modifié de int à Integer
@ManyToOne(fetch = FetchType.LAZY) @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "compid", nullable = false) @JoinColumn(name = "compid", nullable = true) // 🔹 nullable = true pour éviter les erreurs si null
private Company company; private Company company;
@ManyToOne(fetch = FetchType.LAZY) @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "qualiflevelid", nullable = false) @JoinColumn(name = "qualiflevelid", nullable = true) // 🔹 nullable = true pour éviter les erreurs si null
private QualificationLevel qualificationLevel; private QualificationLevel qualificationLevel;
@Column(name="title", nullable = false, length = 50) @Column(name="title", nullable = false, length = 50)
...@@ -54,26 +55,26 @@ public class JobOffer implements java.io.Serializable { ...@@ -54,26 +55,26 @@ public class JobOffer implements java.io.Serializable {
@Column(name="publicationdate") @Column(name="publicationdate")
private Date publicationDate; private Date publicationDate;
@ManyToMany(fetch = FetchType.LAZY) @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) // 🔹 Ajout du cascade pour assurer la persistance
@JoinTable(name="indexjoboffersector", schema="public", @JoinTable(name="indexjoboffersector", schema="public",
joinColumns = { @JoinColumn(name="jobofferid", nullable = false, updatable = false) }, joinColumns = { @JoinColumn(name="jobofferid", nullable = false, updatable = false) },
inverseJoinColumns = { @JoinColumn(name="sectorid", nullable = false, updatable = false) }) inverseJoinColumns = { @JoinColumn(name="sectorid", nullable = false, updatable = false) })
@JsonIgnoreProperties({"applications", "jobOffers"}) // Empêche les boucles JSON infinies @JsonIgnoreProperties({"applications", "jobOffers"}) // Empêche les boucles JSON infinies
private Set<Sector> sectors = new HashSet<>(); private Set<Sector> sectors = new HashSet<>();
@OneToMany(fetch = FetchType.LAZY, mappedBy = "jobOffer") // Correction du mappedBy @OneToMany(fetch = FetchType.LAZY, mappedBy = "jobOffer", cascade = CascadeType.ALL) // 🔹 Ajout du cascade
private Set<OfferMessage> offerMessages = new HashSet<>(); private Set<OfferMessage> offerMessages = new HashSet<>();
public JobOffer() {} public JobOffer() {}
public JobOffer(int id, Company company, QualificationLevel qualificationLevel, String title) { public JobOffer(Integer id, Company company, QualificationLevel qualificationLevel, String title) {
this.id = id; this.id = id;
this.company = company; this.company = company;
this.qualificationLevel = qualificationLevel; this.qualificationLevel = qualificationLevel;
this.title = title; this.title = title;
} }
public JobOffer(int id, Company company, QualificationLevel qualificationLevel, String title, public JobOffer(Integer id, Company company, QualificationLevel qualificationLevel, String title,
String taskDescription, Date publicationDate, Set<Sector> sectors, Set<OfferMessage> offerMessages) { String taskDescription, Date publicationDate, Set<Sector> sectors, Set<OfferMessage> offerMessages) {
this.id = id; this.id = id;
this.company = company; this.company = company;
...@@ -85,8 +86,8 @@ private Date publicationDate; ...@@ -85,8 +86,8 @@ private Date publicationDate;
this.offerMessages = offerMessages; this.offerMessages = offerMessages;
} }
public int getId() { return id; } public Integer getId() { return id; }
public void setId(int id) { this.id = id; } public void setId(Integer id) { this.id = id; }
public Company getCompany() { return company; } public Company getCompany() { return company; }
public void setCompany(Company company) { this.company = company; } public void setCompany(Company company) { this.company = company; }
...@@ -114,12 +115,16 @@ private Date publicationDate; ...@@ -114,12 +115,16 @@ private Date publicationDate;
// package fr.atlantique.imt.inf211.jobmngt.entity; // package fr.atlantique.imt.inf211.jobmngt.entity;
// import java.util.Date; // import java.util.Date;
// import java.util.HashSet; // import java.util.HashSet;
// import java.util.Set; // import java.util.Set;
// import org.springframework.format.annotation.DateTimeFormat;
// import com.fasterxml.jackson.annotation.JsonIgnoreProperties; // import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
// import jakarta.persistence.Column; // import jakarta.persistence.Column;
...@@ -164,6 +169,7 @@ private Date publicationDate; ...@@ -164,6 +169,7 @@ private Date publicationDate;
// private String taskDescription; // private String taskDescription;
// @Temporal(TemporalType.DATE) // @Temporal(TemporalType.DATE)
// @DateTimeFormat(pattern = "yyyy-MM-dd")
// @Column(name="publicationdate") // @Column(name="publicationdate")
// private Date publicationDate; // private Date publicationDate;
...@@ -224,3 +230,116 @@ private Date publicationDate; ...@@ -224,3 +230,116 @@ private Date publicationDate;
// } // }
// // package fr.atlantique.imt.inf211.jobmngt.entity;
// // import java.util.Date;
// // import java.util.HashSet;
// // import java.util.Set;
// // import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
// // import jakarta.persistence.Column;
// // import jakarta.persistence.Entity;
// // import jakarta.persistence.FetchType;
// // import jakarta.persistence.GeneratedValue;
// // import jakarta.persistence.GenerationType;
// // import jakarta.persistence.Id;
// // import jakarta.persistence.JoinColumn;
// // import jakarta.persistence.JoinTable;
// // import jakarta.persistence.ManyToMany;
// // import jakarta.persistence.ManyToOne;
// // import jakarta.persistence.OneToMany;
// // import jakarta.persistence.SequenceGenerator;
// // import jakarta.persistence.Table;
// // import jakarta.persistence.Temporal;
// // import jakarta.persistence.TemporalType;
// // @Entity
// // @Table(name="joboffer", schema="public")
// // @JsonIgnoreProperties({"offerMessages"}) // ✅ Évite la surcharge JSON circulaire
// // public class JobOffer implements java.io.Serializable {
// // @Id
// // @SequenceGenerator(name = "JOBOFFER_ID_GENERATOR", sequenceName = "JOBOFFER_ID_SEQ", allocationSize = 1)
// // @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "JOBOFFER_ID_GENERATOR")
// // @Column(name="id", unique = true, nullable = false)
// // private int id;
// // @ManyToOne(fetch = FetchType.LAZY)
// // @JoinColumn(name = "compid", nullable = false)
// // private Company company;
// // @ManyToOne(fetch = FetchType.LAZY)
// // @JoinColumn(name = "qualiflevelid", nullable = false)
// // private QualificationLevel qualificationLevel;
// // @Column(name="title", nullable = false, length = 50)
// // private String title;
// // @Column(name="taskdescription")
// // private String taskDescription;
// // @Temporal(TemporalType.DATE)
// // @Column(name="publicationdate")
// // private Date publicationDate;
// // @ManyToMany(fetch = FetchType.LAZY)
// // @JoinTable(name="indexjoboffersector", schema="public",
// // joinColumns = { @JoinColumn(name="jobofferid", nullable = false, updatable = false) },
// // inverseJoinColumns = { @JoinColumn(name="sectorid", nullable = false, updatable = false) })
// // @JsonIgnoreProperties({"applications", "jobOffers"}) // Empêche les boucles JSON infinies
// // private Set<Sector> sectors = new HashSet<>();
// // @OneToMany(fetch = FetchType.LAZY, mappedBy = "jobOffer") // Correction du mappedBy
// // private Set<OfferMessage> offerMessages = new HashSet<>();
// // public JobOffer() {}
// // public JobOffer(int id, Company company, QualificationLevel qualificationLevel, String title) {
// // this.id = id;
// // this.company = company;
// // this.qualificationLevel = qualificationLevel;
// // this.title = title;
// // }
// // public JobOffer(int id, Company company, QualificationLevel qualificationLevel, String title,
// // String taskDescription, Date publicationDate, Set<Sector> sectors, Set<OfferMessage> offerMessages) {
// // this.id = id;
// // this.company = company;
// // this.qualificationLevel = qualificationLevel;
// // this.title = title;
// // this.taskDescription = taskDescription;
// // this.publicationDate = publicationDate;
// // this.sectors = sectors;
// // this.offerMessages = offerMessages;
// // }
// // public int getId() { return id; }
// // public void setId(int id) { this.id = id; }
// // public Company getCompany() { return company; }
// // public void setCompany(Company company) { this.company = company; }
// // public QualificationLevel getQualificationLevel() { return qualificationLevel; }
// // public void setQualificationLevel(QualificationLevel qualificationLevel) { this.qualificationLevel = qualificationLevel; }
// // public String getTitle() { return title; }
// // public void setTitle(String title) { this.title = title; }
// // public String getTaskDescription() { return taskDescription; }
// // public void setTaskDescription(String taskDescription) { this.taskDescription = taskDescription; }
// // public Date getPublicationDate() { return publicationDate; }
// // public void setPublicationDate(Date publicationDate) { this.publicationDate = publicationDate; }
// // public Set<Sector> getSectors() { return sectors; }
// // public void setSectors(Set<Sector> sectors) { this.sectors = sectors; }
// // public Set<OfferMessage> getOfferMessages() { return offerMessages; }
// // public void setOfferMessages(Set<OfferMessage> offerMessages) { this.offerMessages = offerMessages; }
// // }
...@@ -28,18 +28,28 @@ ...@@ -28,18 +28,28 @@
<div class="mb-3"> <div class="mb-3">
<label class="form-label">Entreprise :</label> <label class="form-label">Entreprise :</label>
<select class="form-select" th:field="*{company.id}" required> <select class="form-select" th:field="*{company}">
<option value="">-- Sélectionner une entreprise --</option> <option value="">-- Sélectionner une entreprise --</option>
<option th:each="company : ${companies}" th:value="${company.id}" th:text="${company.denomination}"></option> <option th:each="company : ${companies}"
th:value="${company.id}"
th:text="${company.denomination}"
th:selected="${company.id == jobOffer.company?.id}"></option>
</option>
</select> </select>
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label class="form-label">Niveau de qualification :</label> <label class="form-label">Niveau de qualification :</label>
<select class="form-select" th:field="*{qualificationLevel.id}" required> <select class="form-select" th:field="*{qualificationLevel}">
<option value="">Sélectionner un niveau de qualification</option> <option value="">Sélectionner un niveau de qualification</option>
<option th:each="level : ${qualificationLevels}" th:value="${level.id}" th:text="${level.label}"></option> <option th:each="level : ${qualificationLevels}"
th:value="${level.id}"
th:text="${level.label}"
th:selected="${level.id == jobOffer.qualificationLevel?.id}">
</option>
</select> </select>
</div> </div>
<div class="mb-3"> <div class="mb-3">
......
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment