diff --git a/packages/backend/src/controllers/hebergement/post.js b/packages/backend/src/controllers/hebergement/post.js index 38c11be8f..37ae6c5bf 100644 --- a/packages/backend/src/controllers/hebergement/post.js +++ b/packages/backend/src/controllers/hebergement/post.js @@ -4,6 +4,7 @@ const HebergementSchema = require("../../schemas/hebergement"); const logger = require("../../utils/logger"); const ValidationAppError = require("../../utils/validation-error"); const AppError = require("../../utils/error"); +const FOUser = require("../../services/FoUser"); const log = logger(module.filename); @@ -44,11 +45,12 @@ module.exports = async function post(req, res, next) { } try { - const id = await Hebergement.create(userId, hebergement); + const organismeId = await FOUser.getUserOrganisme(userId); + const id = await Hebergement.create(userId, organismeId, hebergement); return res.status(200).json({ id, - message: "sauvegarde organisme OK", + message: "sauvegarde hebegement OK", }); } catch (error) { log.w("DONE with error"); diff --git a/packages/backend/src/controllers/hebergement/update.js b/packages/backend/src/controllers/hebergement/update.js index c400233a6..8d6458cf4 100644 --- a/packages/backend/src/controllers/hebergement/update.js +++ b/packages/backend/src/controllers/hebergement/update.js @@ -10,15 +10,12 @@ const log = logger(module.filename); module.exports = async function post(req, res, next) { const hebergementId = req.params.id; - const { nom, coordonnees, informationsLocaux, informationsTransport } = - req.body; - log.i("IN", { - coordonnees, - hebergementId, - informationsLocaux, - informationsTransport, - nom, - }); + const { body, decoded } = req; + const userId = decoded.id; + + console.log(userId); + + const { nom, coordonnees, informationsLocaux, informationsTransport } = body; if ( !nom || @@ -36,6 +33,7 @@ module.exports = async function post(req, res, next) { ); } let hebergement; + try { hebergement = await yup.object(HebergementSchema.schema()).validate( { @@ -54,7 +52,7 @@ module.exports = async function post(req, res, next) { } try { - await Hebergement.update(hebergementId, hebergement); + await Hebergement.update(userId, hebergementId, hebergement); log.i("DONE"); return res.sendStatus(200); } catch (error) { diff --git a/packages/backend/src/schemas/parts/adresse.js b/packages/backend/src/schemas/parts/adresse.js index 0d2c8a87f..ef540e954 100644 --- a/packages/backend/src/schemas/parts/adresse.js +++ b/packages/backend/src/schemas/parts/adresse.js @@ -3,6 +3,7 @@ const yup = require("yup"); const schema = ({ isFromAPIAdresse } = {}) => { return isFromAPIAdresse ? { + cleInsee: yup.string().required("ce champ est obligatoire"), codeInsee: yup.string().required("ce champ est obligatoire"), codePostal: yup.string().required("ce champ est obligatoire"), coordinates: yup.array().required("ce champ est obligatoire"), diff --git a/packages/backend/src/services/FoUser.js b/packages/backend/src/services/FoUser.js index 3198f23bb..2ad922954 100644 --- a/packages/backend/src/services/FoUser.js +++ b/packages/backend/src/services/FoUser.js @@ -47,6 +47,7 @@ ${additionalParamsQuery} `, additionalParams, ], + getUserOragnisme: `SELECT org_id as "organismeId" FROM front.user_organisme WHERE use_id = $1`, }; module.exports.read = async ({ @@ -150,3 +151,8 @@ module.exports.readOne = async (id) => { log.i("readOne - DONE"); return users[0]; }; + +module.exports.getUserOrganisme = async (userId) => { + const { rows } = await pool.query(query.getUserOragnisme, [userId]); + return rows[0]?.organismeId ?? null; +}; diff --git a/packages/backend/src/services/Hebergement.js b/packages/backend/src/services/Hebergement.js index ee9234dbc..27b3a62e9 100644 --- a/packages/backend/src/services/Hebergement.js +++ b/packages/backend/src/services/Hebergement.js @@ -1,6 +1,6 @@ /* eslint-disable no-param-reassign */ -const AppError = require("../utils/error"); const logger = require("../utils/logger"); +const { saveAdresse } = require("./adresse"); const pool = require("../utils/pgpool").getPool(); const log = logger(module.filename); @@ -9,24 +9,96 @@ const query = { create: ` INSERT INTO front.hebergement( organisme_id, + CREATED_BY, + EDITED_BY, + created_at, + edited_at, + HEBERGEMENT_ID, + CURRENT, nom, coordonnees, informations_locaux, informations_transport, - created_at, - edited_at + EMAIL, + ADRESSE_ID, + TELEPHONE_1, + TELEPHONE_2, + NOM_GESTIONNAIRE, + TYPE_ID, + TYPE_PENSION_ID, + NOMBRE_LITS, + LIT_DESSUS, + NOMBRE_LITS_SUPERPOSES, + NOMBRE_MAX_PERSONNES_COUCHAGE, + VISITE_LOCAUX, + ACCESSIBILITE_ID, + CHAMBRES_DOUBLES, + CHAMBRES_UNISEXES, + REGLEMENTATION_ERP, + COUCHAGE_INDIVIDUEL, + RANGEMENT_INDIVIDUEL, + AMENAGEMENTS_SPECIFIQUES, + DESCRIPTION_LIEU_HEBERGEMENT, + EXCURSION_DESCRIPTION, + DEPLACEMENT_PROXIMITE_DESCRIPTION, + VEHICULES_ADAPTES, + FILE_REPONSE_EXPLOITANT_OU_PROPRIETAIRE, + FILE_DERNIER_ARRETE_AUTORISATION_MAIRE, + FILE_DERNIERE_ATTESTATION_SECURITE ) VALUES ( - (SELECT org_id FROM front.user_organisme WHERE use_id = $1), - $2, - $3, - $4, - $5, - NOW(), - NOW() + $1, --organisme_id, + $2, --CREATED_BY, + $3, --EDITED_BY, + $4, --created_at, + NOW(), --edited_at, + $5, --HEBERGEMENT_ID, + TRUE, --CURRENT, + $6, --nom, + $7, --coordonnees, + $8, --informations_locaux, + $9, --informations_transport, + $10, --EMAIL, + $11, --ADRESSE_ID, + $12, --TELEPHONE_1, + $13, --TELEPHONE_2, + $14, --NOM_GESTIONNAIRE, + (SELECT ID FROM FRONT.HEBERGEMENT_TYPE WHERE VALUE = $15), --TYPE_ID, + (SELECT ID FROM FRONT.HEBERGEMENT_TYPE_PENSION WHERE VALUE = $16), --TYPE_PENSION_ID, + $17, --NOMBRE_LITS, + $18, --LIT_DESSUS, + $19, --NOMBRE_LITS_SUPERPOSES, + $20, --NOMBRE_MAX_PERSONNES_COUCHAGE, + $21, --VISITE_LOCAUX, + (SELECT ID FROM FRONT.HEBERGEMENT_ACCESSIBILITE WHERE VALUE = $22), --ACCESSIBILITE_ID, + $23, --CHAMBRES_DOUBLES, + $24, --CHAMBRES_UNISEXES, + $25, --REGLEMENTATION_ERP, + $26, --COUCHAGE_INDIVIDUEL, + $27, --RANGEMENT_INDIVIDUEL, + $28, --AMENAGEMENTS_SPECIFIQUES, + $29, --DESCRIPTION_LIEU_HEBERGEMENT, + $30, --EXCURSION_DESCRIPTION, + $31, --DEPLACEMENT_PROXIMITE_DESCRIPTION, + $32, --VEHICULES_ADAPTES, + $33, --FILE_REPONSE_EXPLOITANT_OU_PROPRIETAIRE, + $34, --FILE_DERNIER_ARRETE_AUTORISATION_MAIRE, + $35 --FILE_DERNIERE_ATTESTATION_SECURITE ) RETURNING id `, + associatePrestation: (nbRows) => ` +INSERT INTO + FRONT.HEBERGEMENT_TO_PRESTATION_RELATION (HEBERGEMENT_ID, PRESTATION_ID) +VALUES +${new Array(nbRows) + .fill(null) + .map( + (_, index) => + `($1, (SELECT ID FROM FRONT.HEBERGEMENT_PRESTATIONS_HOTELIERES WHERE VALUE = $${index + 2}))`, + ) + .join(",")} + `, getByDepartementCodes: ( departementCodes, { search, limit, offset, order, sort }, @@ -104,6 +176,17 @@ const query = { JOIN front.user_organisme uo ON uo.org_id = h.organisme_id WHERE uo.use_id = $1 `, + getUnchangedValuesForHistory: ` + SELECT + HEBERGEMENT_ID AS "hebergementUuid", + ORGANISME_ID as "organismeId", + CREATED_BY as "createdBy", + CREATED_AT as "createdAt" + FROM + FRONT.HEBERGEMENT + WHERE + ID = $1; + `, update: ` UPDATE front.hebergement SET @@ -114,42 +197,144 @@ const query = { edited_at = NOW() WHERE id = $1 `, + historize: ` + UPDATE front.hebergement + SET current = FALSE + WHERE id = $1 + `, }; -module.exports.create = async ( - userId, +const create = async ( + client, + { createdBy, createdAt, updatedBy, organismeId }, { nom, coordonnees, informationsLocaux, informationsTransport }, + hebergemenetUuid, ) => { log.i("create - IN"); - const { - rows: [{ id }], - } = await pool.query(query.create, [ - userId, + + await client.query("BEGIN"); + const adresseId = await saveAdresse(coordonnees.adresse); + const { rows } = await pool.query(query.create, [ + organismeId, // $1 + createdBy, + updatedBy, + createdAt, + hebergemenetUuid ?? crypto.randomUUID(), // 5 nom, coordonnees, informationsLocaux, informationsTransport, + coordonnees.email, // 10 + adresseId, + coordonnees.numTelephone1, + coordonnees.numTelephone2, + coordonnees.nomGestionnaire, + informationsLocaux.type, // 15 + informationsLocaux.pension, + informationsLocaux.nombreLits, + informationsLocaux.litsDessus, + informationsLocaux.nombreLitsSuperposes, + informationsLocaux.nombreMaxPersonnesCouchage, // 20 + informationsLocaux.visiteLocaux, + informationsLocaux.accessibilite, + informationsLocaux.chambresDoubles, + informationsLocaux.chambresUnisexes, + informationsLocaux.reglementationErp, // 25 + informationsLocaux.couchageIndividuel, + informationsLocaux.rangementIndividuel, + informationsLocaux.amenagementsSpecifiques, + informationsLocaux.descriptionLieuHebergement, + informationsTransport.excursion, // 30 + informationsTransport.deplacementProximite, + informationsTransport.vehiculesAdaptes, + informationsLocaux.fileReponseExploitantOuProprietaire?.uuid ?? null, + informationsLocaux.fileDernierArreteAutorisationMaire?.uuid ?? null, + informationsLocaux.fileDerniereAttestationSecurite?.uuid ?? null, ]); - log.d("create - DONE", { id }); - return id; -}; -module.exports.update = async ( - hebergementId, - { nom, coordonnees, informationsLocaux, informationsTransport }, -) => { - log.i("update - IN"); - const { rowCount } = await pool.query(query.update, [ + const hebergementId = rows[0].id; + const prestationsHotelieres = informationsLocaux.prestationsHotelieres; + await pool.query(query.associatePrestation(prestationsHotelieres.length), [ hebergementId, - nom, - coordonnees, - informationsLocaux, - informationsTransport, + ...prestationsHotelieres, ]); - if (rowCount === 0) { - throw new AppError("hebergement " + hebergementId + " not found"); + await client.query("COMMIT"); + + log.d("create - DONE", { hebergementId }); + return hebergementId; +}; + +module.exports.create = async (userId, organismeId, hebergement) => { + const client = await pool.connect(); + + try { + await client.query("BEGIN"); + create( + client, + { + createdAt: new Date(), + createdBy: userId, + updatedBy: userId, + organismeId, + }, + hebergement, + ); + await client.query("COMMIT"); + } catch (error) { + await client.query("ROLLBACK"); + throw error; + } finally { + client.release(); + } +}; + +module.exports.update = async (userId, hebergementId, hebergement) => { + log.i("update - IN"); + + await pool.query(query.historize, [hebergementId]); + const client = await pool.connect(); + + let newHebergementId; + try { + await client.query("BEGIN"); + + const { + rows: [{ hebergementUuid, organismeId, createdBy, createdAt }], + } = await client.query(query.getUnchangedValuesForHistory, [hebergementId]); + + console.log( + hebergementUuid, + organismeId, + createdBy, + createdAt, + hebergementId, + ); + + await pool.query(query.historize, [hebergementId]); + console.log("laaaaaaa"); + + newHebergementId = await create( + client, + { + createdBy, + createdAt, + updatedBy: userId, + organismeId, + }, + hebergement, + hebergementUuid, + ); + + await client.query("COMMIT"); + } catch (error) { + await client.query("ROLLBACK"); + throw error; + } finally { + client.release(); } log.i("update - DONE"); + + return newHebergementId; }; module.exports.getByDepartementCodes = async (departementsCodes, params) => { diff --git a/packages/backend/src/services/adresse.js b/packages/backend/src/services/adresse.js new file mode 100644 index 000000000..640472c12 --- /dev/null +++ b/packages/backend/src/services/adresse.js @@ -0,0 +1,75 @@ +const pool = require("../utils/pgpool").getPool(); + +const query = { + editCleInsee: ` + UPDATE FRONT.ADRESSE + SET + CLE_INSEE = $2 + WHERE + ID = $1 + RETURNING id + `, + getByCleInseeOrLabel: ` + SELECT + ID, CLE_INSEE as "cleInsee" + FROM + FRONT.ADRESSE + WHERE + CLE_INSEE = $1 + OR LABEL = $2 + `, + insert: ` + INSERT INTO + FRONT.ADRESSE ( + CLE_INSEE, + LABEL, + CODE_INSEE, + CODE_POSTAL, + LONG, + LAT, + DEPARTEMENT + ) + VALUES + ($1, $2, $3, $4, $5, $6, $7) + RETURNING id + `, +}; + +const getByCleInseeOrLabel = async ({ cleInsee, label }) => { + const { rows } = await pool.query(query.getByCleInseeOrLabel, [ + cleInsee, + label, + ]); + return rows?.[0] ?? null; +}; + +module.exports.saveAdresse = async (adresse) => { + const existingAdresse = await getByCleInseeOrLabel({ + cleInsee: adresse.cleInsee, + label: adresse.label, + }); + + if (existingAdresse && !existingAdresse.cleInsee && adresse.cleInsee) { + const { rows } = await pool.query(query.editCleInsee, [ + existingAdresse.id, + adresse.cleInsee, + ]); + return rows[0].id; + } + + if (!existingAdresse) { + const { rows } = await pool.query(query.insert, [ + adresse.cleInsee, + adresse.label, + adresse.codeInsee, + adresse.codePostal, + adresse.coordinates[0], + adresse.coordinates[1], + adresse.departement, + ]); + + return rows[0].id; + } + + return existingAdresse.id; +}; diff --git a/packages/frontend-usagers/src/components/search-address.vue b/packages/frontend-usagers/src/components/search-address.vue index c95462726..cd71c2394 100644 --- a/packages/frontend-usagers/src/components/search-address.vue +++ b/packages/frontend-usagers/src/components/search-address.vue @@ -49,6 +49,7 @@ const searchAddressDebounced = debounce(async function (queryString) { options.value = adresses.map((address) => { return { label: address.properties.label, + cleInsee: address.properties.id, codeInsee: address.properties.citycode, codePostal: address.properties.postcode, coordinates: address.geometry.coordinates, @@ -122,7 +123,7 @@ function select(_value, option) { :is-pointed="isPointed(option)" /> - +

diff --git a/packages/frontend-usagers/src/utils/adresse.js b/packages/frontend-usagers/src/utils/adresse.js deleted file mode 100644 index e3897dd8a..000000000 --- a/packages/frontend-usagers/src/utils/adresse.js +++ /dev/null @@ -1,19 +0,0 @@ -import * as yup from "yup"; - -const schema = ({ isFromAPIAdresse } = {}) => { - return isFromAPIAdresse - ? { - label: yup.string().required("ce champ est obligatoire"), - codeInsee: yup.string().required("ce champ est obligatoire"), - codePostal: yup.string().required("ce champ est obligatoire"), - coordinates: yup.array().required("ce champ est obligatoire"), - departement: yup.string().required("ce champ est obligatoire"), - } - : { - label: yup.string().required(), - }; -}; - -export default { - schema, -}; diff --git a/packages/frontend-usagers/src/utils/organisme.js b/packages/frontend-usagers/src/utils/organisme.js index 5d050231f..d0b10ab36 100644 --- a/packages/frontend-usagers/src/utils/organisme.js +++ b/packages/frontend-usagers/src/utils/organisme.js @@ -1,10 +1,10 @@ import * as yup from "yup"; import dayjs from "dayjs"; import regex from "./regex"; -import adresse from "./adresse"; import personne from "./personne"; import protocoleTransport from "./protocoleTransport"; import protocoleSanitaire from "./protocoleSanitaire"; +import { adresseSchema } from "@vao/shared/src/schema/adresse"; const types = [ { @@ -225,8 +225,8 @@ const personnePhysiqueSchema = { regex.numTelephoneRegex.test(tel), ), adresseIdentique: yup.boolean().required(), - adresseDomicile: yup.object({ ...adresse.schema(true) }).required(), - adresseSiege: yup.object({ ...adresse.schema(true) }).required(), + adresseDomicile: yup.object({ ...adresseSchema(true) }).required(), + adresseSiege: yup.object({ ...adresseSchema(true) }).required(), }; const agrementSchema = (regions) => ({ file: yup.mixed().required(), diff --git a/packages/frontend-usagers/src/utils/personne.js b/packages/frontend-usagers/src/utils/personne.js index 2694b90ef..99bfd1665 100644 --- a/packages/frontend-usagers/src/utils/personne.js +++ b/packages/frontend-usagers/src/utils/personne.js @@ -1,8 +1,8 @@ import * as yup from "yup"; import dayjs from "dayjs"; import regex from "./regex"; -import adresse from "./adresse"; import { informationsPersonnelListe } from "#imports"; +import { adresseSchema } from "@vao/shared/src/schema/adresse"; const schema = ({ showAdresse, @@ -60,7 +60,7 @@ const schema = ({ ...(showAdresse && { adresse: yup.object({ - ...adresse.schema(), + ...adresseSchema(), }), }), ...(showAttestation && { diff --git a/packages/frontend-usagers/src/utils/prestataireUtils.js b/packages/frontend-usagers/src/utils/prestataireUtils.js index dfee2273e..bcb183aed 100644 --- a/packages/frontend-usagers/src/utils/prestataireUtils.js +++ b/packages/frontend-usagers/src/utils/prestataireUtils.js @@ -1,7 +1,7 @@ import * as yup from "yup"; import dayjs from "dayjs"; import regex from "./regex"; -import adresse from "./adresse"; +import { adresseSchema } from "@vao/shared/src/schema/adresse"; const typePrestataireOptions = [ { @@ -53,7 +53,7 @@ const schema = { .required(), adresse: yup.object().when("typePrestataire", { is: (val) => val === "personne_morale", - then: () => yup.object(adresse.schema()), + then: () => yup.object(adresseSchema()), otherwise: (val) => val.nullable().strip(), }), competence: yup.string().when("typePrestataire", { diff --git a/packages/migrations/src/migrations/20241107125107_hebergement-refacto.js b/packages/migrations/src/migrations/20241107125107_hebergement-refacto.js new file mode 100644 index 000000000..c5461e8f3 --- /dev/null +++ b/packages/migrations/src/migrations/20241107125107_hebergement-refacto.js @@ -0,0 +1,326 @@ +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.up = function (knex) { + return knex.raw(` +CREATE TABLE FRONT.ADRESSE ( + ID SERIAL NOT NULL, + CLE_INSEE VARCHAR(50) UNIQUE, + LABEL TEXT NOT NULL, + CODE_INSEE VARCHAR(5) NOT NULL, + CODE_POSTAL VARCHAR(5) NOT NULL, + LONG DOUBLE PRECISION NOT NULL, + LAT DOUBLE PRECISION NOT NULL, + DEPARTEMENT VARCHAR(3) REFERENCES GEO.TERRITOIRES (CODE), + CONSTRAINT PK_ADRESSE PRIMARY KEY (ID), + CONSTRAINT UNIQUE_CLE_INSEE UNIQUE (CLE_INSEE) + +); + +INSERT INTO + FRONT.ADRESSE ( + LABEL, + CODE_INSEE, + CODE_POSTAL, + LONG, + LAT, + DEPARTEMENT + ) +SELECT DISTINCT + COORDONNEES -> 'adresse' ->> 'label' AS LABEL, + COORDONNEES -> 'adresse' ->> 'codeInsee' AS CODE_INSEE, + COORDONNEES -> 'adresse' ->> 'codePostal' AS CODE_POSTAL, + (COORDONNEES -> 'adresse' -> 'coordinates' -> 0)::DOUBLE PRECISION AS LONG, + (COORDONNEES -> 'adresse' -> 'coordinates' -> 1)::DOUBLE PRECISION AS LAT, + COORDONNEES -> 'adresse' ->> 'departement' AS DEPARTEMENT +FROM + FRONT.HEBERGEMENT ; + +CREATE TABLE FRONT.HEBERGEMENT_TYPE ( + ID SERIAL NOT NULL, + VALUE VARCHAR(100), + CONSTRAINT PK_HEBERGEMENT_TYPE PRIMARY KEY (ID) +); + +INSERT INTO + FRONT.HEBERGEMENT_TYPE (VALUE) +VALUES + ('hotel'), + ('meuble_tourisme'), + ('residence_tourisme'), + ('camping'), + ('autre') ; + +CREATE TABLE FRONT.HEBERGEMENT_TYPE_PENSION ( + ID SERIAL NOT NULL, + VALUE VARCHAR(100), + CONSTRAINT PK_HEBERGEMENT_TYPE_PENSION PRIMARY KEY (ID) +); + +INSERT INTO + FRONT.HEBERGEMENT_TYPE_PENSION (VALUE) +VALUES + ('hebergement_seul'), + ('petit_dejeuner'), + ('demi_pension'), + ('pension_complete') ; + +CREATE TABLE FRONT.HEBERGEMENT_ACCESSIBILITE ( + ID SERIAL NOT NULL, + VALUE VARCHAR(100), + CONSTRAINT PK_HEBERGEMENT_ACCESSIBILITE PRIMARY KEY (ID) +); + +INSERT INTO + FRONT.HEBERGEMENT_ACCESSIBILITE (VALUE) +VALUES + ('accessible'), + ('non_adapte'), + ('commentaires') ; + +CREATE TABLE FRONT.HEBERGEMENT_PRESTATIONS_HOTELIERES ( + ID SERIAL NOT NULL, + VALUE VARCHAR(100), + CONSTRAINT PK_HEBERGEMENT_PRESTATIONS_HOTELIERES PRIMARY KEY (ID) +); + +INSERT INTO + FRONT.HEBERGEMENT_PRESTATIONS_HOTELIERES (VALUE) +VALUES + ('blanchisseries'), + ('entretien_locaux') ; + +CREATE TABLE FRONT.HEBERGEMENT_TO_PRESTATION_RELATION ( + HEBERGEMENT_ID INTEGER REFERENCES FRONT.HEBERGEMENT (ID) ON DELETE CASCADE, + PRESTATION_ID INTEGER REFERENCES FRONT.HEBERGEMENT_PRESTATIONS_HOTELIERES (ID) ON DELETE CASCADE, + CONSTRAINT pk_hebergement_prestation PRIMARY KEY (HEBERGEMENT_ID, PRESTATION_ID) +); + +ALTER TABLE FRONT.HEBERGEMENT +ADD COLUMN HEBERGEMENT_ID UUID NOT NULL DEFAULT GEN_RANDOM_UUID (), +ADD COLUMN CURRENT BOOLEAN NOT NULL DEFAULT TRUE, +ADD COLUMN CREATED_BY INTEGER REFERENCES FRONT.USERS (ID), +ADD COLUMN EDITED_BY INTEGER REFERENCES FRONT.USERS (ID), +ADD COLUMN EMAIL VARCHAR(320), +ADD COLUMN ADRESSE_ID INTEGER REFERENCES FRONT.ADRESSE (ID), +ADD COLUMN TELEPHONE_1 VARCHAR(20), +ADD COLUMN TELEPHONE_2 VARCHAR(20), +ADD COLUMN NOM_GESTIONNAIRE VARCHAR(320), +ADD COLUMN TYPE_ID INTEGER REFERENCES FRONT.HEBERGEMENT_TYPE (ID), +ADD COLUMN TYPE_PENSION_ID INTEGER REFERENCES FRONT.HEBERGEMENT_TYPE_PENSION (ID), +ADD COLUMN NOMBRE_LITS INTEGER, +ADD COLUMN LIT_DESSUS BOOLEAN, +ADD COLUMN NOMBRE_LITS_SUPERPOSES INTEGER, +ADD COLUMN NOMBRE_MAX_PERSONNES_COUCHAGE INTEGER, +ADD COLUMN VISITE_LOCAUX BOOLEAN, +ADD COLUMN ACCESSIBILITE_ID INTEGER REFERENCES FRONT.HEBERGEMENT_ACCESSIBILITE (ID), +ADD COLUMN CHAMBRES_DOUBLES BOOLEAN, +ADD COLUMN CHAMBRES_UNISEXES BOOLEAN, +ADD COLUMN REGLEMENTATION_ERP BOOLEAN, +ADD COLUMN COUCHAGE_INDIVIDUEL BOOLEAN, +ADD COLUMN RANGEMENT_INDIVIDUEL BOOLEAN, +ADD COLUMN AMENAGEMENTS_SPECIFIQUES BOOLEAN, +ADD COLUMN DESCRIPTION_LIEU_HEBERGEMENT TEXT, +ADD COLUMN EXCURSION_DESCRIPTION TEXT, +ADD COLUMN DEPLACEMENT_PROXIMITE_DESCRIPTION TEXT, +ADD COLUMN VEHICULES_ADAPTES TEXT, +ADD COLUMN FILE_REPONSE_EXPLOITANT_OU_PROPRIETAIRE UUID, +ADD COLUMN FILE_DERNIER_ARRETE_AUTORISATION_MAIRE UUID, +ADD COLUMN FILE_DERNIERE_ATTESTATION_SECURITE UUID; + +UPDATE FRONT.HEBERGEMENT +SET + EMAIL = COORDONNEES ->> 'email', + ADRESSE_ID = ( + SELECT + ID + FROM + FRONT.ADRESSE A + WHERE + A.LABEL = COORDONNEES -> 'adresse' ->> 'label' + AND A.CODE_INSEE = COORDONNEES -> 'adresse' ->> 'codeInsee' + AND A.CODE_POSTAL = COORDONNEES -> 'adresse' ->> 'codePostal' + AND A.LONG = (COORDONNEES -> 'adresse' -> 'coordinates' -> 0)::DOUBLE PRECISION + AND A.LAT = (COORDONNEES -> 'adresse' -> 'coordinates' -> 1)::DOUBLE PRECISION + AND A.DEPARTEMENT = COORDONNEES -> 'adresse' ->> 'departement' + ), + TELEPHONE_1 = COORDONNEES ->> 'numTelephone1', + TELEPHONE_2 = COORDONNEES ->> 'numTelephone2', + NOM_GESTIONNAIRE = COORDONNEES ->> 'nomGestionnaire', + TYPE_ID = ( + SELECT + ID + FROM + FRONT.HEBERGEMENT_TYPE + WHERE + VALUE = INFORMATIONS_LOCAUX ->> 'type' + ), + TYPE_PENSION_ID = ( + SELECT + ID + FROM + FRONT.HEBERGEMENT_TYPE_PENSION + WHERE + VALUE = INFORMATIONS_LOCAUX ->> 'pension' + ), + LIT_DESSUS = (INFORMATIONS_LOCAUX ->> 'litsDessus')::BOOLEAN, + NOMBRE_LITS = (INFORMATIONS_LOCAUX ->> 'nombreLits')::INTEGER, + NOMBRE_LITS_SUPERPOSES = (INFORMATIONS_LOCAUX ->> 'nombreLitsSuperposes')::INTEGER, + NOMBRE_MAX_PERSONNES_COUCHAGE = ( + INFORMATIONS_LOCAUX ->> 'nombreMaxPersonnesCouchage' + )::INTEGER, + VISITE_LOCAUX = (INFORMATIONS_LOCAUX ->> 'visiteLocaux')::BOOLEAN, + ACCESSIBILITE_ID = ( + SELECT + ID + FROM + FRONT.HEBERGEMENT_ACCESSIBILITE + WHERE + VALUE = INFORMATIONS_LOCAUX ->> 'accessibilite' + ), + CHAMBRES_DOUBLES = (INFORMATIONS_LOCAUX ->> 'chambresDoubles')::BOOLEAN, + CHAMBRES_UNISEXES = (INFORMATIONS_LOCAUX ->> 'chambresUnisexes')::BOOLEAN, + REGLEMENTATION_ERP = (INFORMATIONS_LOCAUX ->> 'reglementationErp')::BOOLEAN, + COUCHAGE_INDIVIDUEL = (INFORMATIONS_LOCAUX ->> 'couchageIndividuel')::BOOLEAN, + RANGEMENT_INDIVIDUEL = (INFORMATIONS_LOCAUX ->> 'rangementIndividuel')::BOOLEAN, + AMENAGEMENTS_SPECIFIQUES = (INFORMATIONS_LOCAUX ->> 'amenagementsSpecifiques')::BOOLEAN, + DESCRIPTION_LIEU_HEBERGEMENT = INFORMATIONS_LOCAUX ->> 'descriptionLieuHebergement', + EXCURSION_DESCRIPTION = INFORMATIONS_TRANSPORT ->> 'excursion', + DEPLACEMENT_PROXIMITE_DESCRIPTION = INFORMATIONS_TRANSPORT ->> 'deplacementProximite', + VEHICULES_ADAPTES = (INFORMATIONS_TRANSPORT ->> 'vehiculesAdaptes')::BOOLEAN, + FILE_REPONSE_EXPLOITANT_OU_PROPRIETAIRE = ( + INFORMATIONS_LOCAUX -> 'fileReponseExploitantOuProprietaire' ->> 'uuid' + )::UUID, + FILE_DERNIER_ARRETE_AUTORISATION_MAIRE = ( + INFORMATIONS_LOCAUX -> 'fileDernierArreteAutorisationMaire' ->> 'uuid' + )::UUID, + FILE_DERNIERE_ATTESTATION_SECURITE = ( + INFORMATIONS_LOCAUX -> 'fileDerniereAttestationSecurite' ->> 'uuid' + )::UUID; + +INSERT INTO + FRONT.HEBERGEMENT_TO_PRESTATION_RELATION (HEBERGEMENT_ID, PRESTATION_ID) +SELECT + HEBERGEMENT_ID, + ( + SELECT + ID + FROM + FRONT.HEBERGEMENT_PRESTATIONS_HOTELIERES + WHERE + VALUE = SUB_HEBERGEMENT.HEBERGEMENT_PRESTATIONS_HOTELIERES_VALUE + ) +FROM + ( + SELECT + ID AS HEBERGEMENT_ID, + JSONB_ARRAY_ELEMENTS( + INFORMATIONS_LOCAUX -> 'prestationsHotelieres'::TEXT + ) ->> 0 AS HEBERGEMENT_PRESTATIONS_HOTELIERES_VALUE + FROM + FRONT.HEBERGEMENT + ) SUB_HEBERGEMENT; + +CREATE TABLE FRONT.DEMANDE_SEJOUR_TO_HEBERGEMENT ( + HEBERGEMENT_ID INTEGER REFERENCES FRONT.HEBERGEMENT (ID), + DEMANDE_SEJOUR_ID INTEGER REFERENCES FRONT.DEMANDE_SEJOUR (ID), + DATE_DEBUT TIMESTAMP WITH TIME ZONE NOT NULL, + DATE_FIN TIMESTAMP WITH TIME ZONE NOT NULL, + CONSTRAINT UNIQUE_IDS_DATES UNIQUE ( + HEBERGEMENT_ID, + DEMANDE_SEJOUR_ID, + DATE_DEBUT, + DATE_FIN + ) +) ; + +INSERT INTO + FRONT.DEMANDE_SEJOUR_TO_HEBERGEMENT ( + HEBERGEMENT_ID, + DEMANDE_SEJOUR_ID, + DATE_DEBUT, + DATE_FIN + ) +SELECT + ( + JSONB_ARRAY_ELEMENTS(HEBERGEMENT -> 'hebergements') -> 'hebergementId' ->> 0 + )::INTEGER AS HEBERGEMENT_ID, + ID AS DEMANDE_SEJOUR_ID, + ( + JSONB_ARRAY_ELEMENTS(HEBERGEMENT -> 'hebergements') -> 'dateDebut' ->> 0 + )::TIMESTAMP WITH TIME ZONE AS DATE_DEBUT, + ( + JSONB_ARRAY_ELEMENTS(HEBERGEMENT -> 'hebergements') -> 'dateFin' ->> 0 + )::TIMESTAMP WITH TIME ZONE AS DATE_FIN +FROM + FRONT.DEMANDE_SEJOUR + +ALTER TABLE FRONT.HEBERGEMENT +ADD CONSTRAINT UNIQUE_HEBERGEMENT_CURRENT UNIQUE (HEBERGEMENT_ID, CURRENT); + +GRANT ALL ON TABLE FRONT.ADRESSE TO vao_u ; +GRANT ALL ON TABLE FRONT.HEBERGEMENT_TYPE TO vao_u ; +GRANT ALL ON TABLE FRONT.HEBERGEMENT_TYPE_PENSION TO vao_u ; +GRANT ALL ON TABLE FRONT.HEBERGEMENT_ACCESSIBILITE TO vao_u ; +GRANT ALL ON TABLE FRONT.HEBERGEMENT_PRESTATIONS_HOTELIERES TO vao_u ; +GRANT ALL ON TABLE FRONT.HEBERGEMENT_TO_PRESTATION_RELATION TO vao_u ; +GRANT ALL ON TABLE FRONT.DEMANDE_SEJOUR_TO_HEBERGEMENT TO vao_u ; + +GRANT ALL ON SEQUENCE FRONT.ADRESSE_ID_SEQ TO VAO_U ; +GRANT ALL ON SEQUENCE FRONT.HEBERGEMENT_TYPE_ID_SEQ TO VAO_U ; +GRANT ALL ON SEQUENCE FRONT.HEBERGEMENT_TYPE_PENSION_ID_SEQ TO VAO_U ; +GRANT ALL ON SEQUENCE FRONT.HEBERGEMENT_ACCESSIBILITE_ID_SEQ TO VAO_U ; +GRANT ALL ON SEQUENCE FRONT.HEBERGEMENT_PRESTATIONS_HOTELIERES_ID_SEQ TO VAO_U ; + + `); +}; + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.down = function (knex) { + return knex.raw(` +ALTER TABLE FRONT.HEBERGEMENT +DROP COLUMN HEBERGEMENT_ID, +DROP COLUMN CURRENT, +DROP COLUMN CREATED_BY, +DROP COLUMN EDITED_BY, +DROP COLUMN EMAIL, +DROP COLUMN ADRESSE_ID, +DROP COLUMN TELEPHONE_1, +DROP COLUMN TELEPHONE_2, +DROP COLUMN NOM_GESTIONNAIRE, +DROP COLUMN TYPE_ID, +DROP COLUMN TYPE_PENSION_ID, +DROP COLUMN NOMBRE_LITS, +DROP COLUMN LIT_DESSUS, +DROP COLUMN NOMBRE_LITS_SUPERPOSES, +DROP COLUMN NOMBRE_MAX_PERSONNES_COUCHAGE, +DROP COLUMN VISITE_LOCAUX, +DROP COLUMN ACCESSIBILITE_ID, +DROP COLUMN CHAMBRES_DOUBLES, +DROP COLUMN CHAMBRES_UNISEXES, +DROP COLUMN REGLEMENTATION_ERP, +DROP COLUMN COUCHAGE_INDIVIDUEL, +DROP COLUMN RANGEMENT_INDIVIDUEL, +DROP COLUMN AMENAGEMENTS_SPECIFIQUES, +DROP COLUMN DESCRIPTION_LIEU_HEBERGEMENT, +DROP COLUMN EXCURSION_DESCRIPTION, +DROP COLUMN DEPLACEMENT_PROXIMITE_DESCRIPTION, +DROP COLUMN VEHICULES_ADAPTES, +DROP COLUMN FILE_REPONSE_EXPLOITANT_OU_PROPRIETAIRE, +DROP COLUMN FILE_DERNIER_ARRETE_AUTORISATION_MAIRE, +DROP COLUMN FILE_DERNIERE_ATTESTATION_SECURITE; + +DROP TABLE FRONT.HEBERGEMENT_TO_PRESTATION_RELATION ; +DROP TABLE FRONT.HEBERGEMENT_PRESTATIONS_HOTELIERES ; +DROP TABLE FRONT.HEBERGEMENT_ACCESSIBILITE ; +DROP TABLE FRONT.HEBERGEMENT_TYPE_PENSION ; +DROP TABLE FRONT.HEBERGEMENT_TYPE ; +DROP TABLE FRONT.ADRESSE ; + +DROP TABLE FRONT.DEMANDE_SEJOUR_TO_HEBERGEMENT ; + `); +}; diff --git a/packages/shared/src/schema/adresse.js b/packages/shared/src/schema/adresse.js index 023eae706..adf24902b 100644 --- a/packages/shared/src/schema/adresse.js +++ b/packages/shared/src/schema/adresse.js @@ -4,6 +4,7 @@ export const adresseSchema = ({ isFromAPIAdresse } = {}) => { return isFromAPIAdresse ? { codeInsee: yup.string().required("ce champ est obligatoire"), + cleInsee: yup.string().required("ce champ est obligatoire"), codePostal: yup.string().required("ce champ est obligatoire"), coordinates: yup.array().required("ce champ est obligatoire"), departement: yup.string().required("ce champ est obligatoire"),