Improve land use processing backend
This commit is contained in:
parent
c3b5c51da7
commit
5170dc7971
6
app/package-lock.json
generated
6
app/package-lock.json
generated
@ -1097,6 +1097,12 @@
|
|||||||
"@types/geojson": "*"
|
"@types/geojson": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/lodash": {
|
||||||
|
"version": "4.14.149",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz",
|
||||||
|
"integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/mapbox__sphericalmercator": {
|
"@types/mapbox__sphericalmercator": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/mapbox__sphericalmercator/-/mapbox__sphericalmercator-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/mapbox__sphericalmercator/-/mapbox__sphericalmercator-1.1.3.tgz",
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
"@types/express": "^4.17.0",
|
"@types/express": "^4.17.0",
|
||||||
"@types/express-session": "^1.15.13",
|
"@types/express-session": "^1.15.13",
|
||||||
"@types/jest": "^24.0.17",
|
"@types/jest": "^24.0.17",
|
||||||
|
"@types/lodash": "^4.14.149",
|
||||||
"@types/mapbox__sphericalmercator": "^1.1.3",
|
"@types/mapbox__sphericalmercator": "^1.1.3",
|
||||||
"@types/node": "^8.10.52",
|
"@types/node": "^8.10.52",
|
||||||
"@types/nodemailer": "^6.2.1",
|
"@types/nodemailer": "^6.2.1",
|
||||||
|
@ -158,7 +158,7 @@ async function getBuildingUPRNsById(id: number) {
|
|||||||
async function saveBuilding(buildingId: number, building: any, userId: string) { // TODO add proper building type
|
async function saveBuilding(buildingId: number, building: any, userId: string) { // TODO add proper building type
|
||||||
try {
|
try {
|
||||||
return await updateBuildingData(buildingId, userId, async () => {
|
return await updateBuildingData(buildingId, userId, async () => {
|
||||||
const processedBuilding = await processBuildingUpdate(building);
|
const processedBuilding = await processBuildingUpdate(buildingId, building);
|
||||||
|
|
||||||
// remove read-only fields from consideration
|
// remove read-only fields from consideration
|
||||||
delete processedBuilding.building_id;
|
delete processedBuilding.building_id;
|
||||||
|
@ -1,48 +1,73 @@
|
|||||||
import db from '../../../db';
|
import * as _ from 'lodash';
|
||||||
import { getBuildingById, getCurrentBuildingDataById } from '../building';
|
|
||||||
|
|
||||||
export async function processCurrentLandUseClassifications(building: any): Promise<any> {
|
import db from '../../../db';
|
||||||
|
import { isNullishOrEmpty } from '../../../helpers';
|
||||||
|
import { getCurrentBuildingDataById } from '../building';
|
||||||
|
|
||||||
|
export async function processCurrentLandUseClassifications(buildingId: number, building: any): Promise<any> {
|
||||||
|
let updateData = _.pick(await getCurrentBuildingDataById(buildingId), [
|
||||||
|
'current_landuse_class',
|
||||||
|
'current_landuse_group',
|
||||||
|
'current_landuse_order'
|
||||||
|
]);
|
||||||
|
|
||||||
|
updateData = Object.assign({}, updateData, getClearValues(building));
|
||||||
|
|
||||||
const updateFrom = getUpdateStartingStage(building);
|
const updateFrom = getUpdateStartingStage(building);
|
||||||
const currentData = await getCurrentBuildingDataById(building.building_id);
|
|
||||||
|
|
||||||
if(updateFrom === 'class') {
|
if(updateFrom === 'class') {
|
||||||
building.current_landuse_group = await deriveGroupFromClass(building.current_landuse_class);
|
updateData.current_landuse_class = building.current_landuse_class;
|
||||||
building.current_landuse_order = await deriveOrderFromGroup(building.current_landuse_group);
|
updateData.current_landuse_group = await deriveGroupFromClass(updateData.current_landuse_class);
|
||||||
|
updateData.current_landuse_order = await deriveOrderFromGroup(updateData.current_landuse_group);
|
||||||
} else if (updateFrom === 'group') {
|
} else if (updateFrom === 'group') {
|
||||||
if(currentData.current_landuse_class == undefined) {
|
if (isNullishOrEmpty(updateData.current_landuse_class)) {
|
||||||
building.current_landuse_order = await deriveOrderFromGroup(building.current_landuse_group);
|
updateData.current_landuse_group = building.current_landuse_group;
|
||||||
|
updateData.current_landuse_order = await deriveOrderFromGroup(building.current_landuse_group);
|
||||||
} else {
|
} else {
|
||||||
delete building.current_landuse_group;
|
throw new Error('Trying to update current_landuse_group field but a more detailed field (current_landuse_class) is already filled');
|
||||||
delete building.current_landuse_order;
|
|
||||||
}
|
}
|
||||||
} else if (updateFrom === 'order') {
|
} else if (updateFrom === 'order') {
|
||||||
if(currentData.current_landuse_class == undefined && currentData.current_landuse_group == undefined) {
|
if (isNullishOrEmpty(updateData.current_landuse_class) && isNullishOrEmpty(updateData.current_landuse_group)) {
|
||||||
// do nothing, building.current_landuse_order is already correctly set and can be used for the update
|
updateData.current_landuse_order = building.current_landuse_order;
|
||||||
} else {
|
} else {
|
||||||
delete building.current_landuse_order;
|
throw new Error('Trying to update current_landuse_order field but a more detailed field (current_landuse_class or current_landuse_group) is already filled');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return building;
|
return Object.assign({}, building, updateData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getClearValues(building) {
|
||||||
|
const clearValues: any = {};
|
||||||
|
if(building.hasOwnProperty('current_landuse_class') && isNullishOrEmpty(building.current_landuse_class)) {
|
||||||
|
clearValues.current_landuse_class = [];
|
||||||
|
}
|
||||||
|
if(building.hasOwnProperty('current_landuse_group') && isNullishOrEmpty(building.current_landuse_group)) {
|
||||||
|
clearValues.current_landuse_group = [];
|
||||||
|
}
|
||||||
|
if(building.hasOwnProperty('current_landuse_order') && isNullishOrEmpty(building.current_landuse_order)) {
|
||||||
|
clearValues.current_landuse_order = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return clearValues;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Choose which level of the land use classification hierarchy the update should start from.
|
* Choose which level of the land use classification hierarchy the update should start from.
|
||||||
* @param building
|
* @param building
|
||||||
*/
|
*/
|
||||||
function getUpdateStartingStage(building) {
|
function getUpdateStartingStage(building) {
|
||||||
if(building.hasOwnProperty('current_landuse_class')) {
|
if(building.hasOwnProperty('current_landuse_class') && !isNullishOrEmpty(building.current_landuse_class)) {
|
||||||
return 'class';
|
return 'class';
|
||||||
} else if(building.hasOwnProperty('current_landuse_group')) {
|
} else if(building.hasOwnProperty('current_landuse_group') && !isNullishOrEmpty(building.current_landuse_group)) {
|
||||||
return 'group';
|
return 'group';
|
||||||
} else if(building.hasOwnProperty('current_landuse_order')) {
|
} else if(building.hasOwnProperty('current_landuse_order') && !isNullishOrEmpty(building.current_landuse_order)) {
|
||||||
return 'order';
|
return 'order';
|
||||||
} else return 'none';
|
} else return 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
function deriveGroupFromClass(classes: string[]): Promise<string[]> {
|
async function deriveGroupFromClass(classes: string[]): Promise<string[]> {
|
||||||
return db.many(
|
if (classes.length === 0) return [];
|
||||||
|
|
||||||
|
return (await db.many(
|
||||||
`
|
`
|
||||||
SELECT DISTINCT parent.description
|
SELECT DISTINCT parent.description
|
||||||
FROM reference_tables.buildings_landuse_group AS parent
|
FROM reference_tables.buildings_landuse_group AS parent
|
||||||
@ -51,11 +76,13 @@ function deriveGroupFromClass(classes: string[]): Promise<string[]> {
|
|||||||
WHERE child.description IN ($1:csv)
|
WHERE child.description IN ($1:csv)
|
||||||
ORDER BY parent.description`,
|
ORDER BY parent.description`,
|
||||||
[classes]
|
[classes]
|
||||||
);
|
)).map(x => x.description);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deriveOrderFromGroup(groups: string[]): Promise<string> {
|
async function deriveOrderFromGroup(groups: string[]): Promise<string> {
|
||||||
const orders = await db.many(
|
if(groups.length === 0) return null;
|
||||||
|
|
||||||
|
const orders = (await db.many(
|
||||||
`
|
`
|
||||||
SELECT DISTINCT parent.description
|
SELECT DISTINCT parent.description
|
||||||
FROM reference_tables.buildings_landuse_order AS parent
|
FROM reference_tables.buildings_landuse_order AS parent
|
||||||
@ -65,7 +92,7 @@ async function deriveOrderFromGroup(groups: string[]): Promise<string> {
|
|||||||
ORDER BY parent.description
|
ORDER BY parent.description
|
||||||
`,
|
`,
|
||||||
[groups]
|
[groups]
|
||||||
);
|
)).map(x => x.description);
|
||||||
|
|
||||||
if(orders.length === 1) {
|
if(orders.length === 1) {
|
||||||
return orders[0];
|
return orders[0];
|
||||||
|
@ -2,9 +2,9 @@ import { hasAnyOwnProperty } from '../../../helpers';
|
|||||||
|
|
||||||
import { processCurrentLandUseClassifications } from './currentLandUseClassifications';
|
import { processCurrentLandUseClassifications } from './currentLandUseClassifications';
|
||||||
|
|
||||||
export async function processBuildingUpdate<T>(building: T): Promise<T> {
|
export async function processBuildingUpdate(buildingId: number, building: any): Promise<any> {
|
||||||
if(hasAnyOwnProperty(building, ['current_landuse_class', 'current_landuse_group', 'current_landuse_order'])) {
|
if(hasAnyOwnProperty(building, ['current_landuse_class', 'current_landuse_group', 'current_landuse_order'])) {
|
||||||
building = await processCurrentLandUseClassifications(building);
|
building = await processCurrentLandUseClassifications(buildingId, building);
|
||||||
}
|
}
|
||||||
|
|
||||||
return building;
|
return building;
|
||||||
|
@ -27,3 +27,10 @@ export function parseJsonOrDefault(jsonString: string) {
|
|||||||
export function hasAnyOwnProperty(obj: {}, keys: string[]) {
|
export function hasAnyOwnProperty(obj: {}, keys: string[]) {
|
||||||
return keys.some(k => obj.hasOwnProperty(k));
|
return keys.some(k => obj.hasOwnProperty(k));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isNullishOrEmpty(obj: any) {
|
||||||
|
return obj == undefined || isEmptyArray(obj);
|
||||||
|
}
|
||||||
|
export function isEmptyArray(obj: any) {
|
||||||
|
return Array.isArray(obj) && obj.length === 0;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user