Skip to content
16 changes: 16 additions & 0 deletions seed/data_importer/match.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from celery import shared_task
from celery.utils.log import get_task_logger
from django.apps import apps
from django.contrib.postgres.aggregates.general import ArrayAgg
from django.db import IntegrityError, transaction
from django.db.models import Subquery
Expand All @@ -31,6 +32,8 @@
PropertyAuditLog,
PropertyState,
PropertyView,
PropertyViewLabel,
StatusLabel,
TaxLotAuditLog,
TaxLotState,
TaxLotView,
Expand Down Expand Up @@ -793,6 +796,19 @@ def link_states(states, ViewClass, cycle, highest_ali, sub_progress_key, tuple_v
state.raw_access_level_instance = ali
view = state.promote(cycle=cycle)

# assign incoming labels to view
if view and state.incoming_labels:
incoming_label_names = state.incoming_labels.split(",")
for incoming_label_name in incoming_label_names:
incoming_label, _ = StatusLabel.objects.get_or_create(
name=incoming_label_name, super_organization=cycle.organization, show_in_list=True
)
if isinstance(view, PropertyView):
PropertyViewLabel.objects.get_or_create(statuslabel=incoming_label, propertyview=view)
elif isinstance(view, TaxLotView):
TaxLotViewLabel = apps.get_model("seed", "TaxLotView_labels")
TaxLotViewLabel.objects.get_or_create(statuslabel=incoming_label, taxlotview=view)

# link state
link_count = _link_matches([*existing_views_matches, view], cycle.organization_id, view, ViewClass)
if link_count == 0:
Expand Down
6 changes: 5 additions & 1 deletion seed/data_importer/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,11 @@ def map_row_chunk(ids, file_pk, source_type, prog_key, **kwargs):
if footprint_details.get("obj_field") and getattr(map_model_obj, footprint_details["obj_field"]) is None:
_store_raw_footprint_and_create_rule(footprint_details, table, org, import_file, original_row, map_model_obj)

# There was an error with a field being too long [> 255 chars].
# Store the incoming label names in state.incoming_labels. -ViewLabels will be created once a view is attatched
label_key = "Property Labels" if isinstance(map_model_obj, PropertyState) else "Tax Lot Labels"
if incoming_labels := map_model_obj.extra_data.pop(label_key, None):
map_model_obj.incoming_labels = incoming_labels

map_model_obj.save()

# if importing BuildingSync create a BuildingFile for the property
Expand Down
9 changes: 9 additions & 0 deletions seed/lib/merging/merging.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,13 @@ def _merge_extra_data(ed1, ed2, priorities, recognize_empty_columns, ignore_merg
return extra_data


def _merge_incoming_labels(state1, state2, merged_state):
state1_labels = state1.incoming_labels.split(",") if state1.incoming_labels else []
state2_labels = state2.incoming_labels.split(",") if state2.incoming_labels else []
combined_labels = set(state1_labels + state2_labels)
merged_state.incoming_labels = ",".join(combined_labels) if combined_labels else None


def merge_state(merged_state, state1, state2, priorities, ignore_merge_protection=False):
"""
Set attributes on our Canonical model, saving differences.
Expand Down Expand Up @@ -217,6 +224,8 @@ def merge_state(merged_state, state1, state2, priorities, ignore_merge_protectio
table_name=state2.__class__.__name__, recognize_empty=True, is_extra_data=True
).values_list("column_name", flat=True)

_merge_incoming_labels(state1, state2, merged_state)

merged_state.extra_data = _merge_extra_data(
state1.extra_data,
state2.extra_data,
Expand Down
22 changes: 22 additions & 0 deletions seed/migrations/0248_state_incoming_labels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Generated by Django 3.2.25 on 2024-12-12 18:14

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("seed", "0247_aggregatemetersystem"),
]

operations = [
migrations.AddField(
model_name="propertystate",
name="incoming_labels",
field=models.TextField(blank=True, null=True),
),
migrations.AddField(
model_name="taxlotstate",
name="incoming_labels",
field=models.TextField(blank=True, null=True),
),
]
7 changes: 4 additions & 3 deletions seed/models/columns.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class Column(models.Model):
"gross_floor_area_orig",
"conditioned_floor_area_orig",
"source_eui_weather_normalized_orig",
"incoming_labels",
]

QUANTITY_UNIT_COLUMNS = [
Expand Down Expand Up @@ -1425,9 +1426,9 @@ def retrieve_db_field_name_for_hash_comparison(inventory_type, organization_id):
f.name
for f in inventory_type._meta.fields
if (
(f.get_internal_type() != "ForeignKey")
and (f.name not in Column.COLUMN_EXCLUDE_FIELDS)
and (f.name not in excluded_columns)
f.get_internal_type() != "ForeignKey"
and (f.name not in Column.COLUMN_EXCLUDE_FIELDS or f.name == "incoming_labels")
and f.name not in excluded_columns
)
]

Expand Down
1 change: 1 addition & 0 deletions seed/models/properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ class PropertyState(models.Model):
merge_state = models.IntegerField(choices=MERGE_STATE, default=MERGE_STATE_UNKNOWN, null=True)
raw_access_level_instance = models.ForeignKey(AccessLevelInstance, null=True, on_delete=models.SET_NULL)
raw_access_level_instance_error = models.TextField(null=True)
incoming_labels = models.TextField(null=True, blank=True)

jurisdiction_property_id = models.TextField(null=True, blank=True, db_collation="natural_sort")

Expand Down
1 change: 1 addition & 0 deletions seed/models/tax_lots.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class TaxLotState(models.Model):
merge_state = models.IntegerField(choices=MERGE_STATE, default=MERGE_STATE_UNKNOWN, null=True)
raw_access_level_instance = models.ForeignKey(AccessLevelInstance, null=True, on_delete=models.SET_NULL)
raw_access_level_instance_error = models.TextField(null=True)
incoming_labels = models.TextField(null=True, blank=True)

custom_id_1 = models.CharField(max_length=255, null=True, blank=True, db_collation="natural_sort")

Expand Down
1 change: 1 addition & 0 deletions seed/serializers/properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ class PropertyStatePromoteWritableSerializer(serializers.ModelSerializer):
import_file_id = serializers.IntegerField(allow_null=True, read_only=True)
organization_id = serializers.IntegerField()
raw_access_level_instance_id = serializers.IntegerField()
incoming_labels = serializers.IntegerField(read_only=True)

# read-only core fields
id = serializers.IntegerField(read_only=True)
Expand Down
1 change: 1 addition & 0 deletions seed/tests/test_columns.py
Original file line number Diff line number Diff line change
Expand Up @@ -1096,6 +1096,7 @@ def test_retrieve_db_field_name_from_db_tables(self):
"generation_date",
"gross_floor_area",
"home_energy_score_id",
"incoming_labels",
"indoor_water_use",
"indoor_wui",
"jurisdiction_property_id",
Expand Down
1 change: 0 additions & 1 deletion seed/views/v3/import_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,6 @@ def map(self, request, pk=None):
if not import_file.exists():
return {"status": "error", "message": f"ImportFile {pk} does not exist"}

# return remap_data(import_file_id)
return JsonResponse(map_data(pk, remap, mark_as_done))

@swagger_auto_schema_org_query_param
Expand Down
Loading