npm package: @kodeme-io/next-core-odoo-types
Description: TypeScript type definitions for Odoo models - Use @kodeme-io/next-core-codegen to generate from your Odoo instance
Author: Kodeme.io
Latest version: 0.8.4

# @kodeme-io/next-core-odoo-types

TypeScript type definitions for Odoo ERP models - Ensuring type safety and data integrity across your Next-Core applications.

## 🎯 Purpose

This package solves the **critical problem** of type mismatches between mock data and real Odoo data by providing:

1. **Single Source of Truth**: Types generated directly from Odoo schema
2. **Type Safety**: Compile-time errors if mock data doesn't match Odoo
3. **Runtime Validation**: Zod schemas for runtime data validation
4. **Auto-Generated**: Types stay in sync with Odoo models
5. **Well-Documented**: Complete field documentation and helpers

## 📦 Installation

```bash
pnpm add @kodeme-io/next-core-odoo-types
```

## 🚀 Quick Start

### Usage Patterns

**✅ Recommended: Type-Only Imports (Components)**
```typescript
// For React components that only need types
import type {
  ResPartner,
  SaleOrder,
  SfaVisit,
} from '@kodeme-io/next-core-odoo-types'

// Use in your code - 0KB runtime overhead!
const customer: ResPartner = {
  id: 1,
  name: 'ABC Corporation',
  email: 'contact@abc.com',
  is_company: true,
  customer_rank: 1,
  // ... TypeScript enforces correct structure!
}
```

**✅ Recommended: Combined Imports (Services)**
```typescript
// For services that need both types and API
import { OdooAdapter } from '@kodeme-io/next-core-odoo-api'
import type { ResPartner } from '@kodeme-io/next-core-odoo-types'

const adapter = new OdooAdapter({...})
const customers = await adapter.searchRead<ResPartner>('res.partner')
```

**⚠️ Avoid: Importing Everything**
```typescript
// ❌ Don't do this - pulls in unused code
import * as OdooTypes from '@kodeme-io/next-core-odoo-types'
```

### Runtime Validation

```typescript
import {
  ResPartnerSchema,
  validateOdooData,
} from '@kodeme-io/next-core-odoo-types'

// Validate data from API
const rawData = await fetch('/api/customers/1').then(r => r.json())
const customer = validateOdooData(ResPartnerSchema, rawData)
// ✅ Throws if data doesn't match schema
```

### Use in Mock Generators

```typescript
import type { SfaVisit } from '@kodeme-io/next-core-odoo-types'

export function generateVisits(count: number): SfaVisit[] {
  return Array.from({ length: count }, (_, i) => ({
    id: i + 1,
    name: `VIS${String(i + 1).padStart(4, '0')}`,
    customer_id: [faker.number.int(), faker.company.name()],
    user_id: [1, 'John Doe'],
    scheduled_date: new Date().toISOString(),
    state: faker.helpers.arrayElement(['draft', 'scheduled', 'done', 'cancelled']),
    // ✅ TypeScript error if we use invalid state!
    visit_type: 'sales_visit',
    duration: 1,
    company_id: [1, 'My Company'],
    active: true,
  }))
}
```

## 📚 Available Types

### Common Types

```typescript
import type {
  Many2One,
  One2Many,
  Many2Many,
  Selection,
  OdooDate,
  OdooDateTime,
  Monetary,
} from '@kodeme-io/next-core-odoo-types'
```

**Many2One**: `[id, display_name]` or `false`
```typescript
customer_id: [123, "ABC Corporation"]
customer_id: false  // No relation
```

**One2Many / Many2Many**: Array of IDs
```typescript
order_line: [1, 2, 3, 4]
```

**Selection**: String literal union
```typescript
state: 'draft' | 'confirmed' | 'done'
```

### Base Models

#### res.partner (Contact/Customer)

