diff --git a/app/models/local_authority.rb b/app/models/local_authority.rb new file mode 100644 index 000000000..4017ada52 --- /dev/null +++ b/app/models/local_authority.rb @@ -0,0 +1,2 @@ +class LocalAuthority < ApplicationRecord +end diff --git a/app/services/imports/local_authorities_service.rb b/app/services/imports/local_authorities_service.rb new file mode 100644 index 000000000..23a4e2375 --- /dev/null +++ b/app/services/imports/local_authorities_service.rb @@ -0,0 +1,25 @@ +require "csv" + +module Imports + class LocalAuthoritiesService + attr_reader :path, :count + + def initialize(path:) + @path = path + @count = 0 + end + + def call + CSV.foreach(path, headers: true) do |row| + LocalAuthority.upsert( + { code: row["code"], + name: row["name"], + start_date: Time.zone.local(row["start_year"], 4, 1), + end_date: (Time.zone.local(row["end_year"], 3, 31) if row["end_year"]) }, + unique_by: %i[code], + ) + @count += 1 + end + end + end +end diff --git a/config/local_authorities_data/initial_local_authorities.csv b/config/local_authorities_data/initial_local_authorities.csv new file mode 100644 index 000000000..f80fbb6f5 --- /dev/null +++ b/config/local_authorities_data/initial_local_authorities.csv @@ -0,0 +1,388 @@ +code,name,start_year,end_year +S12000033,Aberdeen City,2021, +S12000034,Aberdeenshire,2021, +E07000223,Adur,2021, +E07000032,Amber Valley,2021, +S12000041,Angus,2021, +N09000001,Antrim and Newtownabbey,2021, +N09000011,Ards and North Down,2021, +S12000035,Argyll and Bute,2021, +N09000002,"Armagh City, Banbridge and Craigavon",2021, +E07000224,Arun,2021, +E07000170,Ashfield,2021, +E07000105,Ashford,2021, +E07000200,Babergh,2021, +E09000002,Barking and Dagenham,2021, +E09000003,Barnet,2021, +E08000016,Barnsley,2021, +E07000066,Basildon,2021, +E07000084,Basingstoke and Deane,2021, +E07000171,Bassetlaw,2021, +E06000022,Bath and North East Somerset,2021, +E06000055,Bedford,2021, +N09000003,Belfast,2021, +E09000004,Bexley,2021, +E08000025,Birmingham,2021, +E07000129,Blaby,2021, +E06000008,Blackburn with Darwen,2021, +E06000009,Blackpool,2021, +W06000019,Blaenau Gwent,2021, +E07000033,Bolsover,2021, +E08000001,Bolton,2021, +E07000136,Boston,2021, +E06000058,"Bournemouth, Christchurch and Poole",2021, +E06000036,Bracknell Forest,2021, +E08000032,Bradford,2021, +E07000067,Braintree,2021, +E07000143,Breckland,2021, +E09000005,Brent,2021, +E07000068,Brentwood,2021, +W06000013,Bridgend,2021, +E06000043,Brighton and Hove,2021, +E06000023,"Bristol, City of",2021, +E07000144,Broadland,2021, +E09000006,Bromley,2021, +E07000234,Bromsgrove,2021, +E07000095,Broxbourne,2021, +E07000172,Broxtowe,2021, +E06000060,Buckinghamshire,2021, +E07000117,Burnley,2021, +E08000002,Bury,2021, +W06000018,Caerphilly,2021, +E08000033,Calderdale,2021, +E07000008,Cambridge,2021, +E09000007,Camden,2021, +E07000192,Cannock Chase,2021, +E07000106,Canterbury,2021, +W06000015,Cardiff,2021, +W06000010,Carmarthenshire,2021, +E07000069,Castle Point,2021, +N09000004,Causeway Coast and Glens,2021, +E06000056,Central Bedfordshire,2021, +W06000008,Ceredigion,2021, +E07000130,Charnwood,2021, +E07000070,Chelmsford,2021, +E07000078,Cheltenham,2021, +E07000177,Cherwell,2021, +E06000049,Cheshire East,2021, +E06000050,Cheshire West and Chester,2021, +E07000034,Chesterfield,2021, +E07000225,Chichester,2021, +E07000118,Chorley,2021, +S12000036,City of Edinburgh,2021, +E09000001,City of London,2021, +S12000005,Clackmannanshire,2021, +E07000071,Colchester,2021, +W06000003,Conwy,2021, +E07000150,Corby,2021, +E06000052,Cornwall,2021, +E07000079,Cotswold,2021, +E06000047,County Durham,2021, +E08000026,Coventry,2021, +E07000226,Crawley,2021, +E09000008,Croydon,2021, +E06000063,Cumberland,2023, +E07000096,Dacorum,2021, +E06000005,Darlington,2021, +E07000107,Dartford,2021, +E07000151,Daventry,2021, +W06000004,Denbighshire,2021, +E06000015,Derby,2021, +E07000035,Derbyshire Dales,2021, +N09000005,Derry City and Strabane,2021, +E08000017,Doncaster,2021, +E06000059,Dorset,2021, +E07000108,Dover,2021, +E08000027,Dudley,2021, +S12000006,Dumfries and Galloway,2021, +S12000042,Dundee City,2021, +E09000009,Ealing,2021, +S12000008,East Ayrshire,2021, +E07000009,East Cambridgeshire,2021, +E07000040,East Devon,2021, +S12000045,East Dunbartonshire,2021, +E07000085,East Hampshire,2021, +E07000242,East Hertfordshire,2021, +E07000137,East Lindsey,2021, +S12000010,East Lothian,2021, +E07000152,East Northamptonshire,2021, +S12000011,East Renfrewshire,2021, +E06000011,East Riding of Yorkshire,2021, +E07000193,East Staffordshire,2021, +E07000244,East Suffolk,2021, +E07000061,Eastbourne,2021, +E07000086,Eastleigh,2021, +E07000207,Elmbridge,2021, +E09000010,Enfield,2021, +E07000072,Epping Forest,2021, +E07000208,Epsom and Ewell,2021, +E07000036,Erewash,2021, +E07000041,Exeter,2021, +S12000014,Falkirk,2021, +E07000087,Fareham,2021, +E07000010,Fenland,2021, +N09000006,Fermanagh and Omagh,2021, +S12000047,Fife,2021, +W06000005,Flintshire,2021, +E07000112,Folkestone and Hythe,2021, +E07000080,Forest of Dean,2021, +E07000119,Fylde,2021, +E08000037,Gateshead,2021, +E07000173,Gedling,2021, +S12000049,Glasgow City,2021, +E07000081,Gloucester,2021, +E07000088,Gosport,2021, +E07000109,Gravesham,2021, +E07000145,Great Yarmouth,2021, +E09000011,Greenwich,2021, +E07000209,Guildford,2021, +W06000002,Gwynedd,2021, +E09000012,Hackney,2021, +E06000006,Halton,2021, +E09000013,Hammersmith and Fulham,2021, +E07000131,Harborough,2021, +E09000014,Haringey,2021, +E07000073,Harlow,2021, +E09000015,Harrow,2021, +E07000089,Hart,2021, +E06000001,Hartlepool,2021, +E07000062,Hastings,2021, +E07000090,Havant,2021, +E09000016,Havering,2021, +E06000019,"Herefordshire, County of",2021, +E07000098,Hertsmere,2021, +E07000037,High Peak,2021, +S12000017,Highland,2021, +E09000017,Hillingdon,2021, +E07000132,Hinckley and Bosworth,2021, +E07000227,Horsham,2021, +E09000018,Hounslow,2021, +E07000011,Huntingdonshire,2021, +E07000120,Hyndburn,2021, +S12000018,Inverclyde,2021, +E07000202,Ipswich,2021, +W06000001,Isle of Anglesey,2021, +E06000046,Isle of Wight,2021, +E06000053,Isles of Scilly,2021, +E09000019,Islington,2021, +E09000020,Kensington and Chelsea,2021, +E07000153,Kettering,2021, +E07000146,King’s Lynn and West Norfolk,2021, +E06000010,"Kingston upon Hull, City of",2021, +E09000021,Kingston upon Thames,2021, +E08000034,Kirklees,2021, +E08000011,Knowsley,2021, +E09000022,Lambeth,2021, +E07000121,Lancaster,2021, +E08000035,Leeds,2021, +E06000016,Leicester,2021, +E07000063,Lewes,2021, +E09000023,Lewisham,2021, +E07000194,Lichfield,2021, +E07000138,Lincoln,2021, +N09000007,Lisburn and Castlereagh,2021, +E08000012,Liverpool,2021, +E06000032,Luton,2021, +E07000110,Maidstone,2021, +E07000074,Maldon,2021, +E07000235,Malvern Hills,2021, +E08000003,Manchester,2021, +E07000174,Mansfield,2021, +E06000035,Medway,2021, +E07000133,Melton,2021, +W06000024,Merthyr Tydfil,2021, +E09000024,Merton,2021, +E07000042,Mid Devon,2021, +E07000203,Mid Suffolk,2021, +E07000228,Mid Sussex,2021, +N09000009,Mid Ulster,2021, +N09000008,Mid and East Antrim,2021, +E06000002,Middlesbrough,2021, +S12000019,Midlothian,2021, +E06000042,Milton Keynes,2021, +E07000210,Mole Valley,2021, +W06000021,Monmouthshire,2021, +S12000020,Moray,2021, +S12000013,Na h-Eileanan Siar,2021, +W06000012,Neath Port Talbot,2021, +E07000091,New Forest,2021, +E07000175,Newark and Sherwood,2021, +E08000021,Newcastle upon Tyne,2021, +E07000195,Newcastle-under-Lyme,2021, +E09000025,Newham,2021, +W06000022,Newport,2021, +N09000010,"Newry, Mourne and Down",2021, +S12000021,North Ayrshire,2021, +E07000043,North Devon,2021, +E07000038,North East Derbyshire,2021, +E06000012,North East Lincolnshire,2021, +E07000099,North Hertfordshire,2021, +E07000139,North Kesteven,2021, +S12000050,North Lanarkshire,2021, +E06000013,North Lincolnshire,2021, +E07000147,North Norfolk,2021, +E06000024,North Somerset,2021, +E08000022,North Tyneside,2021, +E07000218,North Warwickshire,2021, +E07000134,North West Leicestershire,2021, +E07000154,Northampton,2021, +E06000057,Northumberland,2021, +E07000148,Norwich,2021, +E06000018,Nottingham,2021, +E07000219,Nuneaton and Bedworth,2021, +E07000135,Oadby and Wigston,2021, +E08000004,Oldham,2021, +S12000023,Orkney Islands,2021, +E07000178,Oxford,2021, +W06000009,Pembrokeshire,2021, +E07000122,Pendle,2021, +S12000048,Perth and Kinross,2021, +E06000031,Peterborough,2021, +E06000026,Plymouth,2021, +E06000044,Portsmouth,2021, +W06000023,Powys,2021, +E07000123,Preston,2021, +E06000038,Reading,2021, +E09000026,Redbridge,2021, +E06000003,Redcar and Cleveland,2021, +E07000236,Redditch,2021, +E07000211,Reigate and Banstead,2021, +S12000038,Renfrewshire,2021, +W06000016,Rhondda Cynon Taf,2021, +E07000124,Ribble Valley,2021, +E09000027,Richmond upon Thames,2021, +E08000005,Rochdale,2021, +E07000075,Rochford,2021, +E07000125,Rossendale,2021, +E07000064,Rother,2021, +E08000018,Rotherham,2021, +E07000220,Rugby,2021, +E07000212,Runnymede,2021, +E07000176,Rushcliffe,2021, +E07000092,Rushmoor,2021, +E06000017,Rutland,2021, +E08000006,Salford,2021, +E08000028,Sandwell,2021, +S12000026,Scottish Borders,2021, +E08000014,Sefton,2021, +E07000111,Sevenoaks,2021, +E08000019,Sheffield,2021, +S12000027,Shetland Islands,2021, +E06000051,Shropshire,2021, +E06000039,Slough,2021, +E08000029,Solihull,2021, +E06000066,Somerset,2023, +S12000028,South Ayrshire,2021, +E07000012,South Cambridgeshire,2021, +E07000039,South Derbyshire,2021, +E06000025,South Gloucestershire,2021, +E07000044,South Hams,2021, +E07000140,South Holland,2021, +E07000141,South Kesteven,2021, +S12000029,South Lanarkshire,2021, +E07000149,South Norfolk,2021, +E07000155,South Northamptonshire,2021, +E07000179,South Oxfordshire,2021, +E07000126,South Ribble,2021, +E07000196,South Staffordshire,2021, +E08000023,South Tyneside,2021, +E06000045,Southampton,2021, +E06000033,Southend-on-Sea,2021, +E09000028,Southwark,2021, +E07000213,Spelthorne,2021, +E07000240,St Albans,2021, +E08000013,St. Helens,2021, +E07000197,Stafford,2021, +E07000198,Staffordshire Moorlands,2021, +E07000243,Stevenage,2021, +S12000030,Stirling,2021, +E08000007,Stockport,2021, +E06000004,Stockton-on-Tees,2021, +E06000021,Stoke-on-Trent,2021, +E07000221,Stratford-on-Avon,2021, +E07000082,Stroud,2021, +E08000024,Sunderland,2021, +E07000214,Surrey Heath,2021, +E09000029,Sutton,2021, +E07000113,Swale,2021, +W06000011,Swansea,2021, +E06000030,Swindon,2021, +E08000008,Tameside,2021, +E07000199,Tamworth,2021, +E07000215,Tandridge,2021, +E07000045,Teignbridge,2021, +E06000020,Telford and Wrekin,2021, +E07000076,Tendring,2021, +E07000093,Test Valley,2021, +E07000083,Tewkesbury,2021, +E07000114,Thanet,2021, +E07000102,Three Rivers,2021, +E06000034,Thurrock,2021, +E07000115,Tonbridge and Malling,2021, +E06000027,Torbay,2021, +W06000020,Torfaen,2021, +E07000046,Torridge,2021, +E09000030,Tower Hamlets,2021, +E08000009,Trafford,2021, +E07000116,Tunbridge Wells,2021, +E07000077,Uttlesford,2021, +W06000014,Vale of Glamorgan,2021, +E07000180,Vale of White Horse,2021, +E08000036,Wakefield,2021, +E08000030,Walsall,2021, +E09000031,Waltham Forest,2021, +E09000032,Wandsworth,2021, +E06000007,Warrington,2021, +E07000222,Warwick,2021, +E07000103,Watford,2021, +E07000216,Waverley,2021, +E07000065,Wealden,2021, +E07000156,Wellingborough,2021, +E07000241,Welwyn Hatfield,2021, +E06000037,West Berkshire,2021, +E07000047,West Devon,2021, +S12000039,West Dunbartonshire,2021, +E07000127,West Lancashire,2021, +E07000142,West Lindsey,2021, +S12000040,West Lothian,2021, +E07000181,West Oxfordshire,2021, +E07000245,West Suffolk,2021, +E09000033,Westminster,2021, +E06000064,Westmorland and Furness,2023, +E08000010,Wigan,2021, +E06000054,Wiltshire,2021, +E07000094,Winchester,2021, +E06000040,Windsor and Maidenhead,2021, +E08000015,Wirral,2021, +E07000217,Woking,2021, +E06000041,Wokingham,2021, +E08000031,Wolverhampton,2021, +E07000237,Worcester,2021, +E07000229,Worthing,2021, +W06000006,Wrexham,2021, +E07000238,Wychavon,2021, +E07000128,Wyre,2021, +E07000239,Wyre Forest,2021, +E06000014,York,2021, +E06000065,North Yorkshire,2023, +N92000002,Northern Ireland,2021, +S92000003,Scotland,2021, +W92000004,Wales,2021, +9300000XX,Outside UK,2021, +E07000027,Barrow-in-Furness,2021,2023, +E07000030,Eden,2021,2023, +E07000031,South Lakeland,2021,2023, +E07000026,Allerdale,2021,2023, +E07000028,Carlisle,2021,2023, +E07000029,Copeland,2021,2023, +E07000163,Craven,2021,2023, +E07000164,Hambleton,2021,2023, +E07000165,Harrogate,2021,2023, +E07000166,Richmondshire,2021,2023, +E07000167,Ryedale,2021,2023, +E07000168,Scarborough,2021,2023, +E07000169,Selby,2021,2023, +E07000187,Mendip,2021,2023, +E07000188,Sedgemoor,2021,2023, +E07000246,Somerset West and Taunton,2021,2023, +E07000189,South Somerset,2021,2023, diff --git a/db/migrate/20230308101826_create_local_authorities.rb b/db/migrate/20230308101826_create_local_authorities.rb new file mode 100644 index 000000000..f64964455 --- /dev/null +++ b/db/migrate/20230308101826_create_local_authorities.rb @@ -0,0 +1,13 @@ +class CreateLocalAuthorities < ActiveRecord::Migration[7.0] + def change + create_table :local_authorities do |t| + t.string :code, null: false + t.string :name, null: false + t.datetime :start_date, null: false + t.datetime :end_date + t.index %w[code], name: "index_local_authority_code", unique: true + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index c2f8f8600..eccfa98ca 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_03_01_144555) do +ActiveRecord::Schema[7.0].define(version: 2023_03_08_101826) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -289,6 +289,16 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_01_144555) do t.index ["updated_by_id"], name: "index_lettings_logs_on_updated_by_id" end + create_table "local_authorities", force: :cascade do |t| + t.string "code", null: false + t.string "name", null: false + t.datetime "start_date", null: false + t.datetime "end_date" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["code"], name: "index_local_authority_code", unique: true + end + create_table "location_deactivation_periods", force: :cascade do |t| t.datetime "deactivation_date" t.datetime "reactivation_date" diff --git a/db/seeds.rb b/db/seeds.rb index 341677b27..e677ad50e 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -325,4 +325,10 @@ unless Rails.env.test? end end end + +if LocalAuthority.count.zero? + path = "config/local_authorities_data/initial_local_authorities.csv" + service = Imports::LocalAuthoritiesService.new(path:) + service.call +end # rubocop:enable Rails/Output diff --git a/lib/tasks/local_authorities.rake b/lib/tasks/local_authorities.rake new file mode 100644 index 000000000..b812bbc94 --- /dev/null +++ b/lib/tasks/local_authorities.rake @@ -0,0 +1,13 @@ +namespace :data_import do + desc "Import local authorities data" + task :local_authorities, %i[path] => :environment do |_task, args| + path = args[:path] + + raise "Usage: rake data_import:local_authorities['path/to/csv_file']" if path.blank? + + service = Imports::LocalAuthoritiesService.new(path:) + service.call + + pp "Created/updated #{service.count} local authority records" unless Rails.env.test? + end +end diff --git a/spec/fixtures/files/local_authorities.csv b/spec/fixtures/files/local_authorities.csv new file mode 100644 index 000000000..d1cebba6b --- /dev/null +++ b/spec/fixtures/files/local_authorities.csv @@ -0,0 +1,6 @@ +code,name,start_year,end_year +S12000033,Aberdeen City,2021, +S12000034,Aberdeenshire,2021, +E07000223,Adur,2021, +E07000032,Amber Valley,2021, +S12000041,Angus,2021, \ No newline at end of file diff --git a/spec/lib/tasks/local_authorities_import_spec.rb b/spec/lib/tasks/local_authorities_import_spec.rb new file mode 100644 index 000000000..67d952767 --- /dev/null +++ b/spec/lib/tasks/local_authorities_import_spec.rb @@ -0,0 +1,43 @@ +require "rails_helper" +require "rake" + +RSpec.describe "data_import" do + describe ":local_authorities", type: :task do + subject(:task) { Rake::Task["data_import:local_authorities"] } + + before do + LocalAuthority.destroy_all + Rake.application.rake_require("tasks/local_authorities") + Rake::Task.define_task(:environment) + task.reenable + end + + context "when the rake task is run" do + let(:local_authorities_file_path) { "./spec/fixtures/files/local_authorities.csv" } + let(:wrong_file_path) { "/test/no_csv_here.csv" } + + it "creates new local authorities records" do + expect { task.invoke(local_authorities_file_path) }.to change(LocalAuthority, :count).by(5) + expect(LocalAuthority.where(code: "S12000041").exists?).to be true + end + + it "raises an error when no path is given" do + expect { task.invoke(nil) }.to raise_error(RuntimeError, "Usage: rake data_import:local_authorities['path/to/csv_file']") + end + + it "raises an error when no file exists at the given path" do + expect { task.invoke(wrong_file_path) }.to raise_error(Errno::ENOENT) + end + + context "when a record already exists with a matching code index" do + let!(:local_authority) { LocalAuthority.create(code: "S12000041", name: "Something else", start_date: Time.zone.local(2021, 4, 1)) } + + it "updates local authority if the record is matched on code" do + task.invoke(local_authorities_file_path) + local_authority.reload + expect(local_authority.name).to eq("Angus") + end + end + end + end +end