# LEX App

[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE.txt)
[![Python 3.12](https://img.shields.io/badge/Python-3.12-blue.svg)](https://www.python.org/downloads/release/python-3120/)

**LEX** is a Python/Django framework for building business applications with complex logic — calculations, permissions, audit trails, and interactive dashboards — out of the box.

---

## ✨ Key Features

- **Calculations** — Define business logic in a `calculate()` method. The framework handles state tracking, error recovery, and optional Celery offloading.
- **Lifecycle Hooks** — Attach `@hook` decorators to react to creates, updates, and deletes with full control over timing and conditions.
- **Fine-Grained Permissions** — Field-level and row-level access control with a clean `UserContext` API, integrated with Keycloak.
- **Rich Logging** — Builder-pattern `LexLogger` produces Markdown-formatted logs with tables, code blocks, and DataFrames.
- **Bitemporal History** — Every model automatically tracks *what was true when* (valid time) and *when the system learned it* (system time). Full time-travel support.
- **Streamlit Dashboards** — Attach interactive visualizations to any model — table-level or record-level.
- **Validation Hooks** — `pre_validation()` blocks bad data before save; `post_validation()` auto-rolls back after save if constraints fail.

---

## 🚀 Quick Start

```bash
# Install
pip install lex-app

# Set up project (generates .run/, .env, migrations/)
lex setup

# Initialize (migrations + Keycloak sync)
lex Init

# Start the dev server
python -m lex start --reload --loop asyncio lex_app.asgi:application
```

---

## 📖 Documentation

Full documentation lives in the [`docs/`](docs/Home.md) directory:

- [Getting Started](docs/getting-started/Getting%20Started.md) — Installation, project structure, running your app
- [Guides](docs/guides/Calculations.md) — Calculations, hooks, logging, permissions, dashboards, history
- [Tutorial](docs/tutorial/Tutorial%20Overview.md) — Build a complete app from scratch (TeamBudget)
- [Reference](docs/reference/CLI%20Commands.md) — CLI commands, LexLogger API, import maps

---

## 🛠️ Example

```python
from lex.core.models.CalculationModel import CalculationModel
from lex.core.models.LexModel import LexModel, UserContext, PermissionResult
from lex.audit_logging.handlers.LexLogger import LexLogger
from django.db import models


class Invoice(CalculationModel):
    client = models.CharField(max_length=200)
    amount = models.DecimalField(max_digits=10, decimal_places=2)
    tax_amount = models.DecimalField(max_digits=10, decimal_places=2, null=True)

    def calculate(self):
        """Automatic state tracking, error handling, and save."""
        self.tax_amount = self.amount * 0.19
        LexLogger().add_text(f"Tax calculated: €{self.tax_amount}").log()

    def permission_read(self, user_context: UserContext) -> PermissionResult:
        """Field-level access control."""
        if 'finance' in user_context.groups:
            return PermissionResult.allow_all()
        return PermissionResult.allow_all_except({'amount', 'tax_amount'})
```

---

## 📄 License

MIT — see [LICENSE.txt](LICENSE.txt) for details.

## 🤝 Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
