Index: dataconv/cleansqlite.py
==================================================================
--- dataconv/cleansqlite.py
+++ dataconv/cleansqlite.py
@@ -19,37 +19,53 @@
"""
import os
import sys
import sqlite3
+import pprint
from time import strftime, localtime
class CleanError(Exception):
""" Raised when an error is detected while cleaning a database """
pass
-class SqliteClean(object):
+class SqliteClean():
""" Class with methods to clean an SQLite3 database created from the
Paradox database.
-
- This class must be subclassed by each of the breeds so that actions
- peculiar to that breed can be carried out.
"""
- def __init__(self, breed, dbname, debug=False):
+ def __init__(self, dbname, debug=False):
""" Initialise this instance """
self.warnings = ['']
- self.breed = breed
self.db_name = dbname
self.db_conn = None
self.debug = debug
self.date_now = strftime('%Y-%m-%d', localtime())
self.ts_now = "%s 00:00:00" % self.date_now
- self.breed_flocks = None
- self.flock_unknown = None
- self.flock_owner_corr = None
- self.sheep_flock_corr = None
+ self.breed_flocks = 'SSB%'
+ self.flock_unknown = "SSB901"
+ # A tuple of tuples. Each sub-tuple is new_change_date, flock_no, old_change_date
+ self.flock_owner_corr = (('1983-01-01', '0431', '2001-12-12'),)
+
+ # A tuple of tuples. Each sub-tuple is a missing owner record:
+ # flock_no, owner_person_id, owner_change_date, last_changed
+ # The Zxxxx records appear to be as a result of the owner of flock 2060 buying
+ # sheep and re-registering them...
+ self.sheep_flock_corr = (('039764', '2777','2005-09-01'),
+ ('040573', '2453', '2005-09-24'), # Mistake?
+ ('040573', '2769', '2005-09-24'), # Mistake?
+ ('040574', '2453', '2005-09-24'), # Mistake?
+ ('040574', '2769', '2005-09-24'), # Mistake?
+ ('043326', '1191', '2009-11-14'),
+ ('050081', '2906', '2010-08-19'),
+ ('051146', '2402', '2013-04-06'), # Spurious
+ ('051146', '3072', '2013-04-06'), # Spurious
+ ('Z5491', '2060', '1989-04-01'), # Duplicate Regn
+ ('Z6813', '2060', '1989-04-01'), # Duplicate Regn
+ ('Z6986', '2060', '1989-03-26'), # Duplicate Regn
+ ('Z6989', '2060', '1989-03-24'), # Duplicate Regn
+ ('Z6990', '2060', '1989-04-02')) # Duplicate Regn
try:
self.db_conn = sqlite3.connect(self.db_name)
except sqlite3.Error as err:
raise CleanError("Error opening database: %s" % str(err))
@@ -70,10 +86,20 @@
def clean(self):
""" Run the methods to clean the database.
Subclasses should extend this method to run their own cleaning
method before calling this method
"""
+ self.message( "Correcting persons table...")
+ self.correct_persons()
+ self.message( "Correcting regions tables...")
+ self.correct_regions()
+ self.message( "Correcting miscellaneous tables...")
+ self.correct_breed_tables()
+ self.message( "Correcting sheep transfers...")
+ self.correct_sheep_transfers()
+ self.message( "Correcting inspection venues...")
+ self.clean_insp_venues()
self.message( "Eliminating nulls...")
self.eliminate_nulls()
self.message( "Checking foreign key integrity...")
self.check_integrity()
self.message( "Rationalising phone types...")
@@ -576,13 +602,11 @@
except sqlite3.Error as err:
raise CleanError("Error testing registering persons: "
"%s" % str(err))
- if self.breed == 'sss':
- exception_list = sss_exception_list
-
+ exception_list = sss_exception_list
try:
# The breeder query is very complex if run as one query, so
# much so that the SQLite 3.7.3 query planner has a bug
# (sqlite check-in [d30f7b2def]) and it takes many minutes to run.
# To avoid this a temporary table is created from the base query.
@@ -917,58 +941,12 @@
((self.ts_now, row[0], row[1]) for row in rows))
self.db_conn.commit()
except sqlite3.Error as err:
raise CleanError("Error inserting records into sheep_flock_audit: {}".format(err))
- c.close()
-
-class SSSClean(SqliteClean):
- """ Subclass to clean up the SSS tables """
-
- def __init__(self, db_name, debug):
- """ Initialise this instance """
- super(SSSClean, self).__init__('sss', db_name, debug)
- self.breed_flocks = 'SSB%'
- self.flock_unknown = "SSB901"
- # A tuple of tuples. Each sub-tuple is new_change_date, flock_no, old_change_date
- self.flock_owner_corr = (('1983-01-01', '0431', '2001-12-12'),)
-
- # A tuple of tuples. Each sub-tuple is a missing owner record:
- # flock_no, owner_person_id, owner_change_date, last_changed
-
- # The Zxxxx records appear to be as a result of the owner of flock 2060 buying
- # sheep and re-registering them...
-
- self.sheep_flock_corr = (('039764', '2777','2005-09-01'),
- ('040573', '2453', '2005-09-24'), # Mistake?
- ('040573', '2769', '2005-09-24'), # Mistake?
- ('040574', '2453', '2005-09-24'), # Mistake?
- ('040574', '2769', '2005-09-24'), # Mistake?
- ('043326', '1191', '2009-11-14'),
- ('050081', '2906', '2010-08-19'),
- ('051146', '2402', '2013-04-06'), # Spurious
- ('051146', '3072', '2013-04-06'), # Spurious
- ('Z5491', '2060', '1989-04-01'), # Duplicate Regn
- ('Z6813', '2060', '1989-04-01'), # Duplicate Regn
- ('Z6986', '2060', '1989-03-26'), # Duplicate Regn
- ('Z6989', '2060', '1989-03-24'), # Duplicate Regn
- ('Z6990', '2060', '1989-04-02')) # Duplicate Regn
-
-
- def clean(self):
- """ Run our own methods first, then call the super-class' method """
- self.message("Cleaning SSS database %s" %
- os.path.basename(self.db_name), False, True)
- self.message("Correcting SSS tables...")
- self.correct_persons()
- self.correct_regions()
- self.correct_breed_tables()
- self.correct_sheep_transfers()
- self.correct_insp_venues()
- super(SSSClean, self).clean()
- print("\n".join(self.warnings))
-
+ c.close()
+
def correct_persons(self):
""" Correct some person data """
try:
curs = self.db_conn.cursor()
curs.execute("update persons set forename = 'Stanley', title = 'The Late Dr' "
@@ -1276,83 +1254,10 @@
"WHERE Inspector_1 = 'J.M. Marshall'")
self.db_conn.commit()
except sqlite3.Error as err:
raise CleanError("Correcting inspector name in approval: %s"
% str(err))
-
- try:
- """ Harmonise the Inspection venue names. """
- c.execute("UPDATE approval set venue = 'Unrecorded' "
- "where venue = ''")
- c.execute("UPDATE approval set venue = 'Ardingly' "
- "where venue = 'Ardingley'")
- c.execute("UPDATE approval set venue = 'Bath and West Show' "
- "where venue LIKE 'Bath%'")
- c.execute("UPDATE approval set venue = 'Bellingham Show' "
- "where venue LIKE 'Bellingham%'")
- c.execute("UPDATE approval set venue = 'Bristol Sale' "
- "where venue LIKE 'Bristol%'")
- c.execute("UPDATE approval set venue = 'Braxfield House' "
- "WHERE venue = 'Braxfield';")
- c.execute("UPDATE approval set venue = 'Carlisle Sale' "
- "where venue LIKE 'Carlisle%'")
- c.execute("UPDATE approval set venue = 'Devon Show' "
- "where venue LIKE 'Devon%'")
- c.execute("UPDATE approval set venue = 'Dorchester Show' "
- "where venue LIKE 'Dorchester%'")
- c.execute("UPDATE approval set venue = 'Eccleshall Show' "
- "where venue LIKE 'Eccles%'")
- c.execute("UPDATE approval set venue = 'Ewingston Farm' "
- "where venue = 'Ewinston Farm'")
- c.execute("UPDATE approval set venue = 'Fife Show' "
- "where venue LIKE 'Fife%'")
- c.execute("UPDATE approval set venue = 'Frome Show and Sale' "
- "where venue LIKE 'Frome%'")
- c.execute("UPDATE approval set venue = 'Easter Glentore' "
- "where venue = 'Lonriggend'")
- c.execute("UPDATE approval set venue = 'Nant-y-Derw' "
- "where venue LIKE 'Nant%' and venue NOT LIKE '%Nantymwyn%'")
- c.execute("UPDATE approval set venue = 'New Forest Show' "
- "where venue LIKE 'New Forest%'")
- c.execute("UPDATE approval set venue = 'Newbury Show' "
- "where venue LIKE 'Newbury%'")
- c.execute("UPDATE approval set venue = 'Owner''s Farm' "
- "where venue LIKE 'Owner%' OR venue = 'at home' ")
- c.execute("UPDATE approval set venue = 'Ravendale Farm' "
- "where venue LIKE 'Ravendale%'")
- c.execute("UPDATE approval set venue = 'Royal Highland Show' "
- "where venue LIKE 'Royal Shig%'")
- c.execute("UPDATE approval set venue = 'SSBG Show and Sale' "
- "where venue LIKE 'SSBG%'")
- c.execute("UPDATE approval set venue = 'RBST Show and Sale' "
- "where venue LIKE 'Show %' OR venue LIKE 'Stoneleigh%'")
- c.execute("UPDATE approval set venue = 'Singleton Show' "
- "where venue LIKE 'Singleton%'")
- c.execute("UPDATE approval set venue = 'Skipton Sale' "
- "where venue LIKE 'Skipton%'")
- c.execute("UPDATE approval set venue = 'Shustoke Show' "
- "where venue LIKE 'Shustoke%'")
- c.execute("UPDATE approval set venue = 'South Worden Farm' "
- "where venue LIKE 'South Worden%'")
- c.execute("UPDATE approval set venue = 'South Wales' "
- "where venue = 'SouthWales'")
- c.execute("UPDATE approval set venue = 'Tenbury Wells Show' "
- "where venue LIKE 'Tenbury%'")
- c.execute("UPDATE approval set venue = 'The Brackens, Shropshire' "
- "where venue LIKE 'The Brackens%'")
- c.execute("UPDATE approval set venue = 'Uffculme Show' "
- "where venue LIKE 'Uffculme%'")
- c.execute("UPDATE approval set venue = 'York Show and Sale' "
- "where venue LIKE 'York%' AND venue NOT LIKE '%Museum%'" )
- c.execute("UPDATE approval set venue = 'Unrecorded' "
- "where venue = 'unrecorded'")
-
- self.db_conn.commit()
-
- except sqlite3.Error as err:
- raise CleanError("Error harmonising inspection venues: %s"
- % str(err))
try:
""" Harmonise the genotype testing lab names. """
c.execute("UPDATE prpgene "
"SET testing_lab = 'Catapult Systems Ltd.' "
@@ -1473,113 +1378,353 @@
except Exception as err:
raise CleanError("Error correcting Z0417 and Z10487: {}".format(str(err)))
c.close()
- def correct_insp_venues(self):
+ def clean_insp_venues(self):
""" Clean up the inspection venues """
- venue_clean = [('Ardingly Show', 'Ardingly'),
- ('Member 2502, 18 Queens Court, Irvine', '18 Queens Court' ),
- ('Member 3304, Barry, Glamorgan', 'Barry CF62 8EE'),
- ('Carlisle Show and Sale', 'Carlisle Sale'),
- ('Cranleigh Show', 'Cranleigh'),
- ('Devon County Show', 'Devon Show'),
- ('Dornoch, Sutherland', 'Dornock'),
- ('Dornoch, Sutherland', 'Dornoch'),
- ('Edinburgh Genetics, Malvern', 'Edinburgh'),
- ('Member 1724, Ewingston Farm, East Lothian', 'Ewingsto'),
- ('Member 1724, Ewingston Farm, East Lothian', 'Ewingston'),
- ('Member 2674, Fullwood Stile Farm, Derbyshire', 'Fulwood'),
- ('Goosnargh and Longridge Show', 'Goosnargh and Longridge'),
- ('Member 3204, Greenlands Farm, Carnforth', 'Greenlands'),
- ('Harbridge House Meadow', 'Hasbridge House Meadow'),
- ('Herts County Show', 'Herts Show'),
- ('Member 2152, Middletown Farm, Lanark', 'Middletown'),
- ('Member 2152, Middletown Farm, Lanark', 'Middleton Farm'),
- ('Member 2002, Middle Munty Farm, Taunton', 'Middle Munty'),
- ('Milton Abbot', 'MILTON ABBOT'),
- ('New Forest Show', 'New Hampshire County Show'),
- ('Okehampton Show', 'Okehampton Show'),
- ('Okehampton Show', 'Okehampton'),
- ('Ripley Show','Ripley'),
- ('Sedgemoor Show and Sale', 'Sedgemoor'),
- ('Sedgemoor Show and Sale', 'Sedgemoor Auction'),
- ('Sedgemoor Show and Sale', 'Sedgemoor Show & Sale'),
- ('Sedgemoor Show and Sale', 'Sedgemoor Market'),
- ('Sedgemoor Show and Sale', 'SEDGEMOOR SHOW & SALE'),
- ('South Beds Show', 'South Beds'),
- ('Member 2160, St Baldred''s, East Lothian', 'St.Baldred''s'),
- ('Member 2160, St Baldred''s, East Lothian', 'St Baldred''s'),
- ('Member 2436 Summerside Farm, Lanarkshire', 'Summerside'),
- ('Westmorland Show', 'Westmoreland Show'),
- ('Westmorland Show', 'West Morland Show'),
- ('Member 2580, Wood Cottage Farm, Macclesfield', 'Weod Cottage'),
- ('Member 2580, Wood Cottage Farm, Macclesfield', 'Woodcottage Farm'),
- ('Flag Fen Show', 'Flag Fen'),
- ('Chelford Show', 'Chelford'),
- ('Member 1610, Wycoller, Lancashire', 'Wycoller'),
- ('Member 0108, Braxfield House, Lanark', 'Braxfield House'),
- ('Member 1191, Cedar Cottage, Fife', 'Cedar Cottage'),
- ('Member 2549, The Brackens, Shropshire', 'The Brackens, Shropshire'),
- ('Member 2549, The Brackens, Shropshire', 'Brackens'),
- ('Member 0824, Rivendell, Hexham', 'Rivendell'),
- ('Member 2519, Essex Wildlife Trust', 'Essex Wildlife Trust'),
- ('Member 2848, Sandyacre, Newark', 'Sandyacres'),
- ('Member 1003, Willowcroft, Somerset', 'Willowcroft'),
- ('Member 1003, Willowcroft, Somerset', 'Crockerton'),
- ('Member 2000, The Rench, West Lothian', 'The Rench'),
- ('Member 2000, The Rench, West Lothian', 'Rench'),
- ('Member 2472, Nut Tree Cottage, Salisbury', 'Nut Tree Cottage'),
- ('Member 2472, Nut Tree Cottage, Salisbury', 'Mandeville Flock'),
- ('Member 0306, The Old Surgery, Shropshire', 'The Old Surgery'),
- ('Member 0306, The Old Surgery, Shropshire', 'Ercall Heath'),
- ('Member 1350, Ramsbottom, Bury', 'Ramsbottom'),
- ('Lesmahagow Show', 'Lesmahagow'),
- ('Member 0402, Draywood Cottage, Yeovil', 'Draywood'),
- ('Member 0402, Draywood Cottage, Yeovil', 'Odcombe'),
- ('Member 2592, Romanno Mains, Peeblesshire', 'Romanno Mains'),
- ('Member 3280, Hornacott Manor, Cornwall', 'Hornacott Manor'),
- ('Member 2513, Newhouse Farm, East Sussex', 'Chalvington, E.Sussex'),
- ('Member 2513, Newhouse Farm, East Sussex', 'Calvington, E.Sussex'),
- ('Member 2865, Highfield House, York', 'Highfield House'),
- ('Member 2962, Abacus Acres, Bedfordshire', 'Abacus Acres'),
- ('Member 3252, Cronklea, Lockerbie', 'Cronklea'),
-#~ ('Lockerbie Show', 'Lockerbie'),
- ('Member 3187, The Old Barn, Doncaster', 'The Old Barn, Sutton'),
- ('Member 1003, Fell House, Crockerton, Wilts.', 'Fell House (Jean Curtis''s'),
- ('Member 3146, Fronhaul, Carmarthenshire', 'Fronhaul, Whitland'),
- ('Member 3957, Boggs Holdings, East Lothian', 'Boggs Holdings'),
- ('Member 3298, Twin Oaks, Welwyn, Herts', 'Twin Oaks, Welwyn'),
- ('Member 1483, Clyngwynne Fach, carmarthenshire', 'Llanboidy'),
- ('Member 2536, Dyffryn Isaf, Pembrokeshire', 'Dyffryn Isaf'),
- ('Member 2186, Cefn Llanfair, Ceredigion', 'Landysul'),
- ('Member 2220, Woodlands, Driffield', 'Woodlands, Kilham'),
- ('Member 2220, Woodlands, Driffield', 'Kilham'),
- ('Member 3744, Mount Pleasant, Somerset', 'Mount Pleasant'),
- ('Member 2865, Highfield House, York', 'Harlthorpe'),
- ('Member 3527, Jasmine Cottage, Highbridge, Somerset', 'Jasmine Cottage'),
- ('Member 3230, Winders Wood Cottage, Corbridge, Northumberland', 'Winders Wood Cottage'),
- ]
-
-
- venue_clean_like = [('Compton Basset', 'Compton%'),
- ('Ellingham and Ringwood Show', 'Ellingham%'),
- ('Goosnargh and Longridge Show','Gosssnargh%'),
- ('M6 J36 Auction Mart', 'Junction 36%'),
- ('Llandovery Mart', 'Llandovery%'),
- ('Melton Mowbray Show and Sale', 'Melton Mowbray%'),
- ('Member 2321, Old Seaxpenne Farm, Shaftesbury', '%Seaxpenny%'),
- ('Sedgemoor Show and Sale', 'Sedgmoor%'),
- ('Member 2033, Sunninglye Farmhouse, Kent', 'Sunninglye%'),
- ('Member 2116, Welland Down Farm, Devon', 'Welland%'),]
-
+
+ try:# Add a new columns 'venue_type' and 'member_no' to the approval table
+ curs = self.db_conn.cursor()
+ curs.execute("alter table approval add column venue_type text")
+ curs.execute("update approval set venue_type = 'Unknown'")
+ curs.execute("alter table approval add column member_no text")
+ self.db_conn.commit()
+ except Exception as err:
+ raise CleanError(f"Error adding columns to approval: {str(err)}")
+
+ # Set a real venue for inspections with a venue of 'at home'
+ try:
+ curs = self.db_conn.cursor()
+ curs.execute("update approval set venue = 'Rivendell' where venue like 'Owner%' "
+ "and owner_person = 269 and sort_approval_date = '2002-01-01';")
+ curs.execute("update approval set venue = 'Fasgadh, Clachan Seil, by Oban, Argyll', "
+ "venue_type = '2036' "
+ "where venue like 'Owner%' and owner_person = 1085 and "
+ "sort_approval_date = '2002-09-15';")
+ curs.execute("update approval set venue = 'Bents, Stoneyburn, Bathgate, West Lothian', "
+ "venue_type = '2557' "
+ "where venue like 'Owner%' and owner_person = 1165 and "
+ "sort_approval_date = '2002-09-15';")
+ curs.execute("update approval set venue = 'Braxfield' where venue like 'Owner%' "
+ "and owner_person = 11 and sort_approval_date = '2002-09-15';")
+ curs.execute("update approval set venue = 'The Old Surgery' where venue like 'Owner%' "
+ "and owner_person = 48 and sort_approval_date = '2002-09-29';")
+ curs.execute("update approval set venue = "
+ "'Woodview Farm, Shortheath, Swadlincode, Derbyshire', "
+ "venue_type = '0673' "
+ "where venue like 'Owner%' and owner_person = 194 and "
+ "sort_approval_date = '2002-09-29';")
+
+ curs.execute("update approval set venue = "
+ "'Rose Cottage, Upton Magna, Shrewsbury, Shropshire', "
+ "venue_type = '1308' "
+ "where venue like 'Owner%' and owner_person = 472 and "
+ "sort_approval_date = '2002-09-29';")
+ curs.execute("update approval set venue = "
+ "'The Stables, Lower Penn, Wolverhampton, West Midlands', "
+ "venue_type = '2534' "
+ "where venue like 'Owner%' and owner_person = 1137 and "
+ "sort_approval_date = '2002-09-29';")
+ curs.execute("update approval set venue = "
+ "'Nidus Cottage, Church Aston, Newport, Shropshire', "
+ "venue_type = '0943' "
+ "where venue like 'Owner%' and owner_person = 331 and "
+ "sort_approval_date = '2002-09-29';")
+ curs.execute("update approval set venue = 'Willowcroft' where venue = 'at home' "
+ "and owner_person= 355 and sort_approval_date = '2002-10-06';")
+ curs.execute("update approval set venue = "
+ "'The Bytack, Mynd, Bucknell, Shropshire', "
+ "venue_type = 'Farm', member_no = '2471' "
+ "where venue like 'Owner%' and owner_person = 1116 and "
+ "sort_approval_date = '2002-10-22';")
+
+ curs.execute("update approval set venue = 'Middleton Farm' where venue like 'Owner%' "
+ "and owner_person = 717 and sort_approval_date = '2002-12-10';")
+ curs.execute("update approval set venue = 'Draywood' where venue = 'at home' "
+ "and sort_approval_date = '2006-08-27';")
+ except Exception as err:
+ raise CleanError(f"Error setting real venues instead of 'at home': {str(err)}")
+
+ curs.execute("select * from approval where venue like 'Owner%' "
+ "order by sort_approval_date;")
+ rows = curs.fetchall()
+ for row in rows:
+ pprint.pprint(row)
+
+ curs.execute("select * from approval where venue = 'at home' "
+ "order by sort_approval_date;")
+ rows = curs.fetchall()
+ for row in rows:
+ pprint.pprint(row)
+
+ venue_clean = [
+
+ ('Abacus Acres, Bedfordshire', '2962', 'Abacus Acres'),
+ ("Ainstable, Cumbria", '3092', "Ainstable, Cumbria"),
+ ('Airyholme Farm, York', '1058', 'Airyholme Farm'),
+ ("Applegarth House, Binfield, Berkshire", '0376', "Binfield"),
+ ('Ash Farm, Iddesleigh, Devon', '0031', 'Ash Farm'),
+
+ ("Balcombes Barn, Lewes, East Sussex", '3310', "Balcombes Barn"),
+ ('Barry, Glamorgan', '3304', 'Barry CF62 8EE'),
+ ('Bath and West Show', 'Event', "Bath%"),
+ ("Bellingham Show", 'Event', "Bellingham%"),
+ ('Birch Farm, Guildford, Surrey', '0376', 'Birch Farm'),
+ ('Boggs Holdings, East Lothian', '3957', 'Boggs Holdings'),
+ ("Bradworthy, Devon", 'Unknown', 'Bradworthy'),
+ ("Braunston, Daventry, Northamptonshire", '2833', 'Braunston'),
+ ('Braxfield House, Lanark', '0108', 'Braxfield%'),
+
+
+ ("Breoch Park, New Abbey, Dumfries", '2423', 'Breoch Park'),
+ ("Bristol Sale", 'Event', "Bristol%"),
+ ('Bull Hill Farm, Ashbourne, Derbyshire', '3380', 'Bull Hill Farm'),
+
+ ("Carlisle Show and Sale", 'Unknown', 'Carlisle%'),
+ ('Cedar Cottage, Craigrothie, Cupar, Fife', '1191', 'Cedar Cottage'),
+ ('Cedar Cottage, Craigrothie, Cupar, Fife', '1191', 'Craigrothie'),
+ ('Cefn Llanfair, Ceredigion', '2186', 'Landysul'),
+ ('Cefn Llanfair, Ceredigion', '2186', 'Cefn Llanfair'),
+ ('Chelford Show', 'Unknown', 'Chelford'),
+ ("Chertsey Show, Surrey", "Event", "Chertsey%"),
+ ('Clyngwynne Fach, Carmarthenshire', '1483', 'Llanboidy'),
+ ('Lower End Farm. Compton Bassett, Wiltshire', '1060', 'Compton%'),
+ ('Cotswold Farm Park, Cheltenham, Gloucestershire', 'Event', 'Cotswold Farm Park'),
+ ('Cranleigh Show', 'Unknown', 'Cranleigh'),
+ ('Cronklea, Lockerbie', '3252', 'Cronklea'),
+
+ ('Dancing Gate Farm, Underskiddaw, Keswick, Cumbria', '3159', 'Dancing Gate%'),
+ ('Devon County Show', 'Event', 'Devon%'),
+ ('Dorchester Show', 'Event', 'Dorchester%'),
+ ('Dowmin, Huntly, Aberdeenshire', '3241', 'Dowmin Farm'),
+ ('Draywood Cottage, Yeovil, Somerset', '0402', 'Draywood'),
+ ('Draywood Cottage, Yeovil, Somerset', '0402', 'Odcombe'),
+ ('Dyffryn Isaf, Pembrokeshire', '2536', 'Dyffryn Isaf'),
+ ('Dyke Farm, Penrith, Cumbria', '1015', 'Dyke Farm'),
+
+ ('East Balgray Farm, Irvine, Ayrshire', '2502', 'East Bolgray Farm'),
+ ("East Anglia", 'Event', "E. Anglia"),
+ ("East Down End, Egloskery, Launceston, Cornwall", '2384', "East Down End"),
+ ("Easter Glentore, Airdrie, Lanarkshire", '0937', "Easter Glentore"),
+ ("Easter Glentore, Airdrie, Lanarkshire", '0937', "Longriggend"),
+ ("Easter Glentore, Airdrie, Lanarkshire", '0937', "Lonriggend"),
+ ('Eccleshall Show', 'Event','Eccles%'),
+ ("Edinburgh Genetics, Malvern", "Event", "Edinburgh Genetics, Malvern"),
+ ('Edinburgh Genetics, Malvern','Event', 'Edinburgh'),
+ ('Ellingham and Ringwood Show', 'Unknown', 'Ellingham%'),
+ ('Essex Wildlife Trust', '2519','Essex Wildlife Trust'),
+ ('Ewingston, Humbie, East Lothian', '1724', 'Humbie%'),
+ ('Ewingston, Humbie, East Lothian', '1724', 'Ewingsto%'),
+ ('Ewingston, Humbie, East Lothian', '1724', 'Ewinsto%'),
+
+ ("Fairhaven, Higher Walton, Preston, Lancashire", '2414', "Fairhaven"),
+ ('Fell House, Crockerton, Wilts.', '1003', "Fell House (Jean Curtis's)"),
+ ("Field View, Haddington, East Lothian", '2425', "Haddington"),
+ ('Fife Show', 'Unknown', 'Fife%'),
+ ("Findon Sheep Fair", "Event", "Findon Sheep Fair"),
+ ('Fines House Farm, Bishop Aukland, County Durham', '3610', 'Fines House Farm'),
+ ('Flag Fen Show', 'Unknown', 'Flag Fen'),
+ ('Formakin Farm, Somerset', '1199', 'Formakin Farm'),
+ ('Frome Show and Sale', 'Unknown', 'Frome%'),
+ ('Fronhaul, Whitland, Carmarthenshire', '3146', 'Fronhaul, Whitland'),
+ ('Fullwood Stile Farm, Hope, Derbyshire', '2674', 'Fulwood'),
+ ('Fullwood Stile Farm, Hope, Derbyshire', '2674', 'Fullwood Stile Farm'),
+
+ ("Goldcrest, Foston, Grantham, Lincolnshire", '2638', "Goldcrest"),
+ ('Goosnargh and Longridge Show', 'Unknown', 'Goosnargh and Longridge'),
+ ('Goosnargh and Longridge Show', 'Unknown', 'Gosssnargh%'),
+ ('Greenlands Farm, Carnforth', '3204', 'Greenlands%'),
+
+ ("Harbridge House (Meadow), Harbridge, Hampshire", 'Event', 'Hasbridge House Meadow'),
+ ("Harbridge House (Meadow), Harbridge, Hampshire", 'Event', "Harbridge House Meadow"),
+ ("Hartpury College, Gloucester", "Event", "Hartpury College"),
+ ('Herts County Show', 'Unknown', 'Herts Show'),
+ ('Higher Wringworthy Farm, Looe, Cornwall', '2740', 'Higher Wringworthy Farm'),
+ ('Highfield House, York', '2865', 'Highfield House'),
+ ('Highfield House, York', '2865', 'Harlthorpe'),
+ ('Highlands Farm, Kent', 'Event', 'Highlands Farm'),
+ ("Hill House, Ballindean, Perthshire", '0583', "Ballindean"),
+ ("Hillend Farm, Bishops Castle, Shropshire", '1514', "Hillend"),
+ ("Holme Lacey College, Herefordshire", "Event", "Holme Lacey"),
+ ('Home Farm, Stoney Stratton, Somerset', '1514', 'Home Farm'),
+ ('Home Farm, Stoney Stratton, Somerset', '1514', 'Stoney Stratton'),
+ ('Hornacott Manor, Cornwall', '3280', 'Hornacott Manor'),
+ ('Horton Park Farm (Horton Country Park), Kent', 'Event', 'Horton Park Farm'),
+ ("Howburn Cottage, Kincardine O'Neil, Aberdeenshire", '3023', "Howburn Cottage"),
+ ("Hudley Mill, Charles, Barnstable, Devon", '2046', "Charles, Devon"),
+
+ ("Inspectors Meeting, NAC", "Event", "Inspectors Mtg, NAC"),
+ ('Irvine, Ayrshire', '2502', '18 Queens Court' ),
+
+ ('Jasmine Cottage, Highbridge, Somerset', '3527', 'Jasmine Cottage'),
+
+ ("Lackham, Wiltshire", 'Event', "Lackham"),
+ ('Llandovery Mart', 'Event', 'Llandovery%'),
+ ('Lesmahagow Show', 'Unknown', 'Lesmahagow'),
+ ('Little Copse Farm, Devon', '2157', 'Little Copse Farm'),
+ ('Lothlorien Farm, Denbighshire', '2711', 'Lothlorien Farm'),
+ ('Lower Dickfield Farm, Ramsbotttom, Lancashire', '3041', 'Lower Dickfield Farm'),
+ ('Lower End Farm. Compton Bassett, Wiltshire', '1060', 'Lower End Farm'),
+ ("Lower Gravenor Farm, Bishop's Castle, Shropshire", '0828', "Bishop's Castle"),
+
+ ("Masham Sheep Fair, North Yorkshire", "Event", "Masham Sheep Fair"),
+ ('Meadowcroft Farm, Whitby, North Yorkshire', '2688', 'Meadowcroft Farm'),
+ ('Melton Mowbray Show and Sale', "Event", 'Melton Mowbray%'),
+ ('Middletown Farm, Lanark', '2152', 'Middleton Farm'),
+ ('Middletown Farm, Lanark', '2152', 'Middletown%'),
+ ('Middle Munty Farm, Taunton, Somerset', '2002', 'Middle Munty'),
+ ('Middle Munty Farm, Taunton, Somerset', '2002', 'Middle Munty Farm'),
+ ('Milton Abbot', 'Unknown', 'MILTON ABBOT'),
+ ('Mount Pleasant, Somerset', '3744', 'Mount Pleasant'),
+ ('M6 J36 Auction Mart', 'Event', 'Junction 36%'),
+
+ ("NAC, Stoneleigh", "Event", "NAC"),
+ ("Nant-y-Derw, Builth Wells, Powys", "0833", "Builth Wells"),
+ ("Nantymyn Retreat, Rhandirmwyn, Llandovery, Dyfed", '0768', "Nantymwyn"),
+ ('New Forest Show', 'Unknown', 'New Hampshire County Show'),
+ ('New Forest Show', 'Unknown', 'New Forest%'),
+ ("Newbury Show", "Unknown", "Newbury%"),
+ ('Newhouse Farm, Chalvington, East Sussex', '2513', 'Chalvington, E.Sussex'),
+ ('Newhouse Farm, Chalvington, East Sussex', '2513', 'Calvington, E.Sussex'),
+ ('Not recorded', 'Unknown', ''),
+ ('Not recorded', 'Unknown', 'Unknown'),
+ ('Not recorded', 'Unknown', 'unrecorded'),
+ ('Not recorded', 'Unknown', 'Unrecorded'),
+ ('Not recorded', 'Unknown', 'Not Specified'),
+ ('Nut Tree Cottage, Salisbury', '2472', 'Nut Tree Cottage'),
+ ('Nut Tree Cottage, Salisbury', '2472', 'Mandeville Flock'),
+
+ ('Okehampton Show', 'Unknown', 'Okehampton'),
+ ('Okehampton Show', 'Unknown', 'Okehampton Show'),
+ ('Old Seaxpenne Farm, Shaftesbury', '2321', '%Seaxpenny%'),
+ ("Owner's Farm (multiple unidentified)", 'On Farm', "at home"),
+ ("Owner's Farm (multiple unidentified)", 'On Farm', "Owner%"),
+
+ ('Pretty Oak Farm, Chard, Somerset', '0984', 'Pretty Oak Farm'),
+
+ ('Quendale House, Wheathampstead, Hertfordshire', '1833', 'Quendale Farm'),
+
+ ('Rambridge Farm, Chobham, Surrey', '0582', 'Rambridge'),
+ ('Ramsbottom, Bury, Lancashire', '1350', 'Ramsbottom'),
+ ('Ravendale Farm, Hitchin, Hertfordshire', '0022', 'Ravendale%'),
+ ('RBST Show and Sale', 'Unknown', 'Show %'),
+ ('RBST Show and Sale', 'Unknown', 'Stoneleigh%'),
+
+ ('Tenbury Wells Show', '', 'Tenbury%'),
+ ('The Brackens, Ercall Heath, Shropshire', '0306', 'The Brackens%'),
+
+
+ ("Re-inspection", "Event", "Re-inspection"),
+ ('Ripley Show', 'Unknown', 'Ripley'),
+ ('Rivendell, Hexham', '0824', 'Rivendell'),
+ ('Rivendell, Hexham', '0824', 'Hexham'),
+ ('Romanno Mains, Peeblesshire', '2592', 'Romanno Mains'),
+ ('Royal Highland Show', 'Unknown', 'Royal Shig%'),
+
+ ('Sandyacre, Newark', '2848', 'Sandyacres'),
+ ('Sedgemoor Show and Sale', "Event", 'Sedgemoor'),
+ ('Sedgemoor Show and Sale', "Event", 'Sedgemoor Auction'),
+ ('Sedgemoor Show and Sale', "Event", 'Sedgemoor Show & Sale'),
+ ('Sedgemoor Show and Sale', "Event", 'Sedgemoor Market'),
+ ('Sedgemoor Show and Sale', "Event", 'SEDGEMOOR SHOW & SALE'),
+ ('Sedgemoor Show and Sale', "Event", 'Sedgmoor%'),
+ ('Severn View Farm, Badminton, Gloucestershire', '2371', 'Severn View Farm'),
+ ("Shetland Sheep 2000 Lerwick", "Event", "Shetland Sheep 2000 Lerwick"),
+ ('Shustoke Show', '', 'Shustoke%'),
+ ('Singleton Show', '', 'Singleton%'),
+ ('Skipton Sale', '', 'Skipton%'),
+ ('Snagg Farm, Ditcheat, Somerset', '3958', '%Ditcheat'),
+ ("Snelston Hall, Ashbourne, Derbyshire", '2846', "Snelston Hall"),
+ ('South Beds Show', "Event", 'South Beds'),
+ ("South of England Show, Ardingly", "Unknown", "Ardingl%"),
+ ('South Wales', 'Unknown', 'SouthWales'),
+ ('South Worden Farm, Holmsworthy, Devon', '0771', 'South Worden%'),
+ ('Spring Hill Farm, Eyemouth, Berwickshire', '2270', 'Spring Hill Farm'),
+ ('Spring Holton Farm, Yeovil, Somerset', '2317', 'Spring Holton Farm'),
+ ('SSBG Show and Sale', 'Unknown', 'SSBG%' ),
+ ('St Baldred''s, East Lothian', '2160', "St.Baldred's"),
+ ('St Baldred''s, East Lothian', '2160', "St Baldred's"),
+ ('Staples Farm, Datchworth Hertfordshire', '2141', 'Staples Farm'),
+ ('Stubb Farm, Skipton, North Yorkshire', '3566', 'Stubb Farm'),
+ ('Summerside, Wishaw, Lanarkshire', '2436', 'Summerside Farm'),
+ ('Summerside, Wishaw, Lanarkshire', '2436', 'Summerside'),
+ ('Sunninglye Farmhouse, Kent', '2033', 'Sunninglye%'),
+ ("SW Area Workshop", "Event", "SW Area Workshop"),
+
+ ("Temple Newsam, Leeds", "Event", "Temple Newsam"),
+ ("Teaths Farm, Kirkfield Bank, Lanark, Lanarkshire", '2088', "Teaths Farm, Lanark"),
+ ('The Brackens, Ercall Heath, Shropshire', '0306', 'Brackens'),
+ ('The Bytack, Mynd, Bucknell, Shropshire', "2471", 'Mynd'),
+ ('The Old Barn, Sutton, Doncaster, South Yorkshire', '3187', 'The Old Barn, Sutton'),
+ ('The Old Surgery, Ercall Heath, Shropshire', '0306', 'The Old Surgery'),
+ ('The Old Surgery, Ercall Heath, Shropshire', '0306', 'Ercall Heath'),
+ ('The Rench, West Lothian', '2000', 'The Rench'),
+ ('The Rench, West Lothian', '2000', 'Rench'),
+ ('Twin Oaks, Welwyn, Hertfordshire', '3298', 'Twin Oaks, Welwyn'),
+ ("Tynrhos, Llanrhystud, Aberystwyth, Dyfed", '0544', 'Dunstone'),
+
+ ('Uffculme Show', '', 'Uffculme%'),
+ ('Upper Meadows, Dornoch, Sutherland', '2262', 'Dornock'),
+ ('Upper Meadows, Dornoch, Sutherland', '2262', 'Dornoch'),
+ ("Upper Millsteads, Canonbie, Dumfriesshire", '2583', 'Canonbie'),
+
+ ('Voley Farm, Parracombe, Devon', '2102', 'Voley Farm'),
+
+ ('Welland Down Farm, Devon', '2116', 'Welland%'),
+ ('Westmorland Show', 'Unknown', 'Westmoreland Show'),
+ ('Westmorland Show', 'Unknown', 'West Morland Show'),
+ ('Willowcroft, Crockerton, Somerset', '1003', 'Willowcroft'),
+ ('Willowcroft, Crockerton, Somerset', '1003', 'Crockerton'),
+ ('Winders Wood Cottage, Corbridge, Northumberland', '3230', 'Winders Wood Cottage'),
+ ('Wood Cottage Farm, Macclesfield, Cheshire', '2580', 'Woodcottage Farm'),
+ ("Wood Cottage Farm, Macclesfield, Cheshire", '2580', "Wood Cottage"),
+ ('Woodlands, Driffield, East Yorkshire', '2220', 'Woodlands, Kilham'),
+ ('Woodlands, Driffield, East Yorkshire', '2220' ,'Kilham'),
+ ('Wycoller, Lancashire', '1610', 'Wycoller'),
+ ('Wyndford Farm, Broxburn, West Lothian', '2036', 'Wyndford Farm'),
+
+ ("York Museum", "Event", "York Museum"),
+ ]
+ for row in venue_clean:
+ if len(row) != 3:
+ print(row)
+
+
try:
curs = self.db_conn.cursor()
- curs.executemany("update approval set venue = ? where venue = ?;",
- (row for row in venue_clean))
- curs.executemany("update approval set venue = ? where venue like ?;",
- (row for row in venue_clean_like))
+ curs.executemany("update approval set venue = ? , venue_type = ? "
+ "where venue like ?;", (row for row in venue_clean))
+ self.db_conn.commit()
+ except Exception as err:
+ raise CleanError(f"Error correcting inspection venues: {str(err)}")
+
+ try:
+ curs = self.db_conn.cursor()
+ curs.execute("UPDATE approval set venue = 'York Show and Sale' "
+ "where venue LIKE 'York%' AND venue NOT LIKE '%Museum%'" )
+ curs.execute("update approval set venue = 'Nant-y-Derw, Builth Wells, Powys', "
+ "venue_type = '0833' where venue like 'Nant%' and "
+ "venue not like '%Nantymwyn%';"),
+
self.db_conn.commit()
except Exception as err:
- raise CleanError(f"Error correcting inspection venues: {str(err)}")
+ raise CleanError(f"Error correcting multi-like venues: {str(err)}")
+
+ try: # Update the venue_type and member_no columns
+ curs = self.db_conn.cursor()
+ curs.execute("update approval set venue_type = 'Event' "
+ "where lower(venue) like '%show%' or "
+ "lower(venue) like '%sale%' ;")
+ curs.execute("update approval set venue_type = 'Farm', member_no = venue_type "
+ "where substr(venue_type, 1, 1) in ('0', '1', '2', '3', '4');")
+
+ self.db_conn.commit()
+ except sqlite3.Error as err:
+ raise CleanError(f"Error updating the approval venue_type: {str(err)}")
-
+ curs.execute("select * from approval where venue like 'Owner%' "
+ "order by sort_approval_date;")
+ rows = curs.fetchall()
+ for row in rows:
+ pprint.pprint(row)
+
Index: dataconv/convert.py
==================================================================
--- dataconv/convert.py
+++ dataconv/convert.py
@@ -397,11 +397,11 @@
try:
shutil.copyfile(sourcedb, self.cleandb)
except shutil.Error as sherr:
ConvertError("Error copying raw sqlite file: %s" % str(sherr))
- cleaner = cleansqlite.SSSClean(self.cleandb, debug)
+ cleaner = cleansqlite.SqliteClean(self.cleandb, debug)
cleaner.clean()
if self.ops['extract'] and not self.actions['keep']:
os.remove(sourcedb)
if self.ops['transform']:
Index: dataconv/transform.py
==================================================================
--- dataconv/transform.py
+++ dataconv/transform.py
@@ -309,11 +309,13 @@
self.message(" Transforming sheep identity tables...")
self.transform_sheep_identity_tables()
if not self.nomem:
self.message(" Transforming tag changes...")
self.transform_tag_audit_history()
+
self.message(" Transforming secondary registration data tables...")
+
self.transform_regn_secondary_tables()
self.message(" Creating essential views...")
self.create_essential_views()
self.message(" Creating user tables...")
self.create_user_tables()
@@ -1706,35 +1708,17 @@
self.populate_table_many('eid_type',
"INSERT INTO eid_type "
"VALUES(?, '', CAST(? as TEXT));",
((t, self.ts_now) for t in ('Bolus', 'Chip', 'Ear Tag')))
- self.create_table('venue_type')
- self.populate_table_many('venue_type',
- "INSERT INTO venue_type "
- "VALUES(?, '', CAST(? as TEXT));",
- ((t, self.ts_now) for t in ('Event', 'On Farm', 'Other')))
-
self.create_table('insp_venue')
self.populate_table('insp_venue',
"INSERT INTO insp_venue "
- "SELECT DISTINCT NULL, venue, 'Other', '', "
+ "SELECT DISTINCT NULL, venue, venue_type, member_no, '', "
"CAST(? as TEXT) FROM olddb.approval;",
(self.ts_now,))
- try: # Update the venue_type column
- self.curs.execute("update insp_venue set venue_type = 'Event' "
- "where lower(venue) like '%show%' or "
- "lower(venue) like '%sale%' ;")
- self.curs.execute("update insp_venue set venue_type = 'On Farm' "
- "where lower(venue) like 'Member%' or "
- "lower(venue) like '%farm%';")
- self.dbconn.commit()
- except sqlite3.Error as err:
- raise TransformError(f"Error updating the ins_venue venue_type: {str(err)}")
-
-
self.create_table('testing_lab')
self.populate_table('testing_lab',
"INSERT INTO testing_lab "
"SELECT DISTINCT NULL, testing_lab, '', "
"CAST(? as TEXT) "
@@ -2243,10 +2227,11 @@
"'ear_tag', ?, '', ?, ?);", (row for row in ch_rows))
self.dbconn.commit()
except sqlite3.Error as err:
raise TransformError("Error inserting tag change data "
"into audit_history: %s" % str(err))
+
def transform_regn_secondary_tables(self):
""" Transform the secondary data tables: ai_sires, inspection, inspector and
prp_genetics.
"""
Index: maketest.py
==================================================================
--- maketest.py
+++ maketest.py
@@ -160,11 +160,11 @@
print("Creating tar file '{}'".format(tarf))
out = tarfile.open(os.path.join(self.outdir, tarf), 'w:gz')
out.add(self.tsvpath, '')
out.close()
shutil.rmtree(self.tsvpath)
- os.remove(self.newdb)
+#~ os.remove(self.newdb)
if self.refresh:
test.refresh_test_database(os.path.splitext(self.outfile)[0])
class TestDB(transform.Transform):
@@ -265,10 +265,12 @@
self.reset_transfers()
self.message(" Inserting person related records...")
self.select_person_related()
self.message(" Inserting member related records...")
self.select_member_related()
+ self.message(" Inserting inspection related records...")
+ self.select_insp_related()
self.message(" Adding record to allow Login and Change Password to be tests...")
self.add_login_test()
self.message(" Creating indexes on new tables...")
for tablename in self.new_tables:
self.create_indexes(tablename)
@@ -707,10 +709,12 @@
self.new_table('member')
try:
self.curs.execute("insert into member select * from olddb.member "
"where member_no in (select distinct member_no from person) ;")
self.dbconn.commit()
+ self.curs.execute("select * from member where member_no = '0833';")
+ print(f"Member 0833: {self.curs.fetchone()}")
except sqlite3.Error as err:
raise transform.TransformError(
"Error inserting member records: {}".format(str(err)))
self.new_table('mem_pmts')
@@ -739,10 +743,31 @@
"where member_no in (select member_no from member);")
self.dbconn.commit()
except sqlite3.Error as err:
raise transform.TransformError("Error inserting fbk_order records: %s" %
str(err))
+
+ def select_insp_related(self):
+ """ Add member and person records for the inspection venue foreign key constraint """
+ print("Selecting insp related members")
+ try:
+ self.curs.execute("insert into member select * from olddb.member "
+ "where member_no in "
+ "(select distinct member_no from olddb.insp_venue) "
+ "and member_no not in (select member_no from member);")
+ self.curs.execute("insert into mem_pmts select * from olddb.mem_pmts "
+ "where member_no in "
+ "(select distinct member_no from olddb.insp_venue) "
+ "and member_no not in (select member_no from mem_pmts);")
+ self.curs.execute("insert into person select * from olddb.person "
+ "where member_no in "
+ "(select distinct member_no from olddb.insp_venue) "
+ "and person_id not in (select person_id from person);")
+ self.dbconn.commit()
+ except sqlite3.Error as err:
+ raise transform.TransformError(
+ f"Error inserting member records for venues: {str(err)}")
def reset_transfers(self):
""" Remove transfers, either from real transfers or from running
'Update Presumed Dead' that cause errors when running the test suite.
This will need to be updated at intervals as and when test failures are due to
@@ -778,13 +803,13 @@
try:
self.curs.execute("delete from transfer where regn_no = '041084' "
"and transfer_date > '2006-09-02';")
self.dbconn.commit()
except sqlite3.Error as err:
- raise transform.TransformError("Error deleting transfer records for 041084: %s" %
- str(err))
-
+ raise transform.TransformError(f"Error deleting transfer records for "
+ "041084: {str(err)}")
+
def add_login_test(self):
""" Add records and passwords to allow the Login and Change Password function to be
tested
"""
# Add a test email to member 1189 primary person, and to a secondary person
Index: ppdb/config_db.py
==================================================================
--- ppdb/config_db.py
+++ ppdb/config_db.py
@@ -147,10 +147,16 @@
'DELETE': ()},})
uri_tree.sheep.insp = sheepuri.Inspection(appconf,
{'tools.check_auth.url_roles': {'GET': ('regsec', 'memsec', 'socsec', 'admin'),
'PUT': ('regsec', 'admin',),
+ 'POST': (),
+ 'DELETE': ()},})
+
+ uri_tree.sheep.inspnew = sheepuri.InspNew(appconf,
+ {'tools.check_auth.url_roles': {'GET': ('regsec', 'admin'),
+ 'PUT': (),
'POST': ('regsec', 'admin',),
'DELETE': ()},})
uri_tree.sheep.nav = sheepuri.Nav(appconf,
{'tools.check_auth.url_roles': {'GET': ('regsec', 'memsec', 'socsec', 'admin'),
Index: ppdb/const.py
==================================================================
--- ppdb/const.py
+++ ppdb/const.py
@@ -26,11 +26,11 @@
JINJA_ENV = None
""" The Jinja2 templating environment. Initialised at app startup by ppd.py """
VERSION = '0.93.0'
VERSION__doc = """ The PPDB code version """
-SCHEMA = '34.0'
+SCHEMA = '34.2'
SCHEMA__doc = """ The PPDB database schema version """
BREED_ID_CHAR = 'Z'
Index: ppdb/handlers/sheepuri.py
==================================================================
--- ppdb/handlers/sheepuri.py
+++ ppdb/handlers/sheepuri.py
@@ -843,45 +843,64 @@
@cherrypy.expose
class Inspection(SheepBase):
""" Sheep inspections.
- This class supports the GET, POST and PUT methods.
+ This class supports the GET and PUT methods.
Additional path elements/query args are: 'rid' and 'hist'.
- 'rid' is a sheep registration number, or a name which resolves to a
single sheep.
- - 'hist', as a parameter to GET, specifies that the sheep's transfer
- history is to be reurned, otherwise and HTML form allowing the sheep's
- transfer history to be updated is returned.
-
"""
def __init__(self, config, path_conf=None):
super().__init__(config, path_conf)
self.resname = "Inspections"
def GET(self, rid=None):
- """ GET a sheep's Inspection history. """
+ """ GET a sheep's Inspection history or a summary page if rid is None. """
page_info = self.html_appconf_items()
- page_info.update({'pagetitle': 'Sheep Inspections',
+ page_info.update({'pagetitle': 'Sheep Inspection History',
'requestpath': cherrypy.request.path_info})
page_info['titlebar'] = page_info['pagetitle']
- template = const.JINJA_ENV.get_template('templates/underconst.tmpl')
+ template = const.JINJA_ENV.get_template('templates/inspection.tmpl')
return template.render(page_info)
def PUT(self):
- """ Update a sheep's transfer history. """
+ """ Update a sheep's inspection history. """
return 'Under Construction!'
+
+@cherrypy.expose
+class InspNew(SheepBase):
+ """ New Sheep inspections.
+
+ This class supports the GET and POST methods.
+ Additional path elements/query args are: 'rid' and 'hist'.
+
+ """
+
+ def __init__(self, config, path_conf=None):
+ super().__init__(config, path_conf)
+ self.resname = "Inspections"
+
+ def GET(self):
+ """ GET a page to enter new sheep inspections. """
+ page_info = self.html_appconf_items()
+ page_info['venues'] = memlib.get_insp_venues()
+ page_info['inspectors'] = memlib.get_inspectors()
+ page_info.update({'pagetitle': 'Sheep Inspections',
+ 'requestpath': cherrypy.request.path_info})
+ page_info['titlebar'] = page_info['pagetitle']
+ template = const.JINJA_ENV.get_template('templates/inspnew.tmpl')
+ return template.render(page_info)
+
def POST(self):
- """ Update a sheep's transfer history. """
+ """ Add a new inspection record. """
return 'Under Construction!'
-
-
@cherrypy.expose
class Genotype(SheepBase):
""" Sheep genotyping.
This class supports the GET, POST and PUT methods.
Index: ppdb/lib/memlib.py
==================================================================
--- ppdb/lib/memlib.py
+++ ppdb/lib/memlib.py
@@ -612,11 +612,34 @@
"e.date_assigned, e.change_reason, e.last_changed "
"from email e "
"where e.email_id = ? and address <> '';",
(email_id,))
return curs.fetchone()
-
+def get_inspectors(status=None):
+ """ Return the full and trainee inspectors and their status """
+ with pglib.get_conn():
+ with pglib.cursor() as curs:
+ curs.execute("select p.person_id, substring(r.role from 1 for 1) as status,"
+ " p.initials || ' ' || p.surname as insp_name "
+ "from person p join person_role r on p.person_id = r.person_id "
+ "where r.role in ('Inspector', 'Trainee') "
+ "order by status, p.surname; ")
+#~ return [{key: row[key] for key in row.keys()} for row in curs.fetchall()]
+ return curs.fetchall()
+
+def get_insp_venues(venue_type=None):
+ """ Return the recorded inspection venues """
+ with pglib.get_conn():
+ with pglib.cursor() as curs:
+ if not venue_type:
+ curs.execute("select venue_id, venue, venue_type from insp_venue "
+ "order by venue_type, venue;")
+ else:
+ curs.execute("select venue_id, venue, venue_type from insp_venue "
+ "where venue_type = ? order by venue;", (venue_type,))
+ return curs.fetchall()
+
def get_mem_data_for_dialog(rows, sortby, sortdir):
""" Return rows of member data for the multi-member dialog. """
orderby = MEMBER_SORT_TRANSLATE.get(sortby, 'm.member_no')
qry = ("select m.member_no, p.title, p.initials, p.forename, p.surname, m.address_1, "
"m.address_2, m.address_3, m.post_town, m.county, m.post_code, m.country "
Index: ppdb/lib/sheep_schema.py
==================================================================
--- ppdb/lib/sheep_schema.py
+++ ppdb/lib/sheep_schema.py
@@ -44,11 +44,11 @@
"""
# Disable constant name case warnings
# pylint: disable=C0103
# The schema version
-schema_version = "34.0"
+schema_version = "34.2"
#: The table creation order - parent and look-up tables must be created and populated
#: before their child tables.
table_list = ["version", "audit_history", "mem_dates",
"pmt_method", "mem_source", "nonren_reason", "phone_type", "role_type", "county",
@@ -55,11 +55,11 @@
"adj_county", "country", "region", "in_region", "post_area", "adj_post_area",
"mem_class", "member", "person", "mem_pmts", "privacy_options",
"mem_privacy", "phone", "email",
"person_role", "reps_county", "reps_country", "reps_region", "flock",
"flock_owner", "health_scheme", "tag_prefix", 'eid_type',
- "id_reason", "venue_type", "insp_venue", "testing_lab", "prp_alleles",
+ "id_reason", "insp_venue", "testing_lab", "prp_alleles",
"colour", "pattern", "regn_code", "transfer_reason",
"flock_book_vol", "fbk_order", "flock_stats", "flock_health", "sheep",
"transfer", "ai_sires","flock_prefix", "ear_tag", "eid", "inspection",
"inspector", "prp_genetics", "rc_queue", "pc_queue", "pedcerts"]
@@ -928,33 +928,24 @@
"columns": [("eid_type", "VARCHAR(32) PRIMARY KEY"),
("change_reason", "VARCHAR(32) NOT NULL"),
("last_changed", "TIMESTAMP NOT NULL")]
}
-#: The known Inspection venue types.
-venue_type = {
- "type": "table",
- "history": "yes",
- "triggers": ["set_ts", "audit_action"],
- "select_cols": [0],
- "columns": [("venue_type", "VARCHAR(24) PRIMARY KEY"),
- ("change_reason", "VARCHAR(32) NOT NULL"),
- ("last_changed", "TIMESTAMP NOT NULL")]
-}
-
#: The known Inspection venues.
insp_venue = {
"type": "table",
"history": "yes",
"triggers": ["set_ts", "audit_action"],
"select_cols": [0],
"columns": [("venue_id", "SERIAL PRIMARY KEY"),
("venue", "TEXT NOT NULL UNIQUE"),
- ("venue_type", "VARCHAR(24) NOT NULL REFERENCES venue_type (venue_type) "
- "ON UPDATE RESTRICT ON DELETE RESTRICT"),
- ("change_reason", "VARCHAR(32) NOT NULL"),
- ("last_changed", "TIMESTAMP NOT NULL")]
+ ("venue_type", "TEXT NOT NULL"),
+ ("member_no", "VARCHAR(6) REFERENCES member (member_no) "
+ "ON UPDATE RESTRICT ON DELETE RESTRICT"), ("change_reason", "VARCHAR(32) NOT NULL"),
+ ("last_changed", "TIMESTAMP NOT NULL")],
+#~ "constraints": ["CONSTRAINT venue_type_check CHECK (venue_type in ('Event', 'On Farm', "
+#~ "'Other'))"]
}
#: The known PrP genotyping testing laboratories.
testing_lab = {
"type": "table",
ADDED ppdb/static/js/inspnew.js
Index: ppdb/static/js/inspnew.js
==================================================================
--- /dev/null
+++ ppdb/static/js/inspnew.js
@@ -0,0 +1,126 @@
+//
+// inspection.js
+//
+// A module of event handler assignments for the sheep inspection page.
+//
+// Copyright PR Hardman 2009 - 2022
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details./
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see
| + |
+ Regn No {{sb_regnno}}
+ |
+
+ Sheep Name {{sb_name}}
+ |
+
+ Insp. Date {{sb_date}}
+ |
+
+ Venue {{sb_venue}}
+ |
+
+ Result {{sb_result}}
+ |
+
|---|---|---|---|---|---|
| {{insp[0]}} | +{{insp[1]}} | +{{insp[2]}} | +{{insp[3]}} | +{{insp[4]}} | +{{insp[5]}} | +
| + | T/I | +Name | +Select | +
|---|---|---|---|
| {{insp[0]}} | +{{insp[1]}} | ++ | + |
| + | Venue | +Type | +
|---|---|---|
| {{venue[0]}} | +{{venue[1]}} | +{{venue[2]}} | +