Skip to content

Add document preparation flow - #147

Open
nonprofittechy wants to merge 15 commits into
workflow/case-confirmationfrom
workflow/document-prep
Open

Add document preparation flow#147
nonprofittechy wants to merge 15 commits into
workflow/case-confirmationfrom
workflow/document-prep

Conversation

@nonprofittechy

Copy link
Copy Markdown
Member

Summary

Fourth PR in the staged filing-flow migration. This replaces the remaining document-preparation bridge with two durable-model screens:

  • adds the document checklist with inline missing-document upload and explicit acknowledgement
  • adds per-document organization for names, court filing types, confidentiality, filing components, courtesy email, and supporting-document order
  • extracts shared upload persistence so both intake and checklist uploads use the same path
  • persists checklist completion and all filing metadata to FilingDraft / FilingDocument
  • advances organized filings to the upcoming people slice

Stacked on #146; review only commit fc63330.

Screenshots

Document checklist

Document checklist

Organize documents

Organize documents

Validation

  • uv run pytest -q — 202 passed
  • npm run test:unit — 17 passed
  • Ruff, djlint, CSS/JS formatting, type checks, migration check, and git diff --check passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR continues the staged migration of the filing flow by replacing the remaining document-preparation bridge with durable-model screens for document checklist and per-document organization, while consolidating upload + extraction persistence into a shared service and persisting new draft state.

Changes:

  • Add Document Checklist and Organize Documents screens (views, templates, JS, CSS) and wire them into the v2 workflow.
  • Extract upload + lead-document analysis into a shared document_uploads service and improve cleanup when removing documents.
  • Persist checklist acknowledgement state to FilingDraft (model + migration) and add/adjust tests for the new flow behavior.

Reviewed changes