```typescript
import type { ResPartner } from '@kodeme-io/next-core-odoo-types'

interface ResPartner {
  id: number
  name: string
  email?: string | false
  phone?: string | false
  is_company: boolean
  customer_rank: number
  partner_latitude?: number
  partner_longitude?: number
  // ... 40+ more fields
}
```

#### sale.order (Sales Order)

```typescript
import type { SaleOrder, SaleOrderLine } from '@kodeme-io/next-core-odoo-types'

interface SaleOrder {
  id: number
  name: string  // SO001
  partner_id: Many2One<'res.partner'>
  date_order: OdooDateTime
  state: 'draft' | 'sent' | 'sale' | 'done' | 'cancel'
  order_line: One2Many  // sale.order.line IDs
  amount_total: Monetary
  // ... 60+ more fields
}
```

#### sfa.visit (Field Visit)

```typescript
import type { SfaVisit } from '@kodeme-io/next-core-odoo-types'

interface SfaVisit {
  id: number
  name: string  // VIS001
  customer_id: Many2One<'res.partner'>
  user_id: Many2One<'res.users'>
  scheduled_date: OdooDateTime
  state: 'draft' | 'scheduled' | 'done' | 'cancelled'
  check_in_latitude?: number
  check_in_longitude?: number
  // ... 40+ more fields
}
```

## 🛠️ Validation Schemas

Every type has a corresponding Zod schema:

```typescript
import {
  ResPartnerSchema,
  SaleOrderSchema,
  SfaVisitSchema,
} from '@kodeme-io/next-core-odoo-types'

// Validate data
const customer = ResPartnerSchema.parse(rawData)

// Safe validation (returns result object)
const result = ResPartnerSchema.safeParse(rawData)
if (result.success) {
  console.log('Valid:', result.data)
} else {
  console.error('Invalid:', result.error)
}
```

## 🎨 Field Metadata

For building dynamic UIs (forms, tables):

```typescript
import { SfaVisitFields } from '@kodeme-io/next-core-odoo-types'

SfaVisitFields.customer_id
// {
//   name: 'customer_id',
//   type: 'many2one',
//   label: 'Customer',
//   required: true
// }
```

Use with FormBuilder:

```typescript
import { FormBuilder } from '@kodeme-io/next-core-forms'
import { SfaVisitFields } from '@kodeme-io/next-core-odoo-types'

<FormBuilder
  fields={[
    SfaVisitFields.customer_id,
    SfaVisitFields.scheduled_date,
    SfaVisitFields.purpose,
  ]}
  onSubmit={handleSubmit}
/>
```

## 🔄 Type Generation Workflow

### **Current State (v0.8.0)**
This package currently contains **hand-crafted TypeScript types** for common Odoo models.
These provide a good starting point and serve as templates.

### **Future: Auto-Generation with Codegen**
In future versions, use `@kodeme-io/next-core-codegen` to auto-generate types from YOUR Odoo instance:

```
┌─────────────────────────────────────────┐
│ 1. YOUR Odoo ERP Instance               │
│    - Your custom models                 │
│    - Your custom fields                 │
│    - Your specific configuration        │
└─────────────────────────────────────────┘
                 ↓
    [Introspect via fields_get API]
                 ↓
┌─────────────────────────────────────────┐
│ 2. @kodeme-io/next-core-codegen         │
│    CLI TOOL (the generator)             │
│    - Connects to your Odoo              │
│    - Introspects model schemas          │
│    - Generates TypeScript code          │
└─────────────────────────────────────────┘
                 ↓
    [Generates types into your project]
                 ↓
┌─────────────────────────────────────────┐
│ 3. Your Project's src/types/odoo.ts     │
│    GENERATED OUTPUT                     │
│    - TypeScript interfaces              │
│    - Zod validation schemas             │
│    - Field metadata                     │
└─────────────────────────────────────────┘
                 ↓
    [Import in your components]
                 ↓
┌─────────────────────────────────────────┐
│ 4. Your Next.js App                     │
│    import type { ResPartner }           │
│    from '@/types/odoo'                  │
│    - Type-safe data access              │
│    - Compile-time validation            │
└─────────────────────────────────────────┘
```

