From c58750ad2e850a1a625732c8633432b57baa9843 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 1 Feb 2024 17:01:05 -0800 Subject: [PATCH] feat: updated qaqc filters to use custom filtering and nullchecks --- app/backend/wells/filters.py | 64 ++++++++++++++++++ app/backend/wells/serializers_v2.py | 8 ++- app/backend/wells/views_v2.py | 53 ++++++++------- .../src/qaqc/components/QaQcFilters.vue | 50 ++++++++++---- .../src/qaqc/components/QaQcTable.vue | 40 ++++++++---- app/frontend/src/qaqc/store/index.js | 23 +++---- .../src/wells/components/mixins/filters.js | 65 +++++++++++++++++++ 7 files changed, 238 insertions(+), 65 deletions(-) diff --git a/app/backend/wells/filters.py b/app/backend/wells/filters.py index 147abce479..261169e7cc 100644 --- a/app/backend/wells/filters.py +++ b/app/backend/wells/filters.py @@ -18,6 +18,7 @@ from django import forms from django.core.exceptions import FieldDoesNotExist from django.db import connection +from django.contrib.gis.db import models from django.http import HttpRequest, QueryDict from django.contrib.gis.geos import GEOSException, Polygon, GEOSGeometry, Point from django.contrib.gis.gdal import GDALException @@ -828,3 +829,66 @@ def filter_queryset(self, request, queryset, view): return queryset.order_by(*ordering) return queryset + + +class WellQaQcFilterBackend(filters.DjangoFilterBackend): + """ + Custom well list filtering logic for the QaQc Dashboard. + allows additional 'filter_group' params. + """ + def filter_queryset(self, request, queryset, view): + try: + filter_groups = request.query_params.getlist('filter_group', []) + for group in filter_groups: + try: + group_params = json.loads(group) + except ValueError as exc: + raise ValidationError({ + 'filter_group': 'Error parsing JSON data: {}'.format(exc), + }) + + if not group_params: + continue + + q_objects = Q() + for field, value in group_params.items(): + if field == 'well_tag_number': + queryset = queryset.filter(well_tag_number__icontains=value) + + elif field == 'identification_plate_number': + queryset = queryset.filter(identification_plate_number__icontains=value) + + 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=' ')) + + elif field == 'company_of_person_responsible_name' and value == 'null': + q_objects |= (Q(company_of_person_responsible__isnull=True) | + Q(company_of_person_responsible__name__isnull=True) | + Q(company_of_person_responsible__name='') | Q(company_of_person_responsible__name=' ')) + + # Directly handle special cases for fields like latitude and longitude + elif field in ['latitude', 'longitude']: + if value == 'null': + q_objects &= Q(**{'geom__isnull': True}) + + elif value == 'null': + # Check if the field exists in the model + try: + field_obj = queryset.model._meta.get_field(field) + except models.FieldDoesNotExist: + continue + + # Now handling CharField, including checks for empty strings and spaces + if isinstance(field_obj, models.CharField): + q_objects &= (Q(**{f'{field}__isnull': True}) | Q(**{f'{field}': ''}) | Q(**{f'{field}': ' '})) + else: + # For other field types, just check for null + q_objects &= Q(**{f'{field}__isnull': True}) + + # Apply the combined Q object filters to the queryset + queryset = queryset.filter(q_objects) + + except Exception as e: + print(e) + return queryset diff --git a/app/backend/wells/serializers_v2.py b/app/backend/wells/serializers_v2.py index b7f96d0597..662ec6e02e 100644 --- a/app/backend/wells/serializers_v2.py +++ b/app/backend/wells/serializers_v2.py @@ -506,12 +506,16 @@ class Meta: class RecordComplianceSerializer(serializers.ModelSerializer): work_start_date = serializers.DateField(read_only=True) work_end_date = serializers.DateField(read_only=True) + company_of_person_responsible_name = serializers.ReadOnlyField( + source='company_of_person_responsible.name') + person_responsible_name = serializers.ReadOnlyField(source='person_responsible.name') class Meta: model = Well fields = [ 'well_tag_number', 'identification_plate_number', + 'intended_water_use', 'well_class', 'latitude', 'longitude', @@ -523,8 +527,8 @@ class Meta: 'well_status', 'work_start_date', 'work_end_date', - 'person_responsible', - 'company_of_person_responsible', + 'person_responsible_name', + 'company_of_person_responsible_name', 'create_date', 'create_user', 'natural_resource_region', diff --git a/app/backend/wells/views_v2.py b/app/backend/wells/views_v2.py index d2be7638a5..fad11871e8 100644 --- a/app/backend/wells/views_v2.py +++ b/app/backend/wells/views_v2.py @@ -36,7 +36,8 @@ WellListFilterBackend, WellListOrderingFilter, GeometryFilterBackend, - RadiusFilterBackend + RadiusFilterBackend, + WellQaQcFilterBackend ) from wells.models import Well, WellAttachment, \ WELL_STATUS_CODE_ALTERATION, WELL_STATUS_CODE_CONSTRUCTION, WELL_STATUS_CODE_DECOMMISSION @@ -592,8 +593,8 @@ class MislocatedWellsListView(ListAPIView): pagination_class = APILimitOffsetPagination # Allow searching on name fields, names of related companies, etc. - filter_backends = (WellListFilterBackend, BoundingBoxFilterBackend, - filters.SearchFilter, WellListOrderingFilter, GeometryFilterBackend) + filter_backends = (WellQaQcFilterBackend, filters.SearchFilter) + ordering = ('well_tag_number',) def get_queryset(self): @@ -616,8 +617,7 @@ class RecordComplianceListView(ListAPIView): pagination_class = APILimitOffsetPagination # Allow searching on name fields, names of related companies, etc. - filter_backends = (WellListFilterBackend, BoundingBoxFilterBackend, - filters.SearchFilter, WellListOrderingFilter, GeometryFilterBackend) + filter_backends = (WellQaQcFilterBackend, filters.SearchFilter) ordering = ('well_tag_number',) def get_queryset(self): @@ -628,26 +628,26 @@ def get_queryset(self): 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) + # 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') @@ -670,8 +670,7 @@ class CrossReferencingListView(ListAPIView): pagination_class = APILimitOffsetPagination # Allow searching on name fields, names of related companies, etc. - filter_backends = (WellListFilterBackend, BoundingBoxFilterBackend, - filters.SearchFilter, WellListOrderingFilter, GeometryFilterBackend) + filter_backends = (WellQaQcFilterBackend, filters.SearchFilter) ordering = ('well_tag_number',) def get_queryset(self): diff --git a/app/frontend/src/qaqc/components/QaQcFilters.vue b/app/frontend/src/qaqc/components/QaQcFilters.vue index d265325b84..e9bd3942fe 100644 --- a/app/frontend/src/qaqc/components/QaQcFilters.vue +++ b/app/frontend/src/qaqc/components/QaQcFilters.vue @@ -13,7 +13,7 @@ */