Skip to content

draft - feat: Paperless-ngx integration (import/export)#82

Draft
lcrostarosa wants to merge 1 commit intovas3k:mainfrom
lcrostarosa:feat/paperless-ngx-integration
Draft

draft - feat: Paperless-ngx integration (import/export)#82
lcrostarosa wants to merge 1 commit intovas3k:mainfrom
lcrostarosa:feat/paperless-ngx-integration

Conversation

@lcrostarosa
Copy link
Copy Markdown

Summary

Adds bidirectional integration with Paperless-ngx, a self-hosted document management system. Closes #39.

  • Import: Browse, search, and select documents from Paperless-ngx. Downloads files into TaxHacker's unsorted queue for AI analysis.
  • Export: Upload transaction files to Paperless-ngx with tag and correspondent mapping from the bulk actions menu.
  • Settings: New settings page at /settings/paperless with URL, API token, enable toggle, and connection test button.
  • Deduplication: Tracks paperlessDocumentId on the File model to prevent duplicate imports/exports.
  • Security: All API calls are server-side (server actions), URL validated for SSRF prevention, 30s request timeouts.

New files

  • lib/paperless/ — Typed API client (native fetch, auth, pagination, error handling)
  • app/(app)/settings/paperless/ — Settings page + test connection action
  • app/(app)/import/paperless/ — Import page + server actions
  • app/(app)/export/paperless/ — Export server actions
  • components/settings/paperless-settings-form.tsx — Settings form
  • components/import/paperless.tsx — Import UI (browse, search, select, paginate)
  • components/export/paperless-export-dialog.tsx — Export dialog with tag/correspondent selection
  • docs/paperless-ngx.md — Full documentation
  • Prisma migration adding paperless_document_id to files table

Modified files

  • prisma/schema.prismapaperlessDocumentId field + index on File model
  • forms/settings.ts — Paperless fields in settings Zod schema
  • app/(app)/settings/layout.tsx — "Paperless-ngx" in settings nav
  • models/files.tsgetFileByPaperlessDocumentId() query
  • components/sidebar/sidebar.tsx — "Import from Paperless" sidebar link
  • components/transactions/bulk-actions.tsx — "Export to Paperless" button
  • components/transactions/list.tsx + app/(app)/transactions/page.tsx — Pass Paperless enabled flag

Test plan

  • Run npx prisma migrate dev — migration applies cleanly
  • npm run build — no type errors (verified)
  • Settings: configure URL + token, save, test connection shows document count
  • Import: browse documents with search/pagination, import selected, verify in /unsorted
  • Import: re-import same documents — verify they are skipped (deduplication)
  • Export: select transactions, export to Paperless with tags/correspondent, verify in Paperless
  • Export: re-export same files — verify already-uploaded files are skipped
  • Sidebar shows "Import from Paperless" link
  • Bulk actions show "Export to Paperless" only when Paperless is configured

🤖 Generated with Claude Code

Add bidirectional integration with Paperless-ngx, a self-hosted document
management system. Users can import documents from Paperless-ngx into
TaxHacker for AI-powered financial extraction, and export processed
transactions back to Paperless-ngx for long-term archival.

- Typed API client (lib/paperless/) with auth, pagination, error handling
- Settings UI at /settings/paperless (URL, token, test connection)
- Import flow: browse, search, select, and import Paperless documents
- Export flow: upload transaction files with tag/correspondent mapping
- Prisma migration adding paperlessDocumentId to File model for dedup
- Sidebar link for Paperless import, bulk action button for export
- Full documentation at docs/paperless-ngx.md

Closes vas3k#39

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@lcrostarosa lcrostarosa marked this pull request as draft March 31, 2026 03:48
@lcrostarosa lcrostarosa changed the title feat: Paperless-ngx integration (import/export) draft - feat: Paperless-ngx integration (import/export) Mar 31, 2026
)}
</div>
</td>
<td className="p-2 hidden md:table-cell text-muted-foreground">{doc.created_date}</td>
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Styles and classnames inline

const correspondent = doc.correspondent ? correspondentMap.get(doc.correspondent) : null

return (
<tr className="border-t hover:bg-muted/30 cursor-pointer" onClick={onToggle}>
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

This needs to be rewritten, should not return hardcoded classnames and ideally returns a component

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.

[feature request] Paperless NGX Integration

1 participant