### **Why Separate Packages?**

Our architecture separates **runtime behavior** from **compile-time safety** for optimal performance:

| Package | Purpose | Bundle Size | When to Use |
|---------|---------|-------------|-------------|
| **@kodeme-io/next-core-odoo-api** | Runtime JSON-RPC client | 112K | Services, API calls, data fetching |
| **@kodeme-io/next-core-odoo-types** | TypeScript types & validation | 220K | Components, type safety, validation |
| **@kodeme-io/next-core-codegen** | Generator tool (CLI) | - | Generate types from your Odoo |

**Benefits of Separation:**
- ✅ **Tree-shaking**: Components import only types (0KB runtime)
- ✅ **Independent versioning**: Types can evolve faster than API
- ✅ **Clear boundaries**: Runtime vs compile-time concerns
- ✅ **Better testing**: Test types without network code

| Package | Purpose | You Should... |
|---------|---------|---------------|
| **@kodeme-io/next-core-codegen** | Generator tool (CLI) | Install as devDependency and run to generate types |
| **@kodeme-io/next-core-odoo-types** | Template/reference types | Use as reference or starting point for your types |

**Example Workflow:**
```bash
# 1. Install the generator tool
pnpm add -D @kodeme-io/next-core-codegen

# 2. Generate types from YOUR Odoo instance
npx next-core-codegen generate-types \
  --odoo-url=https://your-odoo.com \
  --database=your-database \
  --output=src/types/odoo.ts

# 3. Use the generated types in your app
import type { ResPartner } from '@/types/odoo'
```

## 📖 Model Registry

```typescript
import {
  OdooModelRegistry,
  ModelType,
  ModelName,
  isModelName,
  getModelSchema,
  validateModelRecord,
} from '@kodeme-io/next-core-odoo-types'

// Type-safe model access
type Customer = ModelType<'res.partner'>  // = ResPartner

// Check if valid model name
if (isModelName('res.partner')) {
  const schema = getModelSchema('res.partner')
}

// Validate record
const customer = validateModelRecord('res.partner', rawData)
```

## 🎯 Benefits

### Before (Manual Types)

```typescript
// ❌ Manual type definition (might not match Odoo)
type Visit = {
  state: 'pending' | 'done' | 'cancelled'  // Wrong! Odoo has 'scheduled'
}

// ❌ No validation
const visit = mockData as Visit  // Type cast, no checks

// ❌ Mock drifts from Odoo
// Mock has 'pending', Odoo has 'scheduled' → Runtime errors!
```

### After (Generated Types)

```typescript
// ✅ Type generated from Odoo
import type { SfaVisit } from '@kodeme-io/next-core-odoo-types'

// ✅ Compile-time validation
const visit: SfaVisit = {
  state: 'pending'  // ❌ TypeScript error! Invalid state
}

// ✅ Runtime validation
const visit = validateOdooData(SfaVisitSchema, rawData)

// ✅ Mock guaranteed to match Odoo
// Both use same type definition from this package
```

## 🔧 Utilities

### Helper Functions

```typescript
import {
  calculateVisitDuration,
  isVisitCompleted,
  getVisitStatusColor,
} from '@kodeme-io/next-core-odoo-types'

const visit: SfaVisit = { /* ... */ }

const duration = calculateVisitDuration(visit)
// Returns: number | null (hours)

const isCompleted = isVisitCompleted(visit)
// Returns: boolean

const color = getVisitStatusColor(visit)
// Returns: 'gray' | 'blue' | 'green' | 'red'
```

### Type Utilities

```typescript
import type {
  PartialRecord,
  OmitMetadata,
  WritableFields,
} from '@kodeme-io/next-core-odoo-types'

// Partial update (all fields optional)
type UpdateVisit = PartialRecord<SfaVisit>

// Without metadata fields
type CleanVisit = OmitMetadata<SfaVisit>

// Only writable fields
type CreateVisit = WritableFields<SfaVisit>
```

