Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • web-et-numerique/factory/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server
1 result
Show changes
Commits on Source (9)
......@@ -2,6 +2,20 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
## [1.16.0](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/compare/v1.15.1...v1.16.0) (2022-03-18)
### Features
* **docker:** add name to docker container ([8a7e463](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/8a7e46357945d6a18cce3eef8105b1b6a471fbc9))
* **findAllFormated Structure:** Now return structures who gave consent ([bd87d2b](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/bd87d2bced66cc8fc0c3272f60892b503d1bb6d9))
### Bug Fixes
* **structures:** Photon-ban and photon-bal results are now returned together ([c02c650](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/c02c650ef0c17409153a1416688537c0a3d84d79))
* **tests:** avoid error for structure search test ([37f05ab](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/commit/37f05ab6fa5734dc03c36f4cfc401cf653388ac7))
### [1.15.1](https://forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server/compare/v1.15.0...v1.15.1) (2022-03-08)
......
......@@ -2,7 +2,8 @@ version: '2'
services:
service-ram:
image: registry.forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server:dev
image: registry.forge.grandlyon.com/web-et-numerique/pamn_plateforme-des-acteurs-de-la-mediation-numerique/pamn_server:dev
container_name: resin-back
ports:
- ${SERVICE_API_BIND_PORT}:3000
extra_hosts:
......@@ -35,6 +36,7 @@ services:
database-ram:
image: bitnami/mongodb:4.2.3
user: root
container_name: resin-db
environment:
MONGODB_ROOT_PASSWORD: ${MONGO_ROOT_PASSWORD}
MONGODB_USERNAME: ${MONGO_NON_ROOT_USERNAME}
......@@ -50,7 +52,8 @@ services:
mongo-express:
image: mongo-express
restart: unless-stopped
restart: unless-stopped
container_name: resin-mongo-express
depends_on:
- database-ram
networks:
......@@ -67,6 +70,7 @@ services:
ghost:
image: ghost:latest
restart: always
container_name: resin-ghost
ports:
- ${GHOST_PORT}:2368
environment:
......@@ -78,11 +82,14 @@ services:
database__connection__database: ghost
# this url value is just an example, and is likely wrong for your environment!
url: http://localhost:${GHOST_PORT}
depends_on:
- ghost-db
volumes:
- ghost-content:/var/lib/ghost/content
ghost-db:
image: mysql:5.7
container_name: resin-ghost-db
restart: always
environment:
MYSQL_ROOT_PASSWORD: ${GHOST_DB_PASSWORD}
......@@ -92,6 +99,7 @@ services:
es01:
image: elasticsearch:7.16.2
restart: unless-stopped
container_name: resin-es
environment:
node.name: es01
cluster.name: es-docker-cluster
......@@ -108,7 +116,7 @@ services:
kib01:
image: docker.elastic.co/kibana/kibana:7.6.1
restart: unless-stopped
container_name: kib01
container_name: resin-kib
ports:
- ${KIBANA_PORT}:5601
environment:
......
{
"name": "ram_server",
"version": "1.15.1",
"version": "1.16.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
......
{
"name": "ram_server",
"private": true,
"version": "1.15.1",
"version": "1.16.0",
"description": "Nest TypeScript starter repository",
"license": "MIT",
"scripts": {
......
......@@ -49,7 +49,7 @@ describe('StructuresSearchService', () => {
// wait for the new structures to be indexed before search
await service.refreshIndexStructure();
// but we still need to wait the refresh to be done
await new Promise((r) => setTimeout(r, 1000));
await new Promise((r) => setTimeout(r, 2000));
});
it('should find maisons de la métropole', async () => {
......
......@@ -222,6 +222,7 @@ export class StructuresService {
): Promise<StructureDocument[]> {
const structures = await this.structureModel.find({ deletedAt: { $exists: false } }).exec();
// Update structures coord and address before sending them
Logger.debug('Find all formated structures, only returning structures who consented to data sharing');
await Promise.all(
structures.map((structure: StructureDocument) => {
// If structure has no address, add it
......@@ -239,8 +240,8 @@ export class StructuresService {
);
return (
await this.structureModel
.find({ deletedAt: { $exists: false }, accountVerified: true })
.select('-_id -accountVerified -otherDescription')
.find({ deletedAt: { $exists: false }, accountVerified: true, $where: 'this.dataShareConsentDate != null' })
.select('-_id -accountVerified -otherDescription -dataShareConsentDate')
.exec()
).map((structure) => {
// If structure has temp email, hide it
......@@ -345,23 +346,57 @@ export class StructuresService {
*/
private getStructurePosition(structure: Structure): Promise<Structure> {
return new Promise((resolve, reject) => {
this.getCoord(structure.address.numero, structure.address.street, structure.address.commune).subscribe(
this.getCoord(structure.address.numero, structure.address.street, structure.address.commune, 'photon').subscribe(
(res) => {
const address = res.data.features[0];
if (address && address.geometry) {
structure.coord = address.geometry.coordinates;
} else {
Logger.error(
`No coord found for: ${structure.address.numero} ${structure.address.street} ${structure.address.commune}`,
'StructureService'
);
structure.coord = [];
}
resolve(structure);
this.getCoord(
structure.address.numero,
structure.address.street,
structure.address.commune,
'photon-bal'
).subscribe((resbal) => {
// check if photon-bal is more precise than photon ban
if (resbal.data.features.length > 0) {
resbal.data.features = resbal.data.features.sort((a, b) => {
return b.properties.housenumber ? 1 : -1;
});
const address = resbal.data.features[0];
if (address && address.geometry) {
structure.coord = address.geometry.coordinates;
} else {
Logger.error(
`No coord found for: ${structure.address.numero} ${structure.address.street} ${structure.address.commune}`,
'StructureService'
);
structure.coord = [];
}
resolve(structure);
// else pick structure from photonban if it exists or throw error
} else {
if (res.data.features.length > 0) {
const address = res.data.features[0];
if (address && address.geometry) {
structure.coord = address.geometry.coordinates;
} else {
Logger.error(
`No coord found for: ${structure.address.numero} ${structure.address.street} ${structure.address.commune}`,
'StructureService'
);
structure.coord = [];
}
resolve(structure);
} else {
Logger.error(
`No structure found for: ${structure.address.numero} ${structure.address.street} ${structure.address.commune}`,
'StructureService'
);
}
}
});
},
(err) => {
Logger.error(`Request error: ${err.config.url}`, 'StructureService');
Logger.error(err);
reject(err);
}
);
});
......@@ -382,32 +417,56 @@ export class StructuresService {
*/
public async searchAddress(data: {
searchQuery: string;
}): Promise<AxiosResponse<{ features: { geometry: {}; type: string; properties: {} }[] }>> {
const req = `https://download.data.grandlyon.com/geocoding/photon/api?q=${data.searchQuery}&lang=fr&limit=500&osm_tag=:!construction&osm_tag=:!bus_stop`;
Logger.debug(`Search request: ${encodeURI(req)}`, 'StructureService');
return new Promise((resolve, reject) => {
this.httpService
.request({
url: encodeURI(req),
method: 'GET',
headers: { 'Content-Type': 'application/json' },
})
.subscribe(
(reply) => {
Logger.debug(`Search request response length : ${reply.data.features.length}`, 'StructureService');
reply.data.features = reply.data.features
.filter((doc) => doc.properties.postcode && doc.properties.postcode.match(depRegex))
.sort((a, b) => {
return b.properties.housenumber ? 1 : -1;
});
return resolve(reply.data);
},
(err) => {
Logger.error(`Search - Request error: ${err.config.url}`, 'StructureService');
Logger.error(err);
}
);
}): Promise<{ features: { geometry: {}; type: string; properties: {} }[] }> {
const reqBan = `https://download.data.grandlyon.com/geocoding/photon/api?q=${data.searchQuery}&lang=fr&limit=500&osm_tag=:!construction&osm_tag=:!bus_stop`;
const reqBal = `https://download.data.grandlyon.com/geocoding/photon-bal/api?q=${data.searchQuery}&lang=fr&limit=500&osm_tag=:!construction&osm_tag=:!bus_stop`;
const requestGroup = (url): Promise<{ features: { geometry: {}; type: string; properties: {} }[] }> =>
new Promise((resolve, reject) => {
Logger.debug(`Search request: ${encodeURI(url)}`, 'StructureService');
return this.httpService
.request({
url: encodeURI(url),
method: 'GET',
headers: { 'Content-Type': 'application/json' },
})
.subscribe(
(reply) => {
Logger.debug(`Search request response length : ${reply.data.features.length}`, 'StructureService');
reply.data.features = reply.data.features
.filter((doc) => doc.properties.postcode && doc.properties.postcode.match(depRegex))
.sort((a, b) => {
return b.properties.housenumber ? 1 : -1;
});
return resolve(reply.data);
},
(err) => {
Logger.error(`Search - Request error: ${err.config.url}`, 'StructureService');
Logger.error(err);
}
);
});
const [reqBanRes, reqBalRes] = await Promise.all([requestGroup(reqBan), requestGroup(reqBal)]);
const mergedArray = [...reqBalRes['features'], ...reqBanRes['features']];
const duplicateFreeArray = _.unionWith(mergedArray, function (a, b) {
return (
// excludes structures from photon-BAN if they share postcode && street or name && housenumber
// checking for name and street existance asserts that we will not compare 2 undefined fields
a.properties.postcode === b.properties.postcode &&
((a.properties.name &&
(a.properties.name === b.properties.name || a.properties.name === b.properties.street)) ||
(a.properties.street &&
(a.properties.street === b.properties.name || a.properties.street === b.properties.street))) &&
(a.properties.housenumber === b.properties.housenumber ||
(!a.properties.housenumber && !b.properties.housenumber))
);
});
return {
features: duplicateFreeArray,
};
}
/**
......@@ -446,9 +505,11 @@ export class StructuresService {
);
}
public getCoord(numero: string, address: string, zipcode: string): Observable<AxiosResponse<any>> {
const req = 'https://download.data.grandlyon.com/geocoding/photon/api?q=' + numero + ' ' + address + ' ' + zipcode;
Logger.log(`getCoord - Request : ${req}`, 'StructureService');
public getCoord(numero: string, address: string, zipcode: string, scope: string): Observable<AxiosResponse<any>> {
const req =
`https://download.data.grandlyon.com/geocoding/${scope}/api?q=` + numero + ' ' + address + ' ' + zipcode;
Logger.debug('Print getCoord' + req);
return this.httpService.get(encodeURI(req));
}
......
......@@ -223,7 +223,7 @@ export class UsersService {
const html = await ejs.renderFile(ejsPath, {
config,
status: status ? 'accepté' : 'refusée',
status: status ? 'acceptée' : 'refusée',
name: structureName,
});
this.mailerService.send(userEmail, jsonConfig.subject, html);
......
......@@ -708,6 +708,7 @@ export class StructuresServiceMock {
nbScanners: 1,
freeWorkShop: false,
accountVerified: true,
dataShareConsentDate: '2022-03-01T09:00:00.000Z',
createdAt: '2021-05-06T09:42:38.000Z',
updatedAt: '2021-05-06T09:42:50.000Z',
__v: 0,
......@@ -782,6 +783,7 @@ export class StructuresServiceMock {
nbScanners: 1,
freeWorkShop: false,
accountVerified: true,
dataShareConsentDate: '2022-03-01T09:00:00.000Z',
createdAt: '2021-05-06T09:42:38.000Z',
updatedAt: '2021-05-06T09:42:50.000Z',
__v: 0,
......