# 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: ```json { "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: ```json { "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: ```json [ { "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)