Skip to content

Commit

Permalink
feat(import): move geom_from_area_code to synthese imports
Browse files Browse the repository at this point in the history
  • Loading branch information
edelclaux committed Feb 20, 2024
1 parent 9aea5a2 commit 2edc5b1
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 90 deletions.
28 changes: 25 additions & 3 deletions backend/geonature/core/gn_synthese/imports/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
check_nomenclature_blurring,
check_nomenclature_source_status,
convert_geom_columns,
set_geom_point,
check_cd_nom,
check_cd_hab,
generate_altitudes,
Expand All @@ -39,9 +40,12 @@
check_depths,
check_digital_proof_urls,
check_geography_outside,
check_geometry_defined,
check_is_valid_geography,
)

from .geo import convert_geom_columns_from_area_code


def check_transient_data(task, logger, imprt):
entity = Entity.query.filter_by(destination=imprt.destination).one() # Observation
Expand Down Expand Up @@ -147,16 +151,34 @@ def update_batch_progress(batch, step):

# Checks in SQL
convert_geom_columns(
imprt,
entity,
geom_4326_field=fields["the_geom_4326"],
geom_local_field=fields["the_geom_local"]
)

convert_geom_columns_from_area_code(
imprt,
entity,
geom_4326_field=fields["the_geom_4326"],
geom_local_field=fields["the_geom_local"],
geom_point_field=fields["the_geom_point"],
codecommune_field=fields["codecommune"],
codemaille_field=fields["codemaille"],
codedepartement_field=fields["codedepartement"],
)
codedepartement_field=fields["codedepartement"])

if fields["the_geom_point"] != None:
set_geom_point(
imprt=imprt,
entity=entity,
geom_4326_field=fields["the_geom_4326"],
geom_point_field=fields["the_geom_point"],
)

check_geometry_defined(
imprt=imprt,
entity=entity,
geom_4326_field=fields["the_geom_4326"])

