Add --print to regenerate PDFs from invoices.json without ledger writes. Support optional dueDate on ledger rows (default remains invoice date + 14 days) and persist dueDate when saving new production rows. Data: limmud_fsu_canada client with invoiceFileName, cruise_event_av_it product, 2026-LFSU01 sample invoice, Levkin contact fields in sender.json. README and project.md describe CLI, schema, and May 2026 changelog. Co-authored-by: Cursor <cursoragent@cursor.com>
9.2 KiB
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
│ └── <sender_name>/ # Organized by sender
└── test/
└── invoice.test.js # Unit tests
Dependencies
Production:
easyinvoice(v3.0.47) - PDF generation libraryinquirer(v8.2.4) - Interactive command-line promptsyargs(v17.7.2) - Command-line argument parsing
Development:
jest(v29.7.0) - Testing framework
Data Flow
1. Data Loading
// 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
inquirerprompts 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
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/<sender>/<client>_<year>-DEV-PREVIEW.pdf - Production:
invoice/<sender>/<client>_<year>-<sequence>.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
easyinvoicelibrary 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
dueDatefrominvoiceData.information.dueDatewhen set, for accurate future--printoutput - Maintains complete invoice history
Data Schema
Sender Schema
{
"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
{
"company": "string",
"address": "string",
"zip": "string",
"city": "string",
"country": "string",
"invoiceFileName": "string (optional)"
}
Product Schema
{
"description": "string",
"price": "number",
"taxRate": "number (optional, default 0)"
}
Invoice Record Schema
{
"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 <number>, 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
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)
node index.js --print <invoice-number>
Looks up invoice-number in data/invoices.json, resolves sender and client by matching company strings to sender.json / client.json, and writes invoice/<senderKey>/<filename>_<number>.pdf. The client’s optional invoiceFileName is used as the filename prefix when set (for example limmud_fsuc_2026-LFSU01.pdf).
Command-Line Options
--interactive # Force interactive mode
--print <invoice-number> # PDF only from invoices.json; does not append ledger
--sender <key> # Sender key from sender.json
--client <key> # Client key from client.json
--products <key1> <key2> # 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
easyinvoicefailures 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
- Edit appropriate JSON file in
data/ - Use interactive mode to test:
npm start - Verify preview generation
- Create production invoice if satisfied
Testing Changes
- Run unit tests:
npm test - Test invoice generation:
npm run test-invoice - Verify file output structure
- 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 fromdata/invoices.jsonwithout modifying the ledger.- Optional ledger
dueDate: Overrides the default “invoice date + 14 days” when printing; stored on new rows when production createsinformation.dueDate. - Data: Client
limmud_fsu_canada(Limmud FSU Canada) withinvoiceFileNamefor PDF naming; productcruise_event_av_it($500 + 13% HST); sample invoice2026-LFSU01(Levkin Inc. → Limmud FSU Canada). - Sender: Optional
contactName,phone, andemailonlevkininsender.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