Copilot reviewed 21 out of 24 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
efile_app/efile/workflow.py Optimizes incomplete-party detection for QuerySet-backed parties and adjusts legacy-workflow detection for shared steps without a draft.
efile_app/efile/views/upload_documents.py Switches upload path to shared upload_files service and deletes S3 objects / stale guesses on removal.
efile_app/efile/views/organize_documents.py Adds new organize-documents endpoint to persist per-document filing metadata and ordering.
efile_app/efile/views/extraction_review.py Ensures draft step state is persisted before redirecting to the next step.
efile_app/efile/views/document_checklist.py Adds checklist screen with inline “missing document” upload and acknowledgement persistence.
efile_app/efile/urls.py Routes document checklist and organize-documents to the new v2 views (removes legacy redirect for those steps).
efile_app/efile/tests/test_workflow.py Adds coverage for legacy default when shared steps are evaluated without a draft context.
efile_app/efile/tests/test_reorganized_start.py Updates mocks for extracted upload logic and adds removal cleanup assertions; adjusts bridging test to target people screen.
efile_app/efile/tests/test_document_prep.py Adds end-to-end tests for checklist acknowledgement, inline upload, and organize-documents persistence.
efile_app/efile/templates/efile/upload_documents.html Updates user copy to reflect analysis of first PDF and deferred main-document choice.
efile_app/efile/templates/efile/organize_documents.html New template for per-document organization (main doc selection, metadata, reordering, courtesy email).
efile_app/efile/templates/efile/document_checklist.html New template for checklist review, inline upload, and acknowledgement gating.
efile_app/efile/templates/efile/case_confirmation.html Improves i18n-safe fallbacks for missing case fields.
efile_app/efile/static/js/upload-documents.js Updates analysis messaging and adds redirect handling for POST responses.
efile_app/efile/static/js/organize-documents.js New client behavior for organizing documents: loads dropdowns, manages ordering UI, submits JSON payload.
efile_app/efile/static/js/document-checklist.js New client behavior for inline checklist uploads.
efile_app/efile/static/css/reorganized-flow.css Adds styling for checklist and organize-documents UI components.
efile_app/efile/services/drafts.py Exposes checklist acknowledgement in draft snapshot; existing upload/case persistence utilities used by new screens.
efile_app/efile/services/document_uploads.py New shared upload + lead analysis implementation for both intake and checklist uploads.
efile_app/efile/models.py Adds document_checklist_acknowledged field to FilingDraft.
efile_app/efile/migrations/0005_document_checklist_state.py Migration to add the new checklist acknowledgement column.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +45 to +48
document.filing_component_code = str(item.get("filing_component") or "")[:100]
document.filing_component_name = str(item.get("filing_component_name") or "")[:255]
document.courtesy_copy_email = str(item.get("courtesy_copy_email") or "")[:254]
if document.pk == main_document_id:
Comment thread efile_app/efile/static/js/document-checklist.js
Comment on lines +228 to +232
});
const result = await response.json();
if (!response.ok || !result.success) throw new Error(result.error || "Could not save document details.");
window.location.assign(result.redirect_url);
} catch (error) {
nonprofittechy and others added 4 commits August 10, 2026 18:46
Validate and strip courtesy copy email server-side before persisting,
and guard the checklist/organize JS fetch handlers against redirected
(session-expired) responses before parsing JSON, matching the pattern
already used in upload-documents.js.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@nonprofittechy
nonprofittechy force-pushed the workflow/document-prep branch from 6d907fe to d992ea0 Compare August 10, 2026 22:46
@nonprofittechy
nonprofittechy marked this pull request as ready for review August 10, 2026 22:47
nonprofittechy and others added 11 commits August 10, 2026 20:20
boto3's upload_fileobj closes the Django UploadedFile it's given once
the S3 upload completes. upload_files() then reused that same file
object afterward to run LLM field extraction on the lead document,
raising "ValueError: I/O operation on closed file." Run the lead
analysis before the S3 upload instead, while the file is still open.

Also log the traceback on upload failures instead of swallowing it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Court, case category, and case type on the extraction review page were
free-text inputs that only ever wrote *_name columns. Tyler's e-filing
API requires exact court/category/type codes, so a new case could never
set draft.court_code -- which left organize_documents stuck permanently
on "Missing required court parameter" once a filer reached it, with no
way to recover even after re-entering a court name.

- Replace the free-text court/category/type/filing-type inputs with
  cascading dropdowns backed by the existing /api/dropdowns/ endpoints,
  matching how organize_documents already resolves these values. A
  matched extraction guess renders as a reviewed value with an Edit
  affordance; an unmatched or absent guess renders as a plain choice to
  make, so reviewing, correcting, and filling in gaps are visually
  distinct.
- When nothing was extracted from the document at all, say so plainly
  instead of presenting empty fields as "here's what we found," and
  link back to try a different upload.
- Require a matched court/category/type before a new case can advance,
  both client- and server-side.
- Persist a best-effort filing type guess onto the lead document so
  organize_documents can pre-fill it.
- organize_documents now redirects back to fix the court instead of
  dead-ending on the missing-parameter error if a draft somehow reaches
  it without one.
- Add the missing "request a certified copy" option next to the
  courtesy-copy-email checkbox, sourced from the same optional-services
  API the old expert form used, and persist selections per document.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…P error text

- Group optional-service checkboxes so common ones (certified copy,
  courtesy copy, expedited, etc.) show by default and the rest sit
  behind a "Show more options" toggle -- some courts return over a
  dozen services, which buried the ones filers actually look for.
- Add a return_to=review mechanism: editing a step from the Review
  screen now saves and returns to Review instead of continuing through
  the rest of the linear workflow. Wired into extraction_review and
  organize_documents here; people/payment pick it up in later commits.
- describe_efsp_error() only read body["error"/"message"/"detail"], so
  Tyler's "Malformed Interview" errors (type + description, no error
  key) fell through to a bare "returned status 500" -- exactly what
  reached the filer for a docket number entered on a would-be new case.
  Surface body["description"] too.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Tyler rejects a docket number on a new case ("doesn't allow subsequent
filing into non-indexed cases"), so presenting it as a normal
always-visible field invited exactly the input that gets rejected.
Hide it behind a "This case already has a number from the court"
checkbox instead; the field is shown plainly for an existing case,
where it's expected. Switching from existing back to new clears
whatever was entered, since that's the value the API would reject.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
test_unmigrated_people_screen_bridges_to_legacy_flow tested
your_information() falling back to the legacy expert_form for an
unmigrated (v1) draft. It was deliberately deleted in 8d269e9 ("Add
people and case question flow") once your_information was actually
implemented and that fallback no longer applied -- but document-prep's
copy of this test file predates that deletion and still had it, so
merging document-prep into people resurrected it instead of respecting
the delete. It fails outright now: your_information always forces
workflow_version=2 and renders normally, never redirecting to
expert_form.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
"Which PDF is the main document?" as a radio group made no sense with
a single document -- there was nothing to actually choose. Show an
informational sentence instead and submit that document's id via a
hidden field, keeping the same form contract; the radio group still
appears once there's more than one document to pick from.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A name suffix (Jr., Sr., III, ...) has to exactly match one of the
court's own codes to be accepted -- it's a closed list from Tyler's
codes API (.../courts/{court_id}/name_suffixes), the same shape as the
other code lookups here. Proxies it the same way so the suffix field
can become a dropdown instead of free text.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Checked ~/EfileProxyServer for what "Malformed Interview" and plain
error messages the proxy actually raises (FilingError call sites in
Ecf4Filer.java, FilingInformationDocassembleJacksonDeserializer.java,
and EcfCourtSpecificSerializer.java -- the deserializer that parses
this app's own efile_case_category/al_court_bundle payload shape).
Not all of it is cataloged; wrong_vars/required_vars were already
handled well by _describe_var, so this focuses on the free-text
messages that weren't: docket number on a non-indexed case (belt and
suspenders alongside the docket-number checkbox), a subsequent filing
missing its docket number, oversized documents (single and combined),
an empty filing-type list for the chosen case category/type, and
amount-in-controversy -- a genuine gap this app doesn't collect yet,
called out as such rather than implying it's self-serve fixable.

Unrecognized messages still pass through unchanged, same as before.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Implements the "amount in controversy" gap flagged by describe_efsp_error's
new hint: the EFSP rejects a filing whose filing type has
amountincontroversy="Required" (from Tyler's filing-types codes API)
unless the top-level amount_in_controversy field is set, and this app
never collected or sent it.

This is the data-capture half: prioritize_options() now passes through
extra fields like amountincontroversy instead of dropping everything
but code/name, organize-documents.js records whether the selected
filing type requires it, and organize_documents persists that onto
FilingDocument.filing_requires_amount_in_controversy. Asking for the
actual dollar amount (case_questions) and sending it in the filing
payload land in the following commits, since those live on other
branches in this stack.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
case_questions saves it directly on FilingDraft (not through
write_case_data, since it isn't config-driven), but read_case_data
never echoed it back -- so the frontend had no way to read it for the
fee quote or submission payload.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
get_filing_types logs response.headers.get("Content-Type") right
before the mocked call; a fake response without .headers raised
AttributeError there, caught by the view's own except Exception and
turned into a 400 that looked like the real thing was broken.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.

2 participants