# @invoiceddd/domain

> Core domain logic and business rules for the InvoiceDDD system.

[![NPM Version](https://img.shields.io/npm/v/@invoiceddd/domain)](https://www.npmjs.com/package/@invoiceddd/domain)

## Overview

This package contains the pure domain logic of the invoice system following Domain-Driven Design principles. It includes entities, value objects, domain services, and business rules with zero dependencies on external frameworks or infrastructure.

## Installation

```bash
npm install @invoiceddd/domain
```

## Key Exports

### Entities

```typescript
import { Invoice, Order, InvoiceAggregate } from '@invoiceddd/domain';

// Create invoice from order data
const invoice = InvoiceAggregate.fromOrder(orderData, {
  invoiceNumber: 'INV-1001',
  createdBy: 'admin@company.com'
});
```

### Value Objects

```typescript
import { 
  Money, 
  CustomerInfo, 
  InvoiceFinancials, 
  OrderItem 
} from '@invoiceddd/domain';

// Create money value with currency
const price = Money.EUR(29.99);

// Create customer information
const customer = CustomerInfo.create({
  firstName: 'John',
  lastName: 'Doe',
  email: 'john@example.com',
  street: '123 Main St',
  city: 'Berlin',
  zip: '10115',
  country: 'Germany'
});

// Calculate invoice financials
const financials = InvoiceFinancials.calculate({
  items: orderItems,
  taxRate: 0.19,
  shippingCost: Money.EUR(5.99)
});
```

### Domain Services

```typescript
import { 
  FinancialCalculationService,
  InvoiceNumberFormatValidator 
} from '@invoiceddd/domain';

// Validate invoice number format
const isValid = InvoiceNumberFormatValidator.validate('INV-1001');

// Calculate totals with business rules
const totals = FinancialCalculationService.calculateTotals(items);
```

### Domain Events

```typescript
import { 
  InvoiceCreated, 
  InvoiceDraftRequested,
  AllDomainEvents 
} from '@invoiceddd/domain';

// Handle domain events
const handleEvent = (event: AllDomainEvents) => {
  switch (event._tag) {
    case 'InvoiceCreated':
      console.log(`Invoice ${event.invoiceNumber} created`);
      break;
    case 'InvoiceDraftRequested':
      console.log(`Draft requested for order ${event.orderId}`);
      break;
  }
};
```

## Domain Rules

### Invoice Business Rules

- Invoice numbers must be unique and follow configured format
- Invoices are immutable once created
- Customer and item data is snapshotted at creation time
- All financial calculations must be precise (no floating point errors)

### Validation Rules

```typescript
import { validateInvoice, validateOrder } from '@invoiceddd/domain';

// Validate complete invoice data
const result = validateInvoice(invoiceData);
if (result._tag === 'Left') {
  console.error('Validation errors:', result.left);
}

// Validate order data
const orderResult = validateOrder(orderData);
```

### Error Handling

```typescript
import { 
  ValidationError,
  BusinessRuleViolationError,
  InvoiceValidationError 
} from '@invoiceddd/domain';

// Domain-specific error types
try {
  const invoice = InvoiceAggregate.create(data);
} catch (error) {
  if (error instanceof InvoiceValidationError) {
    console.error('Invoice validation failed:', error.details);
  }
}
```

## Usage Examples

### Basic Invoice Creation

```typescript
import { InvoiceAggregate, CustomerInfo, OrderItem } from '@invoiceddd/domain';

const customer = CustomerInfo.create({
  firstName: 'John',
  lastName: 'Doe',
  email: 'john@example.com',
  street: '123 Main St',
  city: 'Berlin',
  zip: '10115',
  country: 'Germany'
});

const items = [
  OrderItem.create({
    name: 'Premium Widget',
    unitPrice: 29.99,
    quantity: 2
  })
];

const invoice = InvoiceAggregate.create({
  orderId: 'ORD-001',
  invoiceNumber: 'INV-1001',
  customer,
  items,
  createdBy: 'admin@company.com'
});
```

### Financial Calculations

```typescript
import { FinancialCalculationService, Money } from '@invoiceddd/domain';

const items = [
  { unitPrice: Money.EUR(29.99), quantity: 2 },
  { unitPrice: Money.EUR(15.50), quantity: 1 }
];

const calculations = FinancialCalculationService.calculateTotals(items, {
  taxRate: 0.19,
  shippingCost: Money.EUR(5.99),
  discount: Money.EUR(10.00)
});

console.log({
  subtotal: calculations.subtotal.amount,
  taxes: calculations.taxes.amount,
  grandTotal: calculations.grandTotal.amount
});
```

## Dependencies

This package has minimal dependencies:

- `effect` - For functional programming patterns
- `uuid` - For unique identifier generation

## Architecture

The domain layer follows these principles:

- **Pure Functions**: No side effects in domain logic
- **Immutability**: All domain objects are immutable
- **Type Safety**: Full TypeScript coverage with runtime validation
- **Business Rules**: All business logic centralized in domain services
- **Event Sourcing**: Domain events for state changes

## Related Packages

- `@invoiceddd/application` - Use cases and application services
- `@invoiceddd/infrastructure` - External integrations and implementations
- `invoiceddd` - Complete system with easy setup

## Documentation

For complete documentation, see the [main documentation](../../docs/).