## 📝 Required Odoo Modules

Different models require different Odoo modules:

| Model | Required Module | Description |
|-------|----------------|-------------|
| `res.partner` | Base (built-in) | Contacts/Customers |
| `sale.order` | `sale` | Sales Management |
| `crm.lead` | `crm` | CRM/Leads |
| `sfa.visit` | `sfa_management` | Custom SFA module |
| `sfa.target` | `sfa_management` | Custom SFA module |
| `hr.employee` | `hr` | HR Management |
| `hr.attendance` | `hr_attendance` | Attendance Tracking |

**Note**: Install required modules in your Odoo instance before generating types.

## 🚀 Type Generation

### **Recommended: Use Codegen Package**

Generate types from YOUR Odoo instance using `@kodeme-io/next-core-codegen`:

```bash
# 1. Install codegen (as dev dependency)
pnpm add -D @kodeme-io/next-core-codegen

# 2. Create configuration file (.next-core.json)
{
  "odoo": {
    "url": "https://your-odoo.com",
    "db": "your_database",
    "username": "admin",
    "password": "admin"
  },
  "models": ["res.partner", "sale.order", "sfa.visit"],
  "output": "src/types/odoo.ts"
}

# 3. Generate types
npx next-core-codegen generate-types

# 4. Import generated types in your app
import type { ResPartner, SaleOrder } from '@/types/odoo'
```

Generated output structure:
```typescript
// src/types/odoo.ts (auto-generated)

export type Many2one<T = any> = [number, string] | false
export type One2many = number[]
export type Many2many = number[]

export interface ResPartner {
  id?: number
  name: string
  email?: string
  phone?: string
  // ... all fields from YOUR Odoo instance
}

export const ResPartnerSchema = z.object({
  name: z.string(),
  email: z.string().email().optional(),
  // ... validation schemas
})
```

### **Current Package: Reference Types**

This package (`@kodeme-io/next-core-odoo-types`) provides hand-crafted types for common models as:
- **Reference implementation** - See how types should be structured
- **Starting templates** - Copy and customize for your needs
- **Development aid** - Use while setting up codegen

**Files in this package:**
```
src/models/
├── base/
│   └── res.partner.ts      (hand-crafted example)
├── sales/
│   └── sale.order.ts       (hand-crafted example)
└── sfa/
    └── sfa.visit.ts        (hand-crafted example)
```

## 🤝 Integration

### With MockAdapter

```typescript
import { MockAdapter } from '@next-core/shared-mock-data'
import type { SfaVisit } from '@kodeme-io/next-core-odoo-types'
import { SfaVisitSchema } from '@kodeme-io/next-core-odoo-types'

const adapter = new MockAdapter()

// Generate type-safe mock data
const visits: SfaVisit[] = generateVisits(100)

// Validate before seeding
visits.forEach(visit => {
  SfaVisitSchema.parse(visit)  // Ensures mock matches Odoo
})

adapter.seed({ 'sfa.visit': visits })
```

### With OdooAdapter

```typescript
import { OdooAdapter } from '@kodeme-io/next-core-odoo-api'
import type { SfaVisit } from '@kodeme-io/next-core-odoo-types'
import { SfaVisitSchema } from '@kodeme-io/next-core-odoo-types'

const adapter = new OdooAdapter({
  url: 'https://your-odoo.com',
  database: 'your-db',
})

// Type-safe data access
const visits = await adapter.searchRead<SfaVisit>(
  'sfa.visit',
  [['state', '=', 'scheduled']],
  ['customer_id', 'scheduled_date', 'state']
)

// Validate response
visits.forEach(visit => {
  SfaVisitSchema.parse(visit)
})
```

## 📄 License

MIT

## 🙏 Credits

Built with ❤️ by the Next-Core Team

---

**Next**: See `@next-core/shared-mock-data` for mock data generation using these types