from __future__ import annotations from datetime import date, datetime from decimal import Decimal from uuid import UUID from django.core.management.base import BaseCommand from django.db import transaction from django.utils.dateparse import parse_datetime from location_data.models import ( AnalysisGridCell, AnalysisGridObservation, BlockSubdivision, NdviObservation, RemoteSensingClusterAssignment, RemoteSensingClusterBlock, RemoteSensingRun, RemoteSensingSubdivisionOption, RemoteSensingSubdivisionOptionAssignment, RemoteSensingSubdivisionOptionBlock, RemoteSensingSubdivisionResult, SoilLocation, ) SEED_DATA = { "soillocations": [ { "id": 1, "latitude": "50.000000", "longitude": "50.000000", "task_id": "", "farm_boundary": { "type": "Polygon", "coordinates": [[[49.9995, 49.9995], [50.0005, 49.9995], [50.0005, 50.0005], [49.9995, 50.0005], [49.9995, 49.9995]]], }, "input_block_count": 1, "block_layout": { "blocks": [ { "order": 1, "source": "default", "boundary": {}, "block_code": "block-1", "sub_blocks": [], "needs_subdivision": None, }, { "order": 2, "source": "remote_sensing", "block_code": "", "sub_blocks": [ { "geometry": {"type": "Polygon", "coordinates": [[[49.9995, 49.9995], [49.99992, 49.9995], [50.000339, 49.9995], [50.000339, 49.99977], [50.000339, 50.00004], [49.99992, 50.00004], [49.9995, 50.00004], [49.9995, 49.99977], [49.9995, 49.9995]]]}, "metadata": {"source": "analysis_grid_cells", "center_selection": {"strategy": "coordinate_1_center", "center_radius": 0.0004993, "center_cell_code": "loc-1__block-farm__chunk-900__r0000c0000", "center_mean_distance": 0.00029732}, "cell_geometry_type": "Polygon"}, "cell_count": 4, "centroid_lat": 49.99977, "centroid_lon": 49.99992, "cluster_uuid": "daa278cb-cf75-4f17-bc94-bb3a780dd4d4", "cluster_label": 0, "sub_block_code": "cluster-0", "center_cell_lat": 49.999635, "center_cell_lon": 49.99971, "center_cell_code": "loc-1__block-farm__chunk-900__r0000c0000", }, { "geometry": {"type": "Polygon", "coordinates": [[[50.000339, 49.9995], [50.000759, 49.9995], [50.000759, 49.99977], [50.000759, 50.00004], [50.000759, 50.000309], [50.000759, 50.000579], [50.000339, 50.000579], [49.99992, 50.000579], [49.9995, 50.000579], [49.9995, 50.000309], [49.9995, 50.00004], [49.99992, 50.00004], [50.000339, 50.00004], [50.000339, 49.99977], [50.000339, 49.9995]]]}, "metadata": {"source": "analysis_grid_cells", "center_selection": {"strategy": "coordinate_1_center", "center_radius": 0.0006827, "center_cell_code": "loc-1__block-farm__chunk-900__r0002c0001", "center_mean_distance": 0.00041092}, "cell_geometry_type": "Polygon"}, "cell_count": 8, "centroid_lat": 50.000174, "centroid_lon": 50.000235, "cluster_uuid": "e9beea1c-8736-4c45-ac5b-f186705bad76", "cluster_label": 1, "sub_block_code": "cluster-1", "center_cell_lat": 50.000174, "center_cell_lon": 50.00013, "center_cell_code": "loc-1__block-farm__chunk-900__r0002c0001", }, ], "needs_subdivision": True, "subdivision_summary": { "type": "data_driven_remote_sensing", "run_id": 1, "cluster_count": 2, "used_cell_count": 12, "selected_features": ["ndvi", "ndwi", "soil_vv_db"], "skipped_cell_count": 0, }, }, ], "algorithm_status": "completed", "default_full_farm": True, "input_block_count": 1, "analysis_grid_summary": {"cell_count": 12, "chunk_size_sqm": 900}, }, "created_at": "2026-05-11T14:41:43.319380+00:00", "updated_at": "2026-05-12T12:37:38.239904+00:00", } ], "blocksubdivisions": [], "remotesensingruns": [ { "id": 1, "soil_location_id": 1, "block_subdivision_id": None, "block_code": "", "provider": "openeo", "chunk_size_sqm": 900, "temporal_start": "2026-04-11", "temporal_end": "2026-05-11", "status": "success", "metadata": {"farm_uuid": "11111111-1111-1111-1111-111111111111", "requested_via": "api", "scope": "all_blocks"}, "error_message": "", "started_at": "2026-05-12T12:19:03.911826+00:00", "finished_at": "2026-05-12T12:37:39.018428+00:00", "created_at": "2026-05-12T12:19:03.912346+00:00", "updated_at": "2026-05-12T12:37:39.019007+00:00", } ], "remotesensingsubdivisionresults": [ { "id": 1, "soil_location_id": 1, "run_id": 1, "block_subdivision_id": None, "block_code": "", "chunk_size_sqm": 900, "temporal_start": "2026-04-11", "temporal_end": "2026-05-11", "cluster_count": 2, "selected_features": ["ndvi", "ndwi", "soil_vv_db"], "skipped_cell_codes": [], "metadata": {"selection_strategy": "elbow", "used_cell_count": 12}, "created_at": "2026-05-12T12:37:27.897155+00:00", "updated_at": "2026-05-12T12:37:27.897180+00:00", } ], "remotesensingclusterblocks": [ { "id": 1, "uuid": "daa278cb-cf75-4f17-bc94-bb3a780dd4d4", "result_id": 1, "soil_location_id": 1, "block_subdivision_id": None, "block_code": "", "sub_block_code": "cluster-0", "cluster_label": 0, "chunk_size_sqm": 900, "centroid_lat": "49.999770", "centroid_lon": "49.999920", "center_cell_code": "loc-1__block-farm__chunk-900__r0000c0000", "center_cell_lat": "49.999635", "center_cell_lon": "49.999710", "geometry": {"type": "Polygon", "coordinates": [[[49.9995, 49.9995], [49.99992, 49.9995], [50.000339, 49.9995], [50.000339, 49.99977], [50.000339, 50.00004], [49.99992, 50.00004], [49.9995, 50.00004], [49.9995, 49.99977], [49.9995, 49.9995]]]}, "cell_count": 4, "cell_codes": ["loc-1__block-farm__chunk-900__r0000c0000", "loc-1__block-farm__chunk-900__r0000c0001", "loc-1__block-farm__chunk-900__r0001c0000", "loc-1__block-farm__chunk-900__r0001c0001"], "metadata": {"source": "analysis_grid_cells"}, "created_at": "2026-05-12T12:37:27.899874+00:00", "updated_at": "2026-05-12T12:37:27.899899+00:00", }, { "id": 2, "uuid": "e9beea1c-8736-4c45-ac5b-f186705bad76", "result_id": 1, "soil_location_id": 1, "block_subdivision_id": None, "block_code": "", "sub_block_code": "cluster-1", "cluster_label": 1, "chunk_size_sqm": 900, "centroid_lat": "50.000174", "centroid_lon": "50.000235", "center_cell_code": "loc-1__block-farm__chunk-900__r0002c0001", "center_cell_lat": "50.000174", "center_cell_lon": "50.000130", "geometry": {"type": "Polygon", "coordinates": [[[50.000339, 49.9995], [50.000759, 49.9995], [50.000759, 49.99977], [50.000759, 50.00004], [50.000759, 50.000309], [50.000759, 50.000579], [50.000339, 50.000579], [49.99992, 50.000579], [49.9995, 50.000579], [49.9995, 50.000309], [49.9995, 50.00004], [49.99992, 50.00004], [50.000339, 50.00004], [50.000339, 49.99977], [50.000339, 49.9995]]]}, "cell_count": 8, "cell_codes": ["loc-1__block-farm__chunk-900__r0000c0002", "loc-1__block-farm__chunk-900__r0001c0002", "loc-1__block-farm__chunk-900__r0002c0000", "loc-1__block-farm__chunk-900__r0002c0001", "loc-1__block-farm__chunk-900__r0002c0002", "loc-1__block-farm__chunk-900__r0003c0000", "loc-1__block-farm__chunk-900__r0003c0001", "loc-1__block-farm__chunk-900__r0003c0002"], "metadata": {"source": "analysis_grid_cells"}, "created_at": "2026-05-12T12:37:27.901926+00:00", "updated_at": "2026-05-12T12:37:27.901945+00:00", }, ], "analysisgridcells": [ {"id": 1, "soil_location_id": 1, "block_subdivision_id": None, "block_code": "", "cell_code": "loc-1__block-farm__chunk-900__r0000c0000", "chunk_size_sqm": 900, "geometry": {"type": "Polygon", "coordinates": [[[49.9995, 49.9995], [49.99992, 49.9995], [49.99992, 49.99977], [49.9995, 49.99977], [49.9995, 49.9995]]]}, "centroid_lat": "49.999635", "centroid_lon": "49.999710", "created_at": "2026-05-12T12:19:03.930590+00:00", "updated_at": "2026-05-12T12:19:03.930609+00:00"}, {"id": 2, "soil_location_id": 1, "block_subdivision_id": None, "block_code": "", "cell_code": "loc-1__block-farm__chunk-900__r0000c0001", "chunk_size_sqm": 900, "geometry": {"type": "Polygon", "coordinates": [[[49.99992, 49.9995], [50.000339, 49.9995], [50.000339, 49.99977], [49.99992, 49.99977], [49.99992, 49.9995]]]}, "centroid_lat": "49.999635", "centroid_lon": "50.000130", "created_at": "2026-05-12T12:19:03.931797+00:00", "updated_at": "2026-05-12T12:19:03.931817+00:00"}, {"id": 3, "soil_location_id": 1, "block_subdivision_id": None, "block_code": "", "cell_code": "loc-1__block-farm__chunk-900__r0000c0002", "chunk_size_sqm": 900, "geometry": {"type": "Polygon", "coordinates": [[[50.000339, 49.9995], [50.000759, 49.9995], [50.000759, 49.99977], [50.000339, 49.99977], [50.000339, 49.9995]]]}, "centroid_lat": "49.999635", "centroid_lon": "50.000549", "created_at": "2026-05-12T12:19:03.931857+00:00", "updated_at": "2026-05-12T12:19:03.931864+00:00"}, {"id": 4, "soil_location_id": 1, "block_subdivision_id": None, "block_code": "", "cell_code": "loc-1__block-farm__chunk-900__r0001c0000", "chunk_size_sqm": 900, "geometry": {"type": "Polygon", "coordinates": [[[49.9995, 49.99977], [49.99992, 49.99977], [49.99992, 50.00004], [49.9995, 50.00004], [49.9995, 49.99977]]]}, "centroid_lat": "49.999905", "centroid_lon": "49.999710", "created_at": "2026-05-12T12:19:03.931899+00:00", "updated_at": "2026-05-12T12:19:03.931906+00:00"}, {"id": 5, "soil_location_id": 1, "block_subdivision_id": None, "block_code": "", "cell_code": "loc-1__block-farm__chunk-900__r0001c0001", "chunk_size_sqm": 900, "geometry": {"type": "Polygon", "coordinates": [[[49.99992, 49.99977], [50.000339, 49.99977], [50.000339, 50.00004], [49.99992, 50.00004], [49.99992, 49.99977]]]}, "centroid_lat": "49.999905", "centroid_lon": "50.000130", "created_at": "2026-05-12T12:19:03.931939+00:00", "updated_at": "2026-05-12T12:19:03.931945+00:00"}, {"id": 6, "soil_location_id": 1, "block_subdivision_id": None, "block_code": "", "cell_code": "loc-1__block-farm__chunk-900__r0001c0002", "chunk_size_sqm": 900, "geometry": {"type": "Polygon", "coordinates": [[[50.000339, 49.99977], [50.000759, 49.99977], [50.000759, 50.00004], [50.000339, 50.00004], [50.000339, 49.99977]]]}, "centroid_lat": "49.999905", "centroid_lon": "50.000549", "created_at": "2026-05-12T12:19:03.931978+00:00", "updated_at": "2026-05-12T12:19:03.931985+00:00"}, {"id": 7, "soil_location_id": 1, "block_subdivision_id": None, "block_code": "", "cell_code": "loc-1__block-farm__chunk-900__r0002c0000", "chunk_size_sqm": 900, "geometry": {"type": "Polygon", "coordinates": [[[49.9995, 50.00004], [49.99992, 50.00004], [49.99992, 50.000309], [49.9995, 50.000309], [49.9995, 50.00004]]]}, "centroid_lat": "50.000174", "centroid_lon": "49.999710", "created_at": "2026-05-12T12:19:03.932017+00:00", "updated_at": "2026-05-12T12:19:03.932024+00:00"}, {"id": 8, "soil_location_id": 1, "block_subdivision_id": None, "block_code": "", "cell_code": "loc-1__block-farm__chunk-900__r0002c0001", "chunk_size_sqm": 900, "geometry": {"type": "Polygon", "coordinates": [[[49.99992, 50.00004], [50.000339, 50.00004], [50.000339, 50.000309], [49.99992, 50.000309], [49.99992, 50.00004]]]}, "centroid_lat": "50.000174", "centroid_lon": "50.000130", "created_at": "2026-05-12T12:19:03.932056+00:00", "updated_at": "2026-05-12T12:19:03.932063+00:00"}, {"id": 9, "soil_location_id": 1, "block_subdivision_id": None, "block_code": "", "cell_code": "loc-1__block-farm__chunk-900__r0002c0002", "chunk_size_sqm": 900, "geometry": {"type": "Polygon", "coordinates": [[[50.000339, 50.00004], [50.000759, 50.00004], [50.000759, 50.000309], [50.000339, 50.000309], [50.000339, 50.00004]]]}, "centroid_lat": "50.000174", "centroid_lon": "50.000549", "created_at": "2026-05-12T12:19:03.932100+00:00", "updated_at": "2026-05-12T12:19:03.932107+00:00"}, {"id": 10, "soil_location_id": 1, "block_subdivision_id": None, "block_code": "", "cell_code": "loc-1__block-farm__chunk-900__r0003c0000", "chunk_size_sqm": 900, "geometry": {"type": "Polygon", "coordinates": [[[49.9995, 50.000309], [49.99992, 50.000309], [49.99992, 50.000579], [49.9995, 50.000579], [49.9995, 50.000309]]]}, "centroid_lat": "50.000444", "centroid_lon": "49.999710", "created_at": "2026-05-12T12:19:03.932145+00:00", "updated_at": "2026-05-12T12:19:03.932152+00:00"}, {"id": 11, "soil_location_id": 1, "block_subdivision_id": None, "block_code": "", "cell_code": "loc-1__block-farm__chunk-900__r0003c0001", "chunk_size_sqm": 900, "geometry": {"type": "Polygon", "coordinates": [[[49.99992, 50.000309], [50.000339, 50.000309], [50.000339, 50.000579], [49.99992, 50.000579], [49.99992, 50.000309]]]}, "centroid_lat": "50.000444", "centroid_lon": "50.000130", "created_at": "2026-05-12T12:19:03.932191+00:00", "updated_at": "2026-05-12T12:19:03.932198+00:00"}, {"id": 12, "soil_location_id": 1, "block_subdivision_id": None, "block_code": "", "cell_code": "loc-1__block-farm__chunk-900__r0003c0002", "chunk_size_sqm": 900, "geometry": {"type": "Polygon", "coordinates": [[[50.000339, 50.000309], [50.000759, 50.000309], [50.000759, 50.000579], [50.000339, 50.000579], [50.000339, 50.000309]]]}, "centroid_lat": "50.000444", "centroid_lon": "50.000549", "created_at": "2026-05-12T12:19:03.932234+00:00", "updated_at": "2026-05-12T12:19:03.932241+00:00"}, ], "analysisgridobservations": [ {"id": 1, "cell_id": 1, "run_id": 1, "temporal_start": "2026-04-11", "temporal_end": "2026-05-11", "ndvi": 0.6483580933676826, "ndwi": -0.5629512800110711, "soil_vv": -15.369688, "soil_vv_db": -15.369688, "dem_m": None, "slope_deg": None, "metadata": {}, "created_at": "2026-05-12T12:37:26.614257+00:00", "updated_at": "2026-05-12T12:37:26.614281+00:00"}, {"id": 2, "cell_id": 2, "run_id": 1, "temporal_start": "2026-04-11", "temporal_end": "2026-05-11", "ndvi": 0.6588515573077731, "ndwi": -0.5730775992075602, "soil_vv": -14.043169, "soil_vv_db": -14.043169, "dem_m": None, "slope_deg": None, "metadata": {}, "created_at": "2026-05-12T12:37:26.615124+00:00", "updated_at": "2026-05-12T12:37:26.615143+00:00"}, {"id": 3, "cell_id": 3, "run_id": 1, "temporal_start": "2026-04-11", "temporal_end": "2026-05-11", "ndvi": 0.6946650213665433, "ndwi": -0.6026291714774238, "soil_vv": -13.727797, "soil_vv_db": -13.727797, "dem_m": None, "slope_deg": None, "metadata": {}, "created_at": "2026-05-12T12:37:26.615867+00:00", "updated_at": "2026-05-12T12:37:26.615885+00:00"}, {"id": 4, "cell_id": 4, "run_id": 1, "temporal_start": "2026-04-11", "temporal_end": "2026-05-11", "ndvi": 0.6682408054669698, "ndwi": -0.578668495019277, "soil_vv": -13.127913, "soil_vv_db": -13.127913, "dem_m": None, "slope_deg": None, "metadata": {}, "created_at": "2026-05-12T12:37:26.616668+00:00", "updated_at": "2026-05-12T12:37:26.616687+00:00"}, {"id": 5, "cell_id": 5, "run_id": 1, "temporal_start": "2026-04-11", "temporal_end": "2026-05-11", "ndvi": 0.6642558574676514, "ndwi": -0.5712497035662333, "soil_vv": -12.400669, "soil_vv_db": -12.400669, "dem_m": None, "slope_deg": None, "metadata": {}, "created_at": "2026-05-12T12:37:26.617453+00:00", "updated_at": "2026-05-12T12:37:26.617472+00:00"}, {"id": 6, "cell_id": 6, "run_id": 1, "temporal_start": "2026-04-11", "temporal_end": "2026-05-11", "ndvi": 0.7056174145804511, "ndwi": -0.599965857134925, "soil_vv": -12.273758, "soil_vv_db": -12.273758, "dem_m": None, "slope_deg": None, "metadata": {}, "created_at": "2026-05-12T12:37:26.618181+00:00", "updated_at": "2026-05-12T12:37:26.618199+00:00"}, {"id": 7, "cell_id": 7, "run_id": 1, "temporal_start": "2026-04-11", "temporal_end": "2026-05-11", "ndvi": 0.6824584868219163, "ndwi": -0.5929381317562528, "soil_vv": -12.147284, "soil_vv_db": -12.147284, "dem_m": None, "slope_deg": None, "metadata": {}, "created_at": "2026-05-12T12:37:26.618964+00:00", "updated_at": "2026-05-12T12:37:26.618982+00:00"}, {"id": 8, "cell_id": 8, "run_id": 1, "temporal_start": "2026-04-11", "temporal_end": "2026-05-11", "ndvi": 0.6956862476136949, "ndwi": -0.6001381145583259, "soil_vv": -13.170681, "soil_vv_db": -13.170681, "dem_m": None, "slope_deg": None, "metadata": {}, "created_at": "2026-05-12T12:37:26.619733+00:00", "updated_at": "2026-05-12T12:37:26.619750+00:00"}, {"id": 9, "cell_id": 9, "run_id": 1, "temporal_start": "2026-04-11", "temporal_end": "2026-05-11", "ndvi": 0.7093238963021172, "ndwi": -0.6121659080187479, "soil_vv": -13.873331, "soil_vv_db": -13.873331, "dem_m": None, "slope_deg": None, "metadata": {}, "created_at": "2026-05-12T12:37:26.620504+00:00", "updated_at": "2026-05-12T12:37:26.620522+00:00"}, {"id": 10, "cell_id": 10, "run_id": 1, "temporal_start": "2026-04-11", "temporal_end": "2026-05-11", "ndvi": 0.6764502127965292, "ndwi": -0.5939946042166816, "soil_vv": -14.09151, "soil_vv_db": -14.09151, "dem_m": None, "slope_deg": None, "metadata": {}, "created_at": "2026-05-12T12:37:26.621257+00:00", "updated_at": "2026-05-12T12:37:26.621275+00:00"}, {"id": 11, "cell_id": 11, "run_id": 1, "temporal_start": "2026-04-11", "temporal_end": "2026-05-11", "ndvi": 0.6600760486390855, "ndwi": -0.5822326408492194, "soil_vv": -13.272252, "soil_vv_db": -13.272252, "dem_m": None, "slope_deg": None, "metadata": {}, "created_at": "2026-05-12T12:37:26.621989+00:00", "updated_at": "2026-05-12T12:37:26.622008+00:00"}, {"id": 12, "cell_id": 12, "run_id": 1, "temporal_start": "2026-04-11", "temporal_end": "2026-05-11", "ndvi": 0.6991057925754123, "ndwi": -0.6043583750724792, "soil_vv": -12.991811, "soil_vv_db": -12.991811, "dem_m": None, "slope_deg": None, "metadata": {}, "created_at": "2026-05-12T12:37:26.622751+00:00", "updated_at": "2026-05-12T12:37:26.622769+00:00"}, ], "remotesensingclusterassignments": [ {"id": 1, "result_id": 1, "cell_id": 1, "cluster_label": 0, "raw_feature_values": {"ndvi": 0.6483580933676826, "ndwi": -0.5629512800110711, "soil_vv_db": -15.369688}, "scaled_feature_values": {"ndvi": -1.630738, "ndwi": 1.792215, "soil_vv_db": -2.274005}, "created_at": "2026-05-12T12:37:27.901986+00:00", "updated_at": "2026-05-12T12:37:27.902003+00:00"}, {"id": 2, "result_id": 1, "cell_id": 2, "cluster_label": 0, "raw_feature_values": {"ndvi": 0.6588515573077731, "ndwi": -0.5730775992075602, "soil_vv_db": -14.043169}, "scaled_feature_values": {"ndvi": -1.094298, "ndwi": 1.109414, "soil_vv_db": -0.762373}, "created_at": "2026-05-12T12:37:27.902768+00:00", "updated_at": "2026-05-12T12:37:27.902786+00:00"}, {"id": 3, "result_id": 1, "cell_id": 3, "cluster_label": 1, "raw_feature_values": {"ndvi": 0.6946650213665433, "ndwi": -0.6026291714774238, "soil_vv_db": -13.727797}, "scaled_feature_values": {"ndvi": 0.736534, "ndwi": -0.8832, "soil_vv_db": -0.402992}, "created_at": "2026-05-12T12:37:27.903479+00:00", "updated_at": "2026-05-12T12:37:27.903497+00:00"}, {"id": 4, "result_id": 1, "cell_id": 4, "cluster_label": 0, "raw_feature_values": {"ndvi": 0.6682408054669698, "ndwi": -0.578668495019277, "soil_vv_db": -13.127913}, "scaled_feature_values": {"ndvi": -0.614307, "ndwi": 0.732429, "soil_vv_db": 0.280605}, "created_at": "2026-05-12T12:37:27.904197+00:00", "updated_at": "2026-05-12T12:37:27.904214+00:00"}, {"id": 5, "result_id": 1, "cell_id": 5, "cluster_label": 0, "raw_feature_values": {"ndvi": 0.6642558574676514, "ndwi": -0.5712497035662333, "soil_vv_db": -12.400669}, "scaled_feature_values": {"ndvi": -0.818023, "ndwi": 1.232666, "soil_vv_db": 1.109334}, "created_at": "2026-05-12T12:37:27.904909+00:00", "updated_at": "2026-05-12T12:37:27.904926+00:00"}, {"id": 6, "result_id": 1, "cell_id": 6, "cluster_label": 1, "raw_feature_values": {"ndvi": 0.7056174145804511, "ndwi": -0.599965857134925, "soil_vv_db": -12.273758}, "scaled_feature_values": {"ndvi": 1.296436, "ndwi": -0.703617, "soil_vv_db": 1.253955}, "created_at": "2026-05-12T12:37:27.905606+00:00", "updated_at": "2026-05-12T12:37:27.905623+00:00"}, {"id": 7, "result_id": 1, "cell_id": 7, "cluster_label": 1, "raw_feature_values": {"ndvi": 0.6824584868219163, "ndwi": -0.5929381317562528, "soil_vv_db": -12.147284}, "scaled_feature_values": {"ndvi": 0.11252, "ndwi": -0.229749, "soil_vv_db": 1.398079}, "created_at": "2026-05-12T12:37:27.906325+00:00", "updated_at": "2026-05-12T12:37:27.906343+00:00"}, {"id": 8, "result_id": 1, "cell_id": 8, "cluster_label": 1, "raw_feature_values": {"ndvi": 0.6956862476136949, "ndwi": -0.6001381145583259, "soil_vv_db": -13.170681}, "scaled_feature_values": {"ndvi": 0.788741, "ndwi": -0.715232, "soil_vv_db": 0.231869}, "created_at": "2026-05-12T12:37:27.907052+00:00", "updated_at": "2026-05-12T12:37:27.907069+00:00"}, {"id": 9, "result_id": 1, "cell_id": 9, "cluster_label": 1, "raw_feature_values": {"ndvi": 0.7093238963021172, "ndwi": -0.6121659080187479, "soil_vv_db": -13.873331}, "scaled_feature_values": {"ndvi": 1.485916, "ndwi": -1.526247, "soil_vv_db": -0.568835}, "created_at": "2026-05-12T12:37:27.907735+00:00", "updated_at": "2026-05-12T12:37:27.907752+00:00"}, {"id": 10, "result_id": 1, "cell_id": 10, "cluster_label": 1, "raw_feature_values": {"ndvi": 0.6764502127965292, "ndwi": -0.5939946042166816, "soil_vv_db": -14.09151}, "scaled_feature_values": {"ndvi": -0.194631, "ndwi": -0.300985, "soil_vv_db": -0.81746}, "created_at": "2026-05-12T12:37:27.908441+00:00", "updated_at": "2026-05-12T12:37:27.908458+00:00"}, {"id": 11, "result_id": 1, "cell_id": 11, "cluster_label": 1, "raw_feature_values": {"ndvi": 0.6600760486390855, "ndwi": -0.5822326408492194, "soil_vv_db": -13.272252}, "scaled_feature_values": {"ndvi": -1.031701, "ndwi": 0.492105, "soil_vv_db": 0.116124}, "created_at": "2026-05-12T12:37:27.909117+00:00", "updated_at": "2026-05-12T12:37:27.909134+00:00"}, {"id": 12, "result_id": 1, "cell_id": 12, "cluster_label": 1, "raw_feature_values": {"ndvi": 0.6991057925754123, "ndwi": -0.6043583750724792, "soil_vv_db": -12.991811}, "scaled_feature_values": {"ndvi": 0.963553, "ndwi": -0.999798, "soil_vv_db": 0.4357}, "created_at": "2026-05-12T12:37:27.909828+00:00", "updated_at": "2026-05-12T12:37:27.909845+00:00"}, ], "remotesensingsubdivisionoptions": [], "remotesensingsubdivisionoptionblocks": [], "remotesensingsubdivisionoptionassignments": [], "ndviobservations": [], } def _dt(value: str | None): if not value: return None parsed = parse_datetime(value) if parsed is not None: return parsed return datetime.fromisoformat(value) def _date(value: str | None): if not value: return None return date.fromisoformat(value) def _decimal(value): if value is None: return None return Decimal(str(value)) def _uuid(value): if not value: return None return UUID(str(value)) class Command(BaseCommand): help = "Seed the current location_data database snapshot into local tables." def add_arguments(self, parser): parser.add_argument( "--flush-existing", action="store_true", help="Delete existing location_data seeded tables before inserting the snapshot.", ) @transaction.atomic def handle(self, *args, **options): if options["flush_existing"]: self._flush_existing() self._seed_soil_locations() self._seed_block_subdivisions() self._seed_remote_sensing_runs() self._seed_subdivision_results() self._seed_cluster_blocks() self._seed_analysis_grid_cells() self._seed_analysis_grid_observations() self._seed_cluster_assignments() self._seed_subdivision_options() self._seed_subdivision_option_blocks() self._seed_subdivision_option_assignments() self._seed_ndvi_observations() self.stdout.write(self.style.SUCCESS("location_data seed snapshot applied successfully.")) def _flush_existing(self): RemoteSensingSubdivisionOptionAssignment.objects.all().delete() RemoteSensingSubdivisionOptionBlock.objects.all().delete() RemoteSensingSubdivisionOption.objects.all().delete() RemoteSensingClusterAssignment.objects.all().delete() AnalysisGridObservation.objects.all().delete() RemoteSensingClusterBlock.objects.all().delete() RemoteSensingSubdivisionResult.objects.all().delete() RemoteSensingRun.objects.all().delete() AnalysisGridCell.objects.all().delete() BlockSubdivision.objects.all().delete() NdviObservation.objects.all().delete() SoilLocation.objects.all().delete() def _seed_soil_locations(self): for row in SEED_DATA["soillocations"]: obj, _ = SoilLocation.objects.update_or_create( id=row["id"], defaults={ "latitude": _decimal(row["latitude"]), "longitude": _decimal(row["longitude"]), "task_id": row["task_id"], "farm_boundary": row["farm_boundary"], "input_block_count": row["input_block_count"], "block_layout": row["block_layout"], }, ) self._touch(obj, row) def _seed_block_subdivisions(self): for row in SEED_DATA["blocksubdivisions"]: obj, _ = BlockSubdivision.objects.update_or_create( id=row["id"], defaults={ "soil_location_id": row["soil_location_id"], "block_code": row["block_code"], "source_boundary": row["source_boundary"], "chunk_size_sqm": row["chunk_size_sqm"], "grid_points": row["grid_points"], "centroid_points": row["centroid_points"], "grid_point_count": row["grid_point_count"], "centroid_count": row["centroid_count"], "elbow_plot": row.get("elbow_plot", ""), "subdivision_summary": row.get("subdivision_summary", {}), }, ) self._touch(obj, row) def _seed_remote_sensing_runs(self): for row in SEED_DATA["remotesensingruns"]: obj, _ = RemoteSensingRun.objects.update_or_create( id=row["id"], defaults={ "soil_location_id": row["soil_location_id"], "block_subdivision_id": row["block_subdivision_id"], "block_code": row["block_code"], "provider": row["provider"], "chunk_size_sqm": row["chunk_size_sqm"], "temporal_start": _date(row["temporal_start"]), "temporal_end": _date(row["temporal_end"]), "status": row["status"], "metadata": row["metadata"], "error_message": row["error_message"], "started_at": _dt(row["started_at"]), "finished_at": _dt(row["finished_at"]), }, ) self._touch(obj, row) def _seed_subdivision_results(self): for row in SEED_DATA["remotesensingsubdivisionresults"]: obj, _ = RemoteSensingSubdivisionResult.objects.update_or_create( id=row["id"], defaults={ "soil_location_id": row["soil_location_id"], "run_id": row["run_id"], "block_subdivision_id": row["block_subdivision_id"], "block_code": row["block_code"], "chunk_size_sqm": row["chunk_size_sqm"], "temporal_start": _date(row["temporal_start"]), "temporal_end": _date(row["temporal_end"]), "cluster_count": row["cluster_count"], "selected_features": row["selected_features"], "skipped_cell_codes": row["skipped_cell_codes"], "metadata": row["metadata"], }, ) self._touch(obj, row) def _seed_cluster_blocks(self): for row in SEED_DATA["remotesensingclusterblocks"]: obj, _ = RemoteSensingClusterBlock.objects.update_or_create( id=row["id"], defaults={ "uuid": _uuid(row["uuid"]), "result_id": row["result_id"], "soil_location_id": row["soil_location_id"], "block_subdivision_id": row["block_subdivision_id"], "block_code": row["block_code"], "sub_block_code": row["sub_block_code"], "cluster_label": row["cluster_label"], "chunk_size_sqm": row["chunk_size_sqm"], "centroid_lat": _decimal(row["centroid_lat"]), "centroid_lon": _decimal(row["centroid_lon"]), "center_cell_code": row["center_cell_code"], "center_cell_lat": _decimal(row["center_cell_lat"]), "center_cell_lon": _decimal(row["center_cell_lon"]), "geometry": row["geometry"], "cell_count": row["cell_count"], "cell_codes": row["cell_codes"], "metadata": row["metadata"], }, ) self._touch(obj, row) def _seed_analysis_grid_cells(self): for row in SEED_DATA["analysisgridcells"]: obj, _ = AnalysisGridCell.objects.update_or_create( id=row["id"], defaults={ "soil_location_id": row["soil_location_id"], "block_subdivision_id": row["block_subdivision_id"], "block_code": row["block_code"], "cell_code": row["cell_code"], "chunk_size_sqm": row["chunk_size_sqm"], "geometry": row["geometry"], "centroid_lat": _decimal(row["centroid_lat"]), "centroid_lon": _decimal(row["centroid_lon"]), }, ) self._touch(obj, row) def _seed_analysis_grid_observations(self): for row in SEED_DATA["analysisgridobservations"]: obj, _ = AnalysisGridObservation.objects.update_or_create( id=row["id"], defaults={ "cell_id": row["cell_id"], "run_id": row["run_id"], "temporal_start": _date(row["temporal_start"]), "temporal_end": _date(row["temporal_end"]), "ndvi": row["ndvi"], "ndwi": row["ndwi"], "soil_vv": row["soil_vv"], "soil_vv_db": row["soil_vv_db"], "dem_m": row["dem_m"], "slope_deg": row["slope_deg"], "metadata": row["metadata"], }, ) self._touch(obj, row) def _seed_cluster_assignments(self): for row in SEED_DATA["remotesensingclusterassignments"]: obj, _ = RemoteSensingClusterAssignment.objects.update_or_create( id=row["id"], defaults={ "result_id": row["result_id"], "cell_id": row["cell_id"], "cluster_label": row["cluster_label"], "raw_feature_values": row["raw_feature_values"], "scaled_feature_values": row["scaled_feature_values"], }, ) self._touch(obj, row) def _seed_subdivision_options(self): for row in SEED_DATA["remotesensingsubdivisionoptions"]: obj, _ = RemoteSensingSubdivisionOption.objects.update_or_create( id=row["id"], defaults={ "result_id": row["result_id"], "requested_k": row["requested_k"], "effective_cluster_count": row["effective_cluster_count"], "is_active": row["is_active"], "is_recommended": row["is_recommended"], "selection_source": row["selection_source"], "metadata": row["metadata"], }, ) self._touch(obj, row) def _seed_subdivision_option_blocks(self): for row in SEED_DATA["remotesensingsubdivisionoptionblocks"]: obj, _ = RemoteSensingSubdivisionOptionBlock.objects.update_or_create( id=row["id"], defaults={ "option_id": row["option_id"], "cluster_label": row["cluster_label"], "sub_block_code": row["sub_block_code"], "chunk_size_sqm": row["chunk_size_sqm"], "centroid_lat": _decimal(row["centroid_lat"]), "centroid_lon": _decimal(row["centroid_lon"]), "center_cell_code": row["center_cell_code"], "center_cell_lat": _decimal(row["center_cell_lat"]), "center_cell_lon": _decimal(row["center_cell_lon"]), "geometry": row["geometry"], "cell_count": row["cell_count"], "cell_codes": row["cell_codes"], "metadata": row["metadata"], }, ) self._touch(obj, row) def _seed_subdivision_option_assignments(self): for row in SEED_DATA["remotesensingsubdivisionoptionassignments"]: obj, _ = RemoteSensingSubdivisionOptionAssignment.objects.update_or_create( id=row["id"], defaults={ "option_id": row["option_id"], "cell_id": row["cell_id"], "cluster_label": row["cluster_label"], "raw_feature_values": row["raw_feature_values"], "scaled_feature_values": row["scaled_feature_values"], }, ) self._touch(obj, row) def _seed_ndvi_observations(self): for row in SEED_DATA["ndviobservations"]: obj, _ = NdviObservation.objects.update_or_create( id=row["id"], defaults={ "location_id": row["location_id"], "observation_date": _date(row["observation_date"]), "mean_ndvi": row["mean_ndvi"], "ndvi_map": row["ndvi_map"], "vegetation_health_class": row["vegetation_health_class"], "satellite_source": row["satellite_source"], "cloud_cover": row["cloud_cover"], "metadata": row["metadata"], }, ) self._touch(obj, row, created_field=False) def _touch(self, obj, row, *, created_field=True): updates = [] if created_field and hasattr(obj, "created_at") and row.get("created_at"): obj.created_at = _dt(row["created_at"]) updates.append("created_at") if hasattr(obj, "updated_at") and row.get("updated_at"): obj.updated_at = _dt(row["updated_at"]) updates.append("updated_at") if updates: obj.save(update_fields=updates)