Skip to content

Commit

Permalink
feat: updated filters for all fields, null checks finished
Browse files Browse the repository at this point in the history
  • Loading branch information
Your Name committed Feb 2, 2024
1 parent c58750a commit 89c2771
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 88 deletions.
93 changes: 91 additions & 2 deletions app/backend/wells/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from django.contrib.gis.gdal import GDALException
from django.contrib.gis.db.models.functions import Transform
from django.contrib.gis.measure import D
from django.db.models import Max, Min, Q, QuerySet
from django.db.models import Max, Min, Q, QuerySet, Subquery, OuterRef
from django_filters import rest_framework as filters
from django_filters.widgets import BooleanWidget
from rest_framework.exceptions import ValidationError
Expand All @@ -42,7 +42,10 @@
WellAttachment,
PumpingTestDescriptionCode,
BoundaryEffectCode,
AnalysisMethodCode
AnalysisMethodCode,
LithologyDescription,
Casing,
ActivitySubmission
)
from wells.constants import WELL_TAGS

Expand Down Expand Up @@ -851,13 +854,25 @@ def filter_queryset(self, request, queryset, view):
continue

q_objects = Q()
create_date_gte = None
create_date_lte = None

for field, value in group_params.items():
if field == 'well_tag_number':
queryset = queryset.filter(well_tag_number__icontains=value)

if field == 'create_user':
queryset = queryset.filter(create_user__icontains=value)

elif field == 'identification_plate_number':
queryset = queryset.filter(identification_plate_number__icontains=value)

elif field == 'create_date_after':
create_date_gte = value # Store the value to use later in the date range filter

elif field == 'create_date_before':
create_date_lte = value # Store the value to use later in the date range filter

elif field == 'person_responsible_name' and value == 'null':
q_objects |= (Q(person_responsible__isnull=True) | Q(person_responsible__first_name__isnull=True) |
Q(person_responsible__first_name='') | Q(person_responsible__first_name=' '))
Expand All @@ -871,7 +886,73 @@ def filter_queryset(self, request, queryset, view):
elif field in ['latitude', 'longitude']:
if value == 'null':
q_objects &= Q(**{'geom__isnull': True})

# Check for null or empty 'aquifer_lithology'
elif field == 'aquifer_lithology' and value == 'null':
# Subquery to get the last lithology description's raw data for each well
last_lithology_raw_data = Subquery(
LithologyDescription.objects.filter(
well=OuterRef('pk')
).order_by('-lithology_sequence_number').values('lithology_raw_data')[:1]
)
queryset = queryset.annotate(
last_lithology_raw_data=last_lithology_raw_data
).filter(
Q(last_lithology_raw_data__isnull=True) |
Q(last_lithology_raw_data='') |
Q(last_lithology_raw_data=' ')
)

# Check for null or empty 'casing_diameter' using the subquery
elif field == 'diameter' and value == 'null':
# Subquery to get the last casing's diameter for each well
last_casing_diameter = Subquery(
Casing.objects.filter(
well=OuterRef('pk')
).order_by('-end').values('diameter')[:1]
)
queryset = queryset.annotate(
last_casing_diameter=last_casing_diameter
).filter(
Q(last_casing_diameter__isnull=True)
)

elif field == 'well_status' and value == 'null':
last_activity_type = Subquery(
ActivitySubmission.objects.filter(
well=OuterRef('pk')
).order_by('-work_end_date').values('well_activity_type__description')[:1]
)
queryset = queryset.annotate(
last_well_status=last_activity_type
).filter(
Q(last_well_status__isnull=True) | Q(last_well_status='')
)

elif field == 'work_start_date' and value == 'null':
last_activity_start_date = Subquery(
ActivitySubmission.objects.filter(
well=OuterRef('pk')
).order_by('-work_end_date').values('work_start_date')[:1]
)
queryset = queryset.annotate(
last_work_start_date=last_activity_start_date
).filter(
Q(last_work_start_date__isnull=True)
)

elif field == 'work_end_date' and value == 'null':
last_activity_end_date = Subquery(
ActivitySubmission.objects.filter(
well=OuterRef('pk')
).order_by('-work_end_date').values('work_end_date')[:1]
)
queryset = queryset.annotate(
last_work_end_date=last_activity_end_date
).filter(
Q(last_work_end_date__isnull=True)
)

