Skip to content

Extend promotional classification toggle to OCR review - #116

Closed
thejonathangu wants to merge 7 commits into
mainfrom
jonbranch
Closed

thejonathangu wants to merge 7 commits into
mainfrom
jonbranch

Conversation

@thejonathangu

@thejonathangu thejonathangu commented Apr 22, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Closes the gap that left FEATURE_PROMO_CLASSIFICATION wired into the manual mail-entry form but missing from the OCR-driven path. Admins can now tag a mail piece as promotional while reviewing OCR results, and the flag is persisted end-to-end into the resulting MAIL document — matching the existing RecordEntry behavior.

Along the way, fixes a silent bug where /api/feature-flags responses were being filtered down to three fields inside App.tsx, so promoClassification (and ocrAutoExtract) never reached the store no matter what the backend returned. This is what was hiding the existing RecordEntry toggle as well once the flag was turned on.

What's in here

Bug fix — feature-flag hydration (App.tsx)

  • setFeatureFlags now passes every flag through from the API response. No behavior change when flags are off.

OCR queue — promotional classification

  • Backend
    • ocr_queue_items documents get an isPromotional: bool field (default false).
    • PATCH /api/ocr/queue/:id accepts isPromotional (gated on FEATURE_PROMO_CLASSIFICATION; silently ignored when the flag is off).
    • POST /api/ocr/queue/:id/confirm forwards isPromotional: true into create_mail when set; omitted when false, matching the existing MAIL shape.
  • Frontend
    • ApiOcrQueueItem and the PATCH payload type carry isPromotional.
    • OcrQueue.tsx renders a "Promotional" checkbox between Type and Mailbox when promoClassification is on, persisting immediately via PATCH (same pattern as the Type selector, so the value survives navigation).

Docs

  • .env.sample: rewrite the outdated FEATURE_PROMO_CLASSIFICATION comment to reflect both admin surfaces.
  • data-model.md / data-model.mmd: add isPromotional to OCR_QUEUE_ITEMS; also fill in the previously-undocumented fileId / imagePath fields on the same entity.

Behavior matrix

FEATURE_PROMO_CLASSIFICATION Record-entry toggle OCR review toggle PATCH accepts isPromotional Confirm writes isPromotional on mail
false (default) hidden hidden ignored never
true shown shown yes when true

No indexes, no migration, no backfill — isPromotional is a new optional boolean on ocr_queue_items and simply absent on older docs, which is equivalent to false.

Out of scope

  • No changes to weekly summaries, dashboard counts, notifications, or member views; the flag is still purely informational downstream, consistent with the original classification feature.
  • Console email provider dev-mode print tweaks that were already uncommitted were left out of this PR.

Test plan

  • Backend unit tests pass: cd backend && coverage run -m unittest discover -s tests/unit -p "test_*.py" -t . && coverage report --fail-under=75
  • Frontend checks pass: cd frontend && npm run lint && npx tsc --noEmit && npm run build
  • Manual: with FEATURE_PROMO_CLASSIFICATION=false, checkbox is hidden on both RecordEntry and OcrQueue; PATCHing isPromotional is a no-op; confirm creates mail without the field.
  • Manual: with FEATURE_PROMO_CLASSIFICATION=true, checkbox appears on both screens; toggling on the OCR review persists across navigation; confirmed mail doc has isPromotional: true.
  • Manual: hard-refresh verifies /api/feature-flags populates all five flags in the Zustand store.

Closes #90

Admin mail-entry form gains an optional "Promotional" checkbox, gated
behind a new FEATURE_PROMO_CLASSIFICATION flag (default off). Stored as
an optional isPromotional boolean on the MAIL document — present only
when true on create, explicit true|false on PATCH. No user-facing
effect today; foundation for future summary/notification filtering.
Queue image uploads now write to a host-bind-mounted volume at
IMAGE_STORE_DIR (default /var/lib/avenu/images) instead of GridFS.
OCR_QUEUE_ITEM gains an optional imagePath field; fileId stays as a
read-time fallback for legacy rows so no migration is needed.

A new FEATURE_OCR_AUTO_EXTRACT flag gates background OCR — when off
(default) uploads land as pending for manual review, letting admins
snap photos on their phone and fill in receiver/sender on desktop.

Nightly at 03:00 local, the scheduler hits a new internal endpoint
POST /api/internal/jobs/image-prune which deletes files + soft-deletes
rows past IMAGE_RETENTION_HOURS (24h default), plus sweeps orphaned
files. Scheduler now dispatches weekly-summary and image-prune as
independent cron jobs.
App.tsx was copying only three of the five fields returned by
/api/feature-flags into the Zustand store, so `ocrAutoExtract` and
`promoClassification` were permanently stuck at their default `false`
regardless of backend configuration. Pass every field through.

Made-with: Cursor
Extends the OCR queue so admins can tag an item as promotional during
the review step (same gate as the manual record-entry form:
FEATURE_PROMO_CLASSIFICATION / promoClassification).

- Queue items now persist `isPromotional` (default false); surfaced on
  GET and settable via PATCH /api/ocr/queue/:id.
- POST /api/ocr/queue/:id/confirm forwards `isPromotional: true` into
  the created mail record when set, matching the existing MAIL shape
  (omitted when false).
- OcrQueue.tsx renders a Promotional checkbox between Type and Mailbox
  when the flag is on, persisting immediately via PATCH like the Type
  selector so it survives navigation.

Made-with: Cursor
- .env.sample: rewrite the FEATURE_PROMO_CLASSIFICATION comment, which
  claimed no user-facing effect; the flag now gates the toggle on both
  the record-entry form and the OCR queue review screen.
- data-model.md / data-model.mmd: add `isPromotional` to OCR_QUEUE_ITEM
  and fill in the previously-undocumented `fileId` / `imagePath`
  fields alongside it.

Made-with: Cursor
@gekiclaws gekiclaws added the enhancement New feature or request label Apr 24, 2026
@gekiclaws gekiclaws added this to the v1.0 milestone Apr 24, 2026
@gekiclaws
gekiclaws requested a review from AutumnQiu99 April 24, 2026 20:33
@gekiclaws gekiclaws changed the title feat(ocr-queue): extend promotional classification toggle to OCR review Extend promotional classification toggle to OCR review Apr 24, 2026
@gekiclaws gekiclaws closed this Apr 27, 2026
@gekiclaws gekiclaws added duplicate This issue or pull request already exists and removed enhancement New feature or request labels Apr 27, 2026
@gekiclaws

Copy link
Copy Markdown
Contributor

Closed per duplicate #119

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

duplicate This issue or pull request already exists

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support promotional mail classification

2 participants