npm package: @rivtor/invoice
Description: EU VAT Invoice Generator with country-specific requirements and PDF rendering
Author: Rivtor
Latest version: 1.1.0

# @rivtor/invoice

**Production-ready EU VAT invoice generator with country-specific requirements and PDF rendering**

## Features

- **Country-Specific Requirements**: Built-in support for DACH, France, Italy, and other EU countries
- **VAT Rate Engine**: Real-time VAT rates via EU VAT API with B2B reverse charge support
- **PDF Rendering**: Professional invoice PDFs with EN 16931 XML support
- **Invoice Number Sequencer**: Distributed locks for conflict-free sequential numbering
- **10-Year Archival**: Storage integration for long-term invoice retention
- **Multi-Currency**: Support for EUR, USD, GBP, and other currencies

## Installation

```bash
npm install @rivtor/invoice
# or
yarn add @rivtor/invoice
# or
pnpm add @rivtor/invoice
```

## Quick Start

### 1. Create and Generate Invoice

```typescript
import { createInvoice } from '@rivtor/invoice/server';

const invoice = await createInvoice({
  customer: {
    name: 'Acme Corporation',
    email: 'billing@acme.com',
    vatId: 'DE123456789',
    address: {
      line1: 'Musterstraße 1',
      line2: 'Aufgang 3',
      city: 'Berlin',
      postalCode: '10115',
      country: 'DE',
      state: 'Berlin'
    }
  },
  lineItems: [
    {
      description: 'Web Development Services',
      quantity: 10,
      unitPrice: 100,
      vatRate: 19,
      discount: 0
    },
    {
      description: 'Server Setup',
      quantity: 1,
      unitPrice: 500,
      vatRate: 19
    }
  ],
  countryOfSale: 'DE',
  currency: 'EUR',
  issueDate: '2024-01-15',
  dueDate: '2024-02-15',
  paymentTerms: 'Net 30',
  notes: 'Thank you for your business!'
}, { generatePdf: true });

console.log(invoice);
// {
//   id: 'inv-123',
//   invoiceNumber: 'INV-2024-001',
//   subtotal: 1500,
//   vatAmount: 285,
//   totalAmount: 1785,
//   pdfUrl: 'https://storage.example.com/invoices/inv-123.pdf'
// }
```

### 2. Get VAT Rate

```typescript
import { getVatRate, isValidVatId } from '@rivtor/invoice/server';

// Get standard VAT rate for Germany
const rate = await getVatRate('DE');
// Returns: { country: 'DE', code: 'standard', rate: 19, ... }

// Get reduced VAT rate for Germany
const reducedRate = await getVatRate('DE', null, 'reduced');
// Returns: { country: 'DE', code: 'reduced', rate: 7, ... }

// B2B reverse charge (0% VAT)
const b2bRate = await getVatRate('DE', 'DE123456789');
// Returns: { rate: 0, description: 'Reverse charge applies' }

// Validate VAT ID
const valid = await isValidVatId('DE', 'DE123456789');
// Returns: true or false
```

### 3. Get Country Requirements

```typescript
import { getCountryRequirements } from '@rivtor/invoice/server';

const requirements = getCountryRequirements('DE');
// Returns: {
//   requiresVatId: true,
//   requiresSequentialNumbering: true,
//   requiresSpecificDateFormat: true,
//   minimumRetentionYears: 10,
//   vatRates: { standard: 19, reduced: 7 },
//   requiredFields: ['vat_id', 'invoice_number', 'issue_date']
// }
```

### 4. Download Invoice PDF

```typescript
import { getInvoicePdf, getInvoiceUrl } from '@rivtor/invoice/server';

// Get PDF buffer
const pdfBuffer = await getInvoicePdf('inv-123');

// Get public URL
const url = await getInvoiceUrl('inv-123');
// Returns: 'https://storage.example.com/invoices/inv-123.pdf'
```

## API Reference

### Server Functions

```typescript
import {
  createInvoice,
  updateInvoice,
  deleteInvoice,
  getInvoice,
  listInvoices
} from '@rivtor/invoice/server';

// Create invoice
await createInvoice(data: CreateInvoiceInput, options?: {
  generatePdf?: boolean;
  storePdf?: boolean;
}): Promise<Invoice>;

// Update invoice
await updateInvoice(id: string, data: UpdateInvoiceInput): Promise<Invoice>;

// Delete invoice
await deleteInvoice(id: string): Promise<boolean>;

// Get invoice by ID
await getInvoice(id: string): Promise<Invoice | null>;

// List invoices
await listInvoices(filters?: {
  customerId?: string;
  status?: string;
  countryOfSale?: string;
  dateFrom?: string;
  dateTo?: string;
}): Promise<Invoice[]>;
```

### VAT Management

```typescript
import {
  getVatRate,
  getAllVatRates,
  isValidVatId,
  validateVatId
} from '@rivtor/invoice/server';

// Get VAT rate for country
await getVatRate(
  countryCode: string,
  customerVatId?: string,      // For B2B reverse charge
  rateType?: 'standard' | 'reduced'
): Promise<VatRate>;

// Get all VAT rates
await getAllVatRates(): Promise<Record<string, VatRate>>;

// Validate VAT ID format
isValidVatId(countryCode: string, vatId: string): boolean;

// Validate VAT ID via VIES
await validateVatId('DE', 'DE123456789');
// Returns: { valid: true, name: 'Company Name', address: '...' }
```

