Skip to content

Repository files navigation

invoice.ai

CI Python Django React License: MIT

Processes invoice PDFs end-to-end in <3 s using Tesseract OCR + Django.
Upload any PDF or image invoice and get fully structured, editable JSON fields in seconds.


Architecture

graph LR
    Browser -->|"JWT REST /api"| Django
    Django  -->|"Celery task"| Worker
    Worker  --> Preprocess["Pillow / OpenCV\nPreprocess"]
    Preprocess --> Tesseract["Tesseract OCR"]
    Tesseract  --> Extract["Regex Extract\n+ Normalize"]
    Extract    -->|"bulk_create"| DB[(PostgreSQL)]
    Django     -->|"read"| DB
    Redis[(Redis)] <-->|"broker + results"| Worker
    Nginx -->|"static"| Browser
    Nginx -->|"proxy /api"| Django
Loading

Component map

Directory Role
backend/ Django 4.2 + DRF REST API, Celery task runner
frontend/ React 18 + Vite 5, Neumorphism design system
sample_invoices/ Three synthetic demo invoices (PNG / JPG)
.github/workflows/ CI: lint → pytest (75 % coverage gate) → Docker build

How It Works — 6-Stage Pipeline

Each upload triggers a Celery task that runs synchronously in eager mode during tests and asynchronously in production via Redis:

Upload
  │
  ▼
Stage 1 — LOAD        pdf2image / OpenCV imread
Stage 2 — PREPROCESS  grayscale → adaptive threshold → deskew (Hough) → denoise
Stage 3 — OCR         pytesseract --oem 3 --psm 6  (text + word-box confidence)
Stage 4 — EXTRACT     8 regex pattern groups, priority-ordered, first match wins
Stage 5 — NORMALIZE   dates → ISO 8601 | amounts → float | symbols → ISO 4217
Stage 6 — SAVE        bulk_create 9 ExtractedField rows; invoice.status → completed

Every stage writes a ProcessingLog row. On failure the invoice is marked failed and the task retries up to 3× with exponential backoff (60 s → 120 s → 240 s).


Quick Start

Prerequisites: Docker Desktop with Compose V2.

# 1. Clone
git clone https://github.com/your-org/ai-invoice-processor.git
cd ai-invoice-processor

# 2. Configure environment
cp backend/.env.example backend/.env
# Open backend/.env and set SECRET_KEY and any other required values

# 3. Start all services (first run builds images)
docker-compose up --build

# 4. Open the app
open http://localhost:3000

The stack starts five services: PostgreSQL 15, Redis 7, Django API (port 8000), Celery worker, and the Vite dev server (port 3000).

To register your first account, open http://localhost:3000 and click Sign Up (or POST to /api/auth/register/).


API Reference

All endpoints require Authorization: Bearer <access_token> except where noted.

Method Endpoint Auth Description
POST /api/auth/register/ None Create user account
POST /api/auth/login/ None Obtain JWT access + refresh tokens
POST /api/auth/token/refresh/ None Exchange refresh token for new access token
GET /api/auth/me/ JWT Retrieve / update current user profile
GET /api/invoices/ JWT Paginated invoice list; filter with ?status=pending|processing|completed|failed
POST /api/invoices/upload/ JWT Upload PDF / PNG / JPG (max 10 MB); triggers async processing
GET /api/invoices/{id}/ JWT Invoice detail including all extracted fields and processing logs
GET /api/invoices/{id}/export/ JWT Export fields as JSON (default) or CSV (?export_format=csv)
PATCH /api/invoices/{id}/fields/{fid}/ JWT Correct an extracted field (normalized_value, json_value); auto-sets is_verified=true
GET /api/stats/ JWT Aggregate counts, average confidence score, average processing time


Tech Stack

Backend

  • Python 3.11, Django 4.2, Django REST Framework 3.15
  • JWT authentication via djangorestframework-simplejwt
  • Celery 5 + Redis — async task queue with retries
  • PostgreSQL 15 — primary data store
  • Tesseract OCR, pdf2image (Poppler), OpenCV, Pillow — document processing

