A self-hosted Django application for creating and managing invoices, tracking payments, and generating professional PDFs. Designed for UK tax year tracking (April to April).
- Client Management - Add, edit, and delete clients with full contact and VAT details
- Invoice Creation - Create invoices with multiple line items, VAT calculations, and custom notes
- PDF Generation - Professional PDF invoices with company branding, bank details, and payment links
- Recurring Invoices - Set up weekly, monthly, quarterly, or yearly recurring invoice templates
- Tax Year Tracking - Organise invoices by UK tax year (6 April to 5 April)
- Quick Actions - Mark invoices as Sent or Paid with one click
- Duplicate Invoices - Clone existing invoices for repeat billing
- Client History - View all invoices for a specific client with totals and PDF export
- Payment Integration - Add Stripe or PayPal payment links to invoices
- Docker and Docker Compose
OR for local development:
- Python 3.11+
- pip
git clone https://github.com/yourusername/invoice-generator.git
cd invoice-generatorcp .env.example .envEdit .env with your settings:
SECRET_KEY=generate-a-secure-random-string-here
DEBUG=False
ALLOWED_HOSTS=localhost,127.0.0.1
CSRF_TRUSTED_ORIGINS=http://localhost:8000,http://127.0.0.1:8000
DJANGO_SUPERUSER_EMAIL=your@email.com
DJANGO_SUPERUSER_PASSWORD=your-secure-password
TZ=Europe/LondonGenerate a secret key:
python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"docker compose up --build -d- Application: http://localhost:8000
- Admin Panel: http://localhost:8000/admin
Login with the email and password you set in .env
After logging in for the first time:
Go to Settings in the navigation bar and complete:
- Company Information - Your company name, address, email, phone, VAT number
- Company Logo - Upload your logo (recommended: max 600×300px horizontal or 300×300px square)
- Bank Details - Bank name, account name, account number, sort code (appears on invoices for bank transfers)
- Payment Links - Add your Stripe payment link or PayPal.me link
- Payment Terms - Default terms that appear on all invoices
- Invoice Footer - Optional footer text (e.g., "Thank you for your business!")
Go to Clients → Add Client and enter:
- Client name
- Email address
- Phone (optional)
- Full address
- VAT number (optional)
Go to Invoices → New Invoice:
- Select the client
- Set invoice date and due date
- Add line items with description, quantity, rate, and VAT rate
- Add any notes
- Save the invoice
All persistent data is stored in the ./data/ directory:
data/
├── db/
│ └── db.sqlite3 # SQLite database
├── media/
│ ├── logos/ # Company logos
│ └── invoices/ # Generated PDF invoices (organised by tax year)
└── logs/
└── django.log # Application error logs
Static files are stored in ./staticfiles/
Important: Back up the ./data/ directory regularly to prevent data loss.
# Start the application
docker compose up -d
# Stop the application
docker compose down
# View logs
docker compose logs -f
# Rebuild after code changes
docker compose up --build -d
# Restart the application
docker compose restart
# Create superuser manually
docker compose exec web python manage.py createsuperuser
# Access Django shell
docker compose exec web python manage.py shell
# Run migrations manually
docker compose exec web python manage.py migrate
# Backup database
cp ./data/db/db.sqlite3 ./backups/db-$(date +%Y%m%d).sqlite3# Create virtual environment
python -m venv venv
# Activate virtual environment
# Windows:
venv\Scripts\activate
# macOS/Linux:
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt
# Create data directories
mkdir -p db media logs
# Run migrations
python manage.py migrate
# Create superuser
python manage.py createsuperuser
# Run development server
python manage.py runserver- Draft - Invoice is created but not yet sent
- Sent - Invoice has been sent to the client
- Paid - Client has paid the invoice
- Overdue - Invoice is past due date and unpaid
Use the quick action buttons on the invoice list or detail page to change status.
The application organises invoices by UK tax year (6 April to 5 April).
- Use the dropdown in the top right to switch between tax years
- The dashboard shows statistics for the currently selected tax year
- Invoices are automatically assigned to the correct tax year based on the invoice date
Set up recurring invoice templates for regular billing:
- Go to Recurring → New Recurring Invoice
- Select client and frequency (weekly/monthly/quarterly/yearly)
- Set start date, next invoice date, and optional end date
- Add the standard line items
- Save the template
To generate an invoice from a template:
- Click Generate Invoice Now on the recurring invoice detail page
- The system automatically advances the next invoice date
Recurring invoices can be automatically generated when they're due. There are several ways to set this up:
The docker-compose.yml includes a scheduler service that automatically checks for due recurring invoices daily at 6:00 AM.
To change the schedule time, edit docker-compose.yml:
scheduler:
environment:
- SCHEDULE_HOUR=6 # Hour (0-23)
- SCHEDULE_MINUTE=0 # Minute (0-59)To check scheduler status:
docker compose logs scheduler -fTo manually trigger recurring invoice processing:
docker compose exec web python manage.py process_recurring_invoicesTo see what would be generated (dry run):
docker compose exec web python manage.py process_recurring_invoices --dry-runFor local development, you'll need to run the command manually or set up your own scheduler:
Manual processing:
python manage.py process_recurring_invoicesUsing cron (Linux/macOS):
# Edit crontab
crontab -e
# Add this line to run daily at 6:00 AM
0 6 * * * cd /path/to/invoice-generator && /path/to/venv/bin/python manage.py process_recurring_invoices >> logs/recurring.log 2>&1Using Task Scheduler (Windows):
- Open Task Scheduler
- Create a Basic Task
- Set trigger to Daily at your preferred time
- Action: Start a program
- Program:
C:\path\to\venv\Scripts\python.exe - Arguments:
manage.py process_recurring_invoices - Start in:
C:\path\to\invoice-generator
- The scheduler checks all active recurring invoices
- If
next_invoice_dateis today or earlier, an invoice is generated - The invoice is created as a Draft with items copied from the template
- A PDF is automatically generated
- The
next_invoice_dateadvances based on the frequency (weekly/monthly/quarterly/yearly) - The process continues until the optional
end_dateis reached
If you don't need automatic recurring invoice generation, you can disable the scheduler service:
# Run only the web service
docker compose up -d webOr remove/comment out the scheduler section in docker-compose.yml.
PDFs are generated automatically and include:
- Company logo and details
- Client information
- Invoice number, date, and due date
- Line items with VAT calculations
- Subtotal, VAT total, and grand total
- Bank details for transfers
- Payment link (clickable in PDF)
- Custom payment terms
- Notes
- Footer text
PDFs are stored in ./data/media/invoices/{tax-year}/
docker compose exec web python manage.py collectstatic --noinputdocker compose exec web python manage.py migrate# Linux/macOS
sudo chown -R $USER:$USER ./data# Check logs for errors
docker compose logs web
# Rebuild from scratch
docker compose down
docker compose up --build -ddocker compose exec web python manage.py changepassword your@email.com| Variable | Description | Default |
|---|---|---|
SECRET_KEY |
Django secret key (required for production) | Insecure default |
DEBUG |
Enable debug mode | True |
ALLOWED_HOSTS |
Comma-separated list of allowed hosts | localhost,127.0.0.1 |
CSRF_TRUSTED_ORIGINS |
Comma-separated list with protocol | http://localhost:8000 |
DJANGO_SUPERUSER_EMAIL |
Auto-create admin with this email | - |
DJANGO_SUPERUSER_PASSWORD |
Auto-create admin with this password | - |
TZ |
Timezone | Europe/London |
# Create backup directory
mkdir -p backups
# Backup database
cp ./data/db/db.sqlite3 ./backups/db-$(date +%Y%m%d).sqlite3
# Backup everything
tar -czvf backups/invoice-generator-$(date +%Y%m%d).tar.gz ./data# Stop the application
docker compose down
# Restore database
cp ./backups/db-YYYYMMDD.sqlite3 ./data/db/db.sqlite3
# Start the application
docker compose up -dFor production deployments:
- Generate a strong SECRET_KEY - Never use the default
- Set DEBUG=False - Never run debug mode in production
- Use HTTPS - Put behind a reverse proxy with SSL
- Strong passwords - Use secure passwords for admin accounts
- Regular backups - Back up the data directory regularly
- Keep updated - Update dependencies regularly
This project is licensed under the MIT License.
See the LICENSE file for details.
Please read CONTRIBUTING before submitting a pull request.
This Invoice Generator is provided "as is" without warranty of any kind. If you choose to self-host this software, you do so at your own risk. The developer accepts no responsibility for data loss, inaccuracies, or any issues arising from its use. Always maintain your own backups and verify calculations independently.
Made for UK self employed and sole traders
Introducing Invoice Generator
Maintained by Diane Corriette
