Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jugurtha/api_certificat #462

Merged
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
add certificate table o nban platforme
  • Loading branch information
Jugurtha Bouhadoun committed Aug 12, 2024
commit d95e7d42fc3fe5b8ed028355d51d56a2db9a68b3
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -68,4 +68,6 @@ typings/
/toolbox.dev/data

# Migration data backup
db-migrations/migrations/data-backup
db-migrations/migrations/data-backup
# Ignorer tout le contenu du dossier db-migrations/data/
db-migrations/data
87 changes: 87 additions & 0 deletions db-migrations/migrations/20240808162138-init-certificate-table.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
'use strict';

require('dotenv').config();

const { POSTGRES_BAN_USER } = process.env;

/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface, Sequelize) {
try {
// Create ban schema if not exists
await queryInterface.sequelize.query('CREATE SCHEMA IF NOT EXISTS ban;');

// Grant permissions to ban user on schema ban
await queryInterface.sequelize.query(`GRANT USAGE ON SCHEMA ban TO "${POSTGRES_BAN_USER}";`);

// Create Certificate Table if not exists
await queryInterface.createTable('certificate', {
id: {
type: Sequelize.UUID,
defaultValue: Sequelize.UUIDV4,
allowNull: false,
primaryKey: true,
},
address_id: {
type: Sequelize.UUID,
allowNull: false,
references: {
model: {
tableName: 'address',
schema: 'ban',
},
key: 'id',
},
onUpdate: 'CASCADE',
onDelete: 'CASCADE',
},
number: {
type: Sequelize.INTEGER,
allowNull: true,
},
suffix: {
type: Sequelize.STRING,
allowNull: true,
},
rue: {
type: Sequelize.STRING,
allowNull: false,
},
nom_commune: {
type: Sequelize.STRING,
allowNull: false,
},
cog: {
type: Sequelize.STRING,
allowNull: false,
},
parcelles: {
type: Sequelize.ARRAY(Sequelize.STRING),
allowNull: true,
},
createdAt: {
type: Sequelize.DATE,
defaultValue: Sequelize.NOW,
}
}, {
schema: 'ban',
timestamps: false,
ifNotExists: true,
});

// Grant permissions to ban user on the certificate table
await queryInterface.sequelize.query(`GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE ban.certificate TO "${POSTGRES_BAN_USER}";`);
} catch (error) {
console.error(error);
}
},

async down(queryInterface) {
try {
// Drop the Certificate table
await queryInterface.sequelize.query('DROP TABLE IF EXISTS ban.certificate CASCADE;');
} catch (error) {
console.error(error);
}
}
};
103 changes: 103 additions & 0 deletions lib/api/certificat/models.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import {Certificate, sequelize} from '../../util/sequelize.js'

export const getCertificate = certificateID => Certificate.findByPk(certificateID, {raw: true})

export const getCertificates = certificateIDs => Certificate.findAll({
where: {id: certificateIDs},
raw: true
})

export const getCertificatesByAddress = address_id => Certificate.findAll({ // eslint-disable-line camelcase
jbouhadoun marked this conversation as resolved.
Show resolved Hide resolved
where: {address_id}, // eslint-disable-line camelcase
jbouhadoun marked this conversation as resolved.
Show resolved Hide resolved
aw: true
})

export const setCertificate = async certificates => {
try {
// Récupérer les détails de l'adresse pour chaque certificat
const certificatesWithDetails = await Promise.all(certificates.map(async certificate => {
const addressDetails = await getAddressDetailsById(certificate.address_id)
if (addressDetails.length === 0) {
// Lever une erreur si les détails de l'adresse ne sont pas trouvés
throw new Error(`Address details not found for address_id ${certificate.address_id}`)
}

return {
...certificate,
number: addressDetails[0].number,
suffix: addressDetails[0].suffix,
rue: addressDetails[0].rue,
nom_commune: addressDetails[0].nom_commune, // eslint-disable-line camelcase
cog: addressDetails[0].cog,
parcelles: addressDetails[0].parcelles,
}
}))

// Créer les certificats avec tous les détails remplis
return await Certificate.bulkCreate(certificatesWithDetails)
} catch (error) {
console.error(`Error creating certificates: ${error.message}`)
throw error
}
}

export const getAddressDetailsById = async addressId => {
try {
const results = await sequelize.query(`
SELECT
a.id as address_id,
a.number,
a.suffix,
ct.labels[1]->>'value' as rue,
d.labels[1]->>'value' as nom_commune,
d.meta->'insee'->>'cog' as cog,
a.meta->'cadastre'->'ids' as parcelles
FROM
"ban"."address" AS a
JOIN
"ban"."district" AS d ON a."districtID" = d.id
LEFT JOIN
"ban"."common_toponym" AS ct ON ct.id = a."mainCommonToponymID"
WHERE
a.id = :addressId
`, {
replacements: {addressId},
type: sequelize.QueryTypes.SELECT
})
if (results.length > 0) {
return results
}

return []
} catch (error) {
console.error(`Error executing query: ${error.message}`)
throw error
}
}

