Rewrite landuse domain logic without landuse class
This commit is contained in:
parent
4bda0f0aa6
commit
914d7e56d4
@ -1,15 +1,7 @@
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { DomainLogicError } from '../../../errors/general';
|
|
||||||
import { LandUseState, updateLandUse } from '../../domainLogic/landUse';
|
import { LandUseState, updateLandUse } from '../../domainLogic/landUse';
|
||||||
|
|
||||||
const testClassToGroup = {
|
|
||||||
'Animal breeding places': 'Agriculture',
|
|
||||||
'Egg grading place': 'Agriculture',
|
|
||||||
'Fish farm': 'Fisheries',
|
|
||||||
'Brewery': 'Manufacturing',
|
|
||||||
'Business meeting places': 'Offices'
|
|
||||||
};
|
|
||||||
const testGroupToOrder = {
|
const testGroupToOrder = {
|
||||||
'Agriculture': 'Agriculture And Fisheries',
|
'Agriculture': 'Agriculture And Fisheries',
|
||||||
'Fisheries': 'Agriculture And Fisheries',
|
'Fisheries': 'Agriculture And Fisheries',
|
||||||
@ -18,12 +10,7 @@ const testGroupToOrder = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
jest.mock('../../../dataAccess/landUse', () => ({
|
jest.mock('../../../dataAccess/landUse', () => ({
|
||||||
getLandUseGroupFromClass: jest.fn((classes: string[]) => {
|
getLandUseOrderFromGroup: jest.fn((groups: string[]) => {
|
||||||
const groups = _.chain(classes).map(c => testClassToGroup[c]).uniq().value();
|
|
||||||
|
|
||||||
return Promise.resolve(groups);
|
|
||||||
}),
|
|
||||||
getLandUseOrderGromGroup: jest.fn((groups: string[]) => {
|
|
||||||
const orders = _.chain(groups).map(g => testGroupToOrder[g]).uniq().value();
|
const orders = _.chain(groups).map(g => testGroupToOrder[g]).uniq().value();
|
||||||
|
|
||||||
let result: string;
|
let result: string;
|
||||||
@ -38,66 +25,73 @@ jest.mock('../../../dataAccess/landUse', () => ({
|
|||||||
describe('updateLandUse()', () => {
|
describe('updateLandUse()', () => {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.resetAllMocks();
|
jest.clearAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[{
|
[{
|
||||||
landUseClass: [],
|
|
||||||
landUseGroup: [],
|
landUseGroup: [],
|
||||||
landUseOrder: null
|
landUseOrder: null
|
||||||
}, {
|
}, {
|
||||||
landUseClass: ['Animal breeding places']
|
landUseGroup: ['Agriculture']
|
||||||
}, {
|
}, {
|
||||||
landUseClass: ['Animal breeding places'],
|
|
||||||
landUseGroup: ['Agriculture'],
|
landUseGroup: ['Agriculture'],
|
||||||
landUseOrder: 'Agriculture And Fisheries'
|
landUseOrder: 'Agriculture And Fisheries'
|
||||||
}],
|
}],
|
||||||
|
|
||||||
[{
|
[{
|
||||||
landUseClass: ['Animal breeding places'],
|
|
||||||
landUseGroup: ['Agriculture'],
|
landUseGroup: ['Agriculture'],
|
||||||
landUseOrder: 'Agriculture And Fisheries'
|
landUseOrder: 'Agriculture And Fisheries'
|
||||||
}, {
|
}, {
|
||||||
landUseClass: ['Fish farm']
|
landUseGroup: ['Fisheries']
|
||||||
}, {
|
}, {
|
||||||
landUseClass: ['Fish farm'],
|
|
||||||
landUseGroup: ['Fisheries'],
|
landUseGroup: ['Fisheries'],
|
||||||
landUseOrder: 'Agriculture And Fisheries'
|
landUseOrder: 'Agriculture And Fisheries'
|
||||||
}],
|
}],
|
||||||
|
|
||||||
[{
|
[{
|
||||||
landUseClass: ['Animal breeding places'],
|
|
||||||
landUseGroup: ['Agriculture'],
|
landUseGroup: ['Agriculture'],
|
||||||
landUseOrder: 'Agriculture And Fisheries'
|
landUseOrder: 'Agriculture And Fisheries'
|
||||||
}, {
|
}, {
|
||||||
landUseClass: ['Animal breeding places', 'Business meeting places']
|
landUseGroup: ['Agriculture', 'Offices'],
|
||||||
}, {
|
}, {
|
||||||
landUseClass: ['Animal breeding places', 'Business meeting places'],
|
|
||||||
landUseGroup: ['Agriculture', 'Offices'],
|
landUseGroup: ['Agriculture', 'Offices'],
|
||||||
landUseOrder: 'Mixed Use'
|
landUseOrder: 'Mixed Use'
|
||||||
}]
|
}]
|
||||||
])('Should derive higher level land use classifications from lower level ones',
|
])('Should derive land use order from group',
|
||||||
async (landUse: LandUseState, landUseUpdate: Partial<LandUseState>, expectedUpdate: LandUseState) => {
|
async (landUse: LandUseState, landUseUpdate: Partial<LandUseState>, expectedUpdate: LandUseState) => {
|
||||||
const result = await updateLandUse(landUse, landUseUpdate);
|
const result = await updateLandUse(landUse, landUseUpdate);
|
||||||
|
|
||||||
expect(result).toBe(expectedUpdate);
|
expect(result).toEqual(expectedUpdate);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
[{
|
[{
|
||||||
landUseClass: ['Fish farm'],
|
landUseGroup: ['Agriculture'],
|
||||||
landUseGroup: ['Fisheries'],
|
|
||||||
landUseOrder: 'Agriculture And Fisheries'
|
landUseOrder: 'Agriculture And Fisheries'
|
||||||
}, {
|
}, {
|
||||||
landUseGroup: []
|
landUseGroup: []
|
||||||
}]
|
}, {
|
||||||
])('Should error when update breaks an automatic chain of classifications',
|
landUseGroup: [],
|
||||||
async (landUse: LandUseState, landUseUpdate: Partial<LandUseState>) => {
|
landUseOrder: null
|
||||||
const resultPromise = updateLandUse(landUse, landUseUpdate);
|
}],
|
||||||
|
|
||||||
expect(resultPromise).rejects.toBeInstanceOf(DomainLogicError);
|
[{
|
||||||
|
landUseGroup: ['Agriculture', 'Offices'],
|
||||||
|
landUseOrder: 'Mixed Use',
|
||||||
|
}, {
|
||||||
|
landUseGroup: ['Agriculture'],
|
||||||
|
}, {
|
||||||
|
landUseGroup: ['Agriculture'],
|
||||||
|
landUseOrder: 'Agriculture And Fisheries'
|
||||||
|
}]
|
||||||
|
])('Should remove derived land use order when land use group is removed',
|
||||||
|
async (landUse: LandUseState, landUseUpdate: Partial<LandUseState>, expectedUpdate: LandUseState) => {
|
||||||
|
const result = await updateLandUse(landUse, landUseUpdate);
|
||||||
|
|
||||||
|
expect(result).toEqual(expectedUpdate);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -1,75 +1,18 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
import { isNullishOrEmpty } from '../../../helpers';
|
import { getLandUseOrderFromGroup } from '../../dataAccess/landUse';
|
||||||
import { getLandUseGroupFromClass, getLandUseOrderFromGroup } from '../../dataAccess/landUse';
|
|
||||||
import { getCurrentBuildingDataById } from '../building';
|
|
||||||
|
|
||||||
export interface LandUseState {
|
export interface LandUseState {
|
||||||
landUseClass: string[];
|
|
||||||
landUseGroup: string[];
|
landUseGroup: string[];
|
||||||
landUseOrder: string;
|
landUseOrder: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateLandUse(landUse: LandUseState, landUseUpdate: Partial<LandUseState>): Promise<LandUseState> {
|
export async function updateLandUse(landUse: LandUseState, landUseUpdate: Partial<LandUseState>): Promise<LandUseState> {
|
||||||
throw new Error('Not implemented');
|
const landUseGroupUpdate = landUseUpdate.landUseGroup;
|
||||||
}
|
const landUseOrderUpdate = await getLandUseOrderFromGroup(landUseGroupUpdate);
|
||||||
|
|
||||||
export async function processCurrentLandUseClassifications(buildingId: number, buildingUpdate: any): Promise<any> {
|
return {
|
||||||
let updateData = _.pick(await getCurrentBuildingDataById(buildingId), [
|
landUseGroup: landUseGroupUpdate,
|
||||||
'current_landuse_class',
|
landUseOrder: landUseOrderUpdate
|
||||||
'current_landuse_group',
|
};
|
||||||
'current_landuse_order'
|
|
||||||
]);
|
|
||||||
|
|
||||||
updateData = Object.assign({}, updateData, getClearValues(buildingUpdate));
|
|
||||||
|
|
||||||
const updateFrom = getUpdateStartingStage(buildingUpdate);
|
|
||||||
if(updateFrom === 'class') {
|
|
||||||
updateData.current_landuse_class = buildingUpdate.current_landuse_class;
|
|
||||||
updateData.current_landuse_group = await getLandUseGroupFromClass(updateData.current_landuse_class);
|
|
||||||
updateData.current_landuse_order = await getLandUseOrderFromGroup(updateData.current_landuse_group);
|
|
||||||
} else if (updateFrom === 'group') {
|
|
||||||
if (isNullishOrEmpty(updateData.current_landuse_class)) {
|
|
||||||
updateData.current_landuse_group = buildingUpdate.current_landuse_group;
|
|
||||||
updateData.current_landuse_order = await getLandUseOrderFromGroup(buildingUpdate.current_landuse_group);
|
|
||||||
} else {
|
|
||||||
throw new Error('Trying to update current_landuse_group field but a more detailed field (current_landuse_class) is already filled');
|
|
||||||
}
|
|
||||||
} else if (updateFrom === 'order') {
|
|
||||||
if (isNullishOrEmpty(updateData.current_landuse_class) && isNullishOrEmpty(updateData.current_landuse_group)) {
|
|
||||||
updateData.current_landuse_order = buildingUpdate.current_landuse_order;
|
|
||||||
} else {
|
|
||||||
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 Object.assign({}, buildingUpdate, 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.
|
|
||||||
* @param building
|
|
||||||
*/
|
|
||||||
function getUpdateStartingStage(building) {
|
|
||||||
if(building.hasOwnProperty('current_landuse_class') && !isNullishOrEmpty(building.current_landuse_class)) {
|
|
||||||
return 'class';
|
|
||||||
} else if(building.hasOwnProperty('current_landuse_group') && !isNullishOrEmpty(building.current_landuse_group)) {
|
|
||||||
return 'group';
|
|
||||||
} else if(building.hasOwnProperty('current_landuse_order') && !isNullishOrEmpty(building.current_landuse_order)) {
|
|
||||||
return 'order';
|
|
||||||
} else return 'none';
|
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import { getCurrentBuildingDataById } from '../building';
|
|||||||
import { updateLandUse } from './landUse';
|
import { updateLandUse } from './landUse';
|
||||||
|
|
||||||
export async function processBuildingUpdate(buildingId: number, buildingUpdate: any): Promise<any> {
|
export async function processBuildingUpdate(buildingId: number, buildingUpdate: any): Promise<any> {
|
||||||
if(hasAnyOwnProperty(buildingUpdate, ['current_landuse_class', 'current_landuse_group', 'current_landuse_order'])) {
|
if(hasAnyOwnProperty(buildingUpdate, ['current_landuse_group'])) {
|
||||||
buildingUpdate = await processCurrentLandUseClassifications(buildingId, buildingUpdate);
|
buildingUpdate = await processCurrentLandUseClassifications(buildingId, buildingUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,18 +18,14 @@ async function processCurrentLandUseClassifications(buildingId: number, building
|
|||||||
|
|
||||||
const currentLandUseUpdate = await updateLandUse(
|
const currentLandUseUpdate = await updateLandUse(
|
||||||
{
|
{
|
||||||
landUseClass: currentBuildingData.current_landuse_class,
|
|
||||||
landUseGroup: currentBuildingData.current_landuse_group,
|
landUseGroup: currentBuildingData.current_landuse_group,
|
||||||
landUseOrder: currentBuildingData.current_landuse_order
|
landUseOrder: currentBuildingData.current_landuse_order
|
||||||
}, {
|
}, {
|
||||||
landUseClass: buildingUpdate.current_landuse_class,
|
landUseGroup: buildingUpdate.current_landuse_group
|
||||||
landUseGroup: buildingUpdate.current_landuse_group,
|
|
||||||
landUseOrder: buildingUpdate.current_landuse_order
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return Object.assign({}, buildingUpdate, {
|
return Object.assign({}, buildingUpdate, {
|
||||||
current_landuse_class: currentLandUseUpdate.landUseClass,
|
|
||||||
current_landuse_group: currentLandUseUpdate.landUseGroup,
|
current_landuse_group: currentLandUseUpdate.landUseGroup,
|
||||||
current_landuse_order: currentLandUseUpdate.landUseOrder,
|
current_landuse_order: currentLandUseUpdate.landUseOrder,
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user