@@ -136,8 +136,56 @@ def get_queryset(self):
136136 for property_filter in property_filters :
137137 queryset = queryset .filter (property_filter )
138138
139+ # Apply numeric range filters separately
140+ queryset = self ._apply_numeric_range_filters (queryset )
141+
139142 return queryset .select_related ("category" , "location" , "collection" , "size" )
140143
144+ def _apply_numeric_range_filters (self , queryset ):
145+ """Apply numeric range filters using proper numeric comparison."""
146+ from django .db .models import DecimalField
147+ from django .db .models .functions import Cast
148+
149+ for param_name , param_values in self .request .GET .lists ():
150+ if param_name .endswith (("_min" , "_max" )):
151+ try :
152+ property_slug = param_name .replace ("_min" , "" ).replace ("_max" , "" )
153+ property_obj = AssetProperty .objects .get (slug = property_slug )
154+
155+ if property_obj .property_type == "number" :
156+ range_type = "min" if param_name .endswith ("_min" ) else "max"
157+
158+ for param_value in param_values :
159+ if param_value .strip ():
160+ numeric_value = float (param_value )
161+
162+ # Apply range filter using Cast for proper numeric comparison
163+ if range_type == "min" :
164+ queryset = queryset .filter (
165+ property_values__property = property_obj ,
166+ property_values__value__regex = r"^[0-9]+\.?[0-9]*$" ,
167+ ).extra (
168+ where = [
169+ "CAST(inventory_assetpropertyvalue.value AS DECIMAL(10,2)) >= %s"
170+ ],
171+ params = [numeric_value ],
172+ )
173+ else : # max
174+ queryset = queryset .filter (
175+ property_values__property = property_obj ,
176+ property_values__value__regex = r"^[0-9]+\.?[0-9]*$" ,
177+ ).extra (
178+ where = [
179+ "CAST(inventory_assetpropertyvalue.value AS DECIMAL(10,2)) <= %s"
180+ ],
181+ params = [numeric_value ],
182+ )
183+ break
184+ except (ValueError , TypeError , AssetProperty .DoesNotExist ):
185+ continue
186+
187+ return queryset
188+
141189 def _parse_property_parameters (self ):
142190 """Parse property-related parameters from the request."""
143191 property_params = {}
@@ -210,13 +258,19 @@ def _build_numeric_filter(self, property_id, params):
210258 has_min = "min" in params
211259 has_max = "max" in params
212260
213- if has_min or has_max :
214- return (
215- Q (property_values__property_id = property_id )
216- & Q (property_values__value__regex = r"^[0-9]+\.?[0-9]*$" )
217- & ~ Q (property_values__value = "" )
218- )
219- return None
261+ if not (has_min or has_max ):
262+ return None
263+
264+ # Base filter for valid numeric values
265+ base_filter = (
266+ Q (property_values__property_id = property_id )
267+ & Q (property_values__value__regex = r"^[0-9]+\.?[0-9]*$" )
268+ & ~ Q (property_values__value = "" )
269+ )
270+
271+ # For range filtering, we need to do post-processing since we store numeric values as strings
272+ # We'll return the base filter and let the get_queryset method handle the range logic
273+ return base_filter
220274
221275 def _build_dropdown_filter (self , property_id , params ):
222276 """Build filter for dropdown properties."""
@@ -247,8 +301,8 @@ def _get_property_filters(self):
247301
248302 def _get_properties_with_current_values (self ):
249303 """Get all properties with their current filter values attached."""
250- properties = AssetProperty .objects .select_related ( "category " ).order_by (
251- "category__name " , "order" , "name "
304+ properties = AssetProperty .objects .prefetch_related ( "categories " ).order_by (
305+ "name " , "order"
252306 )
253307
254308 for prop in properties :
@@ -481,7 +535,7 @@ def get_context_data(self, **kwargs):
481535
482536 # Add asset properties
483537 category_properties = AssetProperty .objects .filter (
484- category = asset .category
538+ categories = asset .category
485539 ).order_by ("order" , "name" )
486540
487541 # Get existing property values for this asset
@@ -600,7 +654,7 @@ def post(self, request, *args, **kwargs):
600654 def _update_asset_properties (self , asset , data ):
601655 """Update asset property values from form data."""
602656 updated_properties = []
603- category_properties = AssetProperty .objects .filter (category = asset .category )
657+ category_properties = AssetProperty .objects .filter (categories = asset .category )
604658
605659 for prop in category_properties :
606660 field_name = f"property_{ prop .slug } "
@@ -767,11 +821,11 @@ def get(self, request, *args, **kwargs):
767821 except AssetProperty .DoesNotExist :
768822 return JsonResponse ([], safe = False )
769823
770- # Get distinct values for this property from assets in the same category that match the query
824+ # Get distinct values for this property from assets in categories that use this property
771825 values = (
772826 AssetPropertyValue .objects .filter (
773827 property = property_obj ,
774- asset__category = property_obj .category , # Only from same category
828+ asset__category__in = property_obj .categories . all () , # Only from categories that use this property
775829 value__icontains = query ,
776830 )
777831 .values_list ("value" , flat = True )
0 commit comments