An open API service indexing awesome lists of open source software.

https://github.com/morrismukiri/editableinvoice

An editable HTML invoice and quotation Template
https://github.com/morrismukiri/editableinvoice

html invoice invoice-pdf quotation quotation-generator

Last synced: 4 months ago
JSON representation

An editable HTML invoice and quotation Template

Awesome Lists containing this project

README

          

# Editable Invoice - Self-Hosted Web App

A self-hosted web application for creating, editing, and managing invoices. Converted from a static jQuery-based invoice template into a full Express + SQLite web app while preserving the original layout, print behavior, and user experience.

## Features

- **Authentication**: Secure login system with session management
- Create, edit, and manage invoices
- Search invoices by invoice number or customer
- Duplicate invoices with automatic date and invoice number updates
- Print-friendly layout (uses existing print.css)
- Persistent storage with SQLite
- Docker support for easy deployment

## Stack

- **Backend**: Node.js + Express
- **Database**: SQLite (better-sqlite3)
- **Views**: EJS (server-rendered)
- **Frontend**: jQuery (preserves existing code style)
- **Styling**: Existing CSS (style.css, print.css)
- **Deployment**: Docker + docker-compose

## Quick Start

### Using Docker (Recommended)

1. Build and start the application:
```bash
docker-compose up --build
```

2. Open your browser and navigate to:
```
http://localhost:3000
```

3. Login with default credentials:
- **Username**: `admin`
- **Password**: `admin` (or check console output on first run)

The SQLite database will be persisted in the `./data` directory.

### Local Development

1. Install dependencies:
```bash
npm install
```

2. Start the application:
```bash
npm start
```

3. Open your browser and navigate to:
```
http://localhost:3000
```

4. Login with default credentials:
- **Username**: `admin`
- **Password**: `admin` (or check console output on first run)

The SQLite database will be created in `./data/app.db`.

## Authentication

The application uses session-based authentication. On first run, a default admin user is automatically created:

- **Username**: `admin`
- **Password**: `admin` (or the value set in `DEFAULT_PASSWORD` environment variable)

### Changing the Default Password

You can set a custom default password using an environment variable:
```bash
DEFAULT_PASSWORD=your-secure-password npm start
```

Or in Docker:
```yaml
environment:
- DEFAULT_PASSWORD=your-secure-password
```

**Note**: For production use, change the default password immediately after first login. You can do this by directly updating the database or by setting a custom `DEFAULT_PASSWORD` before first run.

### Session Security

- Sessions expire after 24 hours of inactivity
- Set `SESSION_SECRET` environment variable in production for secure session cookies
- For HTTPS deployments, set `secure: true` in session configuration (app.js)

## Usage

### Creating a New Invoice

1. Click "New Invoice" from the invoice list page
2. Fill in the invoice details:
- Header (e.g., "INVOICE")
- Your company address
- Customer details
- Invoice number and date
- Line items (name, description, unit cost, quantity)
- Payment terms
3. Click "Save Invoice" to persist the invoice

### Editing an Invoice

1. Click "Edit" next to any invoice in the list
2. Make your changes
3. Click "Save Invoice" to update

### Duplicating an Invoice

1. From the invoice list, click "Duplicate" next to an invoice, OR
2. From the invoice editor, click "Duplicate"
3. The new invoice will have:
- All fields and line items copied
- A new invoice number (original + "-COPY")
- Date set to today
- Amount paid reset to $0.00

### Printing

Click the "Print" button in the invoice editor, or use your browser's print function (Cmd/Ctrl+P). The print layout is optimized using the existing print.css.

## Project Structure

```
editableinvoice/
├── app.js # Express application entry point
├── package.json # Node.js dependencies
├── Dockerfile # Docker image definition
├── docker-compose.yml # Docker Compose configuration
├── db/
│ └── database.js # SQLite database initialization and migrations
├── routes/
│ ├── invoices.js # Invoice page routes (list, new, edit)
│ └── api.js # Invoice API routes (create, update, duplicate)
├── views/
│ ├── invoice-list.ejs # Invoice list page
│ └── invoice-editor.ejs # Invoice editor page
├── public/
│ ├── css/ # Stylesheets (style.css, print.css)
│ └── js/ # JavaScript (jQuery, example.js)
└── images/ # Logo images
```

## API Endpoints

### Pages
- `GET /` - Redirects to invoice list
- `GET /invoices` - List all invoices (supports ?search=query)
- `GET /invoices/new` - New invoice page
- `GET /invoices/:id` - Edit invoice page

### API
- `POST /api/invoices` - Create new invoice
- `PUT /api/invoices/:id` - Update existing invoice
- `POST /api/invoices/:id/duplicate` - Duplicate invoice

## Database Schema

### invoices
- `id` (INTEGER PRIMARY KEY)
- `header` (TEXT)
- `address` (TEXT)
- `logo_url` (TEXT)
- `customer_details` (TEXT)
- `invoice_number` (TEXT)
- `invoice_date` (TEXT)
- `payment_terms` (TEXT)
- `currency_prefix` (TEXT, default: "$ ")
- `amount_paid` (TEXT)
- `created_at` (DATETIME)
- `updated_at` (DATETIME)

### invoice_items
- `id` (INTEGER PRIMARY KEY)
- `invoice_id` (INTEGER, FOREIGN KEY)
- `name` (TEXT)
- `description` (TEXT)
- `unit_cost` (TEXT)
- `qty` (TEXT)
- `sort_order` (INTEGER)

## Environment Variables

- `PORT` - Server port (default: 3000)
- `DB_PATH` - SQLite database file path (default: ./data/app.db)
- `DEFAULT_PASSWORD` - Default password for admin user on first run (default: "admin")
- `SESSION_SECRET` - Secret key for session cookies (default: "invoice-app-secret-key-change-in-production")

## Notes

- The application preserves the original invoice template's HTML structure and CSS selectors
- Currency formatting supports any prefix (detected automatically from input)
- Calculations are performed client-side; the backend stores structured data
- No authentication is required (single-user system)
- The database is automatically initialized on first run

## License

ISC