Invoice Generation Service

This is a FastAPI application for generating and managing invoices. It allows users to register, login, and manage their invoices with full authentication and user-specific data access.

Features

  • User registration and authentication with JWT
  • Generate invoices with automatic invoice number generation
  • Store invoice details in SQLite database
  • Retrieve invoice information by ID or invoice number
  • Update invoice details and status
  • Delete invoices
  • User-specific invoice management (users can only access their own invoices)
  • Advanced search and filtering options
  • Web-based user interface for invoice management
  • Health check endpoint

Technical Stack

  • Framework: FastAPI
  • Database: SQLite with SQLAlchemy ORM
  • Migrations: Alembic
  • Validation: Pydantic
  • Authentication: JWT (JSON Web Tokens)
  • Password Hashing: Bcrypt
  • Frontend: Jinja2 Templates, HTML, CSS, JavaScript
  • Linting: Ruff

Project Structure

.
├── alembic.ini               # Alembic configuration file
├── app                       # Application package
│   ├── api                   # API routes
│   │   └── routes            # API route modules
│   │       ├── __init__.py   # Routes initialization
│   │       ├── invoices.py   # Invoice API routes
│   │       └── frontend.py   # Frontend routes
│   ├── core                  # Core functionality
│   │   ├── config.py         # Application settings
│   │   ├── database.py       # Database connection setup
│   │   └── utils.py          # Utility functions
│   ├── models                # SQLAlchemy models
│   │   ├── __init__.py       # Models initialization
│   │   └── invoice.py        # Invoice and InvoiceItem models
│   ├── schemas               # Pydantic schemas
│   │   ├── __init__.py       # Schemas initialization
│   │   └── invoice.py        # Invoice-related schemas
│   ├── static                # Static files
│   │   ├── css               # CSS styles
│   │   │   └── styles.css    # Main stylesheet
│   │   └── js                # JavaScript files
│   │       └── main.js       # Main JavaScript file
│   └── templates             # Jinja2 templates
│       ├── base.html         # Base template with layout
│       ├── home.html         # Home page
│       ├── create_invoice.html # Invoice creation form
│       ├── search_invoice.html # Search for invoices
│       └── invoice_details.html # Invoice details page
├── main.py                   # Application entry point
├── migrations                # Alembic migrations
│   ├── env.py                # Alembic environment
│   ├── script.py.mako        # Migration script template
│   └── versions              # Migration scripts
│       └── ef0aaab3a275_initial_database_tables.py  # Initial migration
├── requirements.txt          # Project dependencies
└── pyproject.toml            # Ruff configuration

API Endpoints

Health Check

  • GET /health: Check if the service is running

Authentication API

  • POST /api/v1/auth/register: Register a new user
    • Request body: User registration details (email, username, password, etc.)
    • Returns: User details (without password)
  • POST /api/v1/auth/login: Login and get an access token
    • Request body: Form data with username/email and password
    • Returns: JWT access token
  • GET /api/v1/auth/me: Get current user details
    • Headers: Authorization: Bearer {token}
    • Returns: Current user details

Invoice Management API

All invoice endpoints require authentication with a valid JWT token in the Authorization header: Authorization: Bearer {token}

  • POST /api/v1/invoices: Create a new invoice (associated with the authenticated user)
  • GET /api/v1/invoices: List invoices belonging to the authenticated user (with pagination)
    • Query parameters:
      • skip: Number of records to skip (default: 0)
      • limit: Maximum number of records to return (default: 100)
      • fields: Comma-separated list of fields to include in the response (e.g., "id,invoice_number,total_amount")
      • status: Filter invoices by status (e.g., "PENDING", "PAID", "CANCELLED")
      • sort_order: Sort by creation date, either "asc" (oldest first) or "desc" (newest first, default)
      • Many more filtering options available (see Advanced Filtering section)
  • GET /api/v1/invoices/{invoice_id}: Get a specific invoice by ID (must belong to the authenticated user)
    • Query parameters:
      • fields: Comma-separated list of fields to include in the response (e.g., "id,invoice_number,total_amount")
  • GET /api/v1/invoices/find: Find an invoice by invoice number (must belong to the authenticated user)
    • Query parameters:
      • invoice_number: Invoice number to search for (required)
      • fields: Comma-separated list of fields to include in the response (e.g., "id,invoice_number,total_amount")
  • PATCH /api/v1/invoices/{invoice_id}: Update an invoice (must belong to the authenticated user)
  • PATCH /api/v1/invoices/{invoice_id}/status: Update invoice status (must belong to the authenticated user)
  • DELETE /api/v1/invoices/{invoice_id}: Delete an invoice (must belong to the authenticated user)

Frontend Routes

  • GET /: Home page with list of recent invoices
  • GET /create: Form to create a new invoice
  • POST /create: Process invoice creation form
  • GET /search: Form to search for invoices by number
  • POST /search: Process invoice search
  • GET /invoice/{invoice_id}: View invoice details
  • POST /invoice/{invoice_id}/status: Update invoice status

Setup and Installation

  1. Clone the repository
  2. Install dependencies:
    pip install -r requirements.txt
    
  3. Run migrations:
    alembic upgrade head
    
  4. Start the application:
    uvicorn main:app --reload
    

Authentication

The application uses JWT (JSON Web Tokens) for authentication. Here's how to use it:

User Registration

To create a new user account:

POST /api/v1/auth/register

Request body:

{
  "email": "user@example.com",
  "username": "user123",
  "password": "securepassword",
  "full_name": "John Doe"
}

