Skip to content

fix(accounting): search on a filter Paperless actually honours - #56

Merged
PhilippTheServer merged 1 commit into
OpenTaberna:mainfrom
PhilippTheServer:pl/fix-document-search
Aug 26, 2026
Merged

PhilippTheServer merged 1 commit into
OpenTaberna:mainfrom
PhilippTheServer:pl/fix-document-search

Conversation

@PhilippTheServer

Copy link
Copy Markdown
Contributor

Closes #55 · found while seeding the new Paperless service with data

GET /v1/admin/accounting/documents?query=… returned every document, whatever the term.

The router mapped query onto a Paperless filter named text. Paperless has no such
filter, and ignores unknown parameters rather than rejecting them — so the request
succeeded, returned 200, and handed back the whole collection.

Measured against 183 seeded documents:

GET /api/documents/?query=Barolo           ->  25   (Paperless, correct)
GET /api/documents/?title_content=Barolo   ->  25   (Paperless, correct)
GET /api/documents/?text=Barolo            -> 183   (unknown filter, ignored)

GET /v1/admin/accounting/documents?query=Barolo -> 183

An operator looking for one invoice gets a full result list that reads as a search matching
a lot. Nothing errors, nothing warns.

The fix

build_document_filters moves the mapping out of the endpoint so it can be tested without a
running Paperless, and PAPERLESS_FILTERS pins every outgoing name against the set
Paperless recognises — because a wrong name here never fails loudly, it just silently widens
the results.

The existing test asserted the buggy value ({"text": "invoice"}), so it is updated
rather than deleted. It was locking the defect in.

Also here

/v1/admin/analytics/storefront gains a limit, matching the /products endpoint beside
it. Its product_interest and top_paths were fixed at ten rows with no way to ask for
more — which surfaced when a shop with real traffic pushed an integration test's own fixture
SKU out of the top ten.

Verification

$ uv run pytest tests/test_accounting_filters_unit.py -q
9 passed

$ uv run pytest -q
1067 passed, 7 skipped in 18.26s

$ ruff check src/app tests/
All checks passed!

The tests catch the bug. Restoring text:

E  assert 'text' not in {'page': 1, 'page_size': 50, 'text': 'Barolo'}
E  AssertionError: assert 'text' == 'query'
FAILED test_full_text_search_uses_a_filter_paperless_honours

GET /v1/admin/accounting/documents?query=... returned every document, whatever
the search term.

The router mapped query onto a Paperless filter named "text". Paperless has no
such filter, and rather than rejecting an unknown parameter it ignores it — so
the request succeeded, returned 200, and handed back the whole collection.
Against 183 seeded documents, ?query=Barolo gave 183 instead of 25.

The failure shape is the problem: an operator looking for one invoice gets a
full result list that reads as a search matching a lot. Nothing errors.

Moves the mapping into build_document_filters so it can be tested without a
running Paperless, and pins every outgoing name against the set Paperless
recognises — because a wrong name here never fails loudly, it just widens the
result set.

The existing test asserted the buggy value, so it is updated rather than
deleted; it was locking in the defect.

Also adds a limit to /v1/admin/analytics/storefront, matching the /products
endpoint beside it. Its product_interest and top_paths were fixed at ten rows,
which meant a caller could not reach anything outside the top ten — including,
as it turned out, an integration test's own fixture once the shop had real
traffic.

Closes #55

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YY1ekLLeFLkAU2kvdQ8Ey4
@PhilippTheServer
PhilippTheServer merged commit 8ed2c97 into OpenTaberna:main Aug 26, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Document search silently returns everything instead of filtering

1 participant