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];