package es.uv.saic.web; import java.io.File; import java.io.IOException; import java.math.BigInteger; import java.sql.Timestamp; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.Authentication; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import es.uv.saic.shared.domain.EvidenciaIndicadorEnquesta; import es.uv.saic.shared.domain.InstanciaTascaVer; import es.uv.saic.shared.domain.Plantilla; import es.uv.saic.shared.domain.Proces; import es.uv.saic.shared.domain.Tipus; import es.uv.saic.shared.domain.Usuari; import es.uv.saic.shared.dto.RolDTO; import es.uv.saic.shared.feign.PlantillaClient; import es.uv.saic.shared.feign.ProceduresClient; import es.uv.saic.shared.feign.UsuariClient; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; @Controller public class ProceduresController { @Autowired private ProceduresClient pc; @Autowired private PlantillaClient plc; @Autowired private UsuariClient uc; @Value("${saic.data.filePath}") private String filePath; /* Redirect root to /procedures */ @GetMapping("/") public void getRoot(Model model, Authentication auth, HttpSession session, HttpServletResponse response) throws IOException { response.sendRedirect("/procedures"); } /* * Load the list of active procedure instances for the logged-in user * * @param model * @param auth Authentication * @param session HttpSession * @param _new Optional parameter to indicate a new access * @return The name of the view to render */ @GetMapping("/procedures") public String getActiveInstances(Model model, Authentication auth, HttpSession session, @RequestParam(required = false) String _new) { HashMap response = pc.getActiveInstances( _new, ((Usuari) auth.getPrincipal()).getUsuari()); if (response == null) { return "401"; } model.addAllAttributes(response); return "procedures"; } /* * Loads a procedure instance and its tasks * * @param model * @param auth Authentication * @param session HttpSession * @param id Instancia ID Instance to load * @return The name of the view to render */ @GetMapping("/procedure/{id}") public String getInstance(Model model, Authentication auth, HttpSession session, @PathVariable BigInteger id) { HashMap response = pc.getInstance(id, ((Usuari) auth.getPrincipal()).getUsuari()); if(session.getAttribute("location") != null) { model.addAttribute("location", session.getAttribute("location")); } else { session.setAttribute("location", "procedures"); model.addAttribute("location", "procedures"); } if(response == null){ return "401"; } model.addAllAttributes(response); return "procedure"; } /* * Updates a task instance with evidence files (for specific task types) * * @param model * @param auth Authentication * @param session HttpSession * @param id Instancia ID Instance to load * @param params Form parameters * @param evidencias List of evidence files (if any) * @return The number of files uploaded (as a String) * @throws IllegalStateException * @throws IOException * @throws InterruptedException */ @PostMapping("/procedure/files/{id}") @ResponseBody public String updateInstanciaTascaEvidencia(Model model, Authentication auth, HttpSession session, @PathVariable BigInteger id, @RequestParam Map params, @RequestParam(required = true) List evidencias) throws IllegalStateException, IOException { List files; // Convert MultipartFiles (evidencias) to Files before sending to the ProceduresClient files = new ArrayList<>(); for (MultipartFile multipartFile : evidencias) { File convFile = new File(filePath + multipartFile.getOriginalFilename()); multipartFile.transferTo(convFile); files.add(convFile); } HashMap response = pc.updateInstanciaTascaEvidencia(id, params, files, ((Usuari) auth.getPrincipal()).getUsuari()); if (response != null && response.get("ammount") != null) { model.addAllAttributes(response); return response.get("ammount").toString(); } return "0"; } /* * Updates a task instance * * @param model * @param auth Authentication * @param session HttpSession * @param id Instancia ID Instance to load * @param params Form parameters * @param evidencias List of evidence files (if any) * @return The name of the view to render */ @PostMapping("/procedure/{id}") public String updateInstanciaTasca(Model model, Authentication auth, HttpSession session, @PathVariable BigInteger id, @RequestParam Map params, @RequestParam(required = false) List evidencias) throws IllegalStateException, IOException, InterruptedException { model.addAttribute("location", "procedures"); HashMap response = pc.updateInstanciaTasca(id, params, evidencias, ((Usuari) auth.getPrincipal()).getUsuari()); if (response == null) { return "401"; } model.addAllAttributes(response); return "procedure"; } /* * Saves a draft of a task instance (for specific task types) * * @param model * @param auth Authentication * @param session HttpSession * @param id Instancia ID Instance to load * @param text Text content of the draft * @param manual Whether the save was manually triggered by the user * @return The timestamp of the save operation formatted as a String */ @PostMapping("/procedure/save/{id}") @ResponseBody public String saveDraft(Model model, Authentication auth, HttpSession session, @PathVariable BigInteger id, @RequestParam String text, @RequestParam boolean manual) { HashMap response = pc.saveDraft(id, text, manual, ((Usuari) auth.getPrincipal()).getUsuari()); if(session.getAttribute("location") != null) { model.addAttribute("location", session.getAttribute("location")); } else { session.setAttribute("location", "procedures"); model.addAttribute("location", "procedures"); } return response.get("date") == null ? "No se pudo obtener la fecha" : response.get("date").toString(); } /* * Get all drafts for a given task instance * @param model * @param auth Authentication * @param session HttpSession * @param id InstanciaTasca ID to load drafts for * @return The name of the view to render */ @GetMapping("/procedure/drafts/{id}") public String getDrafts(Model model, Authentication auth, HttpSession session, @PathVariable BigInteger id) { HashMap response = pc.getDrafts(id); if (response == null) { return "401"; } model.addAllAttributes(response); return "procedure_versions"; } /* * Get a specific draft for a given task instance * @param model * @param auth Authentication * @param session HttpSession * @param id InstanciaTasca ID to load drafts for * @param dataMod Timestamp of the draft to load * @return The InstanciaTascaVer object representing the draft */ @GetMapping("/procedure/draft/{id}") @ResponseBody public InstanciaTascaVer getDraft(Model model, Authentication auth, HttpSession session, @PathVariable BigInteger id, @RequestParam Timestamp dataMod) { return pc.getDraft(id, dataMod); } /* * Restore a specific draft for a given task instance * @param model * @param auth Authentication * @param session HttpSession * @param id InstanciaTasca ID to restore draft for * @param dataMod Timestamp of the draft to restore * @return "1" if successful, "0" otherwise */ @PostMapping("/procedure/draft/{id}") @ResponseBody public String restoreDraft(Model model, Authentication auth, HttpSession session, @PathVariable BigInteger id, @RequestParam Timestamp dataMod) { return pc.restoreDraft(id, dataMod); } // POST que se utiliza para conseguir los cursos a partir de la titulación @PostMapping("/procedure/search/years") public String getYearsByCenterTitulation(Model model, Authentication auth, @RequestParam(name="centers[]", required=false) List centres, @RequestParam("titulations[]") List titulacions) throws IOException { HashMap response = pc.getYearsByCenterTitulation(centres, titulacions, ((Usuari) auth.getPrincipal()).getUsuari()); if (response == null) { return "401"; } model.addAllAttributes(response); return "components/selector_cursos"; } // POST que se utiliza para conseguir los procedimiento que se han llevado a cabo por cursos y por titulación @PostMapping("/procedure/search/procedures") public String getProceduresByCenterTitulationYear(Model model, Authentication auth, @RequestParam(name="centers[]", required=false) List centres, @RequestParam("years[]") List cursos, @RequestParam("titulations[]") List titulacions) throws IOException { HashMap response = pc.getProceduresByCenterTitulationYear(centres, cursos, titulacions, ((Usuari) auth.getPrincipal()).getUsuari()); if (response == null) { return "401"; } model.addAllAttributes(response); return "components/selector_processos"; } @PostMapping("/find/procedure") public String findProcedure(Model model, Authentication auth, @RequestParam("procedure") Integer idProces, @RequestParam("action") String action) throws IOException { HashMap response = pc.findProcedure(idProces.toString(), action); if (response != null) { model.addAllAttributes(response); if (action.equals("remove")) { return "components/form_procedure_remove_confirm"; } else if (action.equals("duplicate") || action.equals("edit") || idProces == 0) { return "components/form_procedure"; } } return "401"; } // POST para crear el form de creación de plantilla @PostMapping("/template/form") public String formTemplate(Model model, Authentication auth, @RequestParam("id") Integer idPlantilla, @RequestParam("action") String action) throws IOException { HashMap response = pc.formTemplate(idPlantilla, action); if (response != null && response.get("redirect") != null) { model.addAllAttributes(response); return (boolean) response.get("redirect") ? "components/form_template" : ""; } return "401"; } // GET para renderizar el formulario de cración de nueva tarea @GetMapping("/newTask/{i}") public String newTaskForm(Model model, Authentication auth, @PathVariable Integer i) throws IOException { List roles = uc.findAssignables(); List tipus = pc.findAll(); List templates = plc.findAll(); model.addAttribute("tipus", tipus); model.addAttribute("roles", roles); model.addAttribute("i", i); model.addAttribute("templates", templates); return "components/form_procedure_task"; } @ResponseBody @PostMapping("/find/template") public String findTemplate(Model model, Authentication auth, @RequestParam("id") Integer idPlantilla) throws IOException { Plantilla p = plc.findByID(idPlantilla); return p.getText(); } // GET para comprobar si una plantilla esta siendo usada @ResponseBody @GetMapping("/template/used/{idPlantilla}") public int isTemplateUsed(Model model, Authentication auth, @PathVariable("idPlantilla") Integer idPlantilla) throws IOException { Boolean u = plc.isUsed(idPlantilla); return u ? 1 : 0; } @ResponseBody @PostMapping("/template/edit") public String templateEdit(Model model, Authentication auth, @RequestParam("id") Integer idPlantilla,@RequestParam("text") String text, @RequestParam("versio") Integer versio, @RequestParam("nomCas") String nomCas, @RequestParam("nomVal") String nomVal, @RequestParam("ambit") String ambit) throws IOException { Plantilla p = plc.findByID(idPlantilla); p.setNomCas(nomCas); p.setNomVal(nomVal); p.setText(text); p.setAmbit(ambit); plc.save(p); return "1"; } @ResponseBody @PostMapping("/template/save") public String templateSave(Model model, Authentication auth, @RequestParam("text") String text, @RequestParam("codi") String codi, @RequestParam("versio") Integer versio, @RequestParam("nomCas") String nomCas, @RequestParam("nomVal") String nomVal, @RequestParam("ambit") String ambit) throws IOException { Plantilla p = new Plantilla(); Plantilla p2 = plc.findByVersioCodiAmbit(versio, codi, ambit); if(p2 != null) { return "0"; } p.setCodi(codi); p.setVersio(versio); p.setNomCas(nomCas); p.setNomVal(nomVal); p.setText(text); p.setAmbit(ambit); plc.save(p); return "1"; } @ResponseBody @PostMapping("/draft/save/{id}") public String saveTemplate(Model model, Authentication auth, @PathVariable("id") Integer idPlantilla, @RequestParam("text") String text) throws IOException { Plantilla p = plc.findByID(idPlantilla); p.setText(text); plc.save(p); return "1"; } @DeleteMapping("/template/form") @ResponseBody public String formTemplateRemove(Model model, Authentication auth, @RequestParam("id") Integer idPlantilla) throws IOException { if(plc.isUsed(idPlantilla)){ return "0"; } else { Plantilla p = plc.findByID(idPlantilla); plc.delete(p); return "1"; } } @PostMapping("/find/template/inds") public String findTemplatesInds(Model model, Authentication auth, @RequestParam("procedure") Integer idProces, @RequestParam("center") String idCentre, @RequestParam("titulation") String idTitulacio, @RequestParam("ev") String evidencia) throws IOException { Proces p = this.pc.findProcesByID(idProces); List inds = this.pc.getByProcesEvidencia(p.getNomProces(), evidencia); model.addAttribute("inds", inds); model.addAttribute("proces", p.getNomProces()); model.addAttribute("idCentre", idCentre); model.addAttribute("idTitulacio", idTitulacio); model.addAttribute("evidencia", evidencia); return "components/form_templates_indicators"; } }