# Invoice Generator - Project Documentation ## Project Overview A Node.js command-line application for generating professional PDF invoices. The system uses a data-driven approach where all business information (senders, clients, products) is stored in JSON files, making it easy to maintain without code changes. ## Architecture ### Core Components ``` invoice/ ├── index.js # Main application entry point ├── data/ # JSON data files │ ├── sender.json # Company/sender profiles │ ├── client.json # Client information │ ├── products.json # Product/service catalog │ └── invoices.json # Invoice ledger (auto-generated) ├── invoice/ # Generated PDF output │ └── / # Organized by sender └── test/ └── invoice.test.js # Unit tests ``` ### Dependencies **Production:** - `easyinvoice` (v3.0.47) - PDF generation library - `inquirer` (v8.2.4) - Interactive command-line prompts - `yargs` (v17.7.2) - Command-line argument parsing **Development:** - `jest` (v29.7.0) - Testing framework ## Data Flow ### 1. Data Loading ```javascript // Loads all JSON files from data/ directory const senders = loadJson(FILES.SENDERS); const clients = loadJson(FILES.CLIENTS); const productsData = loadJson(FILES.PRODUCTS); ``` ### 2. User Input Processing - **Interactive Mode**: Uses `inquirer` prompts for sender, client, and product selection - **Non-Interactive Mode**: Processes command-line arguments via `yargs` - **Test Mode**: Automatically selects first available options ### 3. Invoice Generation Process ```mermaid graph TD A[Load Data] --> B[Validate Inputs] B --> C[Generate Preview PDF] C --> D[User Review] D --> E{Proceed?} E -->|Yes| F[Generate Production PDF] E -->|No| G[Keep Preview Only] F --> H[Save to Ledger] H --> I[Update invoices.json] ``` ### 4. File Output - **Preview**: `invoice//_-DEV-PREVIEW.pdf` - **Production**: `invoice//_-.pdf` ## Key Functions ### `getNextInvoiceNumber(year, invoicesData)` - Generates sequential invoice numbers (YYYY-0001, YYYY-0002...) - Resets numbering annually - Handles unordered invoice numbers correctly ### `createInvoice(invoiceData, invoiceFilePath)` - Uses `easyinvoice` library to generate PDF - Creates directory structure if needed - Returns success/failure status ### `saveInvoiceRecord(invoiceData, invoiceProducts)` - Calculates totals (subtotal, tax, grand total) - Appends invoice record to `invoices.json` - Persists `dueDate` from `invoiceData.information.dueDate` when set, for accurate future `--print` output - Maintains complete invoice history ## Data Schema ### Sender Schema ```json { "company": "string", "contactName": "string (optional)", "phone": "string (optional)", "email": "string (optional)", "address": "string", "zip": "string", "city": "string", "country": "string", "taxName": "string (optional)", "taxNumber": "string (optional)", "paymentInfo": "string (optional)" } ``` ### Client Schema ```json { "company": "string", "address": "string", "zip": "string", "city": "string", "country": "string", "invoiceFileName": "string (optional)" } ``` ### Product Schema ```json { "description": "string", "price": "number", "taxRate": "number (optional, default 0)" } ``` ### Invoice Record Schema ```json { "number": "string (YYYY-0001 or custom e.g. 2026-LFSU01)", "date": "string (YYYY-MM-DD)", "dueDate": "string (YYYY-MM-DD, optional — see Due dates below)", "sender": "string (must match sender.json company name)", "client": "string (must match client.json company name)", "products": [ { "description": "string", "price": "number", "quantity": "number", "taxRate": "number" } ], "subtotal": "number", "taxTotal": "number", "total": "number" } ``` **Due dates:** When you run `node index.js --print `, the PDF due date is taken from `dueDate` if present. Otherwise it defaults to `date` plus 14 days. New production invoices still compute due as “today + 14” in the UI flow; `saveInvoiceRecord` stores that value on the ledger row as `dueDate` when present so reprints stay consistent. You can edit `dueDate` in `invoices.json` for any row (for example, payment terms through end of month). ## Command-Line Interface ### Available Commands ```bash npm start # Interactive mode npm run generate # Non-interactive mode npm test # Run unit tests npm run test-invoice # Test mode (dev only) ``` ### Reprinting from the ledger (no prompts, no ledger changes) ```bash node index.js --print ``` Looks up `invoice-number` in `data/invoices.json`, resolves sender and client by matching `company` strings to `sender.json` / `client.json`, and writes `invoice//_.pdf`. The client’s optional `invoiceFileName` is used as the filename prefix when set (for example `limmud_fsuc_2026-LFSU01.pdf`). ### Command-Line Options ```bash --interactive # Force interactive mode --print # PDF only from invoices.json; does not append ledger --sender # Sender key from sender.json --client # Client key from client.json --products # Product keys from products.json --test # Test mode (uses first available options) --help # Show help ``` ## Testing Strategy ### Unit Tests (`test/invoice.test.js`) - **Invoice Numbering**: Tests sequential numbering logic - **Year Reset**: Verifies numbering resets annually - **Unordered Numbers**: Handles gaps in invoice sequence ### Test Coverage - `getNextInvoiceNumber()` function - Edge cases for invoice numbering - Year boundary scenarios ## Error Handling ### File System Errors - Missing JSON files trigger helpful error messages - Invalid JSON syntax is caught and reported - Directory creation failures are handled gracefully ### Data Validation - Invalid sender/client/product keys are rejected - Missing required fields trigger validation errors - Tax rate calculations handle missing values ### PDF Generation Errors - `easyinvoice` failures are caught and logged - File write errors are handled with user feedback ## Configuration Options ### Currency - Default: CAD (Canadian Dollar) - Set in `commonData.settings.currency` ### Tax Configuration - Per-product tax rates in `products.json` - Tax name customization in `sender.json` - Automatic tax calculations ### Payment Information - Custom payment instructions in `sender.paymentInfo` - Rendered in invoice footer - Supports HTML formatting ## File Organization ### Input Files (`data/`) - **sender.json**: Company profiles and tax information - **client.json**: Client contact details - **products.json**: Service/product catalog with pricing - **invoices.json**: Auto-generated invoice ledger ### Output Files (`invoice/`) - Organized by sender name - Preview files marked with `-DEV-PREVIEW` - Production files with sequential numbering - Automatic directory creation ## Development Workflow ### Adding New Data 1. Edit appropriate JSON file in `data/` 2. Use interactive mode to test: `npm start` 3. Verify preview generation 4. Create production invoice if satisfied ### Testing Changes 1. Run unit tests: `npm test` 2. Test invoice generation: `npm run test-invoice` 3. Verify file output structure 4. Check ledger updates ### Code Modifications - Main logic in `index.js` - Test cases in `test/invoice.test.js` - Data validation in main function - Error handling throughout ## Security Considerations - No external API calls - Local file system only - No sensitive data in code - JSON validation for data integrity - Error boundaries prevent crashes ## Performance - Minimal dependencies - Synchronous file operations - No database overhead - Fast PDF generation - Efficient JSON parsing ## Changelog (May 2026) - **`--print`**: Regenerate PDFs from `data/invoices.json` without modifying the ledger. - **Optional ledger `dueDate`**: Overrides the default “invoice date + 14 days” when printing; stored on new rows when production creates `information.dueDate`. - **Data**: Client `limmud_fsu_canada` (Limmud FSU Canada) with `invoiceFileName` for PDF naming; product `cruise_event_av_it` ($500 + 13% HST); sample invoice `2026-LFSU01` (Levkin Inc. → Limmud FSU Canada). - **Sender**: Optional `contactName`, `phone`, and `email` on `levkin` in `sender.json` (and schema support for other senders). ## Future Enhancements ### Potential Features - Multiple currency support - Invoice templates - Email integration - Export to accounting software - Invoice status tracking - Payment reminders ### Technical Improvements - TypeScript migration - Database integration - Web interface - API endpoints - Docker containerization