From 4c0e849ff3a856083e5225e5665b34763f1f8888 Mon Sep 17 00:00:00 2001 From: Kevin Date: Thu, 11 Jan 2024 10:41:27 +0100 Subject: [PATCH] fix(Cost Surface): Fixes a bug in the insertion of Cost Surface PUs for projects without a shapefile Also includes script to fix incorrect pu data in the DB --- .../planning-units/planning-units.job.ts | 4 +- .../cost-surface-incorrect-pu-data-purge.py | 85 +++++++++++++++++++ 2 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 data/scripts/cost-surface/cost-surface-incorrect-pu-data-purge.py diff --git a/api/apps/geoprocessing/src/modules/planning-units/planning-units.job.ts b/api/apps/geoprocessing/src/modules/planning-units/planning-units.job.ts index da6e68425a..51d950ba6d 100644 --- a/api/apps/geoprocessing/src/modules/planning-units/planning-units.job.ts +++ b/api/apps/geoprocessing/src/modules/planning-units/planning-units.job.ts @@ -253,9 +253,9 @@ grid.geom SELECT ppu.id, round(pug.area / 1000000) as area, $1 FROM projects_pu ppu INNER JOIN planning_units_geom pug ON pug.id = ppu.geom_id - WHERE ppu.geom_id = $2 + WHERE ppu.geom_id = $2 AND ppu.project_id = $3 `, - [job.data.costSurfaceId, geometryId], + [job.data.costSurfaceId, geometryId, job.data.projectId], ); }); }, diff --git a/data/scripts/cost-surface/cost-surface-incorrect-pu-data-purge.py b/data/scripts/cost-surface/cost-surface-incorrect-pu-data-purge.py new file mode 100644 index 0000000000..43873bcf58 --- /dev/null +++ b/data/scripts/cost-surface/cost-surface-incorrect-pu-data-purge.py @@ -0,0 +1,85 @@ +import psycopg2 + + +dry_run = False + +# Connect to Database 1 +api_db = psycopg2.connect( + host="localhost", + database="marxan-api", + user="marxan-api", + password="marxan-api", + port=3432 +) + +# Connect to Database 2 +geo_db = psycopg2.connect( + host="localhost", + database="marxan-geo-api", + user="marxan-geo-api", + password="marxan-geo-api", + port=3433 +) + +# Initialize the cursor for api_db +cur_api_db = api_db.cursor() +cur_geo_db = geo_db.cursor() + +try: + + cur_api_db.execute("BEGIN;") + cur_geo_db.execute("BEGIN;") + + cur_geo_db.execute(''' select cspd.cost_surface_id + from cost_surface_pu_data cspd + inner join projects_pu pp on pp.id = cspd.projects_pu_id + group by cspd.cost_surface_id + having count(distinct pp.project_id) > 1 ''') + incorrect_cost_surfaces = cur_geo_db.fetchall() + + for cost_surface in incorrect_cost_surfaces: + cost_surface_id = cost_surface + + cur_api_db.execute( '''select project_id from cost_surfaces where id = %s ''', (cost_surface_id),) + project = cur_api_db.fetchone() # Retrieve the project id that the cost surface is associated to + + if project is None: + #It can happen that the cost surface has been deleted, but there's dangling data because most probably + #the clean up process doesn't account for this incorrect pu data that has leaked into cost_surface_pu_data + print('Cost Surface ', cost_surface_id, ' not found on API') + delete_incorrect_pu_data_sql = ''' + DELETE FROM cost_surface_pu_data cspd + USING projects_pu pp + WHERE pp.id = cspd.projects_pu_id AND cspd.cost_surface_id = %s + RETURNING pp.project_id + ''' + cur_geo_db.execute(delete_incorrect_pu_data_sql, (cost_surface_id)) + else: + project_id = project + delete_incorrect_pu_data_sql = ''' + DELETE FROM cost_surface_pu_data cspd + USING projects_pu pp + WHERE pp.id = cspd.projects_pu_id AND cspd.cost_surface_id = %s AND NOT pp.project_id = %s + RETURNING pp.project_id + ''' + cur_geo_db.execute(delete_incorrect_pu_data_sql, (cost_surface_id, project_id)) + + deleted_rows = cur_geo_db.fetchall() + + print("Successfully purged ", len(deleted_rows), " rows of incorrect pu data for Cost Surface: ", cost_surface_id) + + + if dry_run is False: + cur_api_db.execute("COMMIT;") + cur_geo_db.execute("COMMIT;") + else: + cur_api_db.execute("ROLLBACK;") + cur_geo_db.execute("ROLLBACK;") + + print("Successfully purged all incorrect Cost Surface pu data") + + +except Exception as e: + print(f"An error occurred: {e}") + cur_api_db.execute("ROLLBACK;") + cur_geo_db.execute("ROLLBACK;")