export const checkCertifiedActiveAndHasParcellesById = async addressId => {
try {
const results = await sequelize.query(`
SELECT
*
FROM
"ban"."address" AS a
WHERE
a.id = :addressId
and certified=true
and "isActive"=true
and jsonb_array_length(a.meta->'cadastre'->'ids') > 0
`, {
jbouhadoun marked this conversation as resolved.
Show resolved Hide resolved
replacements: {addressId},
type: sequelize.QueryTypes.SELECT
})
if (results.length > 0) {
return true
}

return false
} catch (error) {
console.error(`Error executing query: ${error.message}`)
throw error
}
}
84 changes: 84 additions & 0 deletions lib/api/certificat/routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import 'dotenv/config.js' // eslint-disable-line import/no-unassigned-import
import express from 'express'
import {
getCertificate,
setCertificate,
getAddressDetailsById,
checkCertifiedActiveAndHasParcellesById
} from './models.js'

const app = new express.Router()
app.use(express.json())

app.get('/:id', async (req, res) => {
const id = req.params.id // eslint-disable-line prefer-destructuring
try {
// eslint-disable-next-line unicorn/prefer-regexp-test, unicorn/better-regex
if (id.match(/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/)) {
const certificate = await getCertificate(id)
if (certificate) {
console.log(`Certificate retrieved: ${JSON.stringify(certificate)}`)
res.status(200).json(certificate)
} else {
console.log(`Certificate not found with ID: ${id}`)
res.status(404).json({message: 'Certificate not found'})
}
} else {
res.status(400).json({message: 'Invalid UUID format'})
}
} catch (error) {
console.error(`Error retrieving certificate: ${error.message}`)
res.status(500).json({message: 'Internal server error'})
}
})

app.post('/', async (req, res) => {
try {
const {address_id} = req.body // eslint-disable-line camelcase
jbouhadoun marked this conversation as resolved.
Show resolved Hide resolved

if (!address_id) { // eslint-disable-line camelcase
return res.status(400).json({message: 'address_id is required'})
}

const isValidAddress = await checkCertifiedActiveAndHasParcellesById(address_id)

if (!isValidAddress) {
return res.status(400).json({message: 'Address is not certified, not active, or has no parcels.'})
}

const newCertificate = await setCertificate([{
address_id // eslint-disable-line camelcase
jbouhadoun marked this conversation as resolved.
Show resolved Hide resolved
}])

console.log('New certificate details:', newCertificate)
jbouhadoun marked this conversation as resolved.
Show resolved Hide resolved

res.status(201).json(newCertificate[0])
} catch (error) {
console.error(`Error creating certificate: ${error.message}`)
res.status(500).json({message: 'Internal server error'})
}
})

app.get('/addresses/:id', async (req, res) => {
jbouhadoun marked this conversation as resolved.
Show resolved Hide resolved
const addressId = req.params.id // Récupérez l'ID directement comme une chaîne
jbouhadoun marked this conversation as resolved.
Show resolved Hide resolved
try {
if (addressId) {
const addressDetails = await getAddressDetailsById(addressId)
console.log(addressDetails)
jbouhadoun marked this conversation as resolved.
Show resolved Hide resolved
if (addressDetails.length > 0) {
console.log(`Address details retrieved: ${JSON.stringify(addressDetails)}`)
jbouhadoun marked this conversation as resolved.
Show resolved Hide resolved
res.status(200).json(addressDetails[0])
} else {
console.log(`Address not found with ID: ${addressId}`)
res.status(404).json({message: 'Address not found'})
}
} else {
res.status(400).json({message: 'Invalid ID format'})
}
} catch (error) {
console.error(`Error retrieving address details: ${error.message}`)
res.status(500).json({message: 'Internal server error'})
}
})

export default app
2 changes: 2 additions & 0 deletions lib/api/routes.js
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ import commonToponymRoutes from './common-toponym/routes.js'
import districtRoutes from './district/routes.js'
import statusRoutes from './job-status/routes.js'
import banIdRoutes from './ban-id/routes.js'
import certificatRoutes from './certificat/routes.js'

const app = new express.Router()

@@ -14,5 +15,6 @@ app.use('/common-toponym', commonToponymRoutes)
app.use('/district', districtRoutes)
app.use('/job-status', statusRoutes)
app.use('/ban-id', banIdRoutes)
app.use('/certificat', certificatRoutes)
jbouhadoun marked this conversation as resolved.
Show resolved Hide resolved

export default app
48 changes: 48 additions & 0 deletions lib/util/sequelize.js
Original file line number Diff line number Diff line change
@@ -211,6 +211,54 @@ export const JobStatus = sequelize.define('JobStatus', {
tableName: 'job_status'
})

export const Certificate = sequelize.define('Certificate', {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
},
address_id: { // eslint-disable-line camelcase
type: DataTypes.UUID,
allowNull: false,
references: {
model: 'address',
key: 'id',
},
},
number: {
type: DataTypes.INTEGER,
allowNull: true,
},
suffix: {
type: DataTypes.STRING,
allowNull: true,
},
rue: {
type: DataTypes.STRING,
allowNull: false,
},
nom_commune: { // eslint-disable-line camelcase
type: DataTypes.STRING,
allowNull: false,
},
cog: {
type: DataTypes.STRING,
allowNull: false,
},
parcelles: {
antoineludeau marked this conversation as resolved.
Show resolved Hide resolved
type: DataTypes.ARRAY(DataTypes.STRING),
allowNull: true,
},
createdAt: {
type: DataTypes.DATE,
defaultValue: Sequelize.NOW,
}
}, {
schema: 'ban',
tableName: 'certificate',
timestamps: false,
})

export const init = async () => {
try {
await sequelize.authenticate()