do_nomenclatures_mapping(
imprt,
entity,
Expand Down
89 changes: 89 additions & 0 deletions backend/geonature/core/gn_synthese/imports/geo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
from sqlalchemy.sql.expression import select, update, join
import sqlalchemy as sa

from geoalchemy2.functions import ST_Transform, ST_Centroid
from geonature.core.imports.checks.sql.utils import report_erroneous_rows
from geonature.utils.env import db

from ref_geo.models import LAreas, BibAreasTypes


def set_geom_from_area_code(
imprt, entity, geom_4326_col, geom_local_col, source_column, area_type_filter
): # XXX specific synthese
transient_table = imprt.destination.get_transient_table()
# Find area in CTE, then update corresponding column in statement
cte = (
select(
transient_table.c.id_import,
transient_table.c.line_no,
LAreas.id_area,
LAreas.geom,
# TODO: add LAreas.geom_4326
)
.select_from(
join(transient_table, LAreas, source_column == LAreas.area_code).join(BibAreasTypes)
)
.where(transient_table.c.id_import == imprt.id_import)
.where(transient_table.c[entity.validity_column] == True)
.where(transient_table.c[geom_4326_col] == None) # geom_4326 & local should be aligned
.where(area_type_filter)
.cte("cte")
)
stmt = (
update(transient_table)
.values(
{
transient_table.c.id_area_attachment: cte.c.id_area,
transient_table.c[geom_local_col]: cte.c.geom,
transient_table.c[geom_4326_col]: ST_Transform(
cte.c.geom, 4326
), # TODO: replace with cte.c.geom_4326
}
)
.where(transient_table.c.id_import == cte.c.id_import)
.where(transient_table.c.line_no == cte.c.line_no)
)
db.session.execute(stmt)


def convert_geom_columns_from_area_code(
imprt,
entity,
geom_4326_field,
geom_local_field,
codecommune_field=None,
codemaille_field=None,
codedepartement_field=None,
):
transient_table = imprt.destination.get_transient_table()

for field, area_type_filter in [
(codecommune_field, BibAreasTypes.type_code == "COM"),
(codedepartement_field, BibAreasTypes.type_code == "DEP"),
(codemaille_field, BibAreasTypes.type_code.in_(["M1", "M5", "M10"])),
]:
if field is None:
continue
source_column = transient_table.c[field.source_field]
# Set geom from area of the given type and with matching area_code:
set_geom_from_area_code(
imprt,
entity,
geom_4326_field.dest_field,
geom_local_field.dest_field,
source_column,
area_type_filter,
)
# Mark rows with code specified but geom still empty as invalid:
report_erroneous_rows(
imprt,
entity,
error_type="INVALID_ATTACHMENT_CODE",
error_column=field.name_field,
whereclause=sa.and_(
transient_table.c[geom_4326_field.dest_field] == None,
transient_table.c[entity.validity_column] == True,
source_column != None,
),
)
100 changes: 13 additions & 87 deletions backend/geonature/core/imports/checks/sql/geo.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,66 +9,35 @@

from geonature.core.imports.checks.sql.utils import report_erroneous_rows

from ref_geo.models import LAreas, BibAreasTypes
from ref_geo.models import LAreas


__all__ = [
"set_geom_from_area_code",
"set_geom_point",
"convert_geom_columns",
"check_is_valid_geography",
"check_geometry_defined",
"check_geography_outside",
]


def set_geom_from_area_code(
imprt, entity, geom_4326_col, geom_local_col, source_column, area_type_filter
): # XXX specific synthese
def set_geom_point(imprt, entity, geom_4326_field, geom_point_field):
transient_table = imprt.destination.get_transient_table()
# Find area in CTE, then update corresponding column in statement
cte = (
select(
transient_table.c.id_import,
transient_table.c.line_no,
LAreas.id_area,
LAreas.geom,
# TODO: add LAreas.geom_4326
)
.select_from(
join(transient_table, LAreas, source_column == LAreas.area_code).join(BibAreasTypes)
)
.where(transient_table.c.id_import == imprt.id_import)
.where(transient_table.c[entity.validity_column] == True)
.where(transient_table.c[geom_4326_col] == None) # geom_4326 & local should be aligned
.where(area_type_filter)
.cte("cte")
)
# Set the_geom_point:
stmt = (
update(transient_table)
.where(transient_table.c.id_import == imprt.id_import)
.where(transient_table.c[entity.validity_column] == True)
.values(
{
transient_table.c.id_area_attachment: cte.c.id_area,
transient_table.c[geom_local_col]: cte.c.geom,
transient_table.c[geom_4326_col]: ST_Transform(
cte.c.geom, 4326
), # TODO: replace with cte.c.geom_4326
geom_point_field.dest_field: ST_Centroid(
transient_table.c[geom_4326_field.dest_field]
),
}
)
.where(transient_table.c.id_import == cte.c.id_import)
.where(transient_table.c.line_no == cte.c.line_no)
)
db.session.execute(stmt)


def convert_geom_columns(
imprt,
entity,
geom_4326_field,
geom_local_field,
geom_point_field=None,
codecommune_field=None,
codemaille_field=None,
codedepartement_field=None,
):
def convert_geom_columns(imprt, entity, geom_4326_field, geom_local_field):
local_srid = db.session.execute(sa.func.Find_SRID("ref_geo", "l_areas", "geom")).scalar()
transient_table = imprt.destination.get_transient_table()
if geom_4326_field is None:
Expand All @@ -94,35 +63,8 @@ def convert_geom_columns(
)
db.session.execute(stmt)

for field, area_type_filter in [
(codecommune_field, BibAreasTypes.type_code == "COM"),
(codedepartement_field, BibAreasTypes.type_code == "DEP"),
(codemaille_field, BibAreasTypes.type_code.in_(["M1", "M5", "M10"])),
]:
if field is None:
continue
source_column = transient_table.c[field.source_field]
# Set geom from area of the given type and with matching area_code:
set_geom_from_area_code(
imprt,
entity,
geom_4326_field.dest_field,
geom_local_field.dest_field,
source_column,
area_type_filter,
)
# Mark rows with code specified but geom still empty as invalid:
report_erroneous_rows(
imprt,
entity,
error_type="INVALID_ATTACHMENT_CODE",
error_column=field.name_field,
whereclause=sa.and_(
transient_table.c[geom_4326_field.dest_field] == None,
transient_table.c[entity.validity_column] == True,
source_column != None,
),
)
def check_geometry_defined(imprt, entity, geom_4326_field):
transient_table = imprt.destination.get_transient_table()
# Mark rows with no geometry as invalid:
report_erroneous_rows(
imprt,
Expand All @@ -134,22 +76,6 @@ def convert_geom_columns(
transient_table.c[entity.validity_column] == True,
),
)
# Set the_geom_point:
if geom_point_field is not None:
stmt = (
update(transient_table)
.where(transient_table.c.id_import == imprt.id_import)
.where(transient_table.c[entity.validity_column] == True)
.values(
{
geom_point_field.dest_field: ST_Centroid(
transient_table.c[geom_4326_field.dest_field]
),
}
)
)
db.session.execute(stmt)


def check_is_valid_geography(imprt, entity, wkt_field, geom_field):
# It is useless to check valid WKT when created from X/Y
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
check_dates,
check_altitudes,
check_depths,
check_geometry_defined,
check_is_valid_geography,
set_id_parent_from_destination,
set_parent_line_no,
Expand Down Expand Up @@ -142,6 +143,11 @@ def check_transient_data(task, logger, imprt):
geom_4326_field=fields["geom_4326"],
geom_local_field=fields["geom_local"],
)
check_geometry_defined(
imprt=imprt,
entity=entity,
geom_4326_field=fields["geom_4326"]
)
if imprt.fieldmapping.get("altitudes_generate", False):
generate_altitudes(
imprt, fields["the_geom_local"], fields["altitude_min"], fields["altitude_max"]
Expand Down

0 comments on commit 2edc5b1

Please sign in to comment.