From 38b7a056b72b7ae4e5ae72fbd9f40b94afe49a33 Mon Sep 17 00:00:00 2001 From: "luciano.cassettai" <luciano.cassettai@unam.edu.ar> Date: Mon, 2 Jan 2023 10:17:32 -0300 Subject: [PATCH 01/11] ADD api-backend : recursos para realizar crud unidades de gestion --- .../v1/unidades_gestion/unidades_gestion.php | 271 ++++++++++++++++++ .../src/UNAM/Tupa/Backend/API/Factory.php | 15 + .../Tupa/Core/Errors/UnidadGestionError.php | 12 + .../Core/Manager/ManagerUnidadGestion.php | 169 +++++++++++ .../Negocio/Organizacion/UnidadGestion.php | 79 +++++ 5 files changed, 546 insertions(+) create mode 100644 api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php create mode 100644 core/src/UNAM/Tupa/Core/Errors/UnidadGestionError.php create mode 100644 core/src/UNAM/Tupa/Core/Manager/ManagerUnidadGestion.php create mode 100644 core/src/UNAM/Tupa/Core/Negocio/Organizacion/UnidadGestion.php diff --git a/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php b/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php new file mode 100644 index 00000000..8154c4b2 --- /dev/null +++ b/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php @@ -0,0 +1,271 @@ +<?php + +use SIUToba\rest\lib\rest_error; +use SIUToba\rest\lib\rest_hidratador; +use SIUToba\rest\lib\rest_validador; +use SIUToba\rest\rest; + +use UNAM\Tupa\Core\Errors\UnidadGestionError; +use UNAM\Tupa\Backend\API\Factory; +use UNAM\Tupa\Core\Filtros\Filtro; +use UNAM\Tupa\Core\Negocio\Organizacion\UnidadGestion; + + +class unidades_gestion implements SIUToba\rest\lib\modelable +{ + public static function _get_modelos() + { + $unidadGestionEdit = array( + 'sigla' => array( + 'type' => 'string', + 'required' => true, + '_validar' => array( + rest_validador::OBLIGATORIO, + ), + ), + 'nombre' => array( + 'type' => 'string', + 'required' => true, + '_validar' => array( + rest_validador::OBLIGATORIO, + ), + ), + 'id_grupo_arai' => array( + 'type' => 'string', + 'required' => true, + '_validar' => array( + rest_validador::OBLIGATORIO, + ), + ), + + ); + + $unidadGestion = array_merge( + $unidadGestionEdit, + array( + 'id_unidad' => array( + 'type' => 'integer', + ), + ) + ); + + + return $models = array( + 'UnidadGestion' => $unidadGestion, + 'UnidadGestionEdit' => $unidadGestionEdit, + ); + } + + protected function get_spec_usuario($tipo = 'UnidadGestion') + { + $m = $this->_get_modelos(); + + return $m[$tipo]; + } + + /** + * Se consume en GET /unidades_gestion/{id}. + * + * @summary Retorna datos de un unidad de gestion + * @responses 200 {"$ref": "UnidadGestion"} UnidadGestion + * @responses 404 No existe el recurso + * @responses 500 Error interno del servidor + */ + public function get($id) + { + try { + $manager = Factory::getManagerUnidadGestion(); + + $unidadGestion = $manager->getUnidadGestion($id); + + $fila = rest_hidratador::hidratar_fila($this->get_spec_usuario('UnidadGestionEdit'), $unidadGestion->toArray()); + + rest::response()->get($fila); + } catch (UnidadGestionError $e) { + Factory::getMainLogger()->error($e->getMessage()); + rest::response()->not_found(); + } catch (Exception $e) { + Factory::getMainLogger()->error($e->getMessage()); + rest::response()->error_negocio('Error interno del servidor', 500); + } + } + + /** + * Se consume en GET /unidades-gestion. + * + * @summary Retorna las unidades de gestion existentes + * @param_query $sigla string Se define como 'condicion;valor' donde 'condicion' puede ser contiene|no_contiene|comienza_con|termina_con|es_igual_a|es_distinto_de + * @param_query $nombre string Se define como 'condicion;valor' donde 'condicion' puede ser es_menor_que|es_menor_igual_que|es_igual_a|es_distinto_de|es_mayor_igual_que|es_mayor_que|entre + * @param_query $id_grupo_arai string Se define como 'condicion;valor' donde 'condicion' puede ser es_menor_que|es_menor_igual_que|es_igual_a|es_distinto_de|es_mayor_igual_que|es_mayor_que|entre + * + * @param_query $limit integer Limitar a esta cantidad de términos y condiciones + * @param_query $page integer Limitar desde esta pagina + * @param_query $order string +/-campo,... + * @responses 200 array {"$ref":"UnidadesGestion"} + * @responses 500 Error en los operadores ingresados para el filtro + */ + public function get_list() + { + try { + $filtro = $this->get_filtro_get_list(); + $filtro->setlimit(rest::request()->get('limit', null)); + $filtro->setPage(rest::request()->get('page', null)); + $filtro->setOrder(rest::request()->get('order', null)); + + $manager = Factory::getManagerUnidadGestion(); + + $unidadesGestion = $manager->getUnidadesGestion($filtro); + $resultados = []; + foreach ($unidadesGestion as $ug) { + $resultados[] = $ug->toArray(); + } + + $registros = rest_hidratador::hidratar($this->get_spec_usuario('UnidadGestion'), $resultados); + + rest::response()->get($registros); + } catch (Exception $e) { + Factory::getMainLogger()->error($e->getMessage()); + rest::response()->error_negocio('Error interno del servidor', 500); + } + } + + /** + * Se consume en POST /unidades-gestion + * + * @summary Crea una nueva unidad de géstion + * @param_body $unidadGestion UnidadGestionEdit [required] los datos de la unidad de gestion + * @responses 201 {"string"} identificador de unidad de gestion otorgado + * @responses 400 unidad de gestion inválidoa + * @responses 500 Error interno + */ + public function post_list() + { + // Valido y traduzco los datos al formato de mi modelo + $datos = $this->procesar_input_edicion('UnidadGestion',false); + + try { + $manager = Factory::getManagerUnidadGestion(); + + $ug = new UnidadGestion(); + + $ug->loadFromDatos($datos); + + $identificador = $manager->crear($ug); + + $respuesta = [ + 'id_unidad' => $identificador['id_unidad'] + ]; + + rest::response()->post($respuesta); + } catch (rest_error $e) { + rest::response()->error_negocio($e->get_datalle(), 400); + } catch (Exception $e) { + if ($e->getCode() >= 400 || $e->getCode() < 500) { + rest::response()->error_negocio([$e->getMessage()], 400); + } else { + rest::response()->error_negocio([$e->getMessage()], 500); + } + } + } + + /** + * Se consume en PUT /unidades_gestion/{identificador} + * + * @summary Modifica una unidad de gestion + * @param_body $UnidadGestionEdit UnidadGestionEdit [required] los datos a editar de la unidad de gestion + * @responses 204 el código es correcto + * @responses 400 Código no válido + * @responses 404 No existe el recurso + * @responses 500 Error interno + */ + public function put($id) + { + $datos = $this->procesar_input_edicion('UnidadGestionEdit'); + + try { + $manager = Factory::getManagerUnidadGestion(); + $ug = $manager->getUnidadGestion($id); + $ug->loadFromDatos($datos); + $manager->actualizar($ug); + + rest::response()->put([ "respuesta" => true ]); + } catch (UnidadGestionError $e) { + rest::response()->not_found(); + } catch (\Exception $e) { + if ($e->getCode() >= 400 || $e->getCode() < 500) { + rest::response()->error_negocio([$e->getMessage()], 400); + } else { + rest::response()->error_negocio([$e->getMessage()], 500); + } + } + } + + /** + * Se consume en DELETE /unidades_gestion/{identificador} + * + * @summary Elimina una unidad de gestion + * @responses 204 Se elimino correctamente + * @responses 400 El id no existe + * @responses 404 No existe el recurso + * @responses 500 Error interno + */ + public function delete($id) + { + try { + $manager = Factory::getManagerUnidadGestion(); + + $manager->eliminar($id); + + rest::response()->put([ "respuesta" => true ]); + }catch (\Exception $e) { + if ($e->getCode() >= 400 || $e->getCode() < 500) { + rest::response()->error_negocio([$e->getMessage()], 400); + } else { + rest::response()->error_negocio([$e->getMessage()], 500); + } + } + } + + /** + * @return Filtro + * @throws ErrorTupa + */ + protected function get_filtro_get_list() + { + /* @var Filtro $filtro */ + $filtro = new Filtro(); + $filtro->agregarCampoRest('ug.nombre', rest::request()->get('nombre', null)); + $filtro->agregarCampoRest('ug.sigla', rest::request()->get('sigla', null)); + $filtro->agregarCampoRest('ug.id_grupo_arai', rest::request()->get('id_grupo_arai', null)); + + $filtro->agregarCampoOrdenable('nombre'); + $filtro->agregarCampoOrdenable('sigla'); + + return $filtro; + } + + /** + * $relajar_ocultos boolean no checkea campos obligatorios cuando no se especifican. + * @param string $modelo + * @param bool $relajar_ocultos + * @param array $datos + * @return array|string + * @throws rest_error + */ + protected function procesar_input_edicion($modelo = 'UnidadGestionEdit', $relajar_ocultos = false, $datos = null) + { + if (! $datos) { + $datos = rest::request()->get_body_json(); + } + + $spec_usuario = $this->get_spec_usuario($modelo); + + rest_validador::validar($datos, $spec_usuario, $relajar_ocultos); + + $resultado = rest_hidratador::deshidratar_fila($datos, $spec_usuario); + + return Factory::getVarios()->arrayToUtf8($resultado); + } +} + +?> \ No newline at end of file diff --git a/api-backend/src/UNAM/Tupa/Backend/API/Factory.php b/api-backend/src/UNAM/Tupa/Backend/API/Factory.php index e36d3c35..99b99237 100644 --- a/api-backend/src/UNAM/Tupa/Backend/API/Factory.php +++ b/api-backend/src/UNAM/Tupa/Backend/API/Factory.php @@ -26,6 +26,7 @@ use UNAM\Tupa\Core\Manager\ManagerTerminosCondiciones; use UNAM\Tupa\Core\Manager\ManagerVisitante; use UNAM\Tupa\Core\Manager\ManagerVisita; use UNAM\Tupa\Core\Manager\ManagerAutorizante; +use UNAM\Tupa\Core\Manager\ManagerUnidadGestion; use UNAM\Tupa\Core\Manager\ManagerPermiso; use UNAM\Tupa\Core\Manager\ManagerSolicitud; @@ -253,6 +254,10 @@ class Factory $container['manager-autorizante'] = function ($c) { return new ManagerAutorizante($c['db-logger'], $c['db'], $c['codigo']); }; + + $container['manager-unidad-gestion'] = function ($c) { + return new ManagerUnidadGestion($c['db-logger'], $c['db'], $c['codigo']); + }; $container['manager-solicitud'] = function ($c) { return new ManagerSolicitud($c['db-logger'], $c['db'], $c['codigo']); @@ -342,6 +347,16 @@ class Factory { return self::getContainer()['manager-sede']; } + + /** + * Singleton de ManagerSede + * + * @return ManagerUnidadGestion + */ + public static function getManagerUnidadGestion() + { + return self::getContainer()['manager-unidad-gestion']; + } /** * Singleton de ManagerTerminosCondiciones. diff --git a/core/src/UNAM/Tupa/Core/Errors/UnidadGestionError.php b/core/src/UNAM/Tupa/Core/Errors/UnidadGestionError.php new file mode 100644 index 00000000..0ff310c3 --- /dev/null +++ b/core/src/UNAM/Tupa/Core/Errors/UnidadGestionError.php @@ -0,0 +1,12 @@ +<?php declare(strict_types=1); + +namespace UNAM\Tupa\Core\Errors; + +/** + * Sede + * + * @codeCoverageIgnore + */ +class UnidadGestionError extends ErrorTupa +{ +} \ No newline at end of file diff --git a/core/src/UNAM/Tupa/Core/Manager/ManagerUnidadGestion.php b/core/src/UNAM/Tupa/Core/Manager/ManagerUnidadGestion.php new file mode 100644 index 00000000..bf00c59a --- /dev/null +++ b/core/src/UNAM/Tupa/Core/Manager/ManagerUnidadGestion.php @@ -0,0 +1,169 @@ +<?php declare(strict_types=1); + +namespace UNAM\Tupa\Core\Manager; + +use UNAM\Tupa\Core\Errors\UnidadGestionError; +use UNAM\Tupa\Core\Filtros\Filtro; +use UNAM\Tupa\Core\Negocio\Organizacion\UnidadGestion; + +class ManagerUnidadGestion extends Manager +{ + /** + * @param $id + * @return UnidadGestion|null + * @throws UnidadGestionError No se pudo recuperar la Unidad de gestion + */ + public function getUnidadGestion($id) + { + $params = [ + "id" => $id + ]; + + $sql = "SELECT id_unidad, sigla, nombre, id_grupo_arai " + . "FROM unidades_gestion ug " + . "WHERE id_unidad = :id"; + + $result = $this->db->sentencia_consultar_fila($sql, $params); + + if (!$result) { + throw new UnidadGestionError("No se pudo recuperar la unidad de gestion '$id'"); + } + + return $this->hidratarUnidadGestion($result); + } + + /** + * @param Filtro|null $filtro + * @param bool $hidratar + * @return UnidadesGestion[] + */ + public function getUnidadesGestion(Filtro $filtro = null, $hidratar = true) + { + $where = $this->getSqlWhere($filtro); + $orderBy = $this->getSqlOrderBy($filtro); + $limit = $this->getSqlLimit($filtro); + + $sql = sprintf(" + SELECT + ug.id_unidad, ug.nombre, ug.sigla, ug.id_grupo_arai + FROM + unidades_gestion ug + %s + %s + %s;", $where, $orderBy, $limit); + + $result = $this->db->consultar($sql); + + if ($hidratar) { + $result = $this->hidratarUnidaesdGestion($result); + } + + return $result; + } + + /** + * @param UnidadGestion $ug + * @return bool|string + * @throws UnidadGestionError No se pudo crear la unidad de gestion + */ + public function crear(UnidadGestion $ug) + { + $sql = "INSERT INTO unidades_gestion (nombre, sigla, id_grupo_arai) VALUES (:nombre, :sigla, :id_grupo_arai)"; + + $sqlParams = [ + "nombre" => $ug->getNombre(), + "sigla" => $ug->getSigla(), + "id_grupo_arai" => $ug->getIdGrupoArai(), + ]; + + $result = $this->db->sentencia_ejecutar($sql, $sqlParams); + + if (!$result) { + throw new UnidadGestionError("No se pudo crear la unidad de gestion"); + } + + $sql = "SELECT id_unidad FROM unidades_gestion + WHERE nombre = :nombre + AND sigla = :sigla + AND id_grupo_arai = :id_grupo_arai"; + + return $this->db->sentencia_consultar_fila($sql, $sqlParams); + } + + /** + * @param UnidadGestion $unidadGestion + * @return mixed + */ + public function actualizar(UnidadGestion $ug) + { + $params = [ + "sigla" => $ug->getSigla(), + "nombre" => $ug->getNombre(), + "id_grupo_arai" => $ug->getIdGrupoArai(), + "id" => $ug->getId(), + ]; + + $sql = " UPDATE unidades_gestion + SET nombre = :nombre, + sigla = :sigla, + id_grupo_arai = :id_grupo_arai + WHERE id_unidad = :id"; + + return $this->db->sentencia_ejecutar($sql, $params); + } + + /** + * @param $id + * @return bool|null + * @throws UnidadGestionError No se pudo eliminar la Unidad de gestion + */ + public function eliminar($id) + { + $params = [ + "id" => $id + ]; + + $sql = "DELETE FROM unidades_gestion " + . "WHERE id_unidad = :id"; + + $result = $this->db->sentencia_ejecutar($sql, $params); + + if (!$result) { + throw new UnidadGestionError("No se pudo eliminar la unidad de gestion '$id'"); + } + + return $result; + } + + /** + * @param $datos + * @return UnidadGestion + */ + protected function hidratarUnidadGestion($datos) + { + $ug = new UnidadGestion(); + + $ug->loadFromDatos($datos); + + return $ug; + } + + /** + * @param $datos + * @return UnidadGestion[] colección de Unidades de gestion + */ + protected function hidratarUnidaesdGestion($datos) + { + $ug = []; + + if (count($datos) < 1) { + return $ug; + } + + foreach ($datos as $dato) { + $ug[] = $this->hidratarUnidadGestion($dato); + } + + return $ug; + } +} diff --git a/core/src/UNAM/Tupa/Core/Negocio/Organizacion/UnidadGestion.php b/core/src/UNAM/Tupa/Core/Negocio/Organizacion/UnidadGestion.php new file mode 100644 index 00000000..d2b2d034 --- /dev/null +++ b/core/src/UNAM/Tupa/Core/Negocio/Organizacion/UnidadGestion.php @@ -0,0 +1,79 @@ +<?php declare(strict_types=1); + +namespace UNAM\Tupa\Core\Negocio\Organizacion; + + +class UnidadGestion { + + private int $id; + private string $sigla; + private string $nombre; + private string $idGrupoArai; + + public function getId():int{ + return $this->id; + } + + public function getSigla():string{ + return $this->sigla; + } + + public function getNombre():string{ + return $this->nombre; + } + + public function getIdGrupoArai():string{ + return $this->idGrupoArai; + } + + public function setId(int $id){ + $this->id = $id; + } + + public function setSigla(string $sigla):void { + $this->sigla = $sigla; + } + + public function setNombre(string $nombre):void{ + $this->nombre = $nombre; + } + + public function setIdGrupoArai(string $idGrupo):void{ + $this->idGrupoArai = $idGrupo; + } + + /** + * Hidrata los atributos del objeto a partir de $datos + * + * @param array $datos inicializar directamente con un set de datos + */ + public function loadFromDatos(array $datos) + { + if (isset($datos['id_unidad'])) { + $this->setId($datos['id_unidad']); + } + if (isset($datos['sigla'])) { + $this->setSigla($datos['sigla']); + } + if (isset($datos['nombre'])) { + $this->setNombre($datos['nombre']); + } + if (isset($datos['id_grupo_arai'])) { + $this->setIdGrupoArai($datos['id_grupo_arai']); + } + } + + /** + * @return array + */ + public function toArray(): array + { + return [ + 'id_unidad' => $this->getId(), + 'sigla' => $this->getSigla(), + 'nombre' => $this->getNombre(), + 'id_grupo_arai' => $this->getIdGrupoArai() + ]; + } +} + -- GitLab From cb95aab99bfe1d74c2f6307111e235324a391a40 Mon Sep 17 00:00:00 2001 From: "luciano.cassettai" <luciano.cassettai@unam.edu.ar> Date: Wed, 4 Jan 2023 11:23:45 -0300 Subject: [PATCH 02/11] ADD api-backend : recursos para realizar crud servicios --- .../API/Endpoints/v1/servicios/servicios.php | 312 +++++++++++++++ .../src/UNAM/Tupa/Backend/API/Factory.php | 18 +- ...end_servicios_test.postman_collection.json | 359 ++++++++++++++++++ api-backend/www/api.php | 2 +- .../Tupa/Core/Manager/ManagerServicio.php | 152 ++++++++ .../Negocio/SolicitudesServicios/Servicio.php | 100 +++++ 6 files changed, 941 insertions(+), 2 deletions(-) create mode 100644 api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/servicios/servicios.php create mode 100644 api-backend/tests/Integration/v1/collections/servicios/tupa_api_backend_servicios_test.postman_collection.json create mode 100644 core/src/UNAM/Tupa/Core/Manager/ManagerServicio.php create mode 100644 core/src/UNAM/Tupa/Core/Negocio/SolicitudesServicios/Servicio.php diff --git a/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/servicios/servicios.php b/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/servicios/servicios.php new file mode 100644 index 00000000..75effba3 --- /dev/null +++ b/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/servicios/servicios.php @@ -0,0 +1,312 @@ +<?php + +use SIUToba\rest\lib\rest_error; +use SIUToba\rest\lib\rest_hidratador; +use SIUToba\rest\lib\rest_validador; +use SIUToba\rest\rest; + +use UNAM\Tupa\Core\Errors\ErrorTupa; +use UNAM\Tupa\Backend\API\Factory; +use UNAM\Tupa\Core\Filtros\Filtro; +use UNAM\Tupa\Core\Negocio\SolicitudesServicios\Servicio; + + +class servicios implements SIUToba\rest\lib\modelable +{ + public static function _get_modelos() + { + $vigenciaFin = [ + 'vigencia_fin' => [ + 'type' => 'string', + '_validar' => [ + rest_validador::TIPO_DATE => [ + 'format' => 'Y-m-d' + ], + ], + ] + ]; + + $servicioEdit = array( + 'nombre' => array( + 'type' => 'string', + 'required' => true, + '_validar' => array( + rest_validador::OBLIGATORIO, + ), + ), + 'descripcion' => array( + 'type' => 'string', + 'required' => true, + '_validar' => array( + rest_validador::OBLIGATORIO, + ), + ), + 'id_sistema_arai' => array( + 'type' => 'string', + 'required' => true, + '_validar' => array( + rest_validador::OBLIGATORIO, + ), + ), + 'vigencia_inicio' => [ + 'type' => 'date', + '_validar' => [ + rest_validador::OBLIGATORIO, + rest_validador::TIPO_DATE => [ + 'format' => 'Y-m-d' + ], + ], + ] + ); + + $servicio = array_merge( + $servicioEdit, + $vigenciaFin, + array( + 'id_servicio' => array( + 'type' => 'integer', + ), + ) + ); + + + return $models = array( + 'Servicio' => $servicio, + 'ServicioEdit' => $servicioEdit, + 'VigenciaFin' => $vigenciaFin, + ); + } + + protected function get_spec_usuario($tipo = 'Servicio') + { + $m = $this->_get_modelos(); + + return $m[$tipo]; + } + + /** + * Se consume en GET /servicios/{id}. + * + * @summary Retorna datos de un servicio + * @responses 200 {"$ref": "Servicio"} Servicio + * @responses 404 No existe el recurso + * @responses 500 Error interno del servidor + */ + public function get($id) + { + try { + $manager = Factory::getManagerServicio(); + + $servicio = $manager->getServicio($id); + + $fila = rest_hidratador::hidratar_fila($this->get_spec_usuario('Servicio'), $servicio->toArray()); + + rest::response()->get($fila); + } catch (ErrorTupa $e) { + Factory::getMainLogger()->error($e->getMessage()); + rest::response()->not_found(); + } catch (Exception $e) { + Factory::getMainLogger()->error($e->getMessage()); + rest::response()->error_negocio('Error interno del servidor', 500); + } + } + + + /** + * Se consume en GET /servicios. + * + * @summary Retorna los servicios existentes + * @param_query $nombre string Se define como 'condicion;valor' donde 'condicion' puede ser contiene|no_contiene|comienza_con|termina_con|es_igual_a|es_distinto_de + * @param_query $descripcion string Se define como 'condicion;valor' donde 'condicion' puede ser es_menor_que|es_menor_igual_que|es_igual_a|es_distinto_de|es_mayor_igual_que|es_mayor_que|entre + * @param_query $id_sistema_arai string Se define como 'condicion;valor' donde 'condicion' puede ser es_menor_que|es_menor_igual_que|es_igual_a|es_distinto_de|es_mayor_igual_que|es_mayor_que|entre + * @param_query $vigencia_inicio string Se define como 'condicion;valor' donde 'condicion' puede ser es_menor_que|es_menor_igual_que|es_igual_a|es_distinto_de|es_mayor_igual_que|es_mayor_que|entre + * @param_query $vigencia_fin string Se define como 'condicion;valor' donde 'condicion' puede ser es_menor_que|es_menor_igual_que|es_igual_a|es_distinto_de|es_mayor_igual_que|es_mayor_que|entre + * + * @param_query $limit integer Limitar a esta cantidad de servicios + * @param_query $page integer Limitar desde esta pagina + * @param_query $order string +/-campo,... + * @responses 200 array {"$ref":"Servicio"} + * @responses 500 Error en los operadores ingresados para el filtro + */ + public function get_list() + { + try { + $filtro = $this->get_filtro_get_list(); + $filtro->setlimit(rest::request()->get('limit', null)); + $filtro->setPage(rest::request()->get('page', null)); + $filtro->setOrder(rest::request()->get('order', null)); + + $manager = Factory::getManagerServicio(); + + $servicios = $manager->getServicios($filtro); + + $resultados = []; + foreach ($servicios as $s) { + $resultados[] = $s->toArray(); + } + + $registros = rest_hidratador::hidratar($this->get_spec_usuario('Servicio'), $resultados); + + rest::response()->get($registros); + } catch (Exception $e) { + Factory::getMainLogger()->error($e->getMessage()); + rest::response()->error_negocio('Error interno del servidor', 500); + } + } + + + /** + * Se consume en POST /servicios + * + * @summary Crea un nuevo servicio + * @param_body $servicios ServicioEdit [required] los datos del servicio + * @responses 201 {"string"} identificador de un servicio + * @responses 400 Servicio inválido + * @responses 500 Error interno + */ + public function post_list() + { + // Valido y traduzco los datos al formato de mi modelo + $datos = $this->procesar_input_edicion('ServicioEdit',false); + + try { + $manager = Factory::getManagerServicio(); + + $servicio = new Servicio(); + + $servicio->loadFromDatos($datos); + + $identificador = $manager->crear($servicio); + + $respuesta = [ + 'id_servicio' => $identificador['id_servicio'] + ]; + + rest::response()->post($respuesta); + } catch (rest_error $e) { + rest::response()->error_negocio($e->get_datalle(), 400); + } catch (Exception $e) { + if ($e->getCode() >= 400 || $e->getCode() < 500) { + rest::response()->error_negocio([$e->getMessage()], 400); + } else { + rest::response()->error_negocio([$e->getMessage()], 500); + } + } + } + + /** + * Se consume en PUT /servicios/{id} + * + * @summary Modifica un servicio + * @param_body $ServicioEdit ServicioEdit [required] los datos a editar de un servicio + * @responses 204 El id es correcto + * @responses 400 El id no válido + * @responses 404 No existe el recurso + * @responses 500 Error interno + */ + public function put($id) + { + $datos = $this->procesar_input_edicion('ServicioEdit'); + + try { + $manager = Factory::getManagerServicio(); + $servicio = $manager->getServicio($id); + $servicio->loadFromDatos($datos); + $manager->actualizar($servicio); + + rest::response()->put([ "respuesta" => true ]); + } catch (ErrorTupa $e) { + rest::response()->not_found(); + } catch (\Exception $e) { + if ($e->getCode() >= 400 || $e->getCode() < 500) { + rest::response()->error_negocio([$e->getMessage()], 400); + } else { + rest::response()->error_negocio([$e->getMessage()], 500); + } + } + } + + /** + * Se consume en PUT /servicios/{id}/baja. + * + * @summary Setea vigencia fin de un servicio + * @param_body $vigenciaFin VigenciaFin [required] la fecha de fin de vigencia del servicio + * @responses 200 Se seteo la baja correctamente + * @responses 404 No existe el recurso + * @responses 500 Error interno + */ + public function put_baja_list($id) + { + $datos = $this->procesar_input_edicion('VigenciaFin'); + + try { + $manager = Factory::getManagerServicio(); + $servicio = $manager->getServicio($id); + + if(!empty($datos['vigencia_fin'])){ + $servicio->setVigenciaFin($datos['vigencia_fin']); + }else{ + $servicio->setVigenciaFin(date("Y-m-d")); + } + + $manager->actualizar($servicio); + + rest::response()->put([ "respuesta" => true ]); + } catch (ErrorTupa $e) { + Factory::getMainLogger()->error($e->getMessage()); + rest::response()->not_found(); + } catch (Exception $e) { + Factory::getMainLogger()->error($e->getMessage()); + if ($e->getCode() >= 400 || $e->getCode() < 500) { + rest::response()->error_negocio($e->getMessage(), 400); + } else { + rest::response()->error_negocio($e->getMessage(), 500); + } + } + } + + + /** + * @return Filtro + * @throws ErrorTupa + */ + protected function get_filtro_get_list() + { + /* @var Filtro $filtro */ + $filtro = new Filtro(); + $filtro->agregarCampoRest('s.nombre', rest::request()->get('nombre', null)); + $filtro->agregarCampoRest('s.descripcion', rest::request()->get('descripcion', null)); + $filtro->agregarCampoRest('s.id_sistema_arai', rest::request()->get('id_sistema_arai', null)); + $filtro->agregarCampoRest('s.vigencia_inicio', rest::request()->get('vigencia_inicio', null)); + $filtro->agregarCampoRest('s.vigencia_fin', rest::request()->get('vigencia_fin', null)); + + $filtro->agregarCampoOrdenable('nombre'); + $filtro->agregarCampoOrdenable('vigencia_inicio'); + + return $filtro; + } + + /** + * $relajar_ocultos boolean no checkea campos obligatorios cuando no se especifican. + * @param string $modelo + * @param bool $relajar_ocultos + * @param array $datos + * @return array|string + * @throws rest_error + */ + protected function procesar_input_edicion($modelo = 'ServicioEdit', $relajar_ocultos = false, $datos = null) + { + if (! $datos) { + $datos = rest::request()->get_body_json(); + } + + $spec_usuario = $this->get_spec_usuario($modelo); + + rest_validador::validar($datos, $spec_usuario, $relajar_ocultos); + + $resultado = rest_hidratador::deshidratar_fila($datos, $spec_usuario); + + return Factory::getVarios()->arrayToUtf8($resultado); + } + +} \ No newline at end of file diff --git a/api-backend/src/UNAM/Tupa/Backend/API/Factory.php b/api-backend/src/UNAM/Tupa/Backend/API/Factory.php index 99b99237..ae2c8cc2 100644 --- a/api-backend/src/UNAM/Tupa/Backend/API/Factory.php +++ b/api-backend/src/UNAM/Tupa/Backend/API/Factory.php @@ -29,6 +29,7 @@ use UNAM\Tupa\Core\Manager\ManagerAutorizante; use UNAM\Tupa\Core\Manager\ManagerUnidadGestion; use UNAM\Tupa\Core\Manager\ManagerPermiso; use UNAM\Tupa\Core\Manager\ManagerSolicitud; +use UNAM\Tupa\Core\Manager\ManagerServicio; class Factory { @@ -267,6 +268,10 @@ class Factory return new ManagerPermiso($c['db-logger'], $c['db'], $c['codigo']); }; + $container['manager-servicio'] = function ($c) { + return new ManagerServicio($c['db-logger'], $c['db'], $c['codigo']); + }; + $container['worker-redis'] = function ($c) { $config = new \SIU\Queue\Transport\Config\Redis(); @@ -349,7 +354,7 @@ class Factory } /** - * Singleton de ManagerSede + * Singleton de ManagerUnidadGestion * * @return ManagerUnidadGestion */ @@ -358,6 +363,17 @@ class Factory return self::getContainer()['manager-unidad-gestion']; } + /** + * Singleton de ManagerSede + * + * @return ManagerServicio + */ + public static function getManagerServicio() + { + return self::getContainer()['manager-servicio']; + } + + /** * Singleton de ManagerTerminosCondiciones. * diff --git a/api-backend/tests/Integration/v1/collections/servicios/tupa_api_backend_servicios_test.postman_collection.json b/api-backend/tests/Integration/v1/collections/servicios/tupa_api_backend_servicios_test.postman_collection.json new file mode 100644 index 00000000..f543607d --- /dev/null +++ b/api-backend/tests/Integration/v1/collections/servicios/tupa_api_backend_servicios_test.postman_collection.json @@ -0,0 +1,359 @@ +{ + "info": { + "_postman_id": "884ded69-9e28-4c50-b25b-a5035b6d4175", + "name": "Tupa API Backend Servicios", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "16366966" + }, + "item": [ + { + "name": "V1", + "item": [ + { + "name": "Servicios", + "item": [ + { + "name": "Crear un servicio", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", () => {", + " pm.response.to.have.status(201);", + "});", + "", + "const servicioSchema = { ", + " \"nombre\": '',", + " \"descripcion\": '',", + " \"id_sistema_arai\": '',", + " \"vigencia_inicio\": '',", + "}", + "", + "const body = JSON.parse(pm.request.body.raw);", + "const sameSchema = JSON.stringify(Object.keys(servicioSchema)) === JSON.stringify(Object.keys(body));", + "", + "pm.test('Estructura del body correcta', () => {", + " pm.expect(true).to.be.eql(sameSchema);", + "}); ", + "", + "var respuesta = pm.response.json();", + "", + "pm.test(\"Servicio creado con ID \" + respuesta.id_servicio, function () {", + " pm.globals.set(\"idServicio\", respuesta.id_servicio);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"nombre\": \"{{$randomJobTitle}}\",\n \"descripcion\": \"{{$randomJobTitle}}\",\n \"id_sistema_arai\": \"{{$randomUUID}}\",\n \"vigencia_inicio\": \"2022-01-01\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/v1/servicios", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "servicios" + ] + } + }, + "response": [] + }, + { + "name": "Obtener un servicio", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200);", + "});", + "", + "const response = pm.response.json();", + "const hasId = Object.keys(response).includes('id_servicio');", + "", + "pm.test(\"Servicio con id_servicio \" + response.id_servicio, function () {", + " pm.expect(true).to.be.eql(hasId);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/v1/servicios/{{idServicio}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "servicios", + "{{idServicio}}" + ] + } + }, + "response": [] + }, + { + "name": "Obtener servicios activos", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200);", + "});", + "", + "const fechaActual = new Date();", + "const year = fechaActual.getFullYear();", + "const month = fechaActual.getMonth() + 1; ", + "const day = fechaActual.getDate();", + "const fechaFormateada = `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`;", + "", + "const resp = pm.response.json();", + "const filteredResponse = resp.filter((obj) => obj.vigencia_fin > fechaFormateada || obj.vigencia_fin == null);", + "", + "pm.test('Hay un Servicio activo', () => {", + " pm.expect(filteredResponse.length).to.not.eql(0);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/v1/servicios", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "servicios" + ] + } + }, + "response": [] + }, + { + "name": "Modificar un servicio", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200);", + "});", + "", + "const servicioSchema = { ", + " \"nombre\": '',", + " \"descripcion\": '',", + " \"id_sistema_arai\": '',", + " \"vigencia_inicio\": '',", + "}", + "", + "const body = JSON.parse(pm.request.body.raw);", + "const sameSchema = JSON.stringify(Object.keys(servicioSchema)) === JSON.stringify(Object.keys(body));", + "", + "pm.test('Estructura del body correcta', () => {", + " pm.expect(true).to.be.eql(sameSchema);", + "}); ", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"nombre\": \"Servicio Modificado\",\n \"descripcion\": \"Esto es un Servicio Modificado\",\n \"id_sistema_arai\": \"_0e5589b482dc77e8d983db51d7ed2f36a9daaa11b4\",\n \"vigencia_inicio\": \"2050-12-01\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/v1/servicios/{{idServicio}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "servicios", + "{{idServicio}}" + ] + } + }, + "response": [] + }, + { + "name": "Inactivar un servicio", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200);", + "});", + "", + "const servicioSchema = { ", + " \"vigencia_fin\": '',", + "}", + "", + "const body = JSON.parse(pm.request.body.raw);", + "const sameSchema = JSON.stringify(Object.keys(servicioSchema)) === JSON.stringify(Object.keys(body));", + "", + "pm.test('Estructura del body correcta', () => {", + " pm.expect(true).to.be.eql(sameSchema);", + "}); " + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"vigencia_fin\": \"2023-01-01\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/v1/servicios/{{idServicio}}/baja", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "servicios", + "{{idServicio}}", + "baja" + ] + } + }, + "response": [] + }, + { + "name": "Obtener servicios", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200);", + "});", + "", + "const response = pm.response.json();", + "", + "pm.test(\"Se obtuvieron servicios \", function () {", + " // Si existe al menos 1 servicio", + " pm.expect(response.length).to.not.eql(0);", + "", + " if(response.length > 0){", + " const hasId = Object.keys(response[0]).includes('id_servicio');", + "", + " // Si el servicio tiene un id_servicio", + " pm.expect(true).to.be.eql(hasId);", + " }", + " ", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/v1/servicios", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "servicios" + ] + } + }, + "response": [] + } + ] + } + ] + } + ], + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "admin", + "type": "string" + }, + { + "key": "username", + "value": "admin", + "type": "string" + } + ] + }, + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "key": "baseUrl", + "value": "http://localhost:9002/api" + } + ] +} \ No newline at end of file diff --git a/api-backend/www/api.php b/api-backend/www/api.php index 4ffb60d8..a2786a22 100644 --- a/api-backend/www/api.php +++ b/api-backend/www/api.php @@ -21,7 +21,7 @@ $settings = array( 'prefijo_controladores' => '', 'api_version' => $api_version, 'api_titulo' => 'Tupa (backend)', - 'url_protegida' => '/pases|registros|sedes|terminos-condiciones|visitantes|visitas/', + 'url_protegida' => '/pases|registros|sedes|terminos-condiciones|visitantes|visitas|servicios|unidades-gestion/', 'debug' => true, ); diff --git a/core/src/UNAM/Tupa/Core/Manager/ManagerServicio.php b/core/src/UNAM/Tupa/Core/Manager/ManagerServicio.php new file mode 100644 index 00000000..dc9856b4 --- /dev/null +++ b/core/src/UNAM/Tupa/Core/Manager/ManagerServicio.php @@ -0,0 +1,152 @@ +<?php declare(strict_types=1); + +namespace UNAM\Tupa\Core\Manager; + +use UNAM\Tupa\Core\Errors\ErrorTupa; +use UNAM\Tupa\Core\Filtros\Filtro; +use UNAM\Tupa\Core\Negocio\SolicitudesServicios\Servicio; + +class ManagerServicio extends Manager +{ + /** + * @param $id + * @return Servcio|null + * @throws ErrorTupa No se pudo recuperar el servicio + */ + public function getServicio($id) + { + $params = [ + "id" => $id + ]; + + $sql = "SELECT id_servicio, nombre, descripcion, id_sistema_arai, vigencia_inicio,vigencia_fin " + . "FROM servicios s " + . "WHERE id_servicio = :id"; + + $result = $this->db->sentencia_consultar_fila($sql, $params); + + if (!$result) { + throw new ErrorTupa("No se pudo recuperar el servicio '$id'"); + } + + return $this->hidratarServicio($result); + } + + /** + * @param Filtro|null $filtro + * @param bool $hidratar + * @return Servicio[] + */ + public function getServicios(Filtro $filtro = null, $hidratar = true) + { + $where = $this->getSqlWhere($filtro); + $orderBy = $this->getSqlOrderBy($filtro); + $limit = $this->getSqlLimit($filtro); + + $sql = sprintf(" + SELECT + s.id_servicio, s.nombre, s.descripcion, s.id_sistema_arai, s.vigencia_inicio,s.vigencia_fin + FROM + servicios s + %s + %s + %s;", $where, $orderBy, $limit); + + $result = $this->db->consultar($sql); + + if ($hidratar) { + $result = $this->hidratarServicios($result); + } + + return $result; + } + + /** + * @param Servicio $servicio + * @return bool|string + * @throws ErrorTupa No se pudo crear el servicio + */ + public function crear(Servicio $servicio) + { + $sql = "INSERT INTO servicios (nombre, descripcion, id_sistema_arai,vigencia_inicio) VALUES (:nombre, :descripcion, :id_sistema_arai,:vigencia_inicio)"; + + $sqlParams = [ + "nombre" => $servicio->getNombre(), + "descripcion" => $servicio->getDescripcion(), + "id_sistema_arai" => $servicio->getIdSistemaArai(), + "vigencia_inicio" => $servicio->getVigenciaInicio() + ]; + + $result = $this->db->sentencia_ejecutar($sql, $sqlParams); + + if (!$result) { + throw new ErrorTupa("No se pudo crear el servicio"); + } + + $sql = "SELECT id_servicio FROM servicios + WHERE nombre = :nombre + AND descripcion = :descripcion + AND vigencia_inicio = :vigencia_inicio + AND id_sistema_arai = :id_sistema_arai"; + + return $this->db->sentencia_consultar_fila($sql, $sqlParams); + } + + /** + * @param Servicio $servicio + * @return mixed + */ + public function actualizar($servicio) + { + $params = [ + "nombre" => $servicio->getNombre(), + "descripcion" => $servicio->getDescripcion(), + "id_sistema_arai" => $servicio->getIdSistemaArai(), + "vigencia_inicio" => $servicio->getVigenciaInicio(), + "vigencia_fin" => $servicio->getVigenciaFin(), + "id" => $servicio->getId(), + ]; + + $sql = "UPDATE servicios + SET nombre = :nombre, + descripcion = :descripcion, + id_sistema_arai = :id_sistema_arai, + vigencia_inicio = :vigencia_inicio, + vigencia_fin = :vigencia_fin + WHERE id_servicio = :id"; + + return $this->db->sentencia_ejecutar($sql, $params); + } + + /** + * @param $datos + * @return Servicio + */ + protected function hidratarServicio($datos) + { + $servicio = new Servicio(); + + $servicio->loadFromDatos($datos); + + return $servicio; + } + + /** + * @param $datos + * @return Servicio[] colección de Servicios + */ + protected function hidratarServicios($datos) + { + $servicios = []; + + if (count($datos) < 1) { + return $servicios; + } + + foreach ($datos as $dato) { + $servicios[] = $this->hidratarServicio($dato); + } + + return $servicios; + } +} diff --git a/core/src/UNAM/Tupa/Core/Negocio/SolicitudesServicios/Servicio.php b/core/src/UNAM/Tupa/Core/Negocio/SolicitudesServicios/Servicio.php new file mode 100644 index 00000000..66ee2d10 --- /dev/null +++ b/core/src/UNAM/Tupa/Core/Negocio/SolicitudesServicios/Servicio.php @@ -0,0 +1,100 @@ +<?php declare(strict_types=1); + +namespace UNAM\Tupa\Core\Negocio\SolicitudesServicios; + +class Servicio { + private int $idServicio; + private string $nombre; + private ?string $descripcion; + private string $idServicioArai; + private string $vigenciaInicio; + private ?string $vigenciaFin; + + public function getId():int { + return $this->idServicio; + } + + public function getNombre():string { + return $this->nombre; + } + + public function getDescripcion():string { + return $this->descripcion; + } + + public function getIdSistemaArai():string { + return $this->idServicioArai; + } + + public function getVigenciaInicio():string { + return $this->vigenciaInicio; + } + + public function getVigenciaFin():?string { + return $this->vigenciaFin ?? null; + } + + public function setId(int $idServicio):void { + $this->idServicio = $idServicio; + } + + public function setNombre(string $nombre):void { + $this->nombre = $nombre; + } + + public function setDescripcion(?string $descripcion):void { + $this->descripcion = $descripcion; + } + + public function setIdServicioArai(string $idServicioArai):void { + $this->idServicioArai = $idServicioArai; + } + + public function setVigenciaInicio(string $vigenciaInicio):void { + $this->vigenciaInicio = $vigenciaInicio; + } + + public function setVigenciaFin(?string $vigenciaFin):void { + $this->vigenciaFin = $vigenciaFin; + } + + /** + * Hidrata los atributos del objeto a partir de $datos + * + * @param array $datos inicializar directamente con un set de datos + */ + public function loadFromDatos(array $datos) + { + if (isset($datos['id_servicio'])) { + $this->setId($datos['id_servicio']); + } + if (isset($datos['nombre'])) { + $this->setNombre($datos['nombre']); + } + if (isset($datos['descripcion'])) { + $this->setDescripcion($datos['descripcion']); + } + if (isset($datos['id_sistema_arai'])) { + $this->setIdServicioArai($datos['id_sistema_arai']); + } + if (isset($datos['vigencia_inicio'])) { + $this->setVigenciaInicio($datos['vigencia_inicio']); + } + if (isset($datos['vigencia_fin'])) { + $this->setVigenciaFin($datos['vigencia_fin']); + } + } + + public function toArray(): array + { + return [ + 'id_servicio' => $this->getId(), + 'nombre' => $this->getNombre(), + 'descripcion' => $this->getDescripcion(), + 'id_sistema_arai' => $this->getIdSistemaArai(), + 'vigencia_inicio' => $this->getVigenciaInicio(), + 'vigencia_fin' => $this->getVigenciaFin() + ]; + } + +} \ No newline at end of file -- GitLab From a2c5d637de11e9c716f9c6c2be0ef0608ebc158c Mon Sep 17 00:00:00 2001 From: "luciano.cassettai" <luciano.cassettai@unam.edu.ar> Date: Thu, 16 Feb 2023 07:58:06 -0300 Subject: [PATCH 03/11] ADD get de servicios por unidad de gestion --- .../v1/unidades_gestion/unidades_gestion.php | 72 ++++++++++++++++++- .../Tupa/Core/Manager/ManagerServicio.php | 21 ++++++ .../Negocio/Organizacion/UnidadGestion.php | 15 +++- 3 files changed, 105 insertions(+), 3 deletions(-) diff --git a/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php b/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php index 8154c4b2..cc8533c3 100644 --- a/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php +++ b/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php @@ -5,6 +5,7 @@ use SIUToba\rest\lib\rest_hidratador; use SIUToba\rest\lib\rest_validador; use SIUToba\rest\rest; +use UNAM\Tupa\Core\Errors\ErrorTupa; use UNAM\Tupa\Core\Errors\UnidadGestionError; use UNAM\Tupa\Backend\API\Factory; use UNAM\Tupa\Core\Filtros\Filtro; @@ -40,6 +41,42 @@ class unidades_gestion implements SIUToba\rest\lib\modelable ); + $servicios = [ + 'id_servicio' => array( + 'type' => 'string', + ), + 'nombre' => array( + 'type' => 'string', + 'required' => true, + '_validar' => array( + rest_validador::OBLIGATORIO, + ), + ), + 'descripcion' => array( + 'type' => 'string', + 'required' => true, + '_validar' => array( + rest_validador::OBLIGATORIO, + ), + ), + 'id_sistema_arai' => array( + 'type' => 'string', + 'required' => true, + '_validar' => array( + rest_validador::OBLIGATORIO, + ), + ), + 'vigencia_inicio' => [ + 'type' => 'date', + '_validar' => [ + rest_validador::OBLIGATORIO, + rest_validador::TIPO_DATE => [ + 'format' => 'Y-m-d' + ], + ], + ] + ]; + $unidadGestion = array_merge( $unidadGestionEdit, array( @@ -53,6 +90,7 @@ class unidades_gestion implements SIUToba\rest\lib\modelable return $models = array( 'UnidadGestion' => $unidadGestion, 'UnidadGestionEdit' => $unidadGestionEdit, + 'Servicios' => $servicios, ); } @@ -129,6 +167,38 @@ class unidades_gestion implements SIUToba\rest\lib\modelable } } + /** + * Se consume en GET /unidades-gestion/{id}/servicios. + * + * @summary Retorna los servicios asociados a una unidad de gestion + * @responses 200 {"$ref": "UnidadGestion"} UnidadGestion + * @responses 404 No existe el recurso + * @responses 500 Error interno del servidor + */ + public function get_servicios_list($id) + { + try { + $manager = Factory::getManagerServicio(); + + $servicios = $manager->getServiciosUnidadGestion($id); + + $resultados = []; + foreach ($servicios as $s) { + $resultados[] = $s->toArray(); + } + + $registros = rest_hidratador::hidratar($this->get_spec_usuario('Servicios'), $resultados); + + rest::response()->get($registros); + }catch (ErrorTupa $e) { + Factory::getMainLogger()->error($e->getMessage()); + rest::response()->not_found($e->getMessage()); + }catch (Exception $e) { + Factory::getMainLogger()->error($e->getMessage()); + rest::response()->error_negocio('Error interno del servidor', 500); + } + } + /** * Se consume en POST /unidades-gestion * @@ -267,5 +337,3 @@ class unidades_gestion implements SIUToba\rest\lib\modelable return Factory::getVarios()->arrayToUtf8($resultado); } } - -?> \ No newline at end of file diff --git a/core/src/UNAM/Tupa/Core/Manager/ManagerServicio.php b/core/src/UNAM/Tupa/Core/Manager/ManagerServicio.php index dc9856b4..e557caa1 100644 --- a/core/src/UNAM/Tupa/Core/Manager/ManagerServicio.php +++ b/core/src/UNAM/Tupa/Core/Manager/ManagerServicio.php @@ -117,6 +117,27 @@ class ManagerServicio extends Manager return $this->db->sentencia_ejecutar($sql, $params); } + + public function getServiciosUnidadGestion($id_unidad){ + $params = [ + "id" => $id_unidad + ]; + + $sql = "SELECT s.id_servicio,s.nombre,descripcion,id_sistema_arai,vigencia_inicio,vigencia_fin + FROM UNIDADES_GESTION UG + INNER JOIN SERVICIOS_UNIDAD_GESTION SUG ON UG.ID_UNIDAD = SUG.ID_UNIDAD + INNER JOIN SERVICIOS S ON S.ID_SERVICIO = SUG.ID_SERVICIO + WHERE ug.id_unidad = :id"; + + + $result = $this->db->sentencia_consultar($sql,$params); + + if (!$result) { + throw new ErrorTupa("No se pudo recuperar la unidad de gestion '$id_unidad'"); + } + + return $this->hidratarServicios($result); + } /** * @param $datos diff --git a/core/src/UNAM/Tupa/Core/Negocio/Organizacion/UnidadGestion.php b/core/src/UNAM/Tupa/Core/Negocio/Organizacion/UnidadGestion.php index d2b2d034..a269a02a 100644 --- a/core/src/UNAM/Tupa/Core/Negocio/Organizacion/UnidadGestion.php +++ b/core/src/UNAM/Tupa/Core/Negocio/Organizacion/UnidadGestion.php @@ -9,6 +9,7 @@ class UnidadGestion { private string $sigla; private string $nombre; private string $idGrupoArai; + private ?array $servicios; public function getId():int{ return $this->id; @@ -26,6 +27,10 @@ class UnidadGestion { return $this->idGrupoArai; } + public function getServicios():?array{ + return $this->servicios ?? null; + } + public function setId(int $id){ $this->id = $id; } @@ -42,6 +47,10 @@ class UnidadGestion { $this->idGrupoArai = $idGrupo; } + public function setServicios(?array $servicios){ + $this->servicios = $servicios; + } + /** * Hidrata los atributos del objeto a partir de $datos * @@ -61,6 +70,9 @@ class UnidadGestion { if (isset($datos['id_grupo_arai'])) { $this->setIdGrupoArai($datos['id_grupo_arai']); } + if (isset($datos['servicios'])) { + $this->setServicios($datos['servicios']); + } } /** @@ -72,7 +84,8 @@ class UnidadGestion { 'id_unidad' => $this->getId(), 'sigla' => $this->getSigla(), 'nombre' => $this->getNombre(), - 'id_grupo_arai' => $this->getIdGrupoArai() + 'id_grupo_arai' => $this->getIdGrupoArai(), + 'servicios' => $this->getServicios(), ]; } } -- GitLab From e957d29c48616480e6f828c8737712dd18cc9f81 Mon Sep 17 00:00:00 2001 From: Fernando Alvez <fernando.alvez@unam.edu.ar> Date: Wed, 1 Mar 2023 12:03:38 -0300 Subject: [PATCH 04/11] ADD test postman de unidad gestion --- ...nidad_gestion_test.postman_collection.json | 306 ++++++++++++++++++ 1 file changed, 306 insertions(+) create mode 100644 api-backend/tests/Integration/v1/collections/unidad-gestion/tupa_api_backend_unidad_gestion_test.postman_collection.json diff --git a/api-backend/tests/Integration/v1/collections/unidad-gestion/tupa_api_backend_unidad_gestion_test.postman_collection.json b/api-backend/tests/Integration/v1/collections/unidad-gestion/tupa_api_backend_unidad_gestion_test.postman_collection.json new file mode 100644 index 00000000..a6b0a0c2 --- /dev/null +++ b/api-backend/tests/Integration/v1/collections/unidad-gestion/tupa_api_backend_unidad_gestion_test.postman_collection.json @@ -0,0 +1,306 @@ +{ + "info": { + "_postman_id": "f03eb109-43a9-4bb8-8164-50d7134ca6bd", + "name": "Tupa API Backend Unidades Gestion", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "16366966" + }, + "item": [ + { + "name": "V1", + "item": [ + { + "name": "Unidad Gestión", + "item": [ + { + "name": "Crear unidad de gestión", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", () => {", + " pm.response.to.have.status(201);", + "});", + "", + "const servicioSchema = { ", + " \"sigla\": '',", + " \"nombre\": '',", + " \"id_grupo_arai\": ''", + "}", + "", + "const body = JSON.parse(pm.request.body.raw);", + "const sameSchema = JSON.stringify(Object.keys(servicioSchema)) === JSON.stringify(Object.keys(body));", + "", + "pm.test('Estructura del body correcta', () => {", + " pm.expect(true).to.be.eql(sameSchema);", + "}); ", + "", + "var respuesta = pm.response.json();", + "", + "pm.test(\"unidad de gestion creada con ID \" + respuesta.id_unidad, function () {", + " pm.globals.set(\"idUnidadGestion\", respuesta.id_unidad);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"sigla\": \"{{$randomWord}}\",\n \"nombre\": \"{{$randomWords}}\",\n \"id_grupo_arai\": \"{{$randomUUID}}\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/v1/unidades-gestion", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "unidades-gestion" + ] + } + }, + "response": [] + }, + { + "name": "Obtener unidad de gestión", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200);", + "});", + "", + "/*", + "const response = pm.response.json();", + "const hasId = Object.keys(response).includes('id_unidad');", + "", + "pm.test(\"Servicio con id_unidad \" + response.id_unidad, function () {", + " pm.expect(true).to.be.eql(hasId);", + "});", + "*/" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/v1/unidades-gestion/{{idUnidadGestion}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "unidades-gestion", + "{{idUnidadGestion}}" + ] + } + }, + "response": [] + }, + { + "name": "Modificar unidad de gestión", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200);", + "});", + "", + "const unidadGestionSchema = {", + " \"sigla\": \"\",", + " \"nombre\": \"\",", + " \"id_grupo_arai\": \"\"", + "}", + "", + "const body = JSON.parse(pm.request.body.raw);", + "const sameSchema = JSON.stringify(Object.keys(unidadGestionSchema)) === JSON.stringify(Object.keys(body));", + "", + "pm.test('Estructura del body correcta', () => {", + " pm.expect(true).to.be.eql(sameSchema);", + "}); ", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"sigla\": \"UG-MOD\",\n \"nombre\": \"UG Modificada\",\n \"id_grupo_arai\": \"123456789\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/v1/unidades-gestion/{{idUnidadGestion}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "unidades-gestion", + "{{idUnidadGestion}}" + ] + } + }, + "response": [] + }, + { + "name": "Obtener servicios asociados a una unidad de gestion", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Se obtuvieron servicios \", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.length).to.be.above(0);", + "", + " const hasId = Object.keys(jsonData[0]).includes('id_servicio');", + " // Si el servicio tiene un id_servicio", + " pm.expect(true).to.be.eql(hasId);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/v1/unidades-gestion/{{idUnidadGestion}}/servicios", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "unidades-gestion", + "{{idUnidadGestion}}", + "servicios" + ] + } + }, + "response": [] + }, + { + "name": "Elimina una unidad de gestion", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200);", + "});", + "", + "var respuesta = pm.response.json();", + "", + "pm.test(\"Eliminado correctamente\", function () {", + " var jsonData = pm.response.json();", + " pm.expect(jsonData.respuesta).to.eql(true);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/v1/unidades-gestion/{{idUnidadGestion}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "unidades-gestion", + "{{idUnidadGestion}}" + ] + } + }, + "response": [] + } + ] + } + ] + } + ], + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "admin", + "type": "string" + }, + { + "key": "username", + "value": "admin", + "type": "string" + } + ] + }, + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "key": "baseUrl", + "value": "http://localhost:9002/api" + } + ] +} \ No newline at end of file -- GitLab From 193eb10089a73da22dc35285e66aaf439eb6b9aa Mon Sep 17 00:00:00 2001 From: "luciano.cassettai" <luciano.cassettai@unam.edu.ar> Date: Wed, 22 Feb 2023 10:31:33 -0300 Subject: [PATCH 05/11] Fix : agrega vigencia fin al endpoint "unidades-gestion servicios" --- .../v1/unidades_gestion/unidades_gestion.php | 23 ++++--------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php b/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php index cc8533c3..33d1ff9f 100644 --- a/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php +++ b/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php @@ -47,34 +47,19 @@ class unidades_gestion implements SIUToba\rest\lib\modelable ), 'nombre' => array( 'type' => 'string', - 'required' => true, - '_validar' => array( - rest_validador::OBLIGATORIO, - ), ), 'descripcion' => array( 'type' => 'string', - 'required' => true, - '_validar' => array( - rest_validador::OBLIGATORIO, - ), ), 'id_sistema_arai' => array( 'type' => 'string', - 'required' => true, - '_validar' => array( - rest_validador::OBLIGATORIO, - ), ), 'vigencia_inicio' => [ 'type' => 'date', - '_validar' => [ - rest_validador::OBLIGATORIO, - rest_validador::TIPO_DATE => [ - 'format' => 'Y-m-d' - ], - ], - ] + ], + 'vigencia_fin' => [ + 'type' => 'date', + ] ]; $unidadGestion = array_merge( -- GitLab From ba8ef0cd6dcc4e003861a5cab1722800d3b66b21 Mon Sep 17 00:00:00 2001 From: "luciano.cassettai" <luciano.cassettai@unam.edu.ar> Date: Thu, 2 Mar 2023 10:27:47 -0300 Subject: [PATCH 06/11] Agrega filtro de servicios por unidad de gestion --- .../API/Endpoints/v1/servicios/servicios.php | 18 ++++++++++-------- .../UNAM/Tupa/Core/Manager/ManagerServicio.php | 13 +++++++++---- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/servicios/servicios.php b/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/servicios/servicios.php index 75effba3..e3b3e8cf 100644 --- a/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/servicios/servicios.php +++ b/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/servicios/servicios.php @@ -17,7 +17,7 @@ class servicios implements SIUToba\rest\lib\modelable { $vigenciaFin = [ 'vigencia_fin' => [ - 'type' => 'string', + 'type' => 'date', '_validar' => [ rest_validador::TIPO_DATE => [ 'format' => 'Y-m-d' @@ -60,13 +60,13 @@ class servicios implements SIUToba\rest\lib\modelable ); $servicio = array_merge( - $servicioEdit, - $vigenciaFin, array( 'id_servicio' => array( 'type' => 'integer', ), - ) + ), + $servicioEdit, + $vigenciaFin ); @@ -121,6 +121,8 @@ class servicios implements SIUToba\rest\lib\modelable * @param_query $id_sistema_arai string Se define como 'condicion;valor' donde 'condicion' puede ser es_menor_que|es_menor_igual_que|es_igual_a|es_distinto_de|es_mayor_igual_que|es_mayor_que|entre * @param_query $vigencia_inicio string Se define como 'condicion;valor' donde 'condicion' puede ser es_menor_que|es_menor_igual_que|es_igual_a|es_distinto_de|es_mayor_igual_que|es_mayor_que|entre * @param_query $vigencia_fin string Se define como 'condicion;valor' donde 'condicion' puede ser es_menor_que|es_menor_igual_que|es_igual_a|es_distinto_de|es_mayor_igual_que|es_mayor_que|entre + * @param_query $unidad_gestion string Se define como 'condicion;valor' donde 'condicion' puede ser es_menor_que|es_menor_igual_que|es_igual_a|es_distinto_de|es_mayor_igual_que|es_mayor_que|entre + * * @param_query $limit integer Limitar a esta cantidad de servicios * @param_query $page integer Limitar desde esta pagina @@ -137,7 +139,6 @@ class servicios implements SIUToba\rest\lib\modelable $filtro->setOrder(rest::request()->get('order', null)); $manager = Factory::getManagerServicio(); - $servicios = $manager->getServicios($filtro); $resultados = []; @@ -161,7 +162,7 @@ class servicios implements SIUToba\rest\lib\modelable * @summary Crea un nuevo servicio * @param_body $servicios ServicioEdit [required] los datos del servicio * @responses 201 {"string"} identificador de un servicio - * @responses 400 Servicio inválido + * @responses 400 Servicio inválido * @responses 500 Error interno */ public function post_list() @@ -200,7 +201,7 @@ class servicios implements SIUToba\rest\lib\modelable * @summary Modifica un servicio * @param_body $ServicioEdit ServicioEdit [required] los datos a editar de un servicio * @responses 204 El id es correcto - * @responses 400 El id no válido + * @responses 400 El id no válido * @responses 404 No existe el recurso * @responses 500 Error interno */ @@ -279,7 +280,8 @@ class servicios implements SIUToba\rest\lib\modelable $filtro->agregarCampoRest('s.id_sistema_arai', rest::request()->get('id_sistema_arai', null)); $filtro->agregarCampoRest('s.vigencia_inicio', rest::request()->get('vigencia_inicio', null)); $filtro->agregarCampoRest('s.vigencia_fin', rest::request()->get('vigencia_fin', null)); - + $filtro->agregarCampoRest('ug.id_unidad', rest::request()->get('unidad_gestion', null)); + $filtro->agregarCampoOrdenable('nombre'); $filtro->agregarCampoOrdenable('vigencia_inicio'); diff --git a/core/src/UNAM/Tupa/Core/Manager/ManagerServicio.php b/core/src/UNAM/Tupa/Core/Manager/ManagerServicio.php index e557caa1..00247292 100644 --- a/core/src/UNAM/Tupa/Core/Manager/ManagerServicio.php +++ b/core/src/UNAM/Tupa/Core/Manager/ManagerServicio.php @@ -44,10 +44,15 @@ class ManagerServicio extends Manager $limit = $this->getSqlLimit($filtro); $sql = sprintf(" - SELECT - s.id_servicio, s.nombre, s.descripcion, s.id_sistema_arai, s.vigencia_inicio,s.vigencia_fin - FROM - servicios s + SELECT S.ID_SERVICIO, + S.NOMBRE, + S.DESCRIPCION, + S.ID_SISTEMA_ARAI, + S.VIGENCIA_INICIO, + S.VIGENCIA_FIN + FROM SERVICIOS S + LEFT JOIN SERVICIOS_UNIDAD_GESTION SUG ON S.ID_SERVICIO = SUG.ID_SERVICIO + LEFT JOIN UNIDADES_GESTION UG ON SUG.ID_UNIDAD = UG.ID_UNIDAD %s %s %s;", $where, $orderBy, $limit); -- GitLab From a8f74cb3ab9ef4010db48ba80b95c73a962a3843 Mon Sep 17 00:00:00 2001 From: "luciano.cassettai" <luciano.cassettai@unam.edu.ar> Date: Wed, 8 Mar 2023 08:43:14 -0300 Subject: [PATCH 07/11] Permite agregar servicios para una unidad de gestion --- .../v1/unidades_gestion/unidades_gestion.php | 62 +++++++++++++++++-- .../Core/Manager/ManagerUnidadGestion.php | 31 ++++++++++ 2 files changed, 87 insertions(+), 6 deletions(-) diff --git a/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php b/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php index 33d1ff9f..1b09f10a 100644 --- a/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php +++ b/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php @@ -41,10 +41,10 @@ class unidades_gestion implements SIUToba\rest\lib\modelable ); - $servicios = [ - 'id_servicio' => array( - 'type' => 'string', - ), + $servicio = [ + 'id_servicio' => [ + 'type' => 'integer' + ], 'nombre' => array( 'type' => 'string', ), @@ -62,6 +62,23 @@ class unidades_gestion implements SIUToba\rest\lib\modelable ] ]; + $servicios = [ + 'servicios' => [ + 'type' => 'array', + 'required' => true, + '_validar' => [ + rest_validador::OBLIGATORIO, + ], + 'items' => [ + 'type' => 'integer', + 'required' => true, + '_validar' => [ + rest_validador::OBLIGATORIO, + ]] + ] + ]; + + $unidadGestion = array_merge( $unidadGestionEdit, array( @@ -75,7 +92,8 @@ class unidades_gestion implements SIUToba\rest\lib\modelable return $models = array( 'UnidadGestion' => $unidadGestion, 'UnidadGestionEdit' => $unidadGestionEdit, - 'Servicios' => $servicios, + 'Servicio' => $servicio, + 'Servicios' => $servicios ); } @@ -172,7 +190,7 @@ class unidades_gestion implements SIUToba\rest\lib\modelable $resultados[] = $s->toArray(); } - $registros = rest_hidratador::hidratar($this->get_spec_usuario('Servicios'), $resultados); + $registros = rest_hidratador::hidratar($this->get_spec_usuario('Servicio'), $resultados); rest::response()->get($registros); }catch (ErrorTupa $e) { @@ -184,6 +202,38 @@ class unidades_gestion implements SIUToba\rest\lib\modelable } } + /** + * Se consume en POST /unidades-gestion/{id}/servicios. + * + * @summary Asocia distintos servicios a una unidad de gestion + * @param_body $servicios Servicios [required] array de ids de los servicios + * @responses 201 {"boolean"} exito + * @responses 400 unidad de gestion inválida + * @responses 500 Error interno + */ + public function post_servicios_list($id) + { + // Valido y traduzco los datos al formato de mi modelo + $servicios = $this->procesar_input_edicion('Servicios'); + + try { + $manager = Factory::getManagerUnidadGestion(); + + $resultado = $manager->agregarServicios($id,$servicios); + + rest::response()->post([ "respuesta" => $resultado ]); + } + catch (UnidadGestionError $e) { + rest::response()->error_negocio([$e->getMessage()], 400); + } catch (Exception $e) { + if ($e->getCode() >= 400 || $e->getCode() < 500) { + rest::response()->error_negocio([$e->getMessage()], 400); + } else { + rest::response()->error_negocio([$e->getMessage()], 500); + } + } + } + /** * Se consume en POST /unidades-gestion * diff --git a/core/src/UNAM/Tupa/Core/Manager/ManagerUnidadGestion.php b/core/src/UNAM/Tupa/Core/Manager/ManagerUnidadGestion.php index bf00c59a..64dd929e 100644 --- a/core/src/UNAM/Tupa/Core/Manager/ManagerUnidadGestion.php +++ b/core/src/UNAM/Tupa/Core/Manager/ManagerUnidadGestion.php @@ -5,6 +5,7 @@ namespace UNAM\Tupa\Core\Manager; use UNAM\Tupa\Core\Errors\UnidadGestionError; use UNAM\Tupa\Core\Filtros\Filtro; use UNAM\Tupa\Core\Negocio\Organizacion\UnidadGestion; +use UNAM\Tupa\Backend\API\Factory; class ManagerUnidadGestion extends Manager { @@ -135,6 +136,36 @@ class ManagerUnidadGestion extends Manager return $result; } + /** + * @param int $idUnidad id de la unidad de gestion + * @param array $servicios id de los servicios que se van a asociar a la ug + * @return bool + * @throws UnidadGestionError + */ + public function agregarServicios($idUnidad, $servicios) + { + try{ + $this->db->abrir_transaccion(); + foreach($servicios['servicios'] as $idServicio){ + $params = [ + 'id_unidad_gestion' => $idUnidad, + 'id_servicio' => $idServicio + ]; + + $sql = "INSERT INTO servicios_unidad_gestion VALUES (:id_unidad_gestion,:id_servicio)"; + + $this->db->sentencia_ejecutar($sql, $params); + } + $this->db->cerrar_transaccion(); + return true; + }catch(\Exception $e){ + $this->db->abortar_transaccion(); + Factory::getMainLogger()->error($e->getMessage()); + throw new UnidadGestionError("No se pudo agregar el servicio a la unidad $idUnidad"); + } + return false; + } + /** * @param $datos * @return UnidadGestion -- GitLab From 7db4c951f45ec7c7385f36f53f4d0b93ec7f1698 Mon Sep 17 00:00:00 2001 From: "luciano.cassettai" <luciano.cassettai@unam.edu.ar> Date: Wed, 8 Mar 2023 09:36:40 -0300 Subject: [PATCH 08/11] Agrega get_list de unidad de gestion en las pruebas de postman --- ...nidad_gestion_test.postman_collection.json | 80 +++++++++++++++++-- .../Tupa/Core/Manager/ManagerServicio.php | 2 +- 2 files changed, 75 insertions(+), 7 deletions(-) diff --git a/api-backend/tests/Integration/v1/collections/unidad-gestion/tupa_api_backend_unidad_gestion_test.postman_collection.json b/api-backend/tests/Integration/v1/collections/unidad-gestion/tupa_api_backend_unidad_gestion_test.postman_collection.json index a6b0a0c2..82f750ab 100644 --- a/api-backend/tests/Integration/v1/collections/unidad-gestion/tupa_api_backend_unidad_gestion_test.postman_collection.json +++ b/api-backend/tests/Integration/v1/collections/unidad-gestion/tupa_api_backend_unidad_gestion_test.postman_collection.json @@ -1,9 +1,9 @@ { "info": { - "_postman_id": "f03eb109-43a9-4bb8-8164-50d7134ca6bd", + "_postman_id": "414381a0-51a4-429f-a4c1-82e5a8754f14", "name": "Tupa API Backend Unidades Gestion", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", - "_exporter_id": "16366966" + "_exporter_id": "25165965" }, "item": [ { @@ -180,11 +180,16 @@ "", "pm.test(\"Se obtuvieron servicios \", function () {", " var jsonData = pm.response.json();", - " pm.expect(jsonData.length).to.be.above(0);", + " ", + " if(jsonData.length > 0){", + " pm.expect(jsonData.length).to.be.above(0);", "", - " const hasId = Object.keys(jsonData[0]).includes('id_servicio');", - " // Si el servicio tiene un id_servicio", - " pm.expect(true).to.be.eql(hasId);", + " const hasId = Object.keys(jsonData[0]).includes('id_servicio');", + " // Si el servicio tiene un id_servicio", + " pm.expect(true).to.be.eql(hasId);", + " }else{", + " pm.expect(jsonData.length).to.be.equal(0);", + " } ", "});" ], "type": "text/javascript" @@ -209,6 +214,69 @@ }, "response": [] }, + { + "name": "Obtener unidades de gestion", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200);", + "});", + "", + "const jsonData = pm.response.json();", + "", + "pm.test(\"Obtener unidades de gestion \", function () { ", + " if(jsonData.length > 0){", + " pm.expect(jsonData.length).to.be.above(0);", + "", + " const hasId = Object.keys(jsonData[0]).includes('id_unidad');", + " // Si el servicio tiene un id_servicio", + " pm.expect(true).to.be.eql(hasId);", + " }else{", + " pm.expect(jsonData.length).to.be.equal(0);", + " } ", + "});", + "", + "", + "const plantillaUA = { ", + " \"sigla\": '',", + " \"nombre\": '',", + " \"id_grupo_arai\": '',", + " \"id_unidad\": ''", + "};", + "", + "pm.test('Estructura de la respuesta correcta', () => {", + " if(jsonData.length > 0){", + " const sameSchema = JSON.stringify(Object.keys(plantillaUA)) === JSON.stringify(Object.keys(jsonData[0]));", + " pm.expect(true).to.be.eql(sameSchema);", + " }else{", + " const sameSchema = JSON.stringify([]) === JSON.stringify(jsonData);", + " pm.expect(true).to.be.eql(sameSchema);", + " } ", + "}); " + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/v1/unidades-gestion", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "unidades-gestion" + ] + } + }, + "response": [] + }, { "name": "Elimina una unidad de gestion", "event": [ diff --git a/core/src/UNAM/Tupa/Core/Manager/ManagerServicio.php b/core/src/UNAM/Tupa/Core/Manager/ManagerServicio.php index 00247292..bbf6b897 100644 --- a/core/src/UNAM/Tupa/Core/Manager/ManagerServicio.php +++ b/core/src/UNAM/Tupa/Core/Manager/ManagerServicio.php @@ -138,7 +138,7 @@ class ManagerServicio extends Manager $result = $this->db->sentencia_consultar($sql,$params); if (!$result) { - throw new ErrorTupa("No se pudo recuperar la unidad de gestion '$id_unidad'"); + return []; } return $this->hidratarServicios($result); -- GitLab From 6c197ea6f2888da8c63af554dcbfdf7ea7798f79 Mon Sep 17 00:00:00 2001 From: "luciano.cassettai" <luciano.cassettai@unam.edu.ar> Date: Wed, 8 Mar 2023 11:01:21 -0300 Subject: [PATCH 09/11] Perimita eliminar servicios asociados a una unidad de gestion --- .../v1/unidades_gestion/unidades_gestion.php | 33 +++++++++++++++++ .../Core/Manager/ManagerUnidadGestion.php | 37 ++++++++++++++++++- 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php b/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php index 1b09f10a..22ee16ba 100644 --- a/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php +++ b/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php @@ -305,6 +305,39 @@ class unidades_gestion implements SIUToba\rest\lib\modelable } } + /** + * Se consume en DELETE /unidades_gestion/{id}/servicios + * + * @summary Elimina los servicios asociados a una unidad de gestion + * @param_body $servicios Servicios [required] array de ids de los servicios + * @responses 200 Se elimino correctamente + * @responses 400 El id no existe + * @responses 404 No existe el recurso + * @responses 500 Error interno + */ + public function delete_servicios_list($id) + { + $servicios = $this->procesar_input_edicion('Servicios'); + + try { + $manager = Factory::getManagerUnidadGestion(); + + $manager->eliminarServicios($id,$servicios); + + rest::response()->put([ "respuesta" => true ]); + }catch (UnidadGestionError $e) { + rest::response()->error_negocio([$e->getMessage()], 400); + } + catch (\Exception $e) { + Factory::getMainLogger()->error($e->getMessage()); + if ($e->getCode() >= 400 || $e->getCode() < 500) { + rest::response()->error_negocio([$e->getMessage()], 400); + } else { + rest::response()->error_negocio([$e->getMessage()], 500); + } + } + } + /** * Se consume en DELETE /unidades_gestion/{identificador} * diff --git a/core/src/UNAM/Tupa/Core/Manager/ManagerUnidadGestion.php b/core/src/UNAM/Tupa/Core/Manager/ManagerUnidadGestion.php index 64dd929e..e072b27f 100644 --- a/core/src/UNAM/Tupa/Core/Manager/ManagerUnidadGestion.php +++ b/core/src/UNAM/Tupa/Core/Manager/ManagerUnidadGestion.php @@ -145,6 +145,8 @@ class ManagerUnidadGestion extends Manager public function agregarServicios($idUnidad, $servicios) { try{ + $sql = "INSERT INTO servicios_unidad_gestion VALUES (:id_unidad_gestion,:id_servicio)"; + $this->db->abrir_transaccion(); foreach($servicios['servicios'] as $idServicio){ $params = [ @@ -152,7 +154,6 @@ class ManagerUnidadGestion extends Manager 'id_servicio' => $idServicio ]; - $sql = "INSERT INTO servicios_unidad_gestion VALUES (:id_unidad_gestion,:id_servicio)"; $this->db->sentencia_ejecutar($sql, $params); } @@ -166,6 +167,40 @@ class ManagerUnidadGestion extends Manager return false; } + /** + * @param int $idUnidad id de la unidad de gestion + * @param array $servicios id de los servicios que se van a eliminar de laug + * @return bool + * @throws UnidadGestionError + */ + public function eliminarServicios($idUnidad, $servicios) + { + try{ + $sql = "DELETE FROM servicios_unidad_gestion WHERE id_unidad = :id_unidad_gestion and id_servicio = :id_servicio"; + + $this->db->abrir_transaccion(); + foreach($servicios['servicios'] as $idServicio){ + $params = [ + 'id_unidad_gestion' => $idUnidad, + 'id_servicio' => $idServicio + ]; + + $resultado = $this->db->sentencia_ejecutar($sql, $params); + + if(!$resultado){ + throw new \Exception('No se encontro el servicio para esta UG'); + } + } + $this->db->cerrar_transaccion(); + return true; + }catch(\Exception $e){ + $this->db->abortar_transaccion(); + Factory::getMainLogger()->error($e->getMessage()); + throw new UnidadGestionError("No se pudo eliminar el/los servicio de la unidad $idUnidad"); + } + return false; + } + /** * @param $datos * @return UnidadGestion -- GitLab From 4dd5eed5e471ea62325d3e01fa7b8e45de76458d Mon Sep 17 00:00:00 2001 From: "luciano.cassettai" <luciano.cassettai@unam.edu.ar> Date: Thu, 9 Mar 2023 12:44:33 -0300 Subject: [PATCH 10/11] Verifica que el servicio y la ua existen antes de eliminarlos --- .../v1/unidades_gestion/unidades_gestion.php | 15 ++++++++++++--- .../Tupa/Core/Manager/ManagerUnidadGestion.php | 11 +++++------ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php b/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php index 22ee16ba..202ede3b 100644 --- a/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php +++ b/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php @@ -10,6 +10,7 @@ use UNAM\Tupa\Core\Errors\UnidadGestionError; use UNAM\Tupa\Backend\API\Factory; use UNAM\Tupa\Core\Filtros\Filtro; use UNAM\Tupa\Core\Negocio\Organizacion\UnidadGestion; +use UNAM\Tupa\Core\Negocio\SolicitudesServicios\Servicio; class unidades_gestion implements SIUToba\rest\lib\modelable @@ -317,12 +318,20 @@ class unidades_gestion implements SIUToba\rest\lib\modelable */ public function delete_servicios_list($id) { - $servicios = $this->procesar_input_edicion('Servicios'); + $idServicios = $this->procesar_input_edicion('Servicios'); try { - $manager = Factory::getManagerUnidadGestion(); + $managerUG = Factory::getManagerUnidadGestion(); + $managerServicio = Factory::getManagerServicio(); + + $unidadGestion = $managerUG->getUnidadGestion($id); + + $filtro = new Filtro(); + $filtro->agregarCampo('s.id_servicio',$filtro::DENTRO,$idServicios['servicios']); - $manager->eliminarServicios($id,$servicios); + $servicios = $managerServicio->getServicios($filtro); + + $managerUG->eliminarServicios($unidadGestion,$servicios); rest::response()->put([ "respuesta" => true ]); }catch (UnidadGestionError $e) { diff --git a/core/src/UNAM/Tupa/Core/Manager/ManagerUnidadGestion.php b/core/src/UNAM/Tupa/Core/Manager/ManagerUnidadGestion.php index e072b27f..7f55e30e 100644 --- a/core/src/UNAM/Tupa/Core/Manager/ManagerUnidadGestion.php +++ b/core/src/UNAM/Tupa/Core/Manager/ManagerUnidadGestion.php @@ -152,8 +152,7 @@ class ManagerUnidadGestion extends Manager $params = [ 'id_unidad_gestion' => $idUnidad, 'id_servicio' => $idServicio - ]; - + ]; $this->db->sentencia_ejecutar($sql, $params); } @@ -173,16 +172,16 @@ class ManagerUnidadGestion extends Manager * @return bool * @throws UnidadGestionError */ - public function eliminarServicios($idUnidad, $servicios) + public function eliminarServicios($unidadGestion, $servicios) { try{ $sql = "DELETE FROM servicios_unidad_gestion WHERE id_unidad = :id_unidad_gestion and id_servicio = :id_servicio"; $this->db->abrir_transaccion(); - foreach($servicios['servicios'] as $idServicio){ + foreach($servicios as $servicio){ $params = [ - 'id_unidad_gestion' => $idUnidad, - 'id_servicio' => $idServicio + 'id_unidad_gestion' => $unidadGestion->getId(), + 'id_servicio' => $servicio->getId() ]; $resultado = $this->db->sentencia_ejecutar($sql, $params); -- GitLab From 5193f8b4111f3f885d0bdc8e0d73bf15b6f5494a Mon Sep 17 00:00:00 2001 From: "luciano.cassettai" <luciano.cassettai@unam.edu.ar> Date: Tue, 4 Apr 2023 11:21:22 -0300 Subject: [PATCH 11/11] ABM funciones --- .../API/Endpoints/v1/funciones/funciones.php | 386 ++++++++++++++++++ .../API/Endpoints/v1/servicios/servicios.php | 16 +- .../v1/unidades_gestion/unidades_gestion.php | 13 +- .../src/UNAM/Tupa/Backend/API/Factory.php | 15 + ..._autorizantes_test.postman_collection.json | 0 ...end_funciones_test.postman_collection.json | 358 ++++++++++++++++ ...kend_permisos_test.postman_collection.json | 0 ...d_solicitudes_test.postman_collection.json | 0 api-backend/www/api.php | 2 +- .../UNAM/Tupa/Core/Manager/ManagerFuncion.php | 314 ++++++++++++++ .../Negocio/Organizacion/UnidadGestion.php | 2 +- .../Negocio/SolicitudesServicios/Funcion.php | 157 +++++++ 12 files changed, 1248 insertions(+), 15 deletions(-) create mode 100644 api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/funciones/funciones.php rename "api-backend/tests/Integration/v1/collections\342\200\216/autorizantes/tupa_api_backend_autorizantes_test.postman_collection.json" => api-backend/tests/Integration/v1/collections/autorizantes/tupa_api_backend_autorizantes_test.postman_collection.json (100%) create mode 100644 api-backend/tests/Integration/v1/collections/funciones/tupa_api_backend_funciones_test.postman_collection.json rename "api-backend/tests/Integration/v1/collections\342\200\216/permisos/tupa_api_backend_permisos_test.postman_collection.json" => api-backend/tests/Integration/v1/collections/permisos/tupa_api_backend_permisos_test.postman_collection.json (100%) rename "api-backend/tests/Integration/v1/collections\342\200\216/solicitudes/tupa_api_backend_solicitudes_test.postman_collection.json" => api-backend/tests/Integration/v1/collections/solicitudes/tupa_api_backend_solicitudes_test.postman_collection.json (100%) create mode 100644 core/src/UNAM/Tupa/Core/Manager/ManagerFuncion.php create mode 100644 core/src/UNAM/Tupa/Core/Negocio/SolicitudesServicios/Funcion.php diff --git a/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/funciones/funciones.php b/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/funciones/funciones.php new file mode 100644 index 00000000..e0fdc7a9 --- /dev/null +++ b/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/funciones/funciones.php @@ -0,0 +1,386 @@ +<?php +namespace UNAM\Tupa\Backend\API\Endpoints\v1\funciones; + +use SIUToba\rest\lib\rest_error; +use SIUToba\rest\lib\rest_hidratador; +use SIUToba\rest\lib\rest_validador; +use SIUToba\rest\rest; + +use UNAM\Tupa\Core\Errors\ErrorTupa; +use UNAM\Tupa\Backend\API\Factory; +use UNAM\Tupa\Core\Filtros\Filtro; +use UNAM\Tupa\Core\Negocio\SolicitudesServicios\Funcion; + + + +class funciones implements \SIUToba\rest\lib\modelable +{ + public static function _get_modelos() + { + $vigenciaFin = [ + 'vigencia_fin' => [ + 'type' => 'date', + '_validar' => [ + rest_validador::TIPO_DATE => [ + 'format' => 'Y-m-d' + ], + ], + ] + ]; + + $funcionEdit = [ + 'nombre' => [ + 'type' => 'string', + 'required' => true, + '_validar' => array( + rest_validador::OBLIGATORIO, + ), + ], + 'descripcion' => [ + 'type' => 'string', + 'required' => true, + '_validar' => array( + rest_validador::OBLIGATORIO, + ), + ], + 'es_agrupador' => [ + 'type' => 'boolean', + ], + 'vigencia_inicio' => [ + 'type' => 'date', + '_validar' => [ + rest_validador::TIPO_DATE => [ + 'format' => 'Y-m-d' + ], + ], + ], + 'vigencia_fin' => [ + 'type' => 'date', + '_validar' => [ + rest_validador::TIPO_DATE => [ + 'format' => 'Y-m-d' + ], + ], + ], + 'id_funcion_padre' => [ + 'type' => 'integer', + ], + 'id_funcion_predecesor' => [ + 'type' => 'integer', + ], + 'id_servicio' => [ + 'type' => 'integer', + 'required' => true, + '_validar' => [ + rest_validador::OBLIGATORIO, + ], + ] + ]; + + $funcion = array_merge( + array( + 'id_funcion' => array( + 'type' => 'integer', + ), + ), + $funcionEdit + ); + + return $models = array( + 'Funcion' => $funcion, + 'FuncionEdit' => $funcionEdit, + 'VigenciaFin' => $vigenciaFin + ); + } + + protected function get_spec_usuario($tipo = 'Funcion') + { + $m = $this->_get_modelos(); + + return $m[$tipo]; + } + + /** + * Se consume en GET /funciones/{id}. + * + * @summary Retorna datos de una funcion + * @responses 200 {"$ref": "Funcion"} Funcion + * @responses 404 No existe el recurso + * @responses 500 Error interno del servidor + */ + public function get($id) + { + try { + $manager = Factory::getManagerFuncion(); + + $funcion = $manager->getFuncion($id); + + $fila = rest_hidratador::hidratar_fila($this->get_spec_usuario('Funcion'), $funcion->toArray()); + + rest::response()->get($fila); + } catch (ErrorTupa $e) { + Factory::getMainLogger()->error($e->getMessage()); + rest::response()->not_found(); + } catch (\Exception $e) { + Factory::getMainLogger()->error($e->getMessage()); + rest::response()->error_negocio('Error interno del servidor', 500); + } + } + + /** + * Se consume en GET /funciones. + * + * @summary Retorna las funciones existentes + * @param_query $nombre string Se define como 'condicion;valor' donde 'condicion' puede ser contiene|no_contiene|comienza_con|termina_con|es_igual_a|es_distinto_de + * @param_query $descripcion string Se define como 'condicion;valor' donde 'condicion' puede ser es_menor_que|es_menor_igual_que|es_igual_a|es_distinto_de|es_mayor_igual_que|es_mayor_que|entre + * @param_query $id_servicio integer Se define como 'condicion;valor' donde 'condicion' puede ser es_menor_que|es_menor_igual_que|es_igual_a|es_distinto_de|es_mayor_igual_que|es_mayor_que|entre + * @param_query $id_funcion_padre string Se define como 'condicion;valor' donde 'condicion' puede ser es_menor_que|es_menor_igual_que|es_igual_a|es_distinto_de|es_mayor_igual_que|es_mayor_que|entre + * @param_query $id_funcion_predecesor string Se define como 'condicion;valor' donde 'condicion' puede ser es_menor_que|es_menor_igual_que|es_igual_a|es_distinto_de|es_mayor_igual_que|es_mayor_que|entre + * @param_query $vigencia_inicio string Se define como 'condicion;valor' donde 'condicion' puede ser es_menor_que|es_menor_igual_que|es_igual_a|es_distinto_de|es_mayor_igual_que|es_mayor_que|entre + * @param_query $vigencia_fin string Se define como 'condicion;valor' donde 'condicion' puede ser es_menor_que|es_menor_igual_que|es_igual_a|es_distinto_de|es_mayor_igual_que|es_mayor_que|entre + * @param_query $es_agrupador Boolean Es una funcion agrupadora de otras funciones + * @param_query $limit integer Limitar a esta cantidad de servicios + * @param_query $page integer Limitar desde esta pagina + * @param_query $order string +/-campo,... + * @responses 200 array {"$ref":"Funcion"} + * @responses 500 Error en los operadores ingresados para el filtro + */ + public function get_list() + { + try { + $filtro = $this->get_filtro_get_list(); + + $filtro->setlimit(rest::request()->get('limit', null)); + $filtro->setPage(rest::request()->get('page', null)); + $filtro->setOrder(rest::request()->get('order', null)); + + $manager = Factory::getManagerFuncion(); + $funciones = $manager->getFunciones($filtro); + + $resultados = []; + foreach ($funciones as $f) { + $resultados[] = $f->toArray(); + } + + $registros = rest_hidratador::hidratar($this->get_spec_usuario('Funcion'), $resultados); + + rest::response()->get($registros); + } catch (\Exception $e) { + Factory::getMainLogger()->error($e->getMessage()); + rest::response()->error_negocio('Error interno del servidor', 500); + } + } + + /** + * Se consume en GET /funciones/{id_funcion_padre}/hijas + * + * @summary Retorna las funciones hijas de una funcion padre + * @responses 200 array {"$ref":"Funcion"} + * @responses 500 Error en los operadores ingresados para el filtro + */ + public function get_hijas_list($id) + { + try { + $filtro = $this->get_filtro_get_list(); + + $manager = Factory::getManagerFuncion(); + $funciones = $manager->getFuncionesHijas($id); + + $resultados = []; + foreach ($funciones as $f) { + $resultados[] = $f->toArray(); + } + + $registros = rest_hidratador::hidratar($this->get_spec_usuario('Funcion'), $resultados); + + rest::response()->get($registros); + } catch (\Exception $e) { + Factory::getMainLogger()->error($e->getMessage()); + rest::response()->error_negocio('Error interno del servidor', 500); + } + } + + /** + * Se consume en GET /funciones/{id_funcion_predecesor}/sucesor + * + * @summary Retorna todas las funciones sucesoras de una funcion predecesora + * @responses 200 array {"$ref":"Funcion"} + * @responses 500 Error en los operadores ingresados para el filtro + */ + public function get_sucesor_list($id) + { + try { + $filtro = $this->get_filtro_get_list(); + + $manager = Factory::getManagerFuncion(); + $funciones = $manager->getFuncionesPredecesoras($id); + + $resultados = []; + foreach ($funciones as $f) { + $resultados[] = $f->toArray(); + } + + $registros = rest_hidratador::hidratar($this->get_spec_usuario('Funcion'), $resultados); + + rest::response()->get($registros); + } catch (\Exception $e) { + Factory::getMainLogger()->error($e->getMessage()); + rest::response()->error_negocio('Error interno del servidor', 500); + } + } + + /** + * Se consume en POST /funciones + * + * @summary Crea una nueva funcion + * @param_body $funciones FuncionEdit [required] los datos de la funcion + * @responses 201 {"string"} identificador de una funcion + * @responses 400 Funcion inválida + * @responses 500 Error interno + */ + public function post_list() + { + // Valido y traduzco los datos al formato de mi modelo + $datos = $this->procesar_input_edicion('FuncionEdit',false); + + try { + $manager = Factory::getManagerFuncion(); + + $funcion = new Funcion(); + $funcion->loadFromDatos($datos); + + $identificador = $manager->crear($funcion); + + $respuesta = [ + 'id_funcion' => $identificador[0]['id_funcion'] + ]; + + rest::response()->post($respuesta); + } catch (rest_error $e) { + rest::response()->error_negocio($e->get_datalle(), 400); + } catch (\Exception $e) { + if ($e->getCode() >= 400 || $e->getCode() < 500) { + rest::response()->error_negocio([$e->getMessage()], 400); + } else { + rest::response()->error_negocio([$e->getMessage()], 500); + } + } + } + + /** + * Se consume en PUT /funciones/{id} + * + * @summary Modifica una funcion + * @param_body $FuncinEdit FuncionEdit [required] los datos a editar de una funcion + * @responses 204 El id es correcto + * @responses 400 El id no válido + * @responses 404 No existe el recurso + * @responses 500 Error interno + */ + public function put($id) + { + $datos = $this->procesar_input_edicion('FuncionEdit'); + + try { + $manager = Factory::getManagerFuncion(); + $funcion = $manager->getFuncion($id); + $funcion->loadFromDatos($datos); + $manager->actualizar($funcion); + + rest::response()->put([ "respuesta" => true ]); + } catch (ErrorTupa $e) { + rest::response()->not_found(); + } catch (\Exception $e) { + if ($e->getCode() >= 400 || $e->getCode() < 500) { + rest::response()->error_negocio([$e->getMessage()], 400); + } else { + rest::response()->error_negocio([$e->getMessage()], 500); + } + } + } + + /** + * Se consume en PUT /funciones/{id}/baja. + * + * @summary Setea vigencia fin de una funcion + * @param_body $vigenciaFin VigenciaFin [required] la fecha de fin de vigencia de la funcion + * @responses 200 Se seteo la baja correctamente + * @responses 404 No existe el recurso + * @responses 500 Error interno + */ + public function put_baja_list($id) + { + $datos = $this->procesar_input_edicion('VigenciaFin'); + + try { + $manager = Factory::getManagerFuncion(); + $funcion = $manager->getFuncion($id); + + $fechaFin = $datos['vigencia_fin'] ?? date("Y-m-d"); + $funcion->setVigenciaFin($fechaFin); + + $manager->actualizar($funcion); + + rest::response()->put([ "respuesta" => true ]); + } catch (ErrorTupa $e) { + Factory::getMainLogger()->error($e->getMessage()); + rest::response()->not_found(); + } catch (\Exception $e) { + Factory::getMainLogger()->error($e->getMessage()); + if ($e->getCode() >= 400 || $e->getCode() < 500) { + rest::response()->error_negocio($e->getMessage(), 400); + } else { + rest::response()->error_negocio($e->getMessage(), 500); + } + } + } + + /** + * @return Filtro + * @throws ErrorTupa + */ + protected function get_filtro_get_list() + { + /* @var Filtro $filtro */ + $filtro = new Filtro(); + $filtro->agregarCampoRest('f.nombre', rest::request()->get('nombre', null)); + $filtro->agregarCampoRest('f.descripcion', rest::request()->get('descripcion', null)); + $filtro->agregarCampoRest('f.id_servicio', rest::request()->get('id_servicio', null)); + $filtro->agregarCampoRest('f.id_funcion_padre', rest::request()->get('id_funcion_padre', null)); + $filtro->agregarCampoRest('f.id_funcion_predecesor', rest::request()->get('id_funcion_predecesor', null)); + $filtro->agregarCampoRest('f.vigencia_inicio', rest::request()->get('vigencia_inicio', null)); + $filtro->agregarCampoRest('f.vigencia_fin', rest::request()->get('vigencia_fin', null)); + if(rest::request()->get('es_agrupador', null)){ + $filtro->agregarCampoRest('f.es_agrupador', 'es_igual_a;'.rest::request()->get('es_agrupador', null)); + } + + $filtro->agregarCampoOrdenable('nombre'); + $filtro->agregarCampoOrdenable('vigencia_inicio'); + + return $filtro; + } + + /** + * $relajar_ocultos boolean no checkea campos obligatorios cuando no se especifican. + * @param string $modelo + * @param bool $relajar_ocultos + * @param array $datos + * @return array|string + * @throws rest_error + */ + protected function procesar_input_edicion($modelo = 'FuncionEdit', $relajar_ocultos = false, $datos = null) + { + if (! $datos) { + $datos = rest::request()->get_body_json(); + } + + $spec_usuario = $this->get_spec_usuario($modelo); + + rest_validador::validar($datos, $spec_usuario, $relajar_ocultos); + + $resultado = rest_hidratador::deshidratar_fila($datos, $spec_usuario); + + return Factory::getVarios()->arrayToUtf8($resultado); + } +} + diff --git a/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/servicios/servicios.php b/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/servicios/servicios.php index e3b3e8cf..5a5b1b7f 100644 --- a/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/servicios/servicios.php +++ b/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/servicios/servicios.php @@ -1,5 +1,7 @@ <?php +namespace UNAM\Tupa\Backend\API\Endpoints\v1\servicios; + use SIUToba\rest\lib\rest_error; use SIUToba\rest\lib\rest_hidratador; use SIUToba\rest\lib\rest_validador; @@ -11,7 +13,7 @@ use UNAM\Tupa\Core\Filtros\Filtro; use UNAM\Tupa\Core\Negocio\SolicitudesServicios\Servicio; -class servicios implements SIUToba\rest\lib\modelable +class servicios implements \SIUToba\rest\lib\modelable { public static function _get_modelos() { @@ -105,7 +107,7 @@ class servicios implements SIUToba\rest\lib\modelable } catch (ErrorTupa $e) { Factory::getMainLogger()->error($e->getMessage()); rest::response()->not_found(); - } catch (Exception $e) { + } catch (\Exception $e) { Factory::getMainLogger()->error($e->getMessage()); rest::response()->error_negocio('Error interno del servidor', 500); } @@ -149,7 +151,7 @@ class servicios implements SIUToba\rest\lib\modelable $registros = rest_hidratador::hidratar($this->get_spec_usuario('Servicio'), $resultados); rest::response()->get($registros); - } catch (Exception $e) { + } catch (\Exception $e) { Factory::getMainLogger()->error($e->getMessage()); rest::response()->error_negocio('Error interno del servidor', 500); } @@ -162,7 +164,7 @@ class servicios implements SIUToba\rest\lib\modelable * @summary Crea un nuevo servicio * @param_body $servicios ServicioEdit [required] los datos del servicio * @responses 201 {"string"} identificador de un servicio - * @responses 400 Servicio inválido + * @responses 400 Servicio inv�lido * @responses 500 Error interno */ public function post_list() @@ -186,7 +188,7 @@ class servicios implements SIUToba\rest\lib\modelable rest::response()->post($respuesta); } catch (rest_error $e) { rest::response()->error_negocio($e->get_datalle(), 400); - } catch (Exception $e) { + } catch (\Exception $e) { if ($e->getCode() >= 400 || $e->getCode() < 500) { rest::response()->error_negocio([$e->getMessage()], 400); } else { @@ -201,7 +203,7 @@ class servicios implements SIUToba\rest\lib\modelable * @summary Modifica un servicio * @param_body $ServicioEdit ServicioEdit [required] los datos a editar de un servicio * @responses 204 El id es correcto - * @responses 400 El id no válido + * @responses 400 El id no v�lido * @responses 404 No existe el recurso * @responses 500 Error interno */ @@ -256,7 +258,7 @@ class servicios implements SIUToba\rest\lib\modelable } catch (ErrorTupa $e) { Factory::getMainLogger()->error($e->getMessage()); rest::response()->not_found(); - } catch (Exception $e) { + } catch (\Exception $e) { Factory::getMainLogger()->error($e->getMessage()); if ($e->getCode() >= 400 || $e->getCode() < 500) { rest::response()->error_negocio($e->getMessage(), 400); diff --git a/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php b/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php index 202ede3b..f84bf8a3 100644 --- a/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php +++ b/api-backend/src/UNAM/Tupa/Backend/API/Endpoints/v1/unidades_gestion/unidades_gestion.php @@ -1,4 +1,5 @@ <?php +namespace UNAM\Tupa\Backend\API\Endpoints\v1\unidades_gestion; use SIUToba\rest\lib\rest_error; use SIUToba\rest\lib\rest_hidratador; @@ -13,7 +14,7 @@ use UNAM\Tupa\Core\Negocio\Organizacion\UnidadGestion; use UNAM\Tupa\Core\Negocio\SolicitudesServicios\Servicio; -class unidades_gestion implements SIUToba\rest\lib\modelable +class unidadesGestion implements \SIUToba\rest\lib\modelable { public static function _get_modelos() { @@ -126,7 +127,7 @@ class unidades_gestion implements SIUToba\rest\lib\modelable } catch (UnidadGestionError $e) { Factory::getMainLogger()->error($e->getMessage()); rest::response()->not_found(); - } catch (Exception $e) { + } catch (\Exception $e) { Factory::getMainLogger()->error($e->getMessage()); rest::response()->error_negocio('Error interno del servidor', 500); } @@ -165,7 +166,7 @@ class unidades_gestion implements SIUToba\rest\lib\modelable $registros = rest_hidratador::hidratar($this->get_spec_usuario('UnidadGestion'), $resultados); rest::response()->get($registros); - } catch (Exception $e) { + } catch (\Exception $e) { Factory::getMainLogger()->error($e->getMessage()); rest::response()->error_negocio('Error interno del servidor', 500); } @@ -197,7 +198,7 @@ class unidades_gestion implements SIUToba\rest\lib\modelable }catch (ErrorTupa $e) { Factory::getMainLogger()->error($e->getMessage()); rest::response()->not_found($e->getMessage()); - }catch (Exception $e) { + }catch (\Exception $e) { Factory::getMainLogger()->error($e->getMessage()); rest::response()->error_negocio('Error interno del servidor', 500); } @@ -226,7 +227,7 @@ class unidades_gestion implements SIUToba\rest\lib\modelable } catch (UnidadGestionError $e) { rest::response()->error_negocio([$e->getMessage()], 400); - } catch (Exception $e) { + } catch (\Exception $e) { if ($e->getCode() >= 400 || $e->getCode() < 500) { rest::response()->error_negocio([$e->getMessage()], 400); } else { @@ -265,7 +266,7 @@ class unidades_gestion implements SIUToba\rest\lib\modelable rest::response()->post($respuesta); } catch (rest_error $e) { rest::response()->error_negocio($e->get_datalle(), 400); - } catch (Exception $e) { + } catch (\Exception $e) { if ($e->getCode() >= 400 || $e->getCode() < 500) { rest::response()->error_negocio([$e->getMessage()], 400); } else { diff --git a/api-backend/src/UNAM/Tupa/Backend/API/Factory.php b/api-backend/src/UNAM/Tupa/Backend/API/Factory.php index ae2c8cc2..104953c3 100644 --- a/api-backend/src/UNAM/Tupa/Backend/API/Factory.php +++ b/api-backend/src/UNAM/Tupa/Backend/API/Factory.php @@ -30,6 +30,7 @@ use UNAM\Tupa\Core\Manager\ManagerUnidadGestion; use UNAM\Tupa\Core\Manager\ManagerPermiso; use UNAM\Tupa\Core\Manager\ManagerSolicitud; use UNAM\Tupa\Core\Manager\ManagerServicio; +use UNAM\Tupa\Core\Manager\ManagerFuncion; class Factory { @@ -252,6 +253,10 @@ class Factory return new ManagerTerminosCondiciones($c['db-logger'], $c['db'], $c['codigo']); }; + $container['manager-funcion'] = function ($c) { + return new ManagerFuncion($c['db-logger'], $c['db'], $c['codigo']); + }; + $container['manager-autorizante'] = function ($c) { return new ManagerAutorizante($c['db-logger'], $c['db'], $c['codigo']); }; @@ -384,6 +389,16 @@ class Factory return self::getContainer()['manager-terminos-condiciones']; } + /** + * Singleton de ManagerSede + * + * @return ManagerFunciones + */ + public static function getManagerFuncion() + { + return self::getContainer()['manager-funcion']; + } + /** * Singleton de ManagerAutorizante * diff --git "a/api-backend/tests/Integration/v1/collections\342\200\216/autorizantes/tupa_api_backend_autorizantes_test.postman_collection.json" b/api-backend/tests/Integration/v1/collections/autorizantes/tupa_api_backend_autorizantes_test.postman_collection.json similarity index 100% rename from "api-backend/tests/Integration/v1/collections\342\200\216/autorizantes/tupa_api_backend_autorizantes_test.postman_collection.json" rename to api-backend/tests/Integration/v1/collections/autorizantes/tupa_api_backend_autorizantes_test.postman_collection.json diff --git a/api-backend/tests/Integration/v1/collections/funciones/tupa_api_backend_funciones_test.postman_collection.json b/api-backend/tests/Integration/v1/collections/funciones/tupa_api_backend_funciones_test.postman_collection.json new file mode 100644 index 00000000..4c93b01a --- /dev/null +++ b/api-backend/tests/Integration/v1/collections/funciones/tupa_api_backend_funciones_test.postman_collection.json @@ -0,0 +1,358 @@ +{ + "info": { + "_postman_id": "da74add2-5ee3-464b-9be1-9fd6822f98c6", + "name": "Tupa API Backend Funciones", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "16366966" + }, + "item": [ + { + "name": "V1", + "item": [ + { + "name": "Funciones", + "item": [ + { + "name": "Crea una nueva funcion", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 201\", () => {", + " pm.response.to.have.status(201);", + "});", + "", + "const schema = {", + " \"nombre\": \"\",", + " \"descripcion\": \"\",", + " \"es_agrupador\": \"\",", + " \"vigencia_inicio\": \"\",", + " \"vigencia_fin\": \"\",", + " \"id_funcion_padre\": \"\",", + " \"id_funcion_predecesor\": \"\",", + " \"id_servicio\": \"\"", + "}", + "", + "const body = JSON.parse(pm.request.body.raw);", + "const sameSchema = JSON.stringify(Object.keys(schema)) === JSON.stringify(Object.keys(body));", + "", + "pm.test('Estructura del body correcta', () => {", + " pm.expect(true).to.be.eql(sameSchema);", + "}); ", + "", + "var respuesta = pm.response.json();", + "", + "pm.test(\"funcion creada con ID \" + respuesta.id_funcion, function () {", + " pm.globals.set(\"idFuncion\", respuesta.id_funcion);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"nombre\": \"{{$randomWord}}a\",\n \"descripcion\": \"{{$randomWords}}a\",\n \"es_agrupador\": true,\n \"vigencia_inicio\": \"2020-01-01\",\n \"vigencia_fin\": \"2020-01-01\",\n \"id_funcion_padre\": null,\n \"id_funcion_predecesor\": null,\n \"id_servicio\": 1\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/v1/funciones", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "funciones" + ] + } + }, + "response": [] + }, + { + "name": "Retorna datos de una funcion", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200);", + "});", + "", + "", + "const response = pm.response.json();", + "const hasId = Object.keys(response).includes('id_funcion');", + "", + "pm.test(\"Funcion con id_funcion \" + response.id_funcion, function () {", + " pm.expect(true).to.be.eql(hasId);", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/v1/funciones/{{idFuncion}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "funciones", + "{{idFuncion}}" + ] + } + }, + "response": [] + }, + { + "name": "Retorna las funciones existentes", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200);", + "});", + "", + "const response = pm.response.json();", + "", + "pm.test(\"Se obtuvieron funciones \", function () {", + " // Si existe al menos 1 servicio", + " pm.expect(response.length).to.not.eql(0);", + "", + " if(response.length > 0){", + " const hasId = Object.keys(response[0]).includes('id_funcion');", + "", + " // Si la funcion tiene un id_funcion", + " pm.expect(true).to.be.eql(hasId);", + " }", + " ", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/v1/funciones?nombre=contiene;a&descripcion=contiene;a&id_servicio=es_igual_a;1&vigencia_inicio=es_mayor_igual_que;2010-01-01&es_agrupador=true", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "funciones" + ], + "query": [ + { + "key": "nombre", + "value": "contiene;a" + }, + { + "key": "descripcion", + "value": "contiene;a" + }, + { + "key": "id_funcion_padre", + "value": "es_igual_a;null", + "disabled": true + }, + { + "key": "id_funcion_predecesor", + "value": "es_distinto_de;999", + "disabled": true + }, + { + "key": "id_servicio", + "value": "es_igual_a;1" + }, + { + "key": "vigencia_inicio", + "value": "es_mayor_igual_que;2010-01-01" + }, + { + "key": "es_agrupador", + "value": "true" + } + ] + } + }, + "response": [] + }, + { + "name": "Modifica una funcion", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200);", + "});", + "", + "const schema = {", + " \"nombre\": \"\",", + " \"descripcion\": \"\",", + " \"es_agrupador\": \"\",", + " \"vigencia_inicio\": \"\",", + " \"vigencia_fin\": \"\",", + " \"id_funcion_padre\": \"\",", + " \"id_funcion_predecesor\": \"\",", + " \"id_servicio\": \"\"", + "}", + "", + "const body = JSON.parse(pm.request.body.raw);", + "const sameSchema = JSON.stringify(Object.keys(schema)) === JSON.stringify(Object.keys(body));", + "", + "pm.test('Estructura del body correcta', () => {", + " pm.expect(true).to.be.eql(sameSchema);", + "}); ", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"nombre\": \"{{$randomWord}}\",\n \"descripcion\": \"{{$randomWords}}\",\n \"es_agrupador\": true,\n \"vigencia_inicio\": \"2020-02-01\",\n \"vigencia_fin\": \"2025-01-01\",\n \"id_funcion_padre\": null,\n \"id_funcion_predecesor\": null,\n \"id_servicio\": 1\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/v1/funciones/{{idFuncion}}", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "funciones", + "{{idFuncion}}" + ] + } + }, + "response": [] + }, + { + "name": "Setea vigencia fin de una funcion", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status code is 200\", () => {", + " pm.response.to.have.status(200);", + "});", + "", + "const schema = {", + " \"vigencia_fin\": \"\"", + "}", + "", + "const body = JSON.parse(pm.request.body.raw);", + "const sameSchema = JSON.stringify(Object.keys(schema)) === JSON.stringify(Object.keys(body));", + "", + "pm.test('Estructura del body correcta', () => {", + " pm.expect(true).to.be.eql(sameSchema);", + "});" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"vigencia_fin\": \"2028-01-01\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{baseUrl}}/v1/funciones/{{idFuncion}}/baja", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "v1", + "funciones", + "{{idFuncion}}", + "baja" + ] + } + }, + "response": [] + } + ] + } + ] + } + ], + "auth": { + "type": "basic", + "basic": [ + { + "key": "password", + "value": "admin", + "type": "string" + }, + { + "key": "username", + "value": "admin", + "type": "string" + } + ] + }, + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "key": "baseUrl", + "value": "http://localhost:9002/api" + } + ] +} \ No newline at end of file diff --git "a/api-backend/tests/Integration/v1/collections\342\200\216/permisos/tupa_api_backend_permisos_test.postman_collection.json" b/api-backend/tests/Integration/v1/collections/permisos/tupa_api_backend_permisos_test.postman_collection.json similarity index 100% rename from "api-backend/tests/Integration/v1/collections\342\200\216/permisos/tupa_api_backend_permisos_test.postman_collection.json" rename to api-backend/tests/Integration/v1/collections/permisos/tupa_api_backend_permisos_test.postman_collection.json diff --git "a/api-backend/tests/Integration/v1/collections\342\200\216/solicitudes/tupa_api_backend_solicitudes_test.postman_collection.json" b/api-backend/tests/Integration/v1/collections/solicitudes/tupa_api_backend_solicitudes_test.postman_collection.json similarity index 100% rename from "api-backend/tests/Integration/v1/collections\342\200\216/solicitudes/tupa_api_backend_solicitudes_test.postman_collection.json" rename to api-backend/tests/Integration/v1/collections/solicitudes/tupa_api_backend_solicitudes_test.postman_collection.json diff --git a/api-backend/www/api.php b/api-backend/www/api.php index a2786a22..c94e828e 100644 --- a/api-backend/www/api.php +++ b/api-backend/www/api.php @@ -21,7 +21,7 @@ $settings = array( 'prefijo_controladores' => '', 'api_version' => $api_version, 'api_titulo' => 'Tupa (backend)', - 'url_protegida' => '/pases|registros|sedes|terminos-condiciones|visitantes|visitas|servicios|unidades-gestion/', + 'url_protegida' => '/pases|registros|sedes|terminos-condiciones|visitantes|visitas|servicios|unidades-gestion|funciones/', 'debug' => true, ); diff --git a/core/src/UNAM/Tupa/Core/Manager/ManagerFuncion.php b/core/src/UNAM/Tupa/Core/Manager/ManagerFuncion.php new file mode 100644 index 00000000..86d89fde --- /dev/null +++ b/core/src/UNAM/Tupa/Core/Manager/ManagerFuncion.php @@ -0,0 +1,314 @@ +<?php + +declare(strict_types=1); + +namespace UNAM\Tupa\Core\Manager; + +use UNAM\Tupa\Core\Errors\ErrorTupa; +use UNAM\Tupa\Core\Filtros\Filtro; +use UNAM\Tupa\Core\Negocio\SolicitudesServicios\Funcion; + +class ManagerFuncion extends Manager +{ + /** + * @param $id + * @return Funcion|null + * @throws ErrorTupa No se pudo recuperar el servicio + */ + public function getFuncion($id) + { + $params = [ + "id" => $id + ]; + + $sql = "SELECT id_funcion, + nombre, + descripcion, + es_agrupador, + id_funcion_padre, + id_funcion_predecesor, + vigencia_inicio, + vigencia_fin, + id_servicio " + . "FROM funciones s " + . "WHERE id_funcion = :id"; + + $result = $this->db->sentencia_consultar_fila($sql, $params); + + if (!$result) { + throw new ErrorTupa("No se pudo recuperar la funcion '$id'"); + } + + return $this->hidratarFuncion($result); + } + + /** + * @param Filtro|null $filtro + * @param bool $hidratar + * @return Funcion[] + */ + public function getFunciones(Filtro $filtro = null, $hidratar = true) + { + $where = $this->getSqlWhere($filtro); + $orderBy = $this->getSqlOrderBy($filtro); + $limit = $this->getSqlLimit($filtro); + + $sql = sprintf(" + SELECT f.id_funcion, + f.nombre, + f.descripcion, + f.es_agrupador, + f.id_funcion_padre, + f.id_funcion_predecesor, + f.vigencia_inicio, + f.vigencia_fin, + f.id_servicio + from funciones f + %s + %s + %s;", $where, $orderBy, $limit); + + $result = $this->db->consultar($sql); + + if ($hidratar) { + $result = $this->hidratarFunciones($result); + } + + return $result; + } + + /** + * @param Funcion $funcion + * @return bool|string + * @throws ErrorTupa No se pudo crear el servicio + */ + public function crear(Funcion $funcion) + { + $sql = "INSERT INTO funciones (nombre, descripcion, es_agrupador, vigencia_inicio, id_funcion_padre, id_funcion_predecesor, id_servicio) + VALUES (:nombre, :descripcion, :es_agrupador, :vigencia_inicio, :id_funcion_padre, :id_funcion_predecesor, :id_servicio) RETURNING id_funcion"; + + $sqlParams = [ + "nombre" => $funcion->getNombre(), + "descripcion" => $funcion->getDescripcion(), + "es_agrupador" => $funcion->getEsAgrupador() ? 1 : 0, + "vigencia_inicio" => $funcion->getVigenciaInicio(), + "id_funcion_padre" => is_object($funcion->getFuncionPadre()) ? $funcion->getFuncionPadre()->getId() : null, + "id_funcion_predecesor" => is_object($funcion->getFuncionPredecesor()) ? $funcion->getFuncionPredecesor()->getId() : null, + "id_servicio" => $funcion->getServicio()->getId() + ]; + + $result = $this->db->sentencia_consultar($sql, $sqlParams); + + if (!$result) { + throw new ErrorTupa("No se pudo crear el servicio"); + } + + return $result; + } + + /** + * @param Funcion $funcion + * @return mixed + */ + public function actualizar($funcion) + { + $params = [ + "id_funcion" => $funcion->getId(), + "nombre" => $funcion->getNombre(), + "descripcion" => $funcion->getDescripcion(), + "es_agrupador" => $funcion->getEsAgrupador() ? 1 : 0, + "vigencia_inicio" => $funcion->getVigenciaInicio(), + "vigencia_fin" => $funcion->getVigenciaFin(), + "id_funcion_padre" => is_object($funcion->getFuncionPadre()) ? $funcion->getFuncionPadre()->getId() : null, + "id_funcion_predecesor" => is_object($funcion->getFuncionPredecesor()) ? $funcion->getFuncionPredecesor()->getId() : null, + "id_servicio" => $funcion->getServicio()->getId() + ]; + + $sql = "UPDATE funciones + SET nombre = :nombre, + descripcion = :descripcion, + es_agrupador = :es_agrupador, + vigencia_inicio = :vigencia_inicio, + vigencia_fin = :vigencia_fin, + id_funcion_padre = :id_funcion_padre, + id_funcion_predecesor = :id_funcion_predecesor, + id_servicio = :id_servicio + WHERE id_funcion = :id_funcion"; + + return $this->db->sentencia_ejecutar($sql, $params); + } + + + /** + * Retorna todas las funciones que son hijas de una funcion + * @param $id + * @return Funcion|null + */ + public function getFuncionesHijas($idFuncionPadre, $hidratar = true) + { + $sql = sprintf( + "WITH RECURSIVE cte_padres_hijos( + id_funcion, + nombre, + descripcion, + es_agrupador, + id_funcion_predecesor, + id_funcion_padre, + vigencia_inicio, + vigencia_fin, + nivel) AS ( + SELECT + id_funcion, + nombre, + descripcion, + es_agrupador, + id_funcion_predecesor, + id_funcion_padre, + vigencia_inicio, + vigencia_fin, + 1 as nivel + FROM funciones + WHERE id_funcion_padre = %s -- obtener los nodos raíz + UNION ALL + SELECT + funciones.id_funcion, + funciones.nombre, + funciones.descripcion, + funciones.es_agrupador, + funciones.id_funcion_predecesor, + funciones.id_funcion_padre, + funciones.vigencia_inicio, + funciones.vigencia_fin, + cte_padres_hijos.nivel + 1 + FROM funciones + JOIN cte_padres_hijos ON funciones.id_funcion_padre = cte_padres_hijos.id_funcion + ) + SELECT + id_funcion, + nombre, + descripcion, + es_agrupador, + id_funcion_predecesor, + id_funcion_padre, + vigencia_inicio, + vigencia_fin, + nivel + FROM cte_padres_hijos + ORDER BY nivel, id_funcion;", + $idFuncionPadre + ); + + $result = $this->db->consultar($sql); + + if ($hidratar) { + $result = $this->hidratarFunciones($result); + } + + return $result; + } + + /** + * Retorna todas las funciones sucesoras de una funcion predecesora + * + * @param $id + * @return Funcion|null + */ + public function getFuncionesPredecesoras($idFuncionPredecesor, $hidratar = true) + { + $sql = sprintf( + "WITH RECURSIVE cte_predecesores( + id_funcion, + nombre, + descripcion, + es_agrupador, + id_funcion_predecesor, + id_funcion_padre, + vigencia_inicio, + vigencia_fin, + nivel) AS ( + SELECT + id_funcion, + nombre, + descripcion, + es_agrupador, + id_funcion_predecesor, + id_funcion_padre, + vigencia_inicio, + vigencia_fin, + 1 as nivel + FROM funciones + WHERE id_funcion_predecesor = %s -- obtener los nodos raíz + + UNION ALL + + SELECT + funciones.id_funcion, + funciones.nombre, + funciones.descripcion, + funciones.es_agrupador, + funciones.id_funcion_predecesor, + funciones.id_funcion_padre, + funciones.vigencia_inicio, + funciones.vigencia_fin, + cte_predecesores.nivel + 1 + FROM funciones + JOIN cte_predecesores ON funciones.id_funcion_predecesor = cte_predecesores.id_funcion + ) + + SELECT + id_funcion, + nombre, + descripcion, + es_agrupador, + id_funcion_predecesor, + id_funcion_padre, + vigencia_inicio, + vigencia_fin, + nivel + FROM cte_predecesores + ORDER BY nivel, id_funcion;", + $idFuncionPredecesor + ); + + $result = $this->db->consultar($sql); + + if ($hidratar) { + $result = $this->hidratarFunciones($result); + } + + return $result; + } + + + /** + * @param $datos + * @return Funcion + */ + protected function hidratarFuncion($datos) + { + $funcion = new Funcion(); + + $funcion->loadFromDatos($datos); + + return $funcion; + } + + /** + * @param $datos + * @return Funcion[] colección de Funciones + */ + protected function hidratarFunciones($datos) + { + $funciones = []; + + if (count($datos) < 1) { + return $funciones; + } + + foreach ($datos as $dato) { + $funciones[] = $this->hidratarFuncion($dato); + } + + return $funciones; + } +} diff --git a/core/src/UNAM/Tupa/Core/Negocio/Organizacion/UnidadGestion.php b/core/src/UNAM/Tupa/Core/Negocio/Organizacion/UnidadGestion.php index a269a02a..326a911d 100644 --- a/core/src/UNAM/Tupa/Core/Negocio/Organizacion/UnidadGestion.php +++ b/core/src/UNAM/Tupa/Core/Negocio/Organizacion/UnidadGestion.php @@ -47,7 +47,7 @@ class UnidadGestion { $this->idGrupoArai = $idGrupo; } - public function setServicios(?array $servicios){ + public function setServicios(array $servicios){ $this->servicios = $servicios; } diff --git a/core/src/UNAM/Tupa/Core/Negocio/SolicitudesServicios/Funcion.php b/core/src/UNAM/Tupa/Core/Negocio/SolicitudesServicios/Funcion.php new file mode 100644 index 00000000..9f4def59 --- /dev/null +++ b/core/src/UNAM/Tupa/Core/Negocio/SolicitudesServicios/Funcion.php @@ -0,0 +1,157 @@ +<?php declare(strict_types=1); + +namespace UNAM\Tupa\Core\Negocio\SolicitudesServicios; + +use UNAM\Tupa\Core\Negocio\SolicitudesServicios\Servicio; + +class Funcion { + private int $id; + private string $nombre; + private string $descripcion; + private bool $esAgrupador; + private Funcion $funcionPadre; + private Funcion $funcionPredecesor; + private string $vigenciaInicio; + private string $vigenciaFin; + private Servicio $servicio; + + //Getter + public function getId():int { + return $this->id; + } + + public function getNombre():string { + return $this->nombre; + } + + public function getDescripcion():string { + return $this->descripcion; + } + + public function getEsAgrupador():bool { + return $this->esAgrupador; + } + + public function getFuncionPadre():?Funcion { + return $this->funcionPadre ?? null; + } + + public function getFuncionPredecesor():?Funcion { + return $this->funcionPredecesor ?? null; + } + + public function getVigenciaInicio():string { + return $this->vigenciaInicio; + } + + public function getVigenciaFin():?string { + return $this->vigenciaFin ?? null; + } + + public function getServicio():?Servicio { + return $this->servicio ?? null; + } + + //Setter + public function setId($id):void { + $this->id = $id; + } + + public function setNombre(string $nombre):void { + $this->nombre = $nombre; + } + + public function setDescripcion(string $descripcion):void { + $this->descripcion = $descripcion; + } + + public function setEsAgrupador(bool $esAgrupador):void { + $this->esAgrupador = $esAgrupador; + } + + public function setFuncionPadre(Funcion $funcionPadre):void { + $this->funcionPadre = $funcionPadre; + } + + public function setFuncionPredecesor(Funcion $funcionPredecesor):void { + $this->funcionPredecesor = $funcionPredecesor; + } + + public function setVigenciaInicio(string $vigenciaInicio):void { + $this->vigenciaInicio = $vigenciaInicio; + } + + public function setVigenciaFin(string $vigenciaFin):void { + $this->vigenciaFin = $vigenciaFin; + } + + public function setServicio(Servicio $servicio):void { + $this->servicio = $servicio; + } + + /** + * Hidrata los atributos del objeto a partir de $datos + * + * @param array $datos inicializar directamente con un set de datos + */ + public function loadFromDatos(array $datos) + { + if (isset($datos['id_funcion'])) { + $this->setId($datos['id_funcion']); + } + + if (isset($datos['nombre'])) { + $this->setNombre($datos['nombre']); + } + + if (isset($datos['descripcion'])) { + $this->setDescripcion($datos['descripcion']); + } + + if (isset($datos['es_agrupador'])) { + $this->setEsAgrupador($datos['es_agrupador']); + } + + if (isset($datos['id_funcion_padre'])) { + $funcionPadre = new Funcion(); + $funcionPadre->setId($datos['id_funcion_padre']); + $this->setFuncionPadre($funcionPadre); + } + + if (isset($datos['id_funcion_predecesor'])) { + $funcionPredecesor = new Funcion(); + $funcionPredecesor->setId($datos['id_funcion_predecesor']); + $this->setFuncionPredecesor($funcionPredecesor); + } + + if (isset($datos['vigencia_inicio'])) { + $this->setVigenciaInicio($datos['vigencia_inicio']); + } + + if (isset($datos['vigencia_fin'])) { + $this->setVigenciaFin($datos['vigencia_fin']); + } + + if (isset($datos['id_servicio'])) { + $servicio = new Servicio(); + $servicio->setId($datos['id_servicio']); + $this->setServicio($servicio); + } + } + + public function toArray(): array + { + return [ + 'id_funcion' => $this->getId(), + 'nombre' => $this->getNombre(), + 'descripcion' => $this->getDescripcion(), + 'es_agrupador' => $this->getEsAgrupador(), + 'id_funcion_padre' => is_object($this->getFuncionPadre()) ? $this->getFuncionPadre()->getId() : null, + 'id_funcion_predecesor' => is_object($this->getFuncionPredecesor()) ? $this->getFuncionPredecesor()->getId() : null, + 'vigencia_inicio' => $this->getVigenciaInicio(), + 'vigencia_fin' => $this->getVigenciaFin(), + 'id_servicio' => is_object($this->getServicio()) ? $this->getServicio()->getId() : null + ]; + } +} + -- GitLab