User Login

To log in and get an access token:

POST /api/v1/auth/login

This endpoint accepts form data (not JSON) with:

  • username: Your username or email
  • password: Your password

Response:

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "bearer"
}

Using the Token

Include the token in the Authorization header for all invoice-related requests:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Getting Current User

To get the details of the currently authenticated user:

GET /api/v1/auth/me

Headers:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

API Documentation

Once the application is running, you can access:

  • Interactive API documentation at /docs (Swagger UI)
  • Alternative API documentation at /redoc (ReDoc)

Web Interface

The application comes with a full web interface that allows users to:

  • View a list of recent invoices on the home page
  • Create new invoices using a dynamic form
  • Search for existing invoices by invoice number
  • View detailed invoice information
  • Update invoice status (PENDING, PAID, CANCELLED)
  • Print invoices

Invoice Number Format

Invoices are automatically assigned a unique invoice number with the format:

  • INV-YYYYMM-XXXXXX, where:
    • INV is a fixed prefix
    • YYYYMM is the year and month (e.g., 202307 for July 2023)
    • XXXXXX is a random alphanumeric string

Query Parameters

Field Filtering

The API supports field filtering for GET operations. This allows clients to request only the specific fields they need, which can improve performance and reduce bandwidth usage.

How to Use Field Filtering:

  1. Add a fields query parameter to GET requests
  2. Specify a comma-separated list of field names to include in the response

Example:

To get only the ID, invoice number, and total amount of invoices:

GET /api/v1/invoices?fields=id,invoice_number,total_amount

This would return:

[
  {
    "id": 1,
    "invoice_number": "INV-202307-A1B2C3",
    "total_amount": 100.0
  },
  {
    "id": 2,
    "invoice_number": "INV-202307-D4E5F6",
    "total_amount": 200.0
  }
]

Status Filtering

The API supports filtering invoices by their status (PENDING, PAID, CANCELLED).

How to Use Status Filtering:

  1. Add a status query parameter to the GET request
  2. Specify one of the allowed status values: "PENDING", "PAID", or "CANCELLED"

Example:

To get only paid invoices:

GET /api/v1/invoices?status=PAID

To combine with other parameters:

GET /api/v1/invoices?status=PENDING&fields=id,invoice_number,total_amount&limit=5

Advanced Filtering

The API supports advanced filtering options for more precise control over your invoice queries.

Date Range Filtering

Filter invoices by creation date or due date:

  • created_after: Filter invoices created on or after this date (YYYY-MM-DD)
  • created_before: Filter invoices created on or before this date (YYYY-MM-DD)
  • due_after: Filter invoices due on or after this date (YYYY-MM-DD)
  • due_before: Filter invoices due on or before this date (YYYY-MM-DD)

Examples:

# Get invoices created in January 2023
GET /api/v1/invoices?created_after=2023-01-01&created_before=2023-01-31

# Get overdue invoices (due before today)
GET /api/v1/invoices?due_before=2023-07-01&status=PENDING

Customer Filtering

Search for invoices by customer information:

  • customer_name: Filter invoices by customer name (case-insensitive, partial match)
  • customer_email: Filter invoices by customer email (case-insensitive, partial match)

Examples:

# Find all invoices for customers with "smith" in their name
GET /api/v1/invoices?customer_name=smith

# Find invoices for customers with a specific email domain
GET /api/v1/invoices?customer_email=example.com

Amount Range Filtering

Filter invoices by total amount:

  • min_amount: Filter invoices with total amount greater than or equal to this value
  • max_amount: Filter invoices with total amount less than or equal to this value

Examples:

# Get invoices with amounts between $100 and $500
GET /api/v1/invoices?min_amount=100&max_amount=500

# Get high-value invoices
GET /api/v1/invoices?min_amount=1000

Advanced Sorting

The API supports sorting invoices by various fields:

  • sort_by: Field to sort by. Available options:
    • date_created: Sort by creation date (default)
    • due_date: Sort by due date
    • total_amount: Sort by invoice amount
    • customer_name: Sort alphabetically by customer name
  • sort_order: Sort direction:
    • asc: Ascending order (oldest/smallest/A-Z first)
    • desc: Descending order (newest/largest/Z-A first, this is the default)

Examples:

# Get highest-value invoices first
GET /api/v1/invoices?sort_by=total_amount&sort_order=desc

# Get invoices sorted alphabetically by customer name
GET /api/v1/invoices?sort_by=customer_name&sort_order=asc

# Get invoices with the earliest due dates first
GET /api/v1/invoices?sort_by=due_date&sort_order=asc

Combining Filters

All filter parameters can be combined for precise results:

# Get pending invoices over $500 created in 2023, sorted by amount (highest first)
GET /api/v1/invoices?status=PENDING&min_amount=500&created_after=2023-01-01&sort_by=total_amount&sort_order=desc

# Get paid invoices for a specific customer
GET /api/v1/invoices?status=PAID&customer_name=acme&sort_by=date_created&sort_order=desc

Available Fields:

Invoices have the following fields that can be filtered:

  • id
  • invoice_number
  • date_created
  • due_date
  • total_amount
  • status
  • customer_name
  • customer_email
  • customer_address
  • notes
  • items (this includes related invoice items)
Description
Project: Invoice Generation Service
Readme 113 KiB
Languages
Python 68.1%
HTML 18.6%
JavaScript 6.7%
CSS 6%
Mako 0.6%