# Lynara Python SDK

Python SDK for the [Lynara](https://lynara.ai) ERP platform.

## Installation

```bash
pip install lynara-erp
```

With httpx (optional, for better performance):
```bash
pip install lynara-erp[httpx]
```

## Quick Start

```python
from lynara import Lynara

# --- Production ---
client = Lynara(
    url="https://api.lynara.ai",
    api_key="lnr_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    company_id="your-company-uuid",
)

# --- Test / Sandbox ---
test_client = Lynara(
    url="https://api.lynara.ai",
    api_key="lnr_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    company_id="your-company-uuid",
)

# List customers
customers = client.catalog.customers.list(limit=50)
print(f"Found {customers.total_count} customers")

for customer in customers:
    print(customer["name"], customer["contact_email"])

# Search
results = client.rh.employees.list(search="Ali")
print(f"Found {results.total_count} employees matching 'Ali'")

# Count
total_invoices = client.sales.invoices.count()
print(f"Total invoices: {total_invoices}")

# Create a customer
customer = client.catalog.customers.create({
    "name": "Acme Corp",
    "contact_email": "contact@acme.com",
    "customer_type": "B2B",
})
print(f"Created customer: {customer['customer_id']}")

# Update
client.catalog.customers.update(customer["customer_id"], {
    "priority": "high",
    "lifecycle_stage": "loyal",
})

# Delete
client.catalog.customers.delete(customer["customer_id"])

# Iterate through all products (auto-pagination)
for product in client.catalog.products.iterate():
    print(product["name"], product["price"])

# Bulk create
result = client.catalog.products.bulk_create([
    {"name": "Widget A", "price": 29.99, "currency": "EUR"},
    {"name": "Widget B", "price": 49.99, "currency": "EUR"},
])
print(f"Created {result.created_count}/{result.total_submitted}")

# Export to CSV
csv_data = client.catalog.customers.export(format="csv")
with open("customers.csv", "w") as f:
    f.write(csv_data)

# Close when done
client.close()
```

## Context Manager

```python
with Lynara(url="https://api.lynara.ai", api_key="lnr_live_xxx", company_id="xxx") as client:
    invoices = client.sales.invoices.list(status="posted")
    total = client.sales.invoices.count()
    print(f"{total} invoices")
```

## Modules

| Module | Accessor | Resources |
|--------|----------|-----------|
| Sales | `client.sales` | quotes, quote_lines, orders, order_lines, invoices, invoice_lines, delivery_notes, delivery_note_lines, exit_vouchers, exit_voucher_lines, credit_notes, credit_note_lines, allocations, receipts |
| Purchases | `client.purchases` | invoices, invoice_lines, payments, allocations, quotes, quote_lines |
| Banking | `client.banking` | statements, transactions, reconciliations |
| Inventory | `client.inventory` | storage_units, product_settings, stock_levels, lots, movements, serial_numbers, stock_counts |
| Catalog | `client.catalog` | customers, suppliers, products, product_categories, product_subcategories, price_lists |
| CRM | `client.crm` | leads, opportunities, activities, pipeline_stages |
| HR | `client.rh` | employees, contracts, contract_history, addresses, bank_accounts, departments, employee_roles, employee_dependents, employee_history, employee_documents, salary_history, bonuses, bonuses_history, indemnities, indemnities_history, benefits_in_kind, benefits_in_kind_history, employee_leaves, leave_requests, leave_balances, absences, time_entries, expense_reports, expense_lines, trainings, employee_trainings, training_notes, skills, employee_education, employee_certifications, employee_work_experience |

## Resource Methods

Every resource supports:

| Method | Description |
|--------|-------------|
| `.list(limit, offset, order_by, order, search, **filters)` | Paginated list |
| `.get(id)` | Get by ID |
| `.create(data)` | Create record |
| `.update(id, data)` | Update record |
| `.delete(id)` | Delete record |
| `.bulk_create(items)` | Create up to 500 records |
| `.export(format, limit)` | Export as JSON or CSV |
| `.count()` | Total count |
| `.iterate(batch_size, **filters)` | Auto-paginated generator |

## Pagination

```python
# Manual pagination
page1 = client.sales.invoices.list(limit=50, offset=0)
print(page1.total_count, page1.page, page1.total_pages, page1.has_more)

page2 = client.sales.invoices.list(limit=50, offset=50)

# Auto-pagination (recommended for large datasets)
for invoice in client.sales.invoices.iterate(batch_size=100):
    process(invoice)
```

## Search & Count

```python
# Search across searchable fields (name, email, reference, etc.)
results = client.rh.employees.list(search="Ali")
results = client.catalog.customers.list(search="Acme")

# Count records
total_customers = client.catalog.customers.count()
total_leads = client.crm.leads.count()
print(f"{total_customers} customers, {total_leads} leads")

# Ordering
recent = client.crm.leads.list(order_by="created_at", order="desc")
```

## Error Handling

```python
from lynara import (
    Lynara,
    LynaraError,
    AuthenticationError,
    LynaraPermissionError,
    NotFoundError,
    RateLimitError,
    ValidationError,
)

try:
    client.sales.invoices.get("invalid-id")
except NotFoundError:
    print("Invoice not found")
except AuthenticationError:
    print("Invalid API key")
except LynaraPermissionError:
    print("Module not allowed for this key")
except RateLimitError as e:
    print(f"Rate limited, retry after {e.retry_after}s")
except ValidationError:
    print("Invalid data")
except LynaraError as e:
    print(f"API error: {e.message} (status {e.status_code})")
```

## API Keys

Generate API keys from **Lynara > Settings > API Keys**.

- `lnr_live_xxx` — Production key (real data)
- `lnr_test_xxx` — Test key (sandbox)

Each key has configurable:
- **Permissions**: `read`, `write`, `bulk`, `delete`, `export`
- **Modules**: restrict to specific modules (sales, crm, rh, etc.)
- **Rate limit**: 30 to 1000 requests per minute

## Full API Reference

See [lynara.ai/api](https://lynara.ai/api) for complete column definitions of all tables.

## License

MIT
