diff --git a/app/map_styles/polygon.xml b/app/map_styles/polygon.xml
index a2f88975..6c819b37 100644
--- a/app/map_styles/polygon.xml
+++ b/app/map_styles/polygon.xml
@@ -250,4 +250,50 @@
+
diff --git a/app/package-lock.json b/app/package-lock.json
index 8913e572..4c1740ad 100644
--- a/app/package-lock.json
+++ b/app/package-lock.json
@@ -1097,6 +1097,12 @@
"@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": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@types/mapbox__sphericalmercator/-/mapbox__sphericalmercator-1.1.3.tgz",
diff --git a/app/package.json b/app/package.json
index e1048cfd..030b155a 100644
--- a/app/package.json
+++ b/app/package.json
@@ -42,6 +42,7 @@
"@types/express": "^4.17.0",
"@types/express-session": "^1.15.13",
"@types/jest": "^24.0.17",
+ "@types/lodash": "^4.14.149",
"@types/mapbox__sphericalmercator": "^1.1.3",
"@types/node": "^8.10.52",
"@types/nodemailer": "^6.2.1",
diff --git a/app/src/api/services/building.ts b/app/src/api/services/building.ts
index 9cc611d8..38bbc082 100644
--- a/app/src/api/services/building.ts
+++ b/app/src/api/services/building.ts
@@ -2,12 +2,15 @@
* Building data access
*
*/
+import * as _ from 'lodash';
import { ITask } from 'pg-promise';
import db from '../../db';
import { tileCache } from '../../tiles/rendererDefinition';
import { BoundingBox } from '../../tiles/types';
+import { processBuildingUpdate } from './domainLogic/processBuildingUpdate';
+
// data type note: PostgreSQL bigint (64-bit) is handled as string in JavaScript, because of
// JavaScript numerics are 64-bit double, giving only partial coverage.
@@ -92,12 +95,16 @@ async function queryBuildingsByReference(key: string, ref: string) {
}
}
+async function getCurrentBuildingDataById(id: number) {
+ return db.one(
+ 'SELECT * FROM buildings WHERE building_id = $1',
+ [id]
+ );
+}
+
async function getBuildingById(id: number) {
try {
- const building = await db.one(
- 'SELECT * FROM buildings WHERE building_id = $1',
- [id]
- );
+ const building = await getCurrentBuildingDataById(id);
building.edit_history = await getBuildingEditHistory(id);
@@ -151,13 +158,15 @@ async function getBuildingUPRNsById(id: number) {
async function saveBuilding(buildingId: number, building: any, userId: string) { // TODO add proper building type
try {
return await updateBuildingData(buildingId, userId, async () => {
+ const processedBuilding = await processBuildingUpdate(buildingId, building);
+
// remove read-only fields from consideration
- delete building.building_id;
- delete building.revision_id;
- delete building.geometry_id;
+ delete processedBuilding.building_id;
+ delete processedBuilding.revision_id;
+ delete processedBuilding.geometry_id;
// return whitelisted fields to update
- return pickAttributesToUpdate(building, BUILDING_FIELD_WHITELIST);
+ return pickAttributesToUpdate(processedBuilding, BUILDING_FIELD_WHITELIST);
});
} catch(error) {
console.error(error);
@@ -395,6 +404,10 @@ const BUILDING_FIELD_WHITELIST = new Set([
// 'sust_life_expectancy',
'building_attachment_form',
'date_change_building_use',
+
+ 'current_landuse_class',
+ 'current_landuse_group',
+ 'current_landuse_order'
]);
/**
@@ -411,7 +424,7 @@ function compare(oldObj: object, newObj: object): [object, object] {
const reverse = {};
const forward = {};
for (const [key, value] of Object.entries(newObj)) {
- if (oldObj[key] != value) {
+ if (!_.isEqual(oldObj[key], value)) {
reverse[key] = oldObj[key];
forward[key] = value;
}
@@ -422,6 +435,7 @@ function compare(oldObj: object, newObj: object): [object, object] {
export {
queryBuildingsAtPoint,
queryBuildingsByReference,
+ getCurrentBuildingDataById,
getBuildingById,
getBuildingLikeById,
getBuildingEditHistory,
diff --git a/app/src/api/services/domainLogic/currentLandUseClassifications.ts b/app/src/api/services/domainLogic/currentLandUseClassifications.ts
new file mode 100644
index 00000000..e15a9244
--- /dev/null
+++ b/app/src/api/services/domainLogic/currentLandUseClassifications.ts
@@ -0,0 +1,102 @@
+import * as _ from 'lodash';
+
+import db from '../../../db';
+import { isNullishOrEmpty } from '../../../helpers';
+import { getCurrentBuildingDataById } from '../building';
+
+export async function processCurrentLandUseClassifications(buildingId: number, building: any): Promise {
+ 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);
+ if(updateFrom === 'class') {
+ updateData.current_landuse_class = building.current_landuse_class;
+ updateData.current_landuse_group = await deriveGroupFromClass(updateData.current_landuse_class);
+ updateData.current_landuse_order = await deriveOrderFromGroup(updateData.current_landuse_group);
+ } else if (updateFrom === 'group') {
+ if (isNullishOrEmpty(updateData.current_landuse_class)) {
+ updateData.current_landuse_group = building.current_landuse_group;
+ updateData.current_landuse_order = await deriveOrderFromGroup(building.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 = building.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({}, 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.
+ * @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';
+}
+
+async function deriveGroupFromClass(classes: string[]): Promise {
+ if (classes.length === 0) return [];
+
+ return (await db.many(
+ `
+ SELECT DISTINCT parent.description
+ FROM reference_tables.buildings_landuse_group AS parent
+ JOIN reference_tables.buildings_landuse_class AS child
+ ON child.parent_group_id = parent.landuse_id
+ WHERE child.description IN ($1:csv)
+ ORDER BY parent.description`,
+ [classes]
+ )).map(x => x.description);
+}
+
+async function deriveOrderFromGroup(groups: string[]): Promise {
+ if(groups.length === 0) return null;
+
+ const orders = (await db.many(
+ `
+ SELECT DISTINCT parent.description
+ FROM reference_tables.buildings_landuse_order AS parent
+ JOIN reference_tables.buildings_landuse_group AS child
+ ON child.parent_order_id = parent.landuse_id
+ WHERE child.description IN ($1:csv)
+ ORDER BY parent.description
+ `,
+ [groups]
+ )).map(x => x.description);
+
+ if(orders.length === 1) {
+ return orders[0];
+ } else if (orders.length > 1) {
+ return 'Mixed Use';
+ } else return null;
+}
diff --git a/app/src/api/services/domainLogic/processBuildingUpdate.ts b/app/src/api/services/domainLogic/processBuildingUpdate.ts
new file mode 100644
index 00000000..7b7d166f
--- /dev/null
+++ b/app/src/api/services/domainLogic/processBuildingUpdate.ts
@@ -0,0 +1,11 @@
+import { hasAnyOwnProperty } from '../../../helpers';
+
+import { processCurrentLandUseClassifications } from './currentLandUseClassifications';
+
+export async function processBuildingUpdate(buildingId: number, building: any): Promise {
+ if(hasAnyOwnProperty(building, ['current_landuse_class', 'current_landuse_group', 'current_landuse_order'])) {
+ building = await processCurrentLandUseClassifications(buildingId, building);
+ }
+
+ return building;
+}
diff --git a/app/src/frontend/building/building-view.tsx b/app/src/frontend/building/building-view.tsx
index d21f7115..797e8b69 100644
--- a/app/src/frontend/building/building-view.tsx
+++ b/app/src/frontend/building/building-view.tsx
@@ -43,7 +43,7 @@ const BuildingView: React.FunctionComponent = (props) => {
case 'use':
return = (props) => (
- {props.intro}
-
- - Single or multiple use?
- {
- // "disabled": true,
- // "slug": "use_multi",
- // "type": "checkbox"
- }
- - Type of use/s
- {
- // "disabled": true,
- // "slug": "use_type",
- // "type": "text_multi"
- }
- - Number of self-contained units
- {
- // "disabled": true,
- // "slug": "use_number_scu",
- // "type": "number",
- // "step": 1
- }
-
+
+
+
+
);
const UseContainer = withCopyEdit(UseView);
diff --git a/app/src/frontend/building/edit-history/field-edit-summary.tsx b/app/src/frontend/building/edit-history/field-edit-summary.tsx
index 2612d6cb..d7808022 100644
--- a/app/src/frontend/building/edit-history/field-edit-summary.tsx
+++ b/app/src/frontend/building/edit-history/field-edit-summary.tsx
@@ -10,6 +10,9 @@ function formatValue(value: any) {
if(typeof value === 'boolean') {
return value ? 'Yes' : 'No';
}
+ if(Array.isArray(value)) {
+ return value.map(v => `"${v}"`).join(', ');
+ }
return value;
}
diff --git a/app/src/frontend/data_fields.ts b/app/src/frontend/data_fields.ts
index 716292f0..7e46cdad 100644
--- a/app/src/frontend/data_fields.ts
+++ b/app/src/frontend/data_fields.ts
@@ -153,6 +153,19 @@ export const dataFields = {
title: "Longitude",
},
+ current_landuse_class: {
+ category: Category.LandUse,
+ title: "Current Land Use Class"
+ },
+ current_landuse_group: {
+ category: Category.LandUse,
+ title: "Current Land Use Group"
+ },
+ current_landuse_order: {
+ category: Category.LandUse,
+ title: "Current Land Use Order"
+ },
+
building_attachment_form: {
category: Category.Type,
title: "Building configuration (attachment)?",
diff --git a/app/src/frontend/map/legend.tsx b/app/src/frontend/map/legend.tsx
index c865a3bd..161d484c 100644
--- a/app/src/frontend/map/legend.tsx
+++ b/app/src/frontend/map/legend.tsx
@@ -18,8 +18,20 @@ const LEGEND_CONFIG = {
]
},
use: {
- title: 'Use',
- elements: []
+ title: 'Land Use',
+ elements: [
+ { color: '#4a54a6', text: 'Residential' },
+ { color: '#e5050d', text: 'Mixed Use' },
+ { color: '#ff8c00', text: 'Retail' },
+ { color: '#f5f58f', text: 'Industry And Business' },
+ { color: '#73ccd1', text: 'Community Services' },
+ { color: '#ffbfbf', text: 'Recreation And Leisure' },
+ { color: '#b3de69', text: 'Transport' },
+ { color: '#cccccc', text: 'Utilities And Infrastructure' },
+ { color: '#52403C', text: 'Agriculture And Fisheries' },
+ { color: '#898944', text: 'Defence' },
+ { color: '#ffffff', text: 'Vacant And Derelict' },
+ ]
},
type: {
title: 'Type',
diff --git a/app/src/frontend/map/map.tsx b/app/src/frontend/map/map.tsx
index f8c484e4..353b42b7 100644
--- a/app/src/frontend/map/map.tsx
+++ b/app/src/frontend/map/map.tsx
@@ -139,6 +139,7 @@ class ColouringMap extends Component {
planning: 'conservation_area',
sustainability: 'sust_dec',
type: 'building_attachment_form',
+ use: 'landuse'
};
const tileset = tilesetByCat[cat];
// pick revision id to bust browser cache
diff --git a/app/src/helpers.ts b/app/src/helpers.ts
index d0e1ada1..372001e1 100644
--- a/app/src/helpers.ts
+++ b/app/src/helpers.ts
@@ -23,3 +23,14 @@ export function parseJsonOrDefault(jsonString: string) {
return null;
}
}
+
+export function hasAnyOwnProperty(obj: {}, keys: string[]) {
+ 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;
+}
diff --git a/app/src/tiles/dataDefinition.ts b/app/src/tiles/dataDefinition.ts
index 3f029d2b..05e67042 100644
--- a/app/src/tiles/dataDefinition.ts
+++ b/app/src/tiles/dataDefinition.ts
@@ -108,6 +108,14 @@ const BUILDING_LAYER_DEFINITIONS = {
WHERE
g.geometry_id = b.geometry_id
) as building_attachment_form`,
+ landuse: `(
+ SELECT
+ b.current_landuse_order,
+ g.geometry_geom
+ FROM geometries as g
+ JOIN buildings as b
+ ON g.geometry_id = b.geometry_id
+ ) as current_landuse_order`,
};
const GEOMETRY_FIELD = 'geometry_geom';
diff --git a/migrations/0xx.bulk_data_sources.down.sql b/migrations/0xx.bulk_data_sources.down.sql
new file mode 100644
index 00000000..fff8efbf
--- /dev/null
+++ b/migrations/0xx.bulk_data_sources.down.sql
@@ -0,0 +1,2 @@
+--For landuse classifications there are tables containing the landuses, these are stored in a new schema
+DROP SCHEMA IF EXISTS reference_tables CASCADE;
diff --git a/migrations/0xx.bulk_data_sources.up.sql b/migrations/0xx.bulk_data_sources.up.sql
new file mode 100644
index 00000000..6c757331
--- /dev/null
+++ b/migrations/0xx.bulk_data_sources.up.sql
@@ -0,0 +1,837 @@
+--For landuse classifications there are tables containing the landuses, these are stored in a new schema
+CREATE SCHEMA IF NOT EXISTS reference_tables;
+
+--Then create the table for landuse
+CREATE TABLE IF NOT EXISTS reference_tables.landuse_classifications (
+ landuse_id VARCHAR(9) NOT NULL,
+ description VARCHAR(74) NOT NULL,
+ level VARCHAR(5) NOT NULL,
+ parent_id VARCHAR(4),
+ is_used BOOLEAN DEFAULT True
+);
+
+--populate with data
+--These are taking from the NLUD calssifcations as url below, accessed 12th August 2019
+-- https://land.copernicus.eu/eagle/files/eagle-related-projects/22_NLUD_v44.pdf
+
+-- The is_used column is set based on whether we plan to use a given order/class for urban buildings.
+
+INSERT INTO reference_tables.landuse_classifications
+(landuse_id, description, level, parent_id, is_used)
+VALUES
+
+-- order
+('U010','Agriculture And Fisheries','order',NULL,True),
+('U080','Community Services','order',NULL,True),
+('U120','Defence','order',NULL,True),
+('U020','Forestry','order',NULL,False),
+('U100','Industry And Business','order',NULL,True),
+('U030','Minerals','order',NULL,False),
+('U040','Recreation And Leisure','order',NULL,True),
+('U070','Residential','order',NULL,True),
+('U090','Retail','order',NULL,True),
+('U050','Transport','order',NULL,True),
+('U130','Unused Land','order',NULL,False),
+('U060','Utilities And Infrastructure','order',NULL,True),
+('U110','Vacant And Derelict','order',NULL,True),
+--We have created a landuse order that does not exist for mixed use
+('U140','Mixed Use','order',NULL,True),
+
+-- group
+('U011','Agriculture','group','U010', True),
+('U012','Fisheries','group','U010', True),
+('U021','Managed forest','group','U020', True),
+('U022','Un-managed forest','group','U020', True),
+('U031','Mineral workings and quarries','group','U030', True),
+('U041','Outdoor amenity and open spaces','group','U040', True),
+('U042','Amusement and show places','group','U040', True),
+('U043','Libraries, museums and galleries','group','U040', True),
+('U044','Sports facilities and grounds','group','U040', True),
+('U045','Holiday parks and camps','group','U040', True),
+('U046','Allotments and city farms','group','U040', True),
+('U051','Transport tracks and ways','group','U050', True),
+('U052','Transport terminals and interchanges','group','U050', True), -- corrected U054 to U052
+('U053','Car parks','group','U050', True),
+('U054','Vehicle storage','group','U050', True), -- corrected U051 to U054
+('U055','Goods and freight terminals','group','U050', True),
+('U056','Waterways','group','U050', True),
+('U061','Energy production and distribution','group','U060', True),
+('U062','Water storage and treatment','group','U060', True),
+('U063','Refuse disposal','group','U060', True),
+('U064','Cemeteries and crematoria','group','U060', True),
+('U065','Post and telecommunications','group','U060', True),
+('U071','Dwellings','group','U070', True),
+('U072','Hotels, boarding and guest houses','group','U070', True),
+('U073','Residential institutions','group','U070', True),
+('U081','Medical and health care services','group','U080', True),
+('U082','Places of worship','group','U080', True),
+('U083','Education','group','U080', True),
+('U084','Community services','group','U080', True),
+('U091','Shops','group','U090', True),
+('U092','Financial and professional services','group','U090', True),
+('U093','Restaurants and cafes','group','U090', True),
+('U094','Public houses, bars and nightclubs','group','U090', True),
+('U101','Manufacturing','group','U100', True),
+('U102','Offices','group','U100', True),
+('U103','Storage','group','U100', True),
+('U104','Wholesale distribution','group','U100', True),
+('U111','Vacant','group','U110', True),
+('U112','Derelict','group','U110', True),
+('U121','Defence','group','U120', True),
+('U131','Unused land','group','U130', True),
+
+-- class
+('AG05A -A','Agricultural research establishment','class','U011',True),
+('AG','Agriculture and fisheries places','class','U011',False),
+('AG01A -A','Animal artificial insemination centre','class','U011',False),
+('AG01B -A','Animal boarding establishment','class','U011',False),
+('AG02A','Animal breeding places','class','U011',True),
+('AG01B -B','Animal clipping and manicure establishment','class','U011',True),
+('AG01A -B','Animal dipping place','class','U011',True),
+('AG02','Animal living places','class','U011',True),
+('AG03A','Animal milking places','class','U011',True),
+('AG03','Animal product processing places','class','U011',True),
+('AG03F -A','Animal product waste store','class','U011',True),
+('AG03F -B','Animal product waste treatment places','class','U011',True),
+('AG03F','Animal products waste handling places','class','U011',True),
+('AG02B','Animal rearing places','class','U011',True),
+('AG01A','Animal service places','class','U011',True),
+('AG01','Animal service places','class','U011',True),
+('AG03B','Animal shearing places','class','U011',True),
+('AG03C','Animal slaughtering places','class','U011',True),
+('AG03C-A','Animal stunning and killing places','class','U011',True),
+('AG01B','Animal welfare places','class','U011',True),
+('AG06A','Arable farm places','class','U011',True),
+('AG02B -A','Bedding and waste removal','class','U011',True),
+('AG01A -C','Blacksmith premises','class','U011',True),
+('AG06A -A','Cereal crops','class','U011',False),
+('AG07A -A','Cereal crops store','class','U011',True),
+('AG07A','Crop conditioning grading and storage places','class','U011',True),
+('AG07','Crop processing places','class','U011',True),
+('AG06','Cultivated places','class','U011',True),
+('AG03D-A','Egg grading place','class','U011',True),
+('AG06A -B','Fallow land','class','U011',False),
+('AG03E','Feed handling places','class','U011',True),
+('AG03E -A','Feed preparation place','class','U011',True),
+('AG03E -B','Feed storage place','class','U011',True),
+('AG02B -B','Feeding','class','U011',True),
+('AG03D-B','Fish sorting place','class','U011',True),
+('AG06B -B','Flower bed','class','U011',False),
+('AG07A -B','Fruit crops','class','U011',False),
+('AG06B -C','Glass house','class','U011',True),
+('AG08A','Grazing places','class','U011',False),
+('AG06A -C','Green forage crops place','class','U011',False),
+('AG07A -C','Green forage crops store','class','U011',False),
+('AG06B -D','Hop field','class','U011',False),
+('AG06B','Horticultural places','class','U011',True),
+('AG02B -C','Isolation (animal living place)','class','U011',False),
+('AG03C-B','Knackering place','class','U011',True),
+('AG03A -A','Milk extraction place','class','U011',True),
+('AG03A -B','Milk treatment place','class','U011',True),
+('AG07A -F','Mill and mix building','class','U011',True),
+('AG06B -E','Mixed market garden','class','U011',False),
+('AG08','Non cultivated places','class','U011',False),
+('AG06B -F','Nursery','class','U011',False),
+('AG06B -G','Orchard with arable land','class','U011',False),
+('AG06B -H','Orchard with grass','class','U011',False),
+('AG06B -I','Orchard with market garden','class','U011',False),
+('AG07A -G','Packing and sorting (crop processing place)','class','U011',True),
+('AG03D','Packing places (animal products)','class','U011',True),
+('AG02A -C','Parturition place','class','U011',True),
+('AG08A -A','Permanent pasture','class','U011',False),
+('AG03C-C','Processing place (animal slaughtering place)','class','U011',True),
+('AG06A -D','Pulse crops place','class','U011',False),
+('AG07A -D','Pulse crops store','class','U011',True),
+('AG01B -C','Quarantine place, animal','class','U011',True),
+('AG06A -E','Root crops place','class','U011',True),
+('AG07A -E','Root crops store','class','U011',True),
+('AG08A -B','Rough grazing','class','U011',False),
+('AG02A -D','Service pen','class','U011',False),
+('AG06B -J','Soft fruit place','class','U011',False),
+('AG07A -H','Vegetable (crop conditioning and storage)','class','U011',True),
+('AG06B -K','Vegetable field','class','U011',False),
+('AG01B -D','Veterinary hospital','class','U011',True),
+('AG01B -E','Veterinary surgery','class','U011',True),
+('AG02B -E','Weighing place','class','U011',True),
+('AG03B -A','Wool grading place','class','U011',True),
+('AG03B -B','Wool removal place','class','U011',True),
+('AG02A -A','Fish farm','class','U012',True),
+('AG04A','Fishery places','class','U012',True),
+('AG02A -B','Hatchery','class','U012',False),
+('AG04A -A','Net fishery place','class','U012',True),
+('AG04A -B','Pot and other inshore or estuarial fishing place','class','U012',True),
+('AG02B -D','Rearing pond','class','U012',False),
+('AG04A -C','Rod and line fishery place','class','U012',True),
+('AG04','Wild life capturing places','class','U012',True),
+('MA06A -A','Abrasives and other building materials manufacturing place','class','U101',True),
+('MA04E -A','Aerospace equipment manufacturing or repairing place','class','U101',True),
+('MA04A -A','Agricultural machinery manufacturing place','class','U101',True),
+('MA01B -A','Aluminium and aluminium alloy manufacturing','class','U101',True),
+('MA02A -A','Animal and poultry food manufacturing place','class','U101',True),
+('MA02A -B','Bacon curing, meat and fish product manufacturing place','class','U101',True),
+('MA07A -A','Bedding and soft furnishings manufacturing place','class','U101',True),
+('MA02A -C','Biscuit manufacturing','class','U101',True),
+('MA04F -D','Bolts, nuts, screws, rivets etc. manufacturing place','class','U101',True),
+('MA02A -D','Bread and flour confectionery manufacturing place','class','U101',True),
+('MA02A -E','Brewery','class','U101',True),
+('MA06A -B','Bricks, fireclay and refractory goods manufacturing place','class','U101',True),
+('MA06A','Bricks, pottery, glass, cement manufacturing places','class','U101',True),
+('MA04C-A','Broadcast receiving and sound reproducing equipment manufacturing','class','U101',True),
+('MA08A -A','Brushes and brooms manufacturing place','class','U101',True),
+('MA04F -A','Can and metal box manufacturing place','class','U101',True),
+('MA05A -A','Carpet manufacturing place','class','U101',True),
+('MA06A -C','Cement manufacturing place','class','U101',True),
+('MA03A','Chemical and allied industries manufacturing places','class','U101',True),
+('MA05C','Clothing and footwear manufacturing places','class','U101',True),
+('MA05','Clothing, textiles, leather, footwear and fur goods manufacturing places','class','U101',True),
+('MA01A','Coal and petroleum processing places','class','U101',True),
+('MA01','Coal, oil and metal processing places','class','U101',True),
+('MA02A -F','Cocoa, chocolate and sugar confectionery manufacturing place','class','U101',True),
+('MA01A -A','Coke ovens and solid fuel manufacturing place','class','U101',True),
+('MA09A -A','Construction and demolition site','class','U101',True),
+('MA04A -B','Construction and earth moving equipment manufacturing place','class','U101',True),
+('MA09','Construction places','class','U101',True),
+('MA09A','Construction places','class','U101',True),
+('MA01B -B','Copper, brass and other copper alloy manufacturing place','class','U101',True),
+('MA04F -B','Cutlery and plated tableware manufacturing place','class','U101',True),
+('MA05C-A','Dresses, lingerie, infants wear etc. manufacturing place','class','U101',True),
+('MA03A -A','Dyestuffs and pigments manufacturing place','class','U101',True),
+('MA04C-B','Electric appliances primarily for domestic use manufacturing places','class','U101',True),
+('MA04C','Electrical engineering places','class','U101',True),
+('MA04C-C','Electrical machinery manufacturing place','class','U101',True),
+('MA04C-D','Electronic computers manufacturing place','class','U101',True),
+('MA04','Engineering places','class','U101',True),
+('MA03A -B','Explosives and fireworks manufacturing place','class','U101',True),
+('MA03A -C','Fertilizer manufacturing place','class','U101',True),
+('MA02A','Food, drink and tobacco manufacturing place','class','U101',True),
+('MA05C-B','Footwear manufacturing place','class','U101',True),
+('MA02A -G','Fruit and vegetable product manufacturing place','class','U101',True),
+('MA05B -A','Fur goods manufacturing place','class','U101',True),
+('MA07A -B','Furniture and upholstery manufacturing place','class','U101',True),
+('MA03A -D','General chemical manufacturing place','class','U101',True),
+('MA06A -D','Glass manufacturing place','class','U101',True),
+('MA02A -H','Grain mill','class','U101',True),
+('MA05C-C','Hats, cap and millinery manufacturing place','class','U101',True),
+('MA05A -B','Hosiery and other knitted goods manufacturing place','class','U101',True),
+('MA10A -A','Industrial research laboratory','class','U101',True),
+('MA04A -C','Industrial services equipment manufacturing place','class','U101',True),
+('MA04B','Instrument engineering places','class','U101',True),
+('MA04C-E','Insulated wires and cables manufacturing place','class','U101',True),
+('MA01B -C','Iron and steel manufacturing place','class','U101',True),
+('MA04F -C','Jewellery and precious metal manufacturing place','class','U101',True),
+('MA05A -C','Jute manufacturing place','class','U101',True),
+('MA05A -B','Knitted goods manufacturing place','class','U101',True),
+('MA05A -D','Lace manufacturing place','class','U101',True),
+('MA01B -D','Lead manufacturing place','class','U101',True),
+('MA05B -C','Leather (tanning and dressing) and fellmongery place','class','U101',True),
+('MA05B','Leather and fur goods manufacturing places','class','U101',True),
+('MA05B -B','Leather goods manufacturing place','class','U101',True),
+('MA08A -B','Linoleum, plastics floor covering, leather cloth manufacturing place','class','U101',True),
+('MA04E -B','Locomotives and railway track equipment manufacturing place','class','U101',True),
+('MA01A -B','Lubricating oil and grease manufacturing place','class','U101',True),
+('MA05A -E','Made up textile manufacturing place','class','U101',True),
+('MA05A -F','Man made fibre production manufacturing place','class','U101',True),
+('MA10A','Manufacturing research establishments','class','U101',True),
+('MA12A -A','Manufacturing storage place','class','U101',True),
+('MA12A','Manufacturing storage places','class','U101',True),
+('MA11A','Manufacturing waste disposal places','class','U101',True),
+('MA11A -A','Manufacturing waste tip','class','U101',True),
+('MA04A','Mechanical engineering places','class','U101',True),
+('MA04A -D','Mechanical handling equipment manufacturing place','class','U101',True),
+('MA01B','Metal processing places (basic forms)','class','U101',True),
+('MA04A -E','Metal working machine tools manufacturing place','class','U101',True),
+('MA02A -I','Milk and milk product manufacturing place','class','U101',True),
+('MA01A -C','Mineral oil refinery','class','U101',True),
+('MA08A -C','Miscellaneous goods manufacturing place','class','U101',True),
+('MA08A -D','Miscellaneous stationers goods manufacturing place','class','U101',True),
+('MA07A -C','Miscellaneous wood and cork manufacturing place','class','U101',True),
+('MA04E -C','Motor cycle, tricycle and pedal cycle manufacturing place','class','U101',True),
+('MA04E -D','Motor vehicle manufacturing place','class','U101',True),
+('MA05A -G','Narrow fabric manufacturing place','class','U101',True),
+('MA04A -F','Office machinery manufacturing place','class','U101',True),
+('MA04A -G','Ordnance and small arms manufacturing place','class','U101',True),
+('MA05C-D','Overalls and men''s shirts and underwear manufacturing place','class','U101',True),
+('MA07B -B','Packaging products of paper and associated materials manufacturing place','class','U101',True),
+('MA03A -E','Paint manufacturing place','class','U101',True),
+('MA07B -C','Paper and board manufacturing place','class','U101',True),
+('MA07B','Paper, printing and publishing works','class','U101',True),
+('MA07B -D','Periodical and newspaper printing and publishing works','class','U101',True),
+('MA03A -F','Pharmaceutical chemicals and preparation manufacturing place','class','U101',True),
+('MA04B -A','Photographic and document copying equipment manufacturing place','class','U101',True),
+('MA06A -E','Pottery manufacturing place','class','U101',True),
+('MA04A -H','Prime movers manufacturing place','class','U101',True),
+('MA04A -I','Pumps, valves and compressor manufacturing place','class','U101',True),
+('MA04C-F','Radio and electronic capital goods manufacturing place','class','U101',True),
+('MA04C-G','Radio, radar and electronic capital goods manufacturing place','class','U101',True),
+('MA04E -E','Railway carriages and wagons and trams manufacturing place','class','U101',True),
+('MA05A -H','Rope, twine and net manufacturing place','class','U101',True),
+('MA08A -E','Rubber goods manufacturing place','class','U101',True),
+('MA04B -C','Scientific and industrial instruments and systems manufacturing','class','U101',True),
+('MA04D-A','Shipbuilding and marine engineering place','class','U101',True),
+('MA07A -D','Shop and office fittings manufacturing place','class','U101',True),
+('MA04F -E','Small tools, implements and gauges manufacturing place','class','U101',True),
+('MA03A -G','Soap, detergent and fat splitting and distillation manufacturing place','class','U101',True),
+('MA02A -J','Soft drinks manufacturing place','class','U101',True),
+('MA05A -I','Spinning and doubling (cotton and flax systems) manufacturing place','class','U101',True),
+('MA07B -A','Stationery manufacturing place','class','U101',True),
+('MA02A -K','Sugar refinery','class','U101',True),
+('MA04B -B','Surgical instruments and appliances manufacturing place','class','U101',True),
+('MA03A -H','Synthetic resins, plastics and synthetic rubber manufacturing place','class','U101',True),
+('MA05C-E','Tailored outerwear manufacturing place','class','U101',True),
+('MA04C-H','Telegraph and telephone apparatus and equipment manufacturing place','class','U101',True),
+('MA05A -J','Textile finishing place','class','U101',True),
+('MA04A -J','Textile machinery and accessories manufacturing place','class','U101',True),
+('MA05A','Textile manufacturing places','class','U101',True),
+('MA07A','Timber and furniture works','class','U101',True),
+('MA07','Timber furniture, paper, printing and publishing works','class','U101',True),
+('MA07A -E','Timber works','class','U101',True),
+('MA02A -L','Tobacco manufacturing place','class','U101',True),
+('MA03A -I','Toilet preparation manufacturing place','class','U101',True),
+('MA08A -F','Toys, games, children''s carriages and sports equipment manufacturing place','class','U101',True),
+('MA02A -M','Vegetable, animal oil and fat manufacturing place','class','U101',True),
+('MA04E','Vehicle engineering places','class','U101',True),
+('MA04B -D','Watches and clocks manufacturing place','class','U101',True),
+('MA05C-F','Weatherproof outerwear manufacturing place','class','U101',True),
+('MA05A -K','Weaving of cotton, linen and man made fibres manufacturing place','class','U101',True),
+('MA04E -F','Wheeled tractor manufacturing place','class','U101',True),
+('MA04F -F','Wire manufacturing place','class','U101',True),
+('MA07A -F','Wooden containers and baskets manufacturing place','class','U101',True),
+('MA05A -L','Woollen and worsted manufacturing place','class','U101',True),
+('OF03A -A','Business discussion places','class','U102',True),
+('OF03A','Business meeting places','class','U102',True),
+('OF03','Business meeting places','class','U102',True),
+('OF01A -A','Central government administration office','class','U102',True),
+('OF01A','General offices','class','U102',True),
+('OF01A -B','Local government administration office','class','U102',True),
+('OF01A -C','Manufacturing administration office','class','U102',True),
+('OF','Offices','class','U102',True),
+('OF01A -D','Professional services office','class','U102',True),
+('OF04A -A','Studio','class','U102',True),
+('ST01A -A','Agricultural machinery store','class','U103',True),
+('ST02A -A','Builders yard','class','U103',True),
+('ST01A -B','Building equipment store','class','U103',True),
+('ST02A','Bulk material stores','class','U103',True),
+('ST02A -B','Cleaning materials store','class','U103',True),
+('ST01A -C','Engineering equipment store','class','U103',True),
+('ST01A','Equipment stores','class','U103',True),
+('ST03A -A','Furniture depository','class','U103',True),
+('ST03A -B','General goods store','class','U103',True),
+('ST01A -D','Industrial and office machinery store','class','U103',True),
+('ST02','Material stores','class','U103',True),
+('ST03A -C','Refrigerated store','class','U103',True),
+('ST01A -E','Sports equipment store','class','U103',True),
+('ST','Storage','class','U103',True),
+('WH01B -A','Agricultural machinery dealer’s place','class','U104',True),
+('WH01A -C','Builders merchant''s place','class','U104',True),
+('WH01A','Bulk dealing places','class','U104',True),
+('WH01A -A','Coal and oil dealer''s place','class','U104',True),
+('WH01A -B','Corn, seed and agricultural supplies dealer''s place','class','U104',True),
+('WH01','Dealing in industrial materials, machinery and livestock places','class','U104',True),
+('WH02A','Food and drink wholesaling places','class','U104',True),
+('WH02A -A','Grocery and provisions confectionery and drinks wholesaling','class','U104',True),
+('WH01B -B','Hides, skin and leather dealer''s place','class','U104',True),
+('WH01C-A','Horses and livestock dealer','class','U104',True),
+('WH01C','Horses and livestock dealing places','class','U104',True),
+('WH01B','Industrial materials and other machinery dealing places','class','U104',True),
+('WH02B -A','Petroleum products wholesaling place','class','U104',True),
+('WH01B -C','Scrap and waste dealer','class','U104',True),
+('WH01B -D','Timber dealer''s place','class','U104',True),
+('WH02','Wholesale distribution places','class','U104',True),
+('UL02A','Unused buildings','class','U111',True),
+('UL01B','Unused formerly developed land','class','U111',False),
+('UL01B -A','Cleared site','class','U111',True),
+('UL01B -C','Protected land (unused)','class','U111',True),
+('UL02A -B','Vacant building','class','U111',True),
+('UL02A -A','Abandoned building','class','U112',True),
+('UL01B -B','Mineral excavation or pit (dry)','class','U112',True),
+('UL02A -A','Ruined building','class','U112',True),
+('UL01B -D','Spoilt land','class','U112',True),
+('UL01B -E','Waste heap or tip','class','U112',True),
+('DF01','Defence establishments','class','U121',True),
+('DF01A','Defence training places','class','U121',True),
+('DF01A -A','Live firing military training area','class','U121',True),
+('UL01A -A','Beach or sand dune','class','U131',False),
+('UL01C-A','Canal (unused)','class','U131',False),
+('UL01A -B','Cliff or natural outcrop','class','U131',False),
+('UL01C-B','Dock (unused)','class','U131',False),
+('UL01A -C','Grass land','class','U131',False),
+('UL01A -D','Heath and moorland','class','U131',False),
+('UL01C-C','Mineral excavation or pit (wet)','class','U131',False),
+('UL01A -E','Peat, bog, freshwater marsh and swamp','class','U131',False),
+('UL01C-D','Pond or lake','class','U131',False),
+('UL01A -F','Salt marsh (unused)','class','U131',False),
+('UL01','Unused land and water','class','U131',False),
+('UL01A','Unused land in natural or semi natural state','class','U131',False),
+('UL01C','Unused water','class','U131',False),
+('UL01C-E','Water course','class','U131',False),
+('UL01A -G','Woodland and scrub','class','U131',False),
+('AG08B -A','Coniferous forest','class','U022',False),
+('AG08B -D','Deciduous forest','class','U022',False),
+('AG08B','Forestry places','class','U022',False),
+('AG08B -E','Mixed forest','class','U022',False),
+('AG08B -B','Coppice','class','U021',False),
+('AG08B -C','Coppice with standards','class','U021',False),
+('AG08B -F','Tree nursery','class','U021',False),
+('MI01D-A','Aggregate and stone handling installation','class','U031',True),
+('MI01A -A','Chalk working','class','U031',False),
+('MI01A -B','China clay working','class','U031',False),
+('MI01C-A','China clay waste tip and settlement lagoon','class','U031',False),
+('MI01A -C','Clay and shale working','class','U031',False),
+('MI01A -D','Coal mine working','class','U031',False),
+('MI01D-B','Coal handling installation','class','U031',True),
+('MI01C-B','Coal waste tip and settlement lagoon','class','U031',False),
+('MI01B -A','Colliery headgear','class','U031',True),
+('MI01A -E','Gypsum/Anhydrite working','class','U031',False),
+('MI01A -F','Igneous rock working','class','U031',False),
+('MI01D-C','Iron ore handling installation','class','U031',True),
+('MI01A -G','Limestone working','class','U031',True),
+('MI01','Mineral extraction places','class','U031',False),
+('MI01D-E','Mineral fertiliser handling installation','class','U031',True),
+('MI01D-D','Non ferrous ore handling installation','class','U031',True),
+('MI01D-F','Oil and gas handling installation','class','U031',True),
+('MI01B -B','Oil and gas well head','class','U031',True),
+('MI01B -C','Salt and brine pumping installation','class','U031',True),
+('MI01A -H','Sand and gravel working','class','U031',False),
+('MI01A -I','Sandstone working','class','U031',False),
+('MI01A -K','Silica and moulding sand working','class','U031',False),
+('MI01A -L','Slate working','class','U031',False),
+('MI01C-C','Slate waste tip','class','U031',False),
+('MI01B','Surface installations for underground mineral workings','class','U031',True),
+('MI01A','Surface mineral workings','class','U031',False),
+('MI01A -M','Vein mineral working','class','U031',False),
+('MI01C-D','Vein mineral waste tip and settlement lagoon','class','U031',False),
+('MI01C','Waste disposal areas from mineral working and processing','class','U031',False),
+('LE01','Amenity, amusement and show places','class','#N/A',True),
+('LE','Recreation and leisure places','class','#N/A',True),
+('LE01B -A','Ancient monument','class','U041',True),
+('LE01A -A','Botanical garden','class','U041',False),
+('LE01A -B','Country park','class','U041',False),
+('LE01A -C','Gardens','class','U041',False),
+('LE01B -B','Monument','class','U041',True),
+('LE01A','Outdoor amenity places','class','U041',False),
+('LE01A -D','Park','class','U041',False),
+('LE01A -E','Picnic site','class','U041',False),
+('LE01A -F','Recreational open space','class','U041',False),
+('LE01A -G','View point','class','U041',False),
+('LE01A -A','Zoological garden','class','U041',False),
+('LE01C','Amusement places','class','U042',True),
+('LE01C-A','Aquarium','class','U042',True),
+('LE01C-C','Bingo club','class','U042',True),
+('LE01D-A','Broadcasting, filming and sound recording studio','class','U042',True),
+('LE01C-D','Children''s playground','class','U042',False),
+('LE01D-B','Cinema','class','U042',True),
+('LE01D-C','Circus','class','U042',True),
+('LE01D-D','Concert arena','class','U042',True),
+('LE01D-E','Countryside interpretation centre','class','U042',True),
+('LE01C-E','Dance hall','class','U042',True),
+('LE01D-F','Display arena','class','U042',True),
+('LE01C-F','Fun fair','class','U042',True),
+('LE01C-G','Gaming club','class','U042',True),
+('LE01C-H','Night club','class','U042',True),
+('LE01D','Show places','class','U042',True),
+('LE01D-G','Theatre','class','U042',True),
+('LE02C-A','Art gallery','class','U043',True),
+('LE02C','Galleries','class','U043',True),
+('LE02A -A','Lending library','class','U043',True),
+('LE02A','Libraries','class','U043',True),
+('LE02','Libraries, museums and galleries','class','U043',True),
+('LE02B -A','Museum','class','U043',True),
+('LE02A -B','Reference','class','U043',True),
+('LE03 I','Animal training and competing places','class','U044',True),
+('LE03G-A','Archery range','class','U044',True),
+('LE03A -A','Association football ground','class','U044',True),
+('LE03E','Athletic game courses','class','U044',True),
+('LE03D','Athletic games arenas','class','U044',True),
+('LE03D-A','Athletic ground','class','U044',True),
+('LE03B -A','Badminton court','class','U044',True),
+('LE03C','Ball game courses','class','U044',True),
+('LE03B','Ball game greens and courts','class','U044',True),
+('LE03A','Ball game pitches and grounds','class','U044',True),
+('LE03A -B','Baseball ground','class','U044',True),
+('LE04B -A','Boating facilities','class','U044',True),
+('LE03E -A','Bobsleigh course','class','U044',True),
+('LE03B -B','Bowling green','class','U044',False),
+('LE04B -B','Canoeing water','class','U044',False),
+('LE03F -A','Caving place','class','U044',True),
+('LE03F','Climbing, rambling and caving places','class','U044',False),
+('LE03D-B','Combative sports place','class','U044',True),
+('LE03A -C','Cricket ground','class','U044',False),
+('LE03B -C','Croquet lawn','class','U044',False),
+('LE03 I -A','Cross country horse trial course','class','U044',False),
+('LE03E -B','Cross country running course','class','U044',False),
+('LE03H-A','Cycling circuit','class','U044',True),
+('LE03 I -B','Dog racing track','class','U044',True),
+('LE03 I -C','Dog trials area','class','U044',True),
+('LE03C-B','Golf course','class','U044',False),
+('LE03C-A','Golf driving range','class','U044',False),
+('LE03D-C','Gymnasium','class','U044',True),
+('LE03A -D','Hockey ground','class','U044',True),
+('LE03 I -D','Horse racing course','class','U044',True),
+('LE03 I -E','Horse show jumping, dressage and trotting arena','class','U044',False),
+('LE03 I -F','Horse training area','class','U044',True),
+('LE03J -A','Hunting place','class','U044',False),
+('LE03J','Hunting and shooting places','class','U044',True),
+('LE03A -E','Hurling or shinty grounds','class','U044',True),
+('LE03D-D','Ice rink','class','U044',True),
+('LE03A -F','Lacrosse ground','class','U044',True),
+('LE03H-B','Land sailing area','class','U044',False),
+('LE03','Land sport places','class','U044',False),
+('LE03H','Land vehicle performance places','class','U044',False),
+('LE03B -D','Miniature golf course','class','U044',True),
+('LE03H-C','Motor vehicle racing track','class','U044',False),
+('LE03A -G','Polo ground','class','U044',True),
+('LE04B -C','Power craft water','class','U044',False),
+('LE03F -B','Rambling and fell walking','class','U044',False),
+('LE03E -C','Road running and walking course','class','U044',False),
+('LE03F -C','Rock climbing','class','U044',True),
+('LE04C-A','Rod/recreational fishing place','class','U044',False),
+('LE03D-E','Roller skating rink','class','U044',True),
+('LE04B -D','Rowing water','class','U044',False),
+('LE03A -H','Rugby football ground','class','U044',False),
+('LE04B -E','Sailing','class','U044',True),
+('LE03J -B','Shooting and stalking area','class','U044',False),
+('LE03E -D','Skiing and tobogganing run','class','U044',False),
+('LE03G-B','Small arms range','class','U044',False),
+('LE03B -E','Squash court','class','U044',True),
+('LE04A','Swimming and bathing','class','U044',True),
+('LE04A -A','Swimming baths','class','U044',True),
+('LE03G','Target shooting places','class','U044',True),
+('LE03B -G','Ten pin bowling alley','class','U044',True),
+('LE03B -F','Tennis court','class','U044',True),
+('LE04C','Water recreation places','class','U044',True),
+('LE04B -F','Water skiing place','class','U044',False),
+('LE04','Water sport places','class','U044',False),
+('LE04B','Watercraft places','class','U044',True),
+('LE05A -A','Camping site','class','U045',False),
+('LE05A -B','Holiday camp site','class','U045',False),
+('LE05A','Holiday camps','class','U045',True),
+('LE05A -C','Holiday caravan site','class','U045',False),
+('LE05A -D','Youth hostel','class','U045',True),
+('AG06B -A','Allotment gardens','class','U046',False),
+('TR02C','Storage places for vehicles','class','U051',True),
+('TR','Transport tracks and places','class','U051',True),
+('TR01E -A','Access road','class','U051',False),
+('TR01E -B','All purpose road','class','U051',False),
+('TR01F -A','Branch line','class','U051',False),
+('TR01C-A','Bridleway','class','U051',False),
+('TR01D-A','Bus only way','class','U051',False),
+('TR01D-B','Bus way','class','U051',False),
+('TR01B -A','Cycle track','class','U051',False),
+('TR01C-B','Drovers way','class','U051',False),
+('TR01A -A','Footpath','class','U051',False),
+('TR01','Land transport tracks','class','U051',False),
+('TR01F -B','Light railway','class','U051',False),
+('TR01E -C','Local distributor road','class','U051',False),
+('TR01F -C','Main line','class','U051',False),
+('TR01F -D','Mineral line','class','U051',False),
+('TR01E -E','Motor vehicle practice circuit','class','U051',False),
+('TR01E -D','Motor vehicle testing circuit','class','U051',False),
+('TR01E -F','Motorway (special road)','class','U051',False),
+('TR01C-C','Pony trekking route','class','U051',False),
+('TR01A -B','Precinct','class','U051',False),
+('TR01E -G','Primary distributor road','class','U051',False),
+('TR01E -H','Processional route (road)','class','U051',False),
+('TR01A -C','Processional route (walking or marching)','class','U051',False),
+('TR01F','Railways','class','U051',False),
+('TR01C-D','Ride','class','U051',False),
+('TR01E','Roads','class','U051',False),
+('TR01E -I','Secondary distributor road','class','U051',False),
+('TR01F -E','Tramway','class','U051',False),
+('TR01F -F','Underground line','class','U051',False),
+('TR01A -D','Walkway','class','U051',False),
+('TR02A -A','Aerial ropeway passenger terminal','class','U051',True),
+('TR02A -B','Air passenger terminal','class','U051',True),
+('TR02A -C','Airport','class','U051',True),
+('TR02A -D','Bus station','class','U051',True),
+('TR02A -E','Bus stop','class','U051',True),
+('TR02A -F','Car park','class','U051',True),
+('TR02A -G','Coach station','class','U051',True),
+('TR02','Land transport places','class','U051',True),
+('TR02A -H','Railway station','class','U051',True),
+('TR02A -I','Ship passenger terminal','class','U051',True),
+('TR02A','Terminals and interchanges for people','class','U051',True),
+('TR02C-C','Car storage place','class','U053',True),
+('TR02C-A','Aircraft hangar','class','U051',True),
+('TR02C-B','Bus depot','class','U051',True),
+('TR02C-D','Coach depot','class','U051',True),
+('TR02C-E','Long stay lorry park','class','U051',True),
+('TR02C-F','Railway sidings','class','U051',False),
+('TR05A -A','Aerial ropeway','class','U055',False),
+('TR02B -A','Air freight terminal','class','U055',True),
+('TR02B -B','Container depot','class','U055',True),
+('TR05A -B','Conveyor','class','U055',False),
+('TR06A -A','Customs depot','class','U055',True),
+('TR02B -C','Docks','class','U055',True),
+('TR06','Goods handling places','class','U055',True),
+('TR05A -C','Lift','class','U055',True),
+('TR02B -D','Lorry transhipment park','class','U055',False),
+('TR05A','Mechanical handling places','class','U055',True),
+('TR02B -E','Railway goods siding','class','U055',False),
+('TR02B -F','Railway goods yard','class','U055',False),
+('TR02B -G','Railway sorting depot','class','U055',True),
+('TR02B','Terminals and interchanges for goods','class','U055',True),
+('TR04A -A','Anchorage','class','U056',False),
+('TR04A -B','Boatyard','class','U056',False),
+('TR03A -A','Canal','class','U056',False),
+('TR04A -C','Marina','class','U056',False),
+('TR04A -D','Mooring','class','U056',False),
+('TR03A -B','River','class','U056',False),
+('TR04A','Storage places for water craft','class','U056',True),
+('TR03A','Water tracks','class','U056',False),
+('TR04','Water transport places','class','U056',False),
+('TR03','Water transport tracks','class','U056',False),
+('UT','Utility services','class','#N/A',False),
+('UT06A','District heating places','class','U061',True),
+('UT06A -A','District heating plant','class','U061',True),
+('UT02B -A','Electricity cableway','class','U061',True),
+('UT02B','Electricity distribution places','class','U061',True),
+('UT02A','Electricity production places','class','U061',True),
+('UT02','Electricity supply places','class','U061',True),
+('UT02B -B','Electricity transformer station','class','U061',True),
+('UT01B','Gas distribution places','class','U061',True),
+('UT01A -A','Gas holder','class','U061',True),
+('UT01B -A','Gas pressure control station','class','U061',True),
+('UT01A','Gas production and storage places','class','U061',True),
+('UT01','Gas supply places','class','U061',True),
+('UT01A -B','Gas works','class','U061',True),
+('UT02A -A','Hydro electricity generating station','class','U061',True),
+('TR05B -A','Oil pumping station','class','U061',True),
+('TR05B -B','Pipeline','class','U061',False),
+('UT02A -B','Thermal electricity generating station','class','U061',True),
+('UT04A -A','Main drain','class','U062',False),
+('UT03A -A','Reservoir','class','U062',False),
+('UT04','Sewage disposal places','class','U062',True),
+('UT04A','Sewage draining places','class','U062',True),
+('UT04B -A','Sewage farm','class','U062',True),
+('UT04A -B','Sewage pumping station','class','U062',True),
+('UT04B','Sewage treatment places','class','U062',True),
+('UT04B -B','Sewage treatment works','class','U062',True),
+('UT03B','Water distribution places','class','U062',True),
+('UT03C','Water extraction places','class','U062',True),
+('UT03C-B','Water intake from rivers or streams','class','U062',True),
+('UT03C-A','Water intake from springs','class','U062',True),
+('UT03C-C','Water intake from underground sources','class','U062',True),
+('UT03B -B','Water pipeline','class','U062',True),
+('UT03B -A','Water pumping station','class','U062',True),
+('UT03A','Water storage and treatment places','class','U062',True),
+('UT03','Water supply places','class','U062',True),
+('UT03A -B','Water tower','class','U062',True),
+('UT03A -C','Water treatment works','class','U062',True),
+('UT05A','Refuse disposal places','class','U063',False),
+('UT05','Refuse disposal places','class','U063',False),
+('UT05A -A','Refuse disposal plant','class','U063',False),
+('UT05A -B','Refuse tip','class','U063',False),
+('UT07B -A','Cemetery','class','U064',False),
+('UT07A -A','Chapel of rest','class','U064',True),
+('UT07B -B','Crematorium','class','U064',True),
+('UT07B','Dead bodies disposal places','class','U064',True),
+('UT07A','Dead bodies storage places','class','U064',True),
+('UT07A -B','Mortuary','class','U064',True),
+('UT08F','Direction finding places','class','U065',True),
+('UT08F -B','Direction finding transmitter','class','U065',True),
+('UT08F -A','Navigational light beacon','class','U065',False),
+('UT08A','Postal service places','class','U065',True),
+('UT08','Postal service, signalling and telecommunications places','class','U065',True),
+('UT08A -A','Postal sorting depot','class','U065',True),
+('UT08C-A','Radar beacon','class','U065',False),
+('UT08C','Radar places','class','U065',True),
+('UT08C-B','Radar station','class','U065',True),
+('UT08D-B','Radio and television mast','class','U065',False),
+('UT08D-A','Radio station','class','U065',True),
+('UT08E -A','Satellite communication station','class','U065',True),
+('UT08F -C','Signalling station','class','U065',True),
+('UT08B -A','Telephone cableway','class','U065',False),
+('UT08B -B','Telephone exchange','class','U065',True),
+('UT08B -C','Telephone kiosk','class','U065',True),
+('UT08D','Television and radio broadcasting places','class','U065',True),
+('UT08D-C','Television station','class','U065',True),
+('RS','Residences','class','#N/A',False),
+('RS02A -A','Building converted to more than one dwelling','class','U071',True),
+('RS02A -B','Bungalow','class','U071',True),
+('RS02A -C','Detached house','class','U071',True),
+('RS02A','Dwellings','class','U071',True),
+('RS02A -D','Maisonette','class','U071',True),
+('RS01C-A','Movable dwelling site','class','U071',False),
+('RS02A -E','Non residential plus single dwelling','class','U071',True),
+('RS02A -F','Purpose built block of flats','class','U071',True),
+('RS01C-B','Residential caravan site','class','U071',False),
+('RS02','Self contained residences','class','U071',True),
+('RS02A -G','Semi detached house','class','U071',True),
+('RS02A -H','Terraced house','class','U071',True),
+('RS01A -A','Boarding house','class','U072',True),
+('RS01','Group residences','class','U072',True),
+('RS01A -B','Hotel','class','U072',True),
+('RS01A -C','Residential club','class','U072',True),
+('RS01A -D','Rooming house','class','U072',True),
+('RS01B -A','Barracks','class','U073',True),
+('CM04A -A','Children''s home','class','U073',True),
+('RS01B','Communal homes','class','U073',True),
+('CM04A -B','Handicapped and disabled people''s home','class','U073',True),
+('CM04','Non medical care places','class','U073',True),
+('CM04A','Non medical homes','class','U073',True),
+('CM04A -C','Old people''s home','class','U073',True),
+('RS01B -B','Residential retreat','class','U073',True),
+('RS01B -C','School boarding house','class','U073',True),
+('RS01B -D','Staff hostel','class','U073',True),
+('CM','Community and health services','class','#N/A',False),
+('CM01B -A','Ambulance station','class','U081',True),
+('CM01A -A','Ante natal and post natal clinic','class','U081',True),
+('CM01C-A','Artificial limb and appliance hospital','class','U081',True),
+('CM01B','Auxiliary service centres medical','class','U081',True),
+('CM01B -B','Blood transfusion centre','class','U081',True),
+('CM01D-A','Convalescent home','class','U081',True),
+('CM04B -A','Counselling agency','class','U081',True),
+('CM04B','Counselling places','class','U081',True),
+('CM01C-B','Dental hospital','class','U081',True),
+('CM01A -B','Dentist''s surgery and consulting room','class','U081',True),
+('CM01A -C','Dispensary','class','U081',True),
+('CM01A -D','Doctor''s surgery and consulting room','class','U081',True),
+('CM01C-C','Ear, nose and throat hospital','class','U081',True),
+('CM01C-D','Eye hospital','class','U081',True),
+('CM01A -E','Eye clinic and optician''s surgery and consulting room','class','U081',True),
+('CM01B -C','Family planning clinic','class','U081',True),
+('CM01A -F','Foot clinic and chiropodist''s surgery and consulting room','class','U081',True),
+('CM01B -D','Forensic medicine centre','class','U081',True),
+('CM01C-E','General hospital','class','U081',True),
+('CM01C-F','Geriatric hospital','class','U081',True),
+('CM01','Health care places','class','U081',True),
+('CM01A -G','Health centre','class','U081',True),
+('CM01A -H','Hearing aid centre','class','U081',True),
+('CM01C','Hospitals','class','U081',True),
+('CM01C-G','Isolation hospital','class','U081',True),
+('CM01C-H','Maternity hospital','class','U081',True),
+('CM01B','Medical auxiliary service centres','class','U081',True),
+('CM01A','Medical diagnosis and treatment centres','class','U081',True),
+('CM02A','Medical research establishments','class','U081',True),
+('CM02A -A','Medical research laboratory','class','U081',True),
+('CM01C-I','Mental hospital','class','U081',True),
+('CM01A -I','Mental clinic','class','U081',True),
+('CM01A -J','Nervous disorders clinic','class','U081',True),
+('CM01A -K','Occupational therapy and physiotherapy clinic','class','U081',True),
+('CM01C-J','Orthopaedic hosdpital','class','U081',True),
+('CM01A -L','Orthopaedic and rheumatic clinic','class','U081',True),
+('CM01B -E','Radiography centre','class','U081',True),
+('CM01A -M','Surgeon''s surgery and consulting room','class','U081',True),
+('CM07A','Places of worship','class','U082',True),
+('ED01F -A','Adult education centre','class','U083',True),
+('ED02A -A','Archaeological site','class','U083',False),
+('ED01F -B','College of further education','class','U083',True),
+('ED01F -C','College of technology','class','U083',True),
+('ED01A -A','Day nursery school','class','U083',True),
+('ED01','Education places','class','U083',True),
+('ED01B -A','Infant school','class','U083',True),
+('ED01B -B','Junior school','class','U083',True),
+('ED01C-A','Middle school','class','U083',True),
+('ED02B -A','Nature reserve','class','U083',False),
+('ED02B','Nature reserves and sanctuaries','class','U083',False),
+('ED01A -B','Nursery school','class','U083',True),
+('ED02A -B','Observatory','class','U083',True),
+('ED01F -D','Polytechnic','class','U083',True),
+('ED01A','Pre primary schools','class','U083',True),
+('ED01B','Primary schools','class','U083',True),
+('ED02A','Research establishments','class','U083',True),
+('ED02','Research places','class','U083',True),
+('ED01D-A','Secondary school','class','U083',True),
+('ED01D','Secondary schools','class','U083',True),
+('ED02B -B','Site of special scientific interest','class','U083',False),
+('ED01D-B','Sixth form college','class','U083',True),
+('ED01E -A','Special school','class','U083',True),
+('ED01F','Specialised, higher and further education centres','class','U083',True),
+('ED01F -E','Teacher training college','class','U083',True),
+('ED01F -F','Technical college','class','U083',True),
+('ED01F -G','University teaching establishment','class','U083',True),
+('CM06A -A','Advertising hoarding','class','U084',False),
+('CM06A','Advertising places','class','U084',False),
+('CM05A -A','Approved school','class','U084',True),
+('CM08A -A','Arbitration court','class','U084',True),
+('CM05A -B','Borstal institution','class','U084',True),
+('CM06B -A','Church hall','class','U084',True),
+('CM05B -A','Civil Defence centre','class','U084',True),
+('CM06B -B','Club meeting place','class','U084',True),
+('CM05B -B','Coastguard station','class','U084',True),
+('CM06','Communication places','class','U084',True),
+('CM06B -C','Community centre','class','U084',True),
+('CM05','Community protection services','class','U084',True),
+('CM08A','Courts','class','U084',True),
+('CM05A','Detention places','class','U084',True),
+('CM05B -C','Fire station','class','U084',True),
+('CM08','Justice administration places','class','U084',True),
+('CM08A -B','Law court','class','U084',True),
+('CM05B -E','Life boat station','class','U084',True),
+('CM07A -A','Place of worship','class','U084',True),
+('CM05B -D','Police station','class','U084',True),
+('CM05A -C','Prison','class','U084',True),
+('CM05A -D','Prison rehabilitation centre','class','U084',True),
+('CM05B','Protection places','class','U084',True),
+('CM03A -A','Public bath','class','U084',True),
+('CM03A -B','Public convenience','class','U084',True),
+('CM05A -E','Remand centre','class','U084',True),
+('CM05A -F','Remand classifying centre','class','U084',True),
+('CM05A -G','Remand home','class','U084',True),
+('CM03','Sanitation places','class','U084',True),
+('CM03A','Sanitation places','class','U084',True),
+('CM06B','Social meeting places','class','U084',True),
+('CM08A -C','Tribunal place','class','U084',True),
+('RT03','Catering service places','class','U093',True),
+('RT01','Retail distribution places','class','U091',True),
+('RT','Retail distribution and servicing places','class','U091',True),
+('RT01A -A','Baker’s shop','class','U091',True),
+('RT01B -A','Beauty salon','class','U091',True),
+('RT02B -A','Boot and shoe repair establishment','class','U091',True),
+('RT01A -B','Butcher''s shop','class','U091',True),
+('RT01D-A','Caravan sales place','class','U091',True),
+('RT01F -A','Cash and carry store','class','U091',True),
+('RT01A -C','Cats meat shop','class','U091',True),
+('RT01B -C','Clothing and footwear shop','class','U091',True),
+('RT01B -B','Confectionery, tobacco and newspaper shop','class','U091',True),
+('RT01A -D','Dairy shop','class','U091',True),
+('RT01F -B','Department store','class','U091',True),
+('RT02B -B','Dry cleaning and clothing repair establishment','class','U091',True),
+('RT01B -D','Duplicating and copying centre','class','U091',True),
+('RT01C-A','Electricity showroom','class','U091',True),
+('RT01A -E','Fish shop','class','U091',True),
+('RT01A','Food and drink shops','class','U091',True),
+('RT01A -F','Fried fish shop','class','U091',True),
+('RT01A -G','Frozen food shop','class','U091',True),
+('RT01C-B','Gas showroom','class','U091',True),
+('RT01B -E','General stores','class','U091',True),
+('RT01A -H','Green grocer''s shop','class','U091',True),
+('RT01A -I','Grocery and provision','class','U091',True),
+('RT01B -F','Hairdresser''s shop','class','U091',True),
+('RT01A -J','Hot food shop','class','U091',True),
+('RT01C-C','Household goods shop','class','U091',True),
+('RT01C','Household goods shops and showrooms','class','U091',True),
+('RT01F','Hybrid shops and stores','class','U091',True),
+('RT01F -C','Hypermarket','class','U091',True),
+('RT02B -C','Launderette','class','U091',True),
+('RT02B -D','Laundry (cleaning only)','class','U091',True),
+('RT01B -G','Laundry, cleaning and repairing shop (receiving)','class','U091',True),
+('RT02','Maintenance and repair places','class','U091',True),
+('RT01D-C','Motor vehicle dealer display area','class','U091',True),
+('RT01D','Motor vehicle goods shops and filling stations','class','U091',True),
+('RT02A','Motor vehicle maintenance and repair places','class','U091',True),
+('RT02A -A','Motor vehicle repair garage','class','U091',True),
+('RT01D-D','Motor vehicle sales','class','U091',True),
+('RT01D-B','Motor vehicle spare parts and accessories','class','U091',True),
+('RT02A -B','Motor vehicle testing station','class','U091',True),
+('RT01A -K','Off licence','class','U091',True),
+('RT02B','Personal and household goods repair and cleaning places','class','U091',True),
+('RT01B -H','Pet animal and bird shop','class','U091',True),
+('RT01D-E','Petrol and oil filling station','class','U091',True),
+('RT01B -I','Photographic service shop','class','U091',True),
+('RT01B -J','Post office','class','U091',True),
+('RT01E -A','Retail market place','class','U091',True),
+('RT01F -D','Supermarket','class','U091',True),
+('RT01B -K','Ticket agency','class','U091',True),
+('RT01B -L','Travel agency','class','U091',True),
+('RT01A -L','Tripe shop','class','U091',True),
+('RT01D-F','Tyre retailing and fitting place','class','U091',True),
+('RT01B -M','Undertaker','class','U091',True),
+('OF02A -A','Bank','class','U092',True),
+('LE01C-B','Betting office','class','U092',True),
+('OF02A -B','Building society office','class','U092',True),
+('OF02A','Financial service offices','class','U092',True),
+('OF02A -C','Insurance office','class','U092',True),
+('RT03B','Catering places','class','U093',True),
+('RT03B -A','Restaurant','class','U093',True),
+('RT03A -A','Public house','class','U094',True);
diff --git a/migrations/0xx.landuse.down.sql b/migrations/0xx.landuse.down.sql
new file mode 100644
index 00000000..f7bc3f0b
--- /dev/null
+++ b/migrations/0xx.landuse.down.sql
@@ -0,0 +1,30 @@
+--Landuse is hierachical. Highest level is Order (ie. Residential) then Group (ie Residential-Dwelling) then Class (ie Residential-Dwelling-Detached house)
+--Interface will collected most detailed (class) but visualise highest level (order)
+--Landuse is a table as #358
+--Land use class, group and order will be stored in a new table
+DROP TABLE IF EXISTS reference_tables.buildings_landuse_order CASCADE;
+DROP TABLE IF EXISTS reference_tables.buildings_landuse_group CASCADE;
+DROP TABLE IF EXISTS reference_tables.buildings_landuse_class CASCADE;
+
+-- Land use class or classes, array object, client constrained.
+ALTER TABLE buildings DROP COLUMN IF EXISTS current_landuse_class;
+
+ALTER TABLE buildings DROP COLUMN IF EXISTS current_landuse_group;
+
+-- Land use order, singular. Client and db constrained.
+ALTER TABLE buildings DROP COLUMN IF EXISTS current_landuse_order;
+
+
+
+--===========================================
+--
+-- We also collect original landuse, structure & process is as current land use
+-- We don't currently collect intermediate historic uses
+--
+--===========================================
+
+-- Original Land use class or classes, array object, client constrained.
+ALTER TABLE buildings DROP COLUMN IF EXISTS original_landuse_class;
+
+-- Land use order, singular. Client and db constrained.
+ALTER TABLE buildings DROP COLUMN IF EXISTS original_landuse_order;
diff --git a/migrations/0xx.landuse.up.sql b/migrations/0xx.landuse.up.sql
new file mode 100644
index 00000000..f182f9b6
--- /dev/null
+++ b/migrations/0xx.landuse.up.sql
@@ -0,0 +1,58 @@
+-- Create land use and fields
+--Landuse is hierachical. Highest level is Order (Residential) then Group (Residential-Dwelling) then Class (Residential-Dwelling-Detached house)
+--Some ETL work required to get this together refer to analysis repo
+--Prerequesite is to have first run bulk_data_sources migrations
+ --Then create table landuse_order for the app, this is used as foreign key for current and original landuse_order
+
+CREATE TABLE IF NOT EXISTS reference_tables.buildings_landuse_order AS
+SELECT a.landuse_id,
+ a.description
+FROM reference_tables.landuse_classifications a
+WHERE a.level = 'order'
+ AND a.is_used;
+
+ALTER TABLE reference_tables.buildings_landuse_order
+ADD UNIQUE (description);
+
+
+CREATE TABLE IF NOT EXISTS reference_tables.buildings_landuse_group AS
+SELECT a.landuse_id,
+ a.description,
+ a.parent_id AS parent_order_id
+FROM reference_tables.landuse_classifications a
+WHERE a.level = 'group'
+ AND a.is_used;
+
+ALTER TABLE reference_tables.buildings_landuse_group
+ADD UNIQUE (description);
+
+
+--the below is for front end reference, not current used as a constraint
+CREATE TABLE IF NOT EXISTS reference_tables.buildings_landuse_class AS
+SELECT a.landuse_id,
+ a.description,
+ a.parent_id AS parent_group_id
+FROM reference_tables.landuse_classifications a
+WHERE a.level = 'class'
+ AND a.is_used;
+
+--Landuse is hierachical. Highest level is Order (Residential) then Group (Residential-Dwelling) then Class (Residential-Dwelling-Detached house)
+--Interface will collected most detailed (class) but visualise highest level (order)
+--Landuse is a table as #358
+--Prerequisite run bulk_sources migration first
+ -- Land use is table with 3 levels of hierachy (highest to lowest). order > group > class
+
+
+-- Land use order, singular. Client and db constrained with foreign key
+ALTER TABLE buildings
+ ADD COLUMN IF NOT EXISTS current_landuse_order text,
+ ADD FOREIGN KEY (current_landuse_order)
+ REFERENCES reference_tables.buildings_landuse_order (description);
+
+
+-- Land use groups, array. Derived from classes.
+ALTER TABLE buildings ADD COLUMN IF NOT EXISTS current_landuse_group text ARRAY[41];
+
+ -- Land use class or classes, array object, client constrained. ARRAY[] is used to constrain array size. The array is limited to 250 based on Westfield Stratford as a single toid with many uses, this may want to be reduced down to reduce maximum size.
+
+ALTER TABLE buildings ADD COLUMN IF NOT EXISTS current_landuse_class text ARRAY[250];