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)"
/>
- Pas de résultat
+ Pas de résultat
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"),