Files
truenas-stacks/docs/operations/SCHOOL_PAPERLESS_INTAKE.md
2026-05-13 20:53:00 +00:00

4.4 KiB

School Paperless Intake Workflow

Workflows:

  • n8n-workflows/18-school-paperless-intake.json
  • n8n-workflows/19-paperless-school-metadata-enrichment.json

This workflow is meant for a Telegram chat-driven upload pipeline that sends schoolwork into Paperless-NGX while recording intake metadata in shared Postgres.

What it does

  1. Accepts a multipart upload at POST /webhook/school/intake/upload
  2. Requires form fields:
    • class_name
    • assignment_name
    • submission_kind
  3. Accepts optional fields:
    • semester
    • course_code
    • paper_kind
    • notes
    • source (defaults to telegram)
    • telegram_chat_id
    • telegram_message_id
  4. Generates a deterministic intake_id from date + class + assignment + file checksum
  5. Stores/updates the intake row in Postgres first
  6. Uploads the file to Paperless using the deterministic intake ID in the filename
  7. Marks the row as uploaded after Paperless accepts the upload

Shared Postgres expectations

  • Use the shared Postgres network/credentials pattern already used by the automation stack.
  • The workflow expects an n8n Postgres credential named Shared Postgres.
  • Recommended target database: school_intake
  • Tracked schema: docs/reference/SCHOOL_INTAKE_POSTGRES_SCHEMA.sql

Required environment variables

Add to automation/.env:

PAPERLESS_BASE_URL=https://paperless.paccoco.com
PAPERLESS_API_TOKEN=CHANGE_ME
LITELLM_API_KEY=CHANGE_ME
PAPERLESS_CORRESPONDENT_SCHOOL=
PAPERLESS_DOCUMENT_TYPE_SCHOOL=
PAPERLESS_TAG_SCHOOL=
PAPERLESS_TAG_ASSIGNMENTS=
PAPERLESS_TAG_TELEGRAM=
NODE_FUNCTION_ALLOW_BUILTIN=crypto

Add to the n8n service environment: block in automation/docker-compose.yaml:

      PAPERLESS_BASE_URL: ${PAPERLESS_BASE_URL}
      PAPERLESS_API_TOKEN: ${PAPERLESS_API_TOKEN}
      PAPERLESS_CORRESPONDENT_SCHOOL: ${PAPERLESS_CORRESPONDENT_SCHOOL}
      PAPERLESS_DOCUMENT_TYPE_SCHOOL: ${PAPERLESS_DOCUMENT_TYPE_SCHOOL}
      PAPERLESS_TAG_SCHOOL: ${PAPERLESS_TAG_SCHOOL}
      PAPERLESS_TAG_ASSIGNMENTS: ${PAPERLESS_TAG_ASSIGNMENTS}
      PAPERLESS_TAG_TELEGRAM: ${PAPERLESS_TAG_TELEGRAM}
      NODE_FUNCTION_ALLOW_BUILTIN: crypto

Notes:

  • PAPERLESS_CORRESPONDENT_SCHOOL and PAPERLESS_DOCUMENT_TYPE_SCHOOL should be numeric IDs if you want those fields auto-assigned.
  • Leave optional Paperless IDs blank if you prefer Paperless rules to classify later.
  • NODE_FUNCTION_ALLOW_BUILTIN=crypto is required because the Code node hashes the uploaded file.
  • N8N_BLOCK_ENV_ACCESS_IN_NODE must remain false.

Paperless metadata behavior

The upload uses:

  • filename: <intake_id>.<ext>
  • title: <class_name> — <assignment_name> — <submission_kind>

Workflow 18 deliberately keeps the Paperless upload minimal and safe:

  • multipart document
  • deterministic title

The deterministic filename/title preserve the intake_id for later correlation.

Workflow 19 handles the follow-up metadata pass after Paperless finishes processing:

  • fetch Paperless document by webhook document id
  • resolve intake_id from the stored filename
  • look up the intake record in shared Postgres
  • re-apply deterministic title
  • merge generic school tags plus optional class/submission-kind mappings
  • optionally set document type / correspondent from JSON env mappings

Testing

Use the example curl request in:

  • n8n-workflows/fixtures/school-paperless-intake-webhook.curl.example.txt

Minimum test checklist:

  1. Import the workflow into n8n.
  2. Attach the Shared Postgres credential.
  3. Confirm the target DB/table exists.
  4. Send the sample multipart request.
  5. Verify a row appears in school_paperless_intake with status=uploaded.
  6. Verify the uploaded Paperless document title and stored filename both include the deterministic intake ID.
  7. Trigger workflow 19 with the Paperless document id and verify the row moves to status=enriched.
  8. Re-submit the same file and metadata to confirm the same intake_id is reused and the Postgres row is upserted.

Known assumptions / caveats

  • The workflow is repo-only and was not live-tested against the running n8n/Paperless stack.
  • The Postgres node uses SQL expressions inline rather than parameter binding because exported n8n node JSON can differ by version.
  • If your n8n build blocks require('crypto'), add NODE_FUNCTION_ALLOW_BUILTIN=crypto to the container env.
  • If Paperless needs tags as repeated tags[] fields instead of a comma-separated tags field, adjust the HTTP Request node after import.