### Country Requirements

```typescript
import {
  getCountryRequirements,
  getAllCountryRequirements,
  isInvoiceCompliant
} from '@rivtor/invoice/server';

// Get requirements for specific country
await getCountryRequirements(countryCode: string): Promise<CountryRequirements>;

// Get all country requirements
await getAllCountryRequirements(): Promise<Record<string, CountryRequirements>>;

// Check if invoice is compliant
await isInvoiceCompliant(invoice: Invoice): Promise<{
  compliant: boolean;
  errors: string[];
  warnings: string[];
}>;
```

### Invoice Numbering

```typescript
import {
  getNextInvoiceNumber,
  resetInvoiceSequence,
  setInvoiceSequence
} from '@rivtor/invoice/server';

// Get next invoice number
await getNextInvoiceNumber(prefix?: string): Promise<string>;

// Reset sequence
await resetInvoiceSequence(prefix?: string): Promise<void>;

// Set sequence value
await setInvoiceSequence(prefix: string, value: number): Promise<void>;
```

### PDF Generation

```typescript
import {
  generateInvoicePdf,
  getInvoicePdf,
  getInvoiceUrl,
  generateEn16931Xml
} from '@rivtor/invoice/server';

// Generate PDF from invoice
await generateInvoicePdf(invoice: Invoice): Promise<Buffer>;

// Get stored PDF
await getInvoicePdf(invoiceId: string): Promise<Buffer>;

// Get public URL
await getInvoiceUrl(invoiceId: string): Promise<string>;

// Generate EN 16931 XML
await generateEn16931Xml(invoice: Invoice): Promise<string>;
```

## Database Schema

```sql
CREATE TABLE invoices (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    invoice_number TEXT UNIQUE NOT NULL,
    status TEXT NOT NULL DEFAULT 'pending',
    customer_id UUID,
    customer_name TEXT NOT NULL,
    customer_email TEXT NOT NULL,
    customer_vat_id TEXT,
    seller_vat_id TEXT NOT NULL,
    subtotal NUMERIC NOT NULL,
    vat_amount NUMERIC NOT NULL,
    vat_rate NUMERIC NOT NULL,
    total_amount NUMERIC NOT NULL,
    currency TEXT NOT NULL DEFAULT 'EUR',
    country_code TEXT NOT NULL,
    country_of_sale TEXT NOT NULL,
    issue_date TIMESTAMPTZ NOT NULL,
    due_date TIMESTAMPTZ,
    service_date TIMESTAMPTZ,
    paid_date TIMESTAMPTZ,
    line_items JSONB NOT NULL,
    notes TEXT,
    payment_terms TEXT,
    metadata JSONB,
    pdf_url TEXT,
    xml_url TEXT,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- Sequence for invoice numbering
CREATE TABLE invoice_sequences (
    prefix TEXT PRIMARY KEY,
    counter INTEGER NOT NULL DEFAULT 1
);

-- Indexes for efficient queries
CREATE INDEX idx_invoices_number ON invoices(invoice_number);
CREATE INDEX idx_invoices_customer ON invoices(customer_id);
CREATE INDEX idx_invoices_status ON invoices(status);
CREATE INDEX idx_invoices_country_of_sale ON invoices(country_of_sale);
CREATE INDEX idx_invoices_issue_date ON invoices(issue_date);
CREATE INDEX idx_invoices_due_date ON invoices(due_date);
```

## Configuration

```typescript
import { configureInvoice } from '@rivtor/invoice/server';

configureInvoice({
  // Seller information
  seller: {
    name: 'Your Company GmbH',
    vatId: 'DE123456789',
    address: {
      line1: 'Company Street 1',
      city: 'Berlin',
      postalCode: '10115',
      country: 'DE'
    },
    contact: {
      email: 'billing@yourcompany.com',
      phone: '+49 30 12345678',
      website: 'https://yourcompany.com'
    }
  },

  // Invoice numbering
  numbering: {
    prefix: 'INV-',
    format: '{prefix}{year}-{sequence}',
    sequenceLength: 4
  },

  // VAT settings
  vat: {
    defaultRate: 19,
    autoDetectCountry: true,
    enableReverseCharge: true
  },

  // PDF generation
  pdf: {
    template: 'standard',
    logo: '/assets/logo.png',
    fontSize: 10,
    fontFamily: 'Helvetica'
  },

  // Storage
  storage: {
    provider: 's3',
    bucket: 'invoices',
    region: 'eu-central-1'
  }
});
```

## Country-Specific Requirements

### Germany (DE)

- Requires sequential invoice numbers
- 10-year retention period
- VAT ID required for B2B invoices
- Specific date format: DD.MM.YYYY

### France (FR)

- Requires SIRET number
- 10-year retention period
- Mentions légales required
- French language mandatory

### Italy (IT)

- Requires Codice Fiscale/P.IVA
- Electronic invoicing (SDI) required
- 10-year retention period
- Split payment for public entities

## Best Practices

1. **Validate Customer VAT IDs**: Always validate VAT IDs before issuing invoices
2. **Use Sequential Numbering**: Maintain sequential invoice numbers for audit purposes
3. **Store for 10 Years**: EU regulations require 10-year invoice retention
4. **Generate EN 16931 XML**: Use for e-invoicing compliance
5. **Handle Reverse Charge**: Apply 0% VAT for cross-border B2B transactions

## License

MIT

---

Made with ❤️ by [Rivtor](https://rivtor.com)