Org Web Adapter

hungryroot/jira/be_7349_add_contains_all_product_ids_filter_to_v2_and_v3_parirings_api.org

ID
edbff570-b5f3-49de-a6e4-2a2a954b6bb4

BE-7349 Add contains ALL product_ids filter to V2 and V3 parirings API

- source :: https://hungryroot.atlassian.net/browse/BE-7349

- tags :: Hungryroot API Project

- epic :: EP-411 Eng Parking Lot

- sprint :: HR BE Sprint 105

- status :: Status - Complete

Tasks

DONE Ask Cursor to walk through adding product_ids_all filters to V2 and V3 pairings

workaicursorhungryrootbe7349sprint105ep411featureapiv2apiv3
ID
28d7a3c6-a7df-11f0-a4a7-0df08b843da6

DONE Get a screencap of the changes and make sure they work

workfeaturehungryrootbe7349sprint105ep411apiv2apiv3
ID
a75cdc01-9edc-c55d-3ff6-bcf52409a003

Description

Background

The v2 (/api/v2/pairings/) and v3 pairing list APIs currently support a

product_ids query parameter that filters pairings containing any of the

specified ingredient product IDs (OR semantics). There is no way to query for

pairings that contain all of the specified products.

Current behavior

GET /api/v2/pairings/?product_ids=101,202,303 returns pairings that have product

101 OR 202 OR 303 as an ingredient.

This is implemented via ModelMultipleChoiceCSVFilter with conjoined=False and a

filter_product_ids method that uses needed_ingredients__ingredient__in=value.

Desired behavior

Add a new query parameter (e.g. product_ids_all) that returns only pairings

whose ingredients include every product ID in the list (AND semantics).

GET /api/v2/pairings/?product_ids_all=101,202,303 should return only pairings that

have product 101 AND 202 AND 303 as ingredients.

Scope

v2 API - Add the new filter to PairingFilter in app/rest/pairing.py

v3 API - Add the new filter to BasePairingFilter in app/rest/v3/pairing.py

Tests - Add test coverage in app/tests/rest/test_pairings.py (and v3 equivalent)

for:

Single product ID (equivalent to existing behavior)

Multiple product IDs where a pairing matches all

Multiple product IDs where no pairing matches all

Empty value handling

OpenAPI docs - Add OpenApiParameter description for the new filter

Implementation Notes

The filter can be implemented using Count + annotate:

#+begin_src python

from django.db.models import Count, Q

def filter_product_ids_all(self, queryset, name, value): if not value: return

queryset product_ids = [v.pk for v in value] return ( queryset

.filter(needed_ingredients__ingredient__in=product_ids)

.annotate(matched_count=Count( "needed_ingredients__ingredient",

filter=Q(needed_ingredients__ingredient__in=product_ids), ))

.filter(matched_count=len(product_ids)) )

#+end_src

Files to modify

app/rest/pairing.py - PairingFilter

app/rest/v3/pairing.py - BasePairingFilter

app/tests/rest/test_pairings.py

app/tests/rest/v3/test_pairing.py