elif value == 'null':
# Check if the field exists in the model
try:
Expand All @@ -886,6 +967,14 @@ def filter_queryset(self, request, queryset, view):
# For other field types, just check for null
q_objects &= Q(**{f'{field}__isnull': True})

# After processing all fields, apply the date range filter if both values are provided
if create_date_gte and create_date_lte:
q_objects |= Q(create_date__range=(create_date_gte, create_date_lte))
elif create_date_gte: # Only 'after' date is provided
q_objects |= Q(create_date__gte=create_date_gte)
elif create_date_lte: # Only 'before' date is provided
q_objects |= Q(create_date__lte=create_date_lte)

# Apply the combined Q object filters to the queryset
queryset = queryset.filter(q_objects)

Expand Down
56 changes: 46 additions & 10 deletions app/backend/wells/serializers_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from django.contrib.gis.geos import Point

from gwells.utils import isPointInsideBC
from wells.models import Well, DevelopmentMethodCode
from wells.models import Well, DevelopmentMethodCode, ActivitySubmission
from aquifers.models import VerticalAquiferExtent, Aquifer

from aquifers.serializers_v2 import AquiferDetailSerializerV2
Expand Down Expand Up @@ -459,9 +459,24 @@ class Meta(WellDetailSerializerV1.Meta):
ref_name = "well_detail_v2"


class MislocatedWellsSerializer(serializers.ModelSerializer):
work_start_date = serializers.DateField(read_only=True)
work_end_date = serializers.DateField(read_only=True)
class ActivitySubmissionMixin:
def get_well_status(self, obj):
last_activity = ActivitySubmission.objects.filter(well=obj).order_by('-work_end_date').first()
return last_activity.well_activity_type.description if last_activity else None

def get_work_start_date(self, obj):
last_activity = ActivitySubmission.objects.filter(well=obj).order_by('-work_end_date').first()
return last_activity.work_start_date if last_activity else None

def get_work_end_date(self, obj):
last_activity = ActivitySubmission.objects.filter(well=obj).order_by('-work_end_date').first()
return last_activity.work_end_date if last_activity else None


class MislocatedWellsSerializer(ActivitySubmissionMixin, serializers.ModelSerializer):
well_status = serializers.SerializerMethodField()
work_start_date = serializers.SerializerMethodField()
work_end_date = serializers.SerializerMethodField()

class Meta:
model = Well
Expand All @@ -482,9 +497,10 @@ class Meta:
]


class CrossReferencingSerializer(serializers.ModelSerializer):
work_start_date = serializers.DateField(read_only=True)
work_end_date = serializers.DateField(read_only=True)
class CrossReferencingSerializer(ActivitySubmissionMixin, serializers.ModelSerializer):
well_status = serializers.SerializerMethodField()
work_start_date = serializers.SerializerMethodField()
work_end_date = serializers.SerializerMethodField()

class Meta:
model = Well
Expand All @@ -503,13 +519,33 @@ class Meta:
]


class RecordComplianceSerializer(serializers.ModelSerializer):
work_start_date = serializers.DateField(read_only=True)
work_end_date = serializers.DateField(read_only=True)
class RecordComplianceSerializer(ActivitySubmissionMixin, serializers.ModelSerializer):
company_of_person_responsible_name = serializers.ReadOnlyField(
source='company_of_person_responsible.name')
person_responsible_name = serializers.ReadOnlyField(source='person_responsible.name')

# Serializer methods for the last ActivitySubmission's work types
well_status = serializers.SerializerMethodField()
work_start_date = serializers.SerializerMethodField()
work_end_date = serializers.SerializerMethodField()

# last_lithology_raw_data
aquifer_lithology = serializers.SerializerMethodField()
# Serializer method field for the last casing's diameter
diameter = serializers.SerializerMethodField()

def get_aquifer_lithology(self, obj):
# Fetch the last LithologyDescription based on the sequence number
last_lithology = obj.lithologydescription_set.order_by('-lithology_sequence_number').first()
# Return the raw data if it exists, otherwise return None
return last_lithology.lithology_raw_data if last_lithology else None

def get_diameter(self, obj):
# Fetch the last Casing based on the 'end' field
last_casing = obj.casing_set.order_by('-end').first()
# Return the diameter if it exists, otherwise return None
return last_casing.diameter if last_casing else None

