feat(11-02): wire Region/PLZ/Bundesland filter into query builder + FilterPanel
TenderQueryDto gains validated plz (@MaxLength(5)), region, and bundesland fields. buildTenderWhere adds three conditional AND-branches: plz startsWith, bundesland exact-match against the now-backfilled indexed column (Pitfall 1), and region startsWith (usable independent of the bundesland column). FilterPanel gets a PLZ input and a 16-Land Bundesland dropdown (mirrors NUTS1_BUNDESLAND — web/api are separate packages) that write plz/bundesland into the URL searchParams; ResultsList already forwards the full URLSearchParams to listTenders(), so no additional fetch wiring was needed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -135,6 +135,43 @@ describe('buildTenderWhere', () => {
|
||||
const where = buildTenderWhere(dto({ status: 'expired' }));
|
||||
expect(where.status).toBe('expired');
|
||||
});
|
||||
|
||||
it('plz set: adds a plz-startsWith constraint (FILTER-02)', () => {
|
||||
const where = buildTenderWhere(dto({ plz: '10' }));
|
||||
|
||||
expect(where.AND).toEqual(
|
||||
expect.arrayContaining([{ plz: { startsWith: '10' } }]),
|
||||
);
|
||||
});
|
||||
|
||||
it('bundesland set: adds an exact bundesland-equality constraint against the backfilled column (FILTER-02, Pitfall 1)', () => {
|
||||
const where = buildTenderWhere(dto({ bundesland: 'Bayern' }));
|
||||
|
||||
expect(where.AND).toEqual(expect.arrayContaining([{ bundesland: 'Bayern' }]));
|
||||
});
|
||||
|
||||
it('region set: adds a region-startsWith constraint, independent of bundesland (FILTER-02)', () => {
|
||||
const where = buildTenderWhere(dto({ region: 'DE2' }));
|
||||
|
||||
expect(where.AND).toEqual(
|
||||
expect.arrayContaining([{ region: { startsWith: 'DE2' } }]),
|
||||
);
|
||||
});
|
||||
|
||||
it('plz/bundesland/region are omitted from AND when unset', () => {
|
||||
const where = buildTenderWhere(dto());
|
||||
|
||||
const and = (where.AND as unknown[]) ?? [];
|
||||
const hasGeoClause = and.some(
|
||||
(clause) =>
|
||||
typeof clause === 'object' &&
|
||||
clause !== null &&
|
||||
('plz' in (clause as Record<string, unknown>) ||
|
||||
'bundesland' in (clause as Record<string, unknown>) ||
|
||||
'region' in (clause as Record<string, unknown>)),
|
||||
);
|
||||
expect(hasGeoClause).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('buildOrderBy', () => {
|
||||
|
||||
Reference in New Issue
Block a user