# Changelog ## Version 2.0.0 - Invoice System Implementation (2026-01-31) ### Major New Features #### Invoice Management - ✅ Full invoice creation and editing - ✅ Invoice listing with customer names - ✅ Invoice PDF generation with professional formatting - ✅ Terms field (default: "Net 30") - ✅ Authorization/P.O. field for purchase orders or authorization codes - ✅ Automatic invoice numbering (YYYY-NNN format) - ✅ Convert quotes to invoices with one click #### Quote to Invoice Conversion - ✅ "→ Invoice" button on quote list - ✅ Automatic validation (no TBD items allowed) - ✅ One-click conversion preserving all quote data - ✅ Automatic current date assignment - ✅ Default terms applied ("Net 30") - ✅ Links invoice to original quote #### PDF Differences **Quotes:** - Label: "Quote For:" - Email: support@bayarea-cc.com - Header info: Quote #, Account #, Date - Allows TBD items with asterisk notation **Invoices:** - Label: "Bill To:" - Email: accounting@bayarea-cc.com - Header info: Invoice #, Account #, Date, Terms - No TBD items allowed - Optional authorization field displayed ### Database Changes #### New Tables - `invoices` - Main invoice table - `invoice_items` - Invoice line items #### New Columns in Invoices - `invoice_number` - Unique invoice identifier - `terms` - Payment terms (e.g., "Net 30") - `authorization` - P.O. number or authorization code - `created_from_quote_id` - Reference to original quote (if converted) #### Indexes Added - `idx_invoices_invoice_number` - `idx_invoices_customer_id` - `idx_invoice_items_invoice_id` - `idx_invoices_created_from_quote` ### API Endpoints Added #### Invoice Endpoints - `GET /api/invoices` - List all invoices - `GET /api/invoices/:id` - Get invoice details - `POST /api/invoices` - Create new invoice - `PUT /api/invoices/:id` - Update invoice - `DELETE /api/invoices/:id` - Delete invoice - `GET /api/invoices/:id/pdf` - Generate invoice PDF #### Conversion Endpoint - `POST /api/quotes/:id/convert-to-invoice` - Convert quote to invoice ### UI Changes #### New Tab - Added "Invoices" tab to navigation - Invoice list view with all invoice details - Terms column in invoice list #### New Modal - Invoice creation/editing modal - Terms input field - Authorization input field - Tax exempt checkbox - Rich text description editor (Quill.js) #### Quote List Enhancement - Added "→ Invoice" button to convert quotes - Clear visual separation between quotes and invoices ### Business Logic #### Validation Rules - Quotes can have TBD items - Invoices CANNOT have TBD items - Conversion blocked if quote contains TBD items - User receives clear error message for TBD conversion attempts #### Calculations - Same tax rate (8.25%) for both quotes and invoices - Tax exempt option available for both - Automatic subtotal, tax, and total calculations #### Numbering - Separate number sequences for quotes and invoices - Both use YYYY-NNN format - Auto-increment within calendar year - Reset to 001 each January 1st ### Files Modified - `server.js` - Added invoice routes and PDF generation - `public/app.js` - Added invoice management functions - `public/index.html` - Added invoice tab and modal ### Files Added - `add_invoices.sql` - Database migration for invoices - `INSTALLATION.md` - Detailed installation guide - `CHANGELOG.md` - This file - `docker-compose.yml` - Docker deployment configuration - `Dockerfile` - Container image definition - `.dockerignore` - Docker build exclusions ### Migration Path For existing installations: 1. Run the invoice migration: ```sql psql -U quoteuser -d quotes_db -f add_invoices.sql ``` 2. No changes to existing quotes data 3. Invoice numbering starts fresh (2026-001) 4. All existing features remain unchanged ### Technical Details #### Invoice Number Generation ```javascript async function getNextInvoiceNumber() { const year = new Date().getFullYear(); const result = await pool.query( 'SELECT invoice_number FROM invoices WHERE invoice_number LIKE $1 ORDER BY invoice_number DESC LIMIT 1', [`${year}-%`] ); if (result.rows.length === 0) { return `${year}-001`; } const lastNumber = parseInt(result.rows[0].invoice_number.split('-')[1]); const nextNumber = String(lastNumber + 1).padStart(3, '0'); return `${year}-${nextNumber}`; } ``` #### Conversion Validation ```javascript // Check for TBD items const hasTBD = itemsResult.rows.some(item => item.rate.toUpperCase() === 'TBD' || item.amount.toUpperCase() === 'TBD' ); if (hasTBD) { return res.status(400).json({ error: 'Cannot convert quote with TBD items to invoice. Please update all TBD items first.' }); } ``` ### Backward Compatibility - ✅ Fully backward compatible with existing quote system - ✅ No breaking changes to quote functionality - ✅ Existing PDFs continue to work - ✅ Customer data unchanged ### Testing Checklist - [x] Create new invoice manually - [x] Edit existing invoice - [x] Delete invoice - [x] Generate invoice PDF - [x] Convert quote without TBD to invoice - [x] Block conversion of quote with TBD items - [x] Verify "Bill To:" label on invoice PDF - [x] Verify accounting@bayarea-cc.com on invoice PDF - [x] Verify terms display in PDF - [x] Verify authorization display in PDF (when present) - [x] Test tax calculations on invoices - [x] Test tax-exempt invoices ### Known Limitations - None identified ### Future Enhancements (Potential) - Invoice payment tracking - Partial payment support - Invoice status (Paid/Unpaid/Overdue) - Email delivery of PDFs - Invoice reminders - Multi-currency support - Custom tax rates per customer --- ## Version 1.0.0 - Initial Quote System ### Features - Quote creation and management - Customer management - PDF generation - Rich text descriptions - TBD item support - Tax calculations - Company logo upload See README.md for full documentation.