class Meta:
model = Well
fields = [
Expand Down
5 changes: 4 additions & 1 deletion app/backend/wells/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ def is_valid_geom(geom):
else:
# Handling updates to existing instances
original_instance = sender.objects.get(pk=instance.pk)
if original_instance.geom != instance.geom and is_valid_geom(instance.geom):
if original_instance.geom != instance.geom \
or original_instance.street_address != instance.street_address \
or original_instance.city != instance.city \
and is_valid_geom(instance.geom):
set_well_attributes(instance)
except Exception as e:
print(f"Error in update_well for Well ID {instance.pk}: {str(e)}")
Expand Down
19 changes: 0 additions & 19 deletions app/backend/wells/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,22 +169,3 @@ def calculate_score_city(well, geocoded_address):
if not geocoded_address:
return None
return fuzz.token_set_ratio(well.city.lower(), geocoded_address.get('localityName', '').lower())


def get_annotated_well_queryset():
return Well.objects.select_related('well_status').annotate(
work_start_date=Case(
When(well_status__well_status_code=WELL_STATUS_CODE_CONSTRUCTION, then=F('construction_start_date')),
When(well_status__well_status_code=WELL_STATUS_CODE_ALTERATION, then=F('alteration_start_date')),
When(well_status__well_status_code=WELL_STATUS_CODE_DECOMMISSION, then=F('decommission_start_date')),
default=Value(None),
output_field=DateField()
),
work_end_date=Case(
When(well_status__well_status_code=WELL_STATUS_CODE_CONSTRUCTION, then=F('construction_end_date')),
When(well_status__well_status_code=WELL_STATUS_CODE_ALTERATION, then=F('alteration_end_date')),
When(well_status__well_status_code=WELL_STATUS_CODE_DECOMMISSION, then=F('decommission_end_date')),
default=Value(None),
output_field=DateField()
)
)
38 changes: 0 additions & 38 deletions app/backend/wells/views_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@
from aquifers.permissions import HasAquiferEditRole
from wells.views import WellDetail as WellDetailV1
from wells.constants import MAX_EXPORT_COUNT, MAX_LOCATION_COUNT
from wells.utils import get_annotated_well_queryset

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -603,7 +602,6 @@ def get_queryset(self):
for the currently authenticated user.
"""
queryset = Well.objects.all()
queryset = get_annotated_well_queryset()

return queryset

Expand All @@ -621,42 +619,7 @@ class RecordComplianceListView(ListAPIView):
ordering = ('well_tag_number',)

def get_queryset(self):
"""
Retrieves wells that are missing information in any of the specified fields.
"""
queryset = Well.objects.all()
queryset = get_annotated_well_queryset()

# Filtering for records missing any of the specified fields
# missing_info_filter = (
# Q(well_tag_number__isnull=True) |
# Q(identification_plate_number__isnull=True) |
# Q(well_class__isnull=True) |
# Q(geom__isnull=True) | # for latitude and longitude
# Q(finished_well_depth__isnull=True) |
# Q(surface_seal_depth__isnull=True) |
# Q(surface_seal_thickness__isnull=True) |
# Q(aquifer_lithology__isnull=True) |
# Q(well_status__isnull=True) |
# Q(work_start_date__isnull=True) |
# Q(work_end_date__isnull=True) |
# Q(person_responsible__isnull=True) |
# Q(company_of_person_responsible__isnull=True) |
# Q(create_date__isnull=True) |
# Q(create_user__isnull=True) |
# Q(natural_resource_region__isnull=True)
# )

# queryset = queryset.filter(missing_info_filter)

# Additional filtering based on query parameters
work_start_date = self.request.query_params.get('work_start_date')
work_end_date = self.request.query_params.get('work_end_date')

if work_start_date:
queryset = queryset.filter(work_start_date__gte=work_start_date)
if work_end_date:
queryset = queryset.filter(work_end_date__lte=work_end_date)

return queryset

Expand All @@ -679,7 +642,6 @@ def get_queryset(self):
in their internal_comments.
"""
queryset = Well.objects.all()
queryset = get_annotated_well_queryset()

search_terms = ["x-ref'd", "x-ref", "cross-ref", "cross r", "cross-r", "ref'd", "referenced", "refd", "xref", "x-r", "x r"]

Expand Down
Loading

0 comments on commit 89c2771

Please sign in to comment.