Frontend

  • React 18, Vite 5
  • Tailwind CSS (layout / spacing utilities only)
  • Neumorphism design system — inline styles with #E7E5E4 surface, 6px 6px 12px #c8c6c4 / -6px -6px 12px #fff shadow pair
  • Space Mono (Google Fonts), react-dropzone, react-pdf, Axios with JWT interceptor

Infrastructure

  • Docker Compose — five-service local stack
  • Nginx — production static serving + /api proxy
  • GitHub Actions CI — lint → test (75 % coverage gate) → Docker build

Development

Backend

cd backend

# Install runtime + test dependencies
pip install -r requirements.txt -r requirements-test.txt

# Apply migrations
python manage.py migrate

# Run tests (SQLite in-memory, Celery eager)
pytest

# Run tests with coverage report
pytest --cov=apps --cov-report=term-missing --cov-fail-under=75

# Lint
flake8 . --max-line-length=100 --exclude=migrations

Frontend

cd frontend

# Install dependencies
npm install

# Start Vite dev server (proxies /api to localhost:8000)
npm run dev

# Lint
npm run lint

Generate sample invoice images

# Demo images → sample_invoices/*.png / *.jpg
python sample_invoices/generate.py

# Test fixture images → backend/tests/fixtures/*.png / *.jpg
python backend/tests/fixtures/generate.py

Environment Variables

Copy backend/.env.example to backend/.env:

Variable Required Default Description
SECRET_KEY Yes Django secret key (generate with python -c "import secrets; print(secrets.token_urlsafe(50))")
DATABASE_URL Yes sqlite:///db.sqlite3 PostgreSQL connection string
CELERY_BROKER_URL No redis://redis:6379/0 Redis broker URL
CELERY_RESULT_BACKEND No redis://redis:6379/0 Redis result backend URL
CORS_ALLOWED_ORIGINS No http://localhost:3000 Comma-separated allowed origins
DEBUG No False Enable Django debug mode
JWT_ACCESS_TOKEN_LIFETIME_MINUTES No 60 Access token TTL in minutes
JWT_REFRESH_TOKEN_LIFETIME_DAYS No 7 Refresh token TTL in days

CI Pipeline

GitHub Actions runs three jobs on every push to main and every pull request:

lint  ──────────────────────────────►  flake8 (backend) + ESLint (frontend)
                                        │
test  ──────────────────────────────►  pytest + postgres service + coverage ≥ 75 %
                                        │
build-docker  (needs lint + test)  ──►  docker build backend + frontend images

Coverage is uploaded to Codecov. Set CODECOV_TOKEN in repository secrets to enable the integration.


Project Structure

ai-invoice-processor/
├── .github/workflows/ci.yml     GitHub Actions CI
├── backend/
│   ├── apps/
│   │   ├── core/                User model, JWT auth endpoints
│   │   └── invoices/            Invoice model, OCR pipeline, REST views
│   ├── config/settings/         base / development / production / test / ci
│   ├── tests/
│   │   ├── fixtures/            Pillow-generated test images + generate.py
│   │   ├── test_pipeline_e2e.py Upload → process → export end-to-end
│   │   ├── test_confidence.py   Confidence score range + model validators
│   │   └── test_field_correction.py  PATCH semantics, access control
│   ├── conftest.py              Shared pytest fixtures (images, auth clients)
│   ├── pytest.ini
│   └── requirements-test.txt
├── frontend/
│   ├── src/
│   │   ├── components/          Layout, StatCard, StatusBadge, ConfidenceBar
│   │   ├── pages/               AuthPage, DashboardPage, UploadPage,
│   │   │                        InvoiceDetailPage, InvoiceListPage
│   │   └── styles/tokens.js     Design token constants (T, S, typ)
│   └── eslint.config.js
├── sample_invoices/
│   └── generate.py              Generates 3 demo invoice images with Pillow
└── docker-compose.yml

License

MIT — see LICENSE.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages