Files
gh-jamshu-jamshi-marketplac…/commands/api-reference.md
2025-11-29 18:50:06 +08:00

735 lines
13 KiB
Markdown

Complete API reference for the Odoo client and cache stores in generated PWAs.
## What this command does:
- Provides comprehensive API documentation
- Lists all available methods and functions
- Shows parameter types and return values
- Includes code examples for each method
- Helps developers use the generated code effectively
---
## Odoo API Client Reference 🔌
The Odoo API client (`src/lib/odoo.js` or equivalent) provides methods for interacting with Odoo Studio models.
### Configuration
#### Environment Variables
```bash
VITE_ODOO_URL=https://yourcompany.odoo.com
VITE_ODOO_DB=yourcompany-main
ODOO_API_KEY=your_api_key
ODOO_USERNAME=your.email@company.com
VITE_MODEL_NAME=x_expense
```
---
## CRUD Operations
### createRecord()
Create a new record in Odoo.
**Signature:**
```javascript
async function createRecord(model, fields)
```
**Parameters:**
- `model` (string) - Odoo model name (e.g., 'x_expense')
- `fields` (object) - Field values to set
**Returns:** Promise<number> - ID of created record
**Example:**
```javascript
const newId = await odoo.createRecord('x_expense', {
x_studio_description: 'Team lunch',
x_studio_amount: 45.50,
x_studio_date: '2025-01-15',
x_studio_category: 'meal',
x_studio_employee: odoo.formatMany2one(12)
});
console.log(`Created expense with ID: ${newId}`);
```
**Error Handling:**
```javascript
try {
const id = await odoo.createRecord('x_expense', fields);
} catch (error) {
console.error('Failed to create:', error.message);
// Handle error (show message to user, retry, etc.)
}
```
---
### searchRecords()
Search and read records from Odoo.
**Signature:**
```javascript
async function searchRecords(model, domain, fields, limit = null, offset = null)
```
**Parameters:**
- `model` (string) - Odoo model name
- `domain` (array) - Odoo domain filter (e.g., [['id', '>', 100]])
- `fields` (array) - List of field names to fetch
- `limit` (number, optional) - Maximum number of records
- `offset` (number, optional) - Number of records to skip
**Returns:** Promise<Array<Object>> - Array of record objects
**Example:**
```javascript
// Get all expenses
const allExpenses = await odoo.searchRecords(
'x_expense',
[],
['x_studio_description', 'x_studio_amount', 'x_studio_date']
);
// Get expenses > $100
const largeExpenses = await odoo.searchRecords(
'x_expense',
[['x_studio_amount', '>', 100]],
['x_studio_description', 'x_studio_amount']
);
// Get recent 10 expenses
const recentExpenses = await odoo.searchRecords(
'x_expense',
[],
['x_studio_description', 'x_studio_date'],
10 // limit
);
// Get expenses with pagination
const page2 = await odoo.searchRecords(
'x_expense',
[],
fields,
20, // limit: 20 per page
20 // offset: skip first 20 (page 2)
);
```
**Domain Syntax:**
```javascript
// Equals
[['x_studio_status', '=', 'draft']]
// Greater than
[['x_studio_amount', '>', 100]]
// In list
[['x_studio_category', 'in', ['meal', 'travel']]]
// Multiple conditions (AND)
[
['x_studio_amount', '>', 50],
['x_studio_status', '=', 'draft']
]
// OR conditions
['|',
['x_studio_amount', '>', 100],
['x_studio_category', '=', 'travel']
]
// Complex: (amount > 100 OR category = travel) AND status = draft
['&',
'|',
['x_studio_amount', '>', 100],
['x_studio_category', '=', 'travel'],
['x_studio_status', '=', 'draft']
]
```
---
### updateRecord()
Update an existing record.
**Signature:**
```javascript
async function updateRecord(model, id, values)
```
**Parameters:**
- `model` (string) - Odoo model name
- `id` (number) - Record ID to update
- `values` (object) - Fields to update
**Returns:** Promise<boolean> - true if successful
**Example:**
```javascript
await odoo.updateRecord('x_expense', 123, {
x_studio_status: 'approved',
x_studio_amount: 55.00
});
// Update multiple fields
await odoo.updateRecord('x_expense', 123, {
x_studio_description: 'Updated description',
x_studio_date: '2025-01-20',
x_studio_notes: 'Added receipt'
});
```
---
### deleteRecord()
Delete a record from Odoo.
**Signature:**
```javascript
async function deleteRecord(model, id)
```
**Parameters:**
- `model` (string) - Odoo model name
- `id` (number) - Record ID to delete
**Returns:** Promise<boolean> - true if successful
**Example:**
```javascript
await odoo.deleteRecord('x_expense', 123);
// With confirmation
if (confirm('Are you sure you want to delete this expense?')) {
await odoo.deleteRecord('x_expense', expenseId);
}
```
**Error Handling:**
```javascript
try {
await odoo.deleteRecord('x_expense', id);
console.log('Deleted successfully');
} catch (error) {
console.error('Failed to delete:', error.message);
alert('Could not delete: ' + error.message);
}
```
---
## Helper Methods
### fetchPartners()
Fetch partner (res.partner) records.
**Signature:**
```javascript
async function fetchPartners(ids = null)
```
**Parameters:**
- `ids` (array, optional) - Specific partner IDs to fetch. If null, fetches all.
**Returns:** Promise<Array<Object>> - Array of partner objects
**Example:**
```javascript
// Fetch all partners
const allPartners = await odoo.fetchPartners();
// Fetch specific partners
const somePartners = await odoo.fetchPartners([1, 2, 3]);
// Use in dropdown
const partners = await odoo.fetchPartners();
// Display: partners.map(p => ({ value: p.id, label: p.name }))
```
---
### formatMany2one()
Format a Many2one field value for Odoo.
**Signature:**
```javascript
function formatMany2one(id)
```
**Parameters:**
- `id` (number | null) - Partner/record ID
**Returns:** Array<number, boolean> | false - Odoo-formatted value
**Example:**
```javascript
// Set employee field
const fields = {
x_studio_employee: odoo.formatMany2one(12)
// Result: [12, false]
};
// Clear employee field
const fields = {
x_studio_employee: odoo.formatMany2one(null)
// Result: false
};
```
---
### formatMany2many()
Format a Many2many field value for Odoo.
**Signature:**
```javascript
function formatMany2many(ids)
```
**Parameters:**
- `ids` (array) - Array of record IDs
**Returns:** Array - Odoo command format
**Example:**
```javascript
// Set tags (replace all)
const fields = {
x_studio_tags: odoo.formatMany2many([1, 2, 3])
// Result: [[6, 0, [1, 2, 3]]]
};
// Clear tags
const fields = {
x_studio_tags: odoo.formatMany2many([])
// Result: [[6, 0, []]]
};
```
**Odoo Many2many Commands:**
```javascript
// (6, 0, [ids]) - Replace all (what formatMany2many uses)
// (4, id) - Add link to id
// (3, id) - Remove link to id
// (5, 0) - Remove all links
```
---
## Cache Store API Reference 💾
The cache store provides reactive state management with offline-first capabilities.
### Properties
#### records
**Type:** Reactive Array<Object>
Current cached records.
**Example:**
```javascript
// SvelteKit
$: totalAmount = $expenseCache.reduce((sum, e) => sum + e.x_studio_amount, 0);
// React
const totalAmount = useMemo(() =>
records.reduce((sum, e) => sum + e.x_studio_amount, 0),
[records]
);
// Vue
const totalAmount = computed(() =>
expenseStore.records.reduce((sum, e) => sum + e.x_studio_amount, 0)
);
```
#### isLoading
**Type:** Reactive Boolean
Loading state indicator.
**Example:**
```javascript
{#if $expenseCache.isLoading}
<LoadingSpinner />
{:else}
<ExpenseList />
{/if}
```
#### error
**Type:** Reactive String | null
Current error message, if any.
**Example:**
```javascript
{#if $expenseCache.error}
<ErrorAlert message={$expenseCache.error} />
{/if}
```
#### lastSync
**Type:** Reactive Number (timestamp)
Timestamp of last successful sync.
**Example:**
```javascript
const timeSinceSync = Date.now() - $expenseCache.lastSync;
const minutes = Math.floor(timeSinceSync / 60000);
// Display: "Last synced ${minutes} minutes ago"
```
---
### Methods
### load()
Load records from cache and trigger background sync.
**Signature:**
```javascript
async function load()
```
**Returns:** Promise<void>
**Behavior:**
1. Loads from cache immediately (instant UI update)
2. Checks if cache is stale (> 5 minutes)
3. If stale, syncs in background
4. Updates UI when new data arrives
**Example:**
```javascript
// SvelteKit
$effect(() => {
expenseCache.load();
});
// React
useEffect(() => {
expenseCache.load();
}, []);
// Vue
onMounted(() => {
expenseStore.load();
});
```
---
### create()
Create a new record with optimistic update.
**Signature:**
```javascript
async function create(data)
```
**Parameters:**
- `data` (object) - Field values for new record
**Returns:** Promise<number> - ID of created record
**Behavior:**
1. Generates temporary ID
2. Adds to cache immediately (optimistic)
3. Creates in Odoo (background)
4. Replaces temp ID with real ID
5. Rolls back on error
**Example:**
```javascript
try {
const newId = await expenseCache.create({
x_studio_description: 'Lunch meeting',
x_studio_amount: 45.50,
x_studio_date: '2025-01-15',
x_studio_category: 'meal'
});
console.log('Created:', newId);
navigate(`/expenses/${newId}`);
} catch (error) {
alert('Failed to create: ' + error.message);
}
```
---
### update()
Update an existing record.
**Signature:**
```javascript
async function update(id, data)
```
**Parameters:**
- `id` (number) - Record ID
- `data` (object) - Fields to update
**Returns:** Promise<boolean>
**Behavior:**
1. Updates cache immediately (optimistic)
2. Updates in Odoo (background)
3. Rolls back on error
**Example:**
```javascript
await expenseCache.update(123, {
x_studio_amount: 50.00,
x_studio_status: 'submitted'
});
```
---
### delete()
Delete a record.
**Signature:**
```javascript
async function remove(id)
```
**Parameters:**
- `id` (number) - Record ID to delete
**Returns:** Promise<boolean>
**Behavior:**
1. Removes from cache immediately
2. Deletes from Odoo (background)
3. Restores on error
**Example:**
```javascript
if (confirm('Delete this expense?')) {
try {
await expenseCache.remove(123);
navigate('/expenses');
} catch (error) {
alert('Failed to delete: ' + error.message);
}
}
```
---
### refresh()
Force refresh from Odoo.
**Signature:**
```javascript
async function refresh()
```
**Returns:** Promise<void>
**Behavior:**
1. Fetches all records from Odoo
2. Replaces cache
3. Updates UI
**Example:**
```javascript
// Manual refresh button
<button onclick={() => expenseCache.refresh()}>
Refresh
</button>
```
---
### clearCache()
Clear all cached data.
**Signature:**
```javascript
function clearCache()
```
**Returns:** void
**Behavior:**
1. Clears localStorage
2. Clears IndexedDB
3. Resets records to empty array
**Example:**
```javascript
// Logout function
async function logout() {
expenseCache.clearCache();
// Clear other caches
navigate('/login');
}
```
---
## Advanced Patterns
### Custom Filters
```javascript
// Derived store (SvelteKit)
import { derived } from 'svelte/store';
export const draftExpenses = derived(
expenseCache,
$cache => $cache.filter(e => e.x_studio_status === 'draft')
);
// Hook (React)
function useDraftExpenses() {
const { records } = useExpense();
return useMemo(
() => records.filter(e => e.x_studio_status === 'draft'),
[records]
);
}
// Computed (Vue)
const draftExpenses = computed(() =>
expenseStore.records.filter(e => e.x_studio_status === 'draft')
);
```
### Sorting
```javascript
export const sortedExpenses = derived(
expenseCache,
$cache => [...$cache].sort((a, b) =>
b.x_studio_date.localeCompare(a.x_studio_date)
)
);
```
### Search
```javascript
function searchExpenses(query) {
return records.filter(e =>
e.x_studio_description.toLowerCase().includes(query.toLowerCase())
);
}
```
### Grouping
```javascript
function groupByCategory(records) {
return records.reduce((groups, record) => {
const category = record.x_studio_category;
if (!groups[category]) groups[category] = [];
groups[category].push(record);
return groups;
}, {});
}
```
### Aggregation
```javascript
function getTotalByCategory(records) {
return records.reduce((totals, record) => {
const cat = record.x_studio_category;
totals[cat] = (totals[cat] || 0) + record.x_studio_amount;
return totals;
}, {});
}
```
---
## Server Route API Reference 🔐
The server route (`src/routes/api/odoo/+server.js`) handles Odoo communication.
### Endpoint
**URL:** `/api/odoo`
**Method:** POST
**Content-Type:** application/json
### Request Format
```json
{
"action": "create|search|update|delete",
"model": "x_expense",
...parameters
}
```
### Actions
#### create
```json
{
"action": "create",
"model": "x_expense",
"fields": {
"x_studio_description": "Lunch",
"x_studio_amount": 45.50
}
}
```
**Response:** `{ "id": 123 }`
#### search
```json
{
"action": "search",
"model": "x_expense",
"domain": [["id", ">", 100]],
"fields": ["x_studio_description", "x_studio_amount"]
}
```
**Response:** `{ "records": [...] }`
#### update
```json
{
"action": "update",
"model": "x_expense",
"id": 123,
"values": {
"x_studio_amount": 50.00
}
}
```
**Response:** `{ "success": true }`
#### delete
```json
{
"action": "delete",
"model": "x_expense",
"id": 123
}
```
**Response:** `{ "success": true }`
---
## Example prompts to use this command:
- `/api-reference` - Show complete API documentation
- User: "What methods are available in the Odoo client?"
- User: "How do I use the cache store?"
- User: "Show me API examples"
## Next Steps:
- Try the methods in your project
- Review `/examples` for practical use cases
- See `/architecture` for design patterns
- Check `/help` for more information