class ProductFilter(FilterSet): # explicit filter declaration max_price = NumberFilter(field_name="price", lookup_expr='lte', label='highest price') max_sub_price = NumberFilter(field_name="subproduct__sub_price", lookup_expr='lte') sub = NumberFilter(field_name="subproduct", lookup_expr='exact') int_id = NumberFilter(method='filter_method_typed') number_id = NumberFilter(method='filter_method_untyped', help_text='some injected help text') number_id_ext = NumberFilter(method=external_filter_method) # implicit filter declaration subproduct__sub_price = NumberFilter() # reverse relation other_sub_product__uuid = UUIDFilter() # forward relation # special cases ordering = OrderingFilter( fields=('price', 'in_stock'), field_labels={ 'price': 'Price', 'in_stock': 'in stock' }, ) in_categories = BaseInFilter(field_name='category') is_free = BooleanFilter(field_name='price', lookup_expr='isnull') price_range = RangeFilter(field_name='price') model_multi_cat = ModelMultipleChoiceFilter(field_name='category', queryset=Product.objects.all()) model_single_cat = ModelChoiceFilter(field_name='category', queryset=Product.objects.all()) all_values = AllValuesFilter(field_name='price') custom_filter = CustomBooleanFilter(field_name='price', lookup_expr='isnull') custom_underspec_filter = CustomBaseInFilter(field_name='category') model_multi_cat_relation = ModelMultipleChoiceFilter( field_name='other_sub_product', queryset=OtherSubProduct.objects.all()) price_range_vat = RangeFilter(field_name='price_vat') price_range_vat_decorated = extend_schema_field(OpenApiTypes.INT)( RangeFilter(field_name='price_vat')) class Meta: model = Product fields = [ 'category', 'in_stock', 'max_price', 'max_sub_price', 'sub', 'subproduct__sub_price', 'other_sub_product__uuid', ] def filter_method_typed(self, queryset, name, value: int): return queryset.filter(id=int(value)) def filter_method_untyped(self, queryset, name, value): return queryset.filter(id=int(value)) # pragma: no cover
class ApplicationListFilter(FilterSet): label = BaseInFilter(field_name="applicationlabel__slug", distinct=True, validators=[label_slug_exists, label_slug_excluded]) class Meta: model = Application fields = ['label']
class ProductFilter(FilterSet): # explicit filter declaration max_price = NumberFilter(field_name="price", lookup_expr='lte', label='highest price') max_sub_price = NumberFilter(field_name="subproduct__sub_price", lookup_expr='lte') sub = NumberFilter(field_name="subproduct", lookup_expr='exact') int_id = NumberFilter(method='filter_method_typed') number_id = NumberFilter(method='filter_method_untyped', help_text='some injected help text') number_id_ext = NumberFilter(method=external_filter_method) # implicit filter declaration subproduct__sub_price = NumberFilter() # reverse relation other_sub_product__uuid = CharFilter() # forward relation # special cases ordering = OrderingFilter( fields=('price', 'in_stock'), field_labels={ 'price': 'Price', 'in_stock': 'in stock' }, ) in_categories = BaseInFilter(field_name='category') class Meta: model = Product fields = [ 'category', 'in_stock', 'max_price', 'max_sub_price', 'sub', 'subproduct__sub_price', 'other_sub_product__uuid', ] def filter_method_typed(self, queryset, name, value: int): return queryset.filter(id=int(value)) def filter_method_untyped(self, queryset, name, value): return queryset.filter(id=int(value)) # pragma: no cover
class ReportFilterSet(FilterSet): """Filter set for the reports endpoint.""" id = BaseInFilter() from_date = DateFilter(field_name="date", lookup_expr="gte") to_date = DateFilter(field_name="date", lookup_expr="lte") project = NumberFilter(field_name="task__project") customer = NumberFilter(field_name="task__project__customer") review = NumberFilter(field_name="review") editable = NumberFilter(method="filter_editable") not_billable = NumberFilter(field_name="not_billable") billed = NumberFilter(field_name="billed") verified = NumberFilter(field_name="verified_by_id", lookup_expr="isnull", exclude=True) reviewer = NumberFilter(field_name="task__project__reviewers") verifier = NumberFilter(field_name="verified_by") billing_type = NumberFilter(field_name="task__project__billing_type") user = NumberFilter(field_name="user_id") cost_center = NumberFilter(method="filter_cost_center") def filter_editable(self, queryset, name, value): """Filter reports whether they are editable by current user. When set to `1` filter all results to what is editable by current user. If set to `0` to not editable. """ user = self.request.user def get_editable_query(): return ( # avoid duplicates by using subqueries instead of joins Q(user__in=user.supervisees.values("id")) | Q(task__project__in=user.reviews.values("id")) | Q(user=user) ) & ~(Q(verified_by__isnull=False) & Q(billed=True)) if value: # editable if user.is_superuser: # superuser may edit all reports return queryset # only owner, reviewer or supervisor may change unverified reports queryset = queryset.filter(get_editable_query()) return queryset else: # not editable if user.is_superuser: # no reports which are not editable return queryset.none() queryset = queryset.exclude(get_editable_query()) return queryset def filter_cost_center(self, queryset, name, value): """ Filter report by cost center. Cost center on task has higher priority over project cost center. """ return queryset.filter( Q(task__cost_center=value) | Q(task__project__cost_center=value) & Q(task__cost_center__isnull=True)) class Meta: """Meta information for the report filter set.""" model = models.Report fields = ( "date", "from_date", "to_date", "user", "task", "project", "verified", "not_billable", "review", "reviewer", "billing_type", )
class ReportFilterSet(FilterSet): """Filter set for the reports endpoint.""" id = BaseInFilter() from_date = DateFilter(field_name='date', lookup_expr='gte') to_date = DateFilter(field_name='date', lookup_expr='lte') project = NumberFilter(field_name='task__project') customer = NumberFilter(field_name='task__project__customer') review = NumberFilter(field_name='review') editable = NumberFilter(method='filter_editable') not_billable = NumberFilter(field_name='not_billable') verified = NumberFilter(field_name='verified_by_id', lookup_expr='isnull', exclude=True) reviewer = NumberFilter(field_name='task__project__reviewers') verifier = NumberFilter(field_name='verified_by') billing_type = NumberFilter(field_name='task__project__billing_type') user = NumberFilter(field_name='user_id') cost_center = NumberFilter(method='filter_cost_center') def filter_editable(self, queryset, name, value): """Filter reports whether they are editable by current user. When set to `1` filter all results to what is editable by current user. If set to `0` to not editable. """ user = self.request.user def get_editable_query(): return ( # avoid duplicates by using subqueries instead of joins Q(user__in=user.supervisees.values('id')) | Q(task__project__in=user.reviews.values('id')) | Q(user=user)) & Q(verified_by__isnull=True) if value: # editable if user.is_superuser: # superuser may edit all reports return queryset # only owner, reviewer or supervisor may change unverified reports queryset = queryset.filter(get_editable_query()) return queryset else: # not editable if user.is_superuser: # no reports which are not editable return queryset.none() queryset = queryset.exclude(get_editable_query()) return queryset def filter_cost_center(self, queryset, name, value): """ Filter report by cost center. Cost center on task has higher priority over project cost center. """ return queryset.filter( Q(task__cost_center=value) | Q(task__project__cost_center=value) & Q(task__cost_center__isnull=True)) class Meta: """Meta information for the report filter set.""" model = models.Report fields = ('date', 'from_date', 'to_date', 'user', 'task', 'project', 'verified', 'not_billable', 'review', 'reviewer', 'billing_type')