Metadata-Version: 2.4
Name: odoodev-equitania
Version: 0.4.6
Summary: Unified CLI tool for native Odoo development environment management
Author-email: Equitania Software GmbH <info@equitania.de>
License-Expression: AGPL-3.0-or-later
License-File: LICENSE
Keywords: cli,development,devtool,native,odoo
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.12
Requires-Dist: click>=8.1.7
Requires-Dist: jinja2>=3.1.6
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: questionary>=2.0.0
Requires-Dist: rich>=13.7.0
Provides-Extra: dev
Requires-Dist: build>=1.0.0; extra == 'dev'
Requires-Dist: mypy>=1.8.0; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest-mock>=3.12.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.8.0; extra == 'dev'
Requires-Dist: types-pyyaml>=6.0.0; extra == 'dev'
Description-Content-Type: text/markdown

# odoodev — Unified Odoo Development CLI

> **Language / Sprache**: [DE](#deutsche-dokumentation) | [EN](#english-documentation)

[![Version](https://img.shields.io/badge/version-0.3.4-blue.svg)]()
[![Python](https://img.shields.io/badge/python-≥3.10-yellow.svg)]()
[![License](https://img.shields.io/badge/license-AGPL--3.0-green.svg)]()

---

## Deutsche Dokumentation

### Projektübersicht

**odoodev** ist ein einheitliches CLI-Tool für die Verwaltung nativer Odoo-Entwicklungsumgebungen über mehrere Versionen hinweg (v16–v19). Es ersetzt eine Vielzahl manueller Skripte, Shell-Funktionen und Konfigurationsdateien durch ein konsistentes Werkzeug mit vollständigem Lifecycle-Management.

**Hauptfunktionen:**
- Multi-Version Support (v16, v17, v18, v19)
- Automatische Versionserkennung aus dem aktuellen Verzeichnis
- **Interaktiver Setup-Wizard** für die Ersteinrichtung
- Native Entwicklung mit UV Virtual Environments
- Repository-Management (Odoo, OCA, Enterprise, Custom)
- Datenbank-Backup-Wiederherstellung (ZIP, 7z, tar, SQL)
- Docker-Service-Verwaltung (PostgreSQL, Mailpit)
- Shell-Integration (Fish, Bash, Zsh)
- Odoo-Konfigurationsgenerierung mit Template-System

### Schnelleinrichtung

#### 1. Installation

**Option A: Dauerhaft als CLI-Tool installieren (empfohlen)**

```bash
# Dauerhaft als globales CLI-Tool installieren
uv tool install odoodev-equitania

# Oder direkt von GitLab/GitHub installieren (neueste Version)
uv tool install git+https://github.com/equitania/odoo-dev.git

# Update auf neueste Version
uv tool upgrade odoodev-equitania

# Einmalig ausfuehren ohne Installation
uvx odoodev-equitania --help
```

Nach `uv tool install` ist `odoodev` systemweit verfuegbar — kein Virtual Environment noetig.

**Option B: Entwicklungsinstallation (fuer Beitragende)**

```bash
# Repository klonen
git clone https://github.com/equitania/odoo-dev.git
cd odoo-dev

# Virtual Environment erstellen und aktivieren
uv venv && source .venv/bin/activate.fish  # Fish
# oder: source .venv/bin/activate           # Bash/Zsh

# Paket im Entwicklungsmodus installieren
uv pip install -e ".[dev]"
```

#### 2. Setup-Wizard

Beim ersten Aufruf eines beliebigen `odoodev`-Befehls erscheint automatisch ein Hinweis:

```
[INFO] Keine Konfiguration gefunden. Tipp: 'odoodev setup' (verwende Defaults)
```

Starte den interaktiven Wizard:

```bash
# Interaktiver Setup-Wizard (empfohlen für Erstbenutzer)
odoodev setup
```

Der Wizard führt durch 4 Schritte:

| Schritt | Frage | Standard |
|---------|-------|----------|
| 1 | Basisverzeichnis für Odoo-Projekte | `~/gitbase` |
| 2 | Aktive Odoo-Versionen (Mehrfachauswahl) | v16, v17, v18, v19 |
| 3 | PostgreSQL-Benutzer und -Passwort | `ownerp` / `CHANGE_AT_FIRST` |
| 4 | Zusammenfassung und Bestätigung | — |

Die Konfiguration wird in `~/.config/odoodev/config.yaml` gespeichert:

```yaml
# Generated by: odoodev setup
base_dir: ~/projects/odoo      # Eigener Basispfad
database:
  user: ownerp
  password: CHANGE_AT_FIRST
active_versions:
  - '18'
  - '19'
```

**Weitere Setup-Optionen:**

```bash
# Mit Standardwerten ohne Interaktion (z.B. für CI/Skripte)
odoodev setup --non-interactive

# Konfiguration auf Standardwerte zurücksetzen
odoodev setup --reset

# Aktuelle Konfiguration anzeigen
odoodev config show
```

**Was `base_dir` bewirkt:** Alle Versionspfade aus `versions.yaml` werden automatisch umgebogen. Wenn `base_dir` auf `~/projects/odoo` gesetzt ist, wird aus `~/gitbase/v18` automatisch `~/projects/odoo/v18`. Die automatische Versionserkennung (`odoodev start` ohne Versionsangabe) funktioniert dann ebenfalls im neuen Basisverzeichnis.

**Rückwärtskompatibilität:**
- Ohne `config.yaml` verwendet odoodev die bisherigen Standardwerte (`~/gitbase`)
- Bestehende `versions-override.yaml` funktioniert unverändert
- Pfade mit expliziten Overrides werden **nicht** von `base_dir` umgebogen

#### 3. Umgebung initialisieren und starten

```bash
# Neue Odoo 18 Umgebung initialisieren
odoodev init 18

# Odoo im Entwicklungsmodus starten
odoodev start 18 --dev

# Shell-Integration installieren
odoodev shell-setup
```

### Voraussetzungen und Dateien

#### Systemvoraussetzungen im Detail

| Tool | Prüfung | Pflicht | Anmerkung |
|------|---------|---------|-----------|
| UV | `uv --version` | Ja | Python-Paketmanager — ersetzt pip |
| Docker | `docker info` | Ja | Für PostgreSQL- und Mailpit-Container |
| Docker Compose V2 | `docker compose version` | Ja | Service-Orchestrierung |
| wkhtmltopdf | Pfad-Detection (plattformspezifisch) | Ja | macOS: `/usr/local/bin`, `/opt/homebrew/bin`; Linux: `/usr/local/bin`, `/usr/bin` |
| PostgreSQL-Tools | `pg_dump`, `psql` | Für DB-Operationen | macOS: `/opt/homebrew/opt/libpq/bin` |
| Git | SSH-Zugang | Ja | Für Repository-Klonen |
| Python-Pakete | babel, psycopg2, lxml, PIL, werkzeug, dateutil | Ja | In .venv via requirements.txt |

Installation der Systemvoraussetzungen:
```bash
# macOS
brew install uv
brew install libpq && brew link libpq --force
# wkhtmltopdf: "patched qt"-Version von https://wkhtmltopdf.org/downloads.html herunterladen
# Hinweis: brew install wkhtmltopdf enthält kein gepatchtes Qt — Odoo-PDF-Rendering funktioniert ggf. nicht korrekt

# Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
sudo apt-get install -y postgresql-client
# wkhtmltopdf: "patched qt"-Version von https://wkhtmltopdf.org/downloads.html herunterladen
# Hinweis: apt-get install wkhtmltopdf enthält kein gepatchtes Qt — Odoo-PDF-Rendering funktioniert ggf. nicht korrekt
```

#### Vom Benutzer bereitzustellende Dateien

| Datei | Pfad | Zweck |
|-------|------|-------|
| `repos.yaml` | `vXX-dev/scripts/repos.yaml` | Definiert alle zu klonenden Repositories |
| `requirements.txt` | `vXX-dev/devXX_native/requirements.txt` | Python-Abhängigkeiten für Odoo |
| `odoo_template.conf` | `vXX-dev/conf/odooXX_template.conf` | Template für Odoo-Konfigurationsgenerierung |
| SSH-Keys | `~/.ssh/id_rsa` (oder via repos.yaml konfigurierbar) | Zugang zu privaten Git-Repositories |

Diese Dateien sind **projektspezifisch** und werden nicht von odoodev generiert. Sie müssen im jeweiligen Versions-Repository vorhanden sein.

#### Von odoodev generierte Dateien

| Datei | Befehl | Zweck |
|-------|--------|-------|
| `config.yaml` | `odoodev setup` | Globale Konfiguration (Basispfad, DB-Credentials) |
| `.env` | `odoodev env setup` | Umgebungsvariablen (Ports, Credentials, Pfade) |
| `docker-compose.yml` | `odoodev init` | Docker-Services (PostgreSQL, Mailpit) |
| `.venv/` | `odoodev venv setup` | Python Virtual Environment via UV |
| `odoo_YYMMDD.conf` | `odoodev repos` | Odoo-Konfiguration mit addons_path |
| `odoodev-activate.fish/.sh` | `odoodev shell-setup` | Shell-Integration |

### Verzeichnisstruktur im Detail

Vollständige Darstellung aller Verzeichnisse und Dateien mit Markierung, was odoodev generiert vs. was vorhanden sein muss:

```
~/.config/odoodev/
├── config.yaml                      # [GENERATED] odoodev setup — Globale Konfiguration
└── versions-override.yaml           # [MANUELL] Optionale Versions-Overrides

~/gitbase/vXX/                       # (oder eigener base_dir aus config.yaml)
├── vXX-server/                      # [REPOS] Git-Clone des Odoo-Servers
│   ├── odoo-bin                     # Odoo-Executable (von odoodev start erwartet)
│   ├── odoo/addons/                 # Core-Addons
│   └── addons/                      # Standard-Addons
├── vXX-dev/
│   ├── devXX_native/                # [INIT] Erstellt von odoodev
│   │   ├── .env                     # [GENERATED] odoodev env setup
│   │   ├── docker-compose.yml       # [GENERATED] odoodev init
│   │   ├── .venv/                   # [GENERATED] odoodev venv setup
│   │   └── requirements.txt         # [MANUELL] Muss vorhanden sein!
│   ├── conf/
│   │   └── odooXX_template.conf     # [MANUELL] Template fuer Config-Generierung
│   └── scripts/
│       └── repos.yaml               # [MANUELL] Repository-Definitionen
├── myconfs/                         # [GENERATED] odoodev repos
│   └── odoo_YYMMDD.conf            # Generierte Odoo-Konfiguration
├── vXX-addons/                      # [REPOS] Geklont von odoodev repos
├── vXX-oca/                         # [REPOS] Geklont von odoodev repos
└── ...weitere Addon-Repos...        # [REPOS] Gemaess repos.yaml
```

**Legende:**
- `[GENERATED]` — Wird von odoodev automatisch erzeugt
- `[REPOS]` — Wird von `odoodev repos` per git clone erstellt
- `[INIT]` — Verzeichnis wird von `odoodev init` angelegt
- `[MANUELL]` — Muss vom Benutzer bereitgestellt werden

### Datenfluss

Der komplette Workflow von der Ersteinrichtung bis zum Server-Start:

```
odoodev setup (einmalig)
    ├── Basispfad festlegen (Standard: ~/gitbase)
    ├── Aktive Versionen waehlen
    ├── DB-Credentials konfigurieren
    └── config.yaml speichern → ~/.config/odoodev/config.yaml

odoodev init
    ├── Verzeichnisse anlegen (devXX_native/)
    ├── .env generieren (aus Jinja2-Template + versions.yaml + config.yaml)
    ├── docker-compose.yml generieren (PostgreSQL + Mailpit)
    ├── .venv erstellen (UV + requirements.txt)
    └── repos ausfuehren (optional, --skip-repos ueberspringt)
            │
            ├── repos.yaml laden
            ├── SSH-Zugang pruefen
            ├── git clone/pull fuer alle Repositories
            └── odoo_YYMMDD.conf generieren
                    │
                    ├── Template lesen (odooXX_template.conf)
                    ├── addons_path aus Repo-Pfaden zusammenbauen
                    │   (gruppiert nach: Odoo, OCA, Enterprise,
                    │    Syscoon, 3rd-party, Equitania, Customer, Other)
                    └── Config in myconfs/ speichern

odoodev start
    ├── .env laden (DB_PORT, PGUSER, ODOO_PORT...)
    ├── Voraussetzungen pruefen:
    │   ├── .venv vorhanden?
    │   ├── odoo-bin vorhanden?
    │   ├── odoo_*.conf vorhanden?
    │   └── PostgreSQL-Port erreichbar?
    ├── requirements.txt Freshness pruefen (SHA256)
    └── odoo-bin starten (mit odoo_YYMMDD.conf)
```

### Verwendung

#### Befehle im Überblick

| Befehl | Beschreibung |
|--------|--------------|
| `odoodev setup` | **Interaktiver Setup-Wizard** für die Ersteinrichtung |
| `odoodev init [VERSION]` | Neue Entwicklungsumgebung initialisieren |
| `odoodev start [VERSION]` | Odoo-Server starten |
| `odoodev stop [VERSION]` | Odoo-Server und Docker-Services stoppen |
| `odoodev repos [VERSION]` | Repositories klonen/aktualisieren |
| `odoodev pull [VERSION]` | Schneller `git pull` aller vorhandenen Repos |
| `odoodev db [SUBCOMMAND] [VERSION]` | Datenbankoperationen (backup, restore, list, drop) |
| `odoodev env [SUBCOMMAND] [VERSION]` | .env-Dateiverwaltung |
| `odoodev venv [SUBCOMMAND] [VERSION]` | Virtual Environment verwalten |
| `odoodev docker [SUBCOMMAND] [VERSION]` | Docker-Services steuern |
| `odoodev config [SUBCOMMAND]` | Konfiguration und Versionen |
| `odoodev run [PLAYBOOK] [OPTIONS]` | YAML-Playbook oder Inline-Steps ausführen |
| `odoodev shell-setup` | Shell-Wrapper installieren |

#### Setup-Wizard

```bash
# Interaktiver Wizard (empfohlen)
odoodev setup

# Standardwerte ohne Interaktion speichern
odoodev setup --non-interactive

# Konfiguration auf Defaults zurücksetzen
odoodev setup --reset
```

#### Umgebung initialisieren

```bash
# Interaktiv (mit Bestätigungsdialogen)
odoodev init 18

# Nicht-interaktiv (mit Standardwerten)
odoodev init 18 --non-interactive

# Ohne Repository-Klonen
odoodev init 18 --skip-repos

# Ohne Docker-Services
odoodev init 18 --skip-docker
```

#### Server starten

```bash
# Entwicklungsmodus (Hot-Reload)
odoodev start 18 --dev

# Interaktive Shell
odoodev start 18 --shell

# Tests ausführen
odoodev start 18 --test

# Venv aktivieren ohne Server zu starten
odoodev start 18 --prepare

# Zusätzliche Odoo-Argumente übergeben
odoodev start 18 -- -d mydb -u my_module
```

**Start-Modi im Überblick:**

| Modus | Flag | Beschreibung |
|-------|------|-------------|
| **Normal** | *(kein Flag)* | Produktionsnaher Start. Views werden aus der Datenbank geladen, kein Auto-Reload. |
| **Development** | `--dev` | Entwicklungsmodus (`--dev=all`): Views aus XML-Dateien laden, Auto-Reload bei Code-Änderungen, pdb-Debugger bei Exceptions. **Nur für Entwicklung!** |
| **Shell** | `--shell` | Interaktive Odoo-Python-Shell mit vollem Zugriff auf die ORM-API. |
| **Test** | `--test` | Startet Odoo mit `--test-enable --stop-after-init` — führt Unit-Tests aus und beendet sich. |
| **Prepare** | `--prepare` | Aktiviert nur die virtuelle Umgebung und öffnet eine Shell, ohne Odoo zu starten. |

> **Hinweis:** `--dev=all` aktiviert alle Entwickler-Features (XML-Reload, Python Auto-Reload, pdb-Debugger). Einzelne Features können kommagetrennt gewählt werden, z.B. `--dev=reload,xml`. Niemals in Produktion verwenden!

#### Server stoppen

```bash
# Odoo-Prozess und Docker-Services stoppen
odoodev stop 18

# Nur Odoo-Prozess stoppen (Docker weiter laufen lassen)
odoodev stop 18 --keep-docker

# Sofortiger Kill ohne graceful Shutdown
odoodev stop 18 --force
```

Der `stop`-Befehl erkennt den laufenden Odoo-Prozess anhand des konfigurierten Ports (via `lsof`) und beendet ihn zunächst mit SIGTERM, dann bei Bedarf mit SIGKILL.

#### Repository-Verwaltung

```bash
# Alle Repositories klonen/aktualisieren
odoodev repos 18

# Nur Odoo-Server verarbeiten
odoodev repos 18 --server-only

# Nur Odoo-Konfiguration generieren
odoodev repos 18 --config-only

# Custom repos.yaml verwenden
odoodev repos 18 -c /pfad/zu/repos.yaml
```

#### Schneller Pull aller Repos

```bash
# Alle vorhandenen Repos aktualisieren (kein Clone, kein Access-Check)
odoodev pull 18

# Mit Custom repos.yaml
odoodev pull 18 -c /pfad/zu/repos.yaml
```

#### Datenbankoperationen

```bash
# Datenbanken auflisten
odoodev db list 18

# Backup erstellen (interaktiv)
odoodev db backup 18

# Backup als SQL-Dump
odoodev db backup 18 -n v18_exam -t sql -o /tmp

# Backup als ZIP mit Filestore
odoodev db backup 18 -n v18_exam -t zip -o /tmp

# Backup wiederherstellen
odoodev db restore 18 -n v18_test -z backup.zip

# Datenbank löschen
odoodev db drop 18 -n v18_test

# Datenbank löschen ohne Bestätigungsprompt
odoodev db drop 18 -n v18_test --yes
```

#### Playbook-Automation (run)

```bash
# YAML-Playbook ausführen
odoodev run playbook.yaml

# Dry-Run — Schritte anzeigen ohne auszuführen
odoodev run playbook.yaml --dry-run

# JSON-Output (NDJSON) für maschinelle Verarbeitung
odoodev run playbook.yaml --output json

# Inline-Steps ohne YAML-Datei
odoodev run --step docker.up --step pull -V 18

# Version überschreiben
odoodev run playbook.yaml -V 19
```

**Playbook-Format:**

```yaml
version: "18"
on_error: stop          # stop | continue

steps:
  - name: "Start Docker"
    command: docker.up
  - name: "Pull code"
    command: pull
  - name: "Generate config"
    command: repos
    args:
      config-only: true
```

**Verfügbare Commands:** `docker.up`, `docker.down`, `docker.status`, `pull`, `repos`, `start`, `stop`, `db.list`, `db.backup`, `db.restore`, `db.drop`, `env.check`, `venv.check`, `venv.setup`

Beispiel-Playbooks unter `odoodev/data/examples/playbooks/`: `daily-update.yaml`, `start-dev.yaml`, `full-refresh.yaml`, `restore-db.yaml`

#### Docker-Services

```bash
# Services starten
odoodev docker up 18

# Services stoppen
odoodev docker down 18

# Status anzeigen
odoodev docker status 18

# Logs anzeigen
odoodev docker logs 18 -f
```

### repos.yaml Format

Die Datei `repos.yaml` steuert, welche Repositories geklont und wie sie in der Odoo-Konfiguration organisiert werden. Erwartet unter `vXX-dev/scripts/repos.yaml`:

```yaml
version: "18"
branch: "develop"
ssh_key: "~/.ssh/id_rsa"

paths:
  base: ~/gitbase/v18
  template: ~/gitbase/v18/v18-dev/conf/odoo18_template.conf
  config_dir: ~/gitbase/v18/myconfs

base_addons:
  - $HOME/gitbase/v18/v18-server/odoo/addons
  - $HOME/gitbase/v18/v18-server/addons

addons:
  - key: eq_module
    path: v18-addons
    git_url: git@gitlab.ownerp.io:v18/v18-addons.git
    section: Equitania       # Odoo|OCA|Enterprise|Syscoon|3rd-party|Equitania|Customer|Other
    commented: false          # false=aktiv, true=auskommentiert in odoo.conf
    suffix: ""                # Unterverzeichnis fuer Module (z.B. /modules)

customers:
  - key: v18-customer
    path: v18-customer
    git_url: git@gitlab.ownerp.io:customer/v18-customer.git
    section: Customer
    commented: true           # Auskommentiert in odoo.conf bis aktiviert
```

**Felder-Referenz:**

| Feld | Pflicht | Beschreibung |
|------|---------|--------------|
| `version` | Ja | Odoo-Version (z.B. "18") |
| `branch` | Ja | Git-Branch fuer alle Repositories |
| `ssh_key` | Nein | Pfad zum SSH-Key (Standard: System-Default) |
| `paths.base` | Ja | Basis-Verzeichnis der Odoo-Version |
| `paths.template` | Ja | Pfad zum odoo_template.conf |
| `paths.config_dir` | Ja | Zielverzeichnis fuer generierte Configs |
| `base_addons` | Ja | Odoo Core- und Standard-Addon-Pfade |
| `addons[].key` | Ja | Eindeutiger Identifier fuer das Repository |
| `addons[].path` | Ja | Zielverzeichnis (relativ zu paths.base) |
| `addons[].git_url` | Ja | Git-Repository-URL |
| `addons[].section` | Nein | Gruppierung in odoo.conf (Standard: "Other") |
| `addons[].commented` | Nein | true = als Kommentar in odoo.conf (Standard: false) |
| `addons[].suffix` | Nein | Unterverzeichnis-Suffix fuer addons_path |

**Sektionen im addons_path** (Reihenfolge in generierter odoo.conf):
1. Odoo (Core)
2. OCA
3. Enterprise
4. Syscoon
5. 3rd-party
6. Equitania
7. Customer
8. Other

**Repository-Abschnitte in repos.yaml:** `addons`, `additional`, `special`, `customers` — alle werden identisch verarbeitet.

### Unterstützte Versionen

| Version | Python | PostgreSQL | DB Port | Odoo Port | Gevent | Mailpit | SMTP |
|---------|--------|------------|---------|-----------|--------|---------|------|
| v16 | 3.12 | 16.11 | 16432 | 16069 | 16072 | 16025 | 11025 |
| v17 | 3.12 | 16.11 | 17432 | 17069 | 17072 | 17025 | 11725 |
| v18 | 3.13 | 16.11 | 18432 | 18069 | 18072 | 18025 | 1025 |
| v19 | 3.13 | 17.4 | 19432 | 19069 | 19072 | 19025 | 1925 |

Port-Schema: `{version}{service}` — z.B. v18: DB=18432, Odoo=18069, Gevent=18072

### Konfiguration

#### Globale Konfiguration (`odoodev setup`)

Die globale Konfiguration wird in `~/.config/odoodev/config.yaml` gespeichert und steuert:

| Einstellung | Standard | Beschreibung |
|-------------|----------|--------------|
| `base_dir` | `~/gitbase` | Basisverzeichnis für alle Odoo-Versionen |
| `database.user` | `ownerp` | Standard-PostgreSQL-Benutzer |
| `database.password` | `CHANGE_AT_FIRST` | Standard-PostgreSQL-Passwort |
| `active_versions` | `16, 17, 18, 19` | Aktive Odoo-Versionen |

Die DB-Credentials aus `config.yaml` werden automatisch in `.env`-Dateien und Datenbankoperationen verwendet.

#### Versionsspezifische Overrides (`versions-override.yaml`)

Benutzer können versionsspezifische Einstellungen ueberschreiben, ohne `versions.yaml` im Paket zu ändern:

**Datei:** `~/.config/odoodev/versions-override.yaml`

```yaml
versions:
  "18":
    ports:
      db: 15432          # Eigener PostgreSQL-Port
      odoo: 8069         # Standard-Odoo-Port statt 18069
    paths:
      base: "~/projects/odoo18"   # Anderer Basispfad
    git:
      branch: "main"     # Anderer Default-Branch
```

Die Override-Datei wird beim Laden der Versionsregistry automatisch zusammengeführt. Nur angegebene Felder werden ueberschrieben — alle anderen behalten ihre Standardwerte.

**Priorität:**
1. `versions-override.yaml` (höchste — versionsspezifische Pfade werden **nicht** von `base_dir` umgebogen)
2. `config.yaml` (globale Einstellungen wie `base_dir`)
3. `versions.yaml` im Paket (Standardwerte)

### Obsolete Komponenten

odoodev ersetzt folgende Artefakte aus den bestehenden vXX-dev Repositories:

| Obsolete Datei/Komponente | Ersetzt durch | Anmerkung |
|---------------------------|---------------|-----------|
| `start-native.sh` | `odoodev start` | Alle Startmodi abgedeckt (dev, shell, test, prepare) |
| `.env.template` | `odoodev env setup` | Template ist im Tool integriert (Jinja2) |
| `docker-compose.yml` (manuell) | `odoodev init` | Generiert aus internem Template |
| Fish-Funktionen (`odoo-env`, `odoo-start`, `odoo-stop`) | `odoodev` CLI | Alle Befehle konsolidiert |
| Fish-Aliase (`dev16`, `dev18`) | `odoodev-activate` | Shell-Integration via `odoodev shell-setup` |
| Manuelle `git clone` pro Repo | `odoodev repos` | Gesteuert ueber repos.yaml |
| Manuelle Config-Generierung | `odoodev repos --config-only` | Automatisch aus repos.yaml + Template |
| `docker-compose-arm64.yml` | `odoodev init` | Plattform wird automatisch erkannt |

**Weiterhin benötigt** (nicht ersetzt):

| Datei | Grund |
|-------|-------|
| `repos.yaml` | Projektspezifisch — definiert welche Repos geklont werden |
| `requirements.txt` | Versionsspezifisch — Odoo-Dependencies + Custom-Pakete |
| `odooXX_template.conf` | Versionsspezifisch — Basis fuer Konfigurationsgenerierung |
| SSH-Keys | Zugang zu privaten Git-Repositories |

### Filestore-Verwaltung

Bei der Datenbank-Wiederherstellung verwaltet odoodev auch den Odoo-Filestore:

**Filestore-Pfad:** `~/odoo-share/filestore/{db_name}/`

Dieser Pfad ist fest im Tool hinterlegt und wird bei `odoodev db restore` automatisch verwendet:

1. Backup wird extrahiert (ZIP, 7z, tar, gz, SQL)
2. SQL-Dump wird in neue Datenbank eingespielt
3. Filestore wird nach `~/odoo-share/filestore/{db_name}/` kopiert
4. **Post-Restore Deaktivierungen:**
   - Cron-Jobs (`ir_cron.active = false`)
   - Mail-Server (`ir_mail_server.active = false`)
   - Fetchmail-Server (`fetchmail_server.active = false`)
   - Nextcloud-Integration (Config-Parameter geleert)
   - Office365-Integration (Config-Parameter geleert)

### Architektur

```
odoodev/
├── cli.py                  # CLI-Einstiegspunkt (Click) + First-Run-Hint
├── output.py               # Rich-Konsolenausgabe
├── commands/
│   ├── setup_cmd.py        # Setup-Wizard (questionary)
│   ├── init_cmd.py         # Umgebungsinitialisierung
│   ├── start.py            # Server-Start
│   ├── repos.py            # Repository-Verwaltung
│   ├── db.py               # Datenbankoperationen
│   ├── env.py              # .env-Verwaltung
│   ├── venv.py             # Virtual Environment
│   ├── docker.py           # Docker-Services
│   ├── config.py           # Konfiguration
│   ├── run.py              # Playbook-Automation (run)
│   └── shell_setup.py      # Shell-Integration
├── core/
│   ├── global_config.py    # Globale Konfiguration (config.yaml)
│   ├── version_registry.py # Versionsmanagement + base_dir Rebasing
│   ├── environment.py      # Plattformerkennung
│   ├── git_ops.py          # Git-Operationen
│   ├── database.py         # PostgreSQL-Operationen
│   ├── odoo_config.py      # Konfigurationsgenerierung
│   ├── venv_manager.py     # UV-Venv-Verwaltung
│   ├── docker_compose.py   # Docker-Compose-Operationen
│   ├── prerequisites.py    # Voraussetzungsprüfungen
│   ├── shell_integration.py# Shell-Aktivierung
│   ├── playbook.py         # Playbook-Engine (Dataclasses, Runner)
│   └── automation.py       # Non-Interactive Command-Handler
├── templates/              # Jinja2-Templates
│   ├── docker-compose.yml.j2
│   ├── env.template.j2
│   └── shell/              # Shell-Aktivierungsskripte
└── data/
    ├── versions.yaml       # Versionsregistry
    └── examples/playbooks/ # Beispiel-Playbooks (daily-update, start-dev, ...)
```

### Entwicklung

```bash
# Entwicklungsumgebung einrichten
uv venv && source .venv/bin/activate.fish
uv pip install -e ".[dev]"

# Tests ausführen
pytest

# Linting
ruff check . && ruff format --check .

# Formatierung anwenden
ruff check --fix . && ruff format .

# Typ-Prüfung
mypy odoodev

# Paket bauen
uv build
```

### Lizenz

Dieses Projekt ist unter der [AGPL-3.0-or-later](LICENSE) Lizenz lizenziert.

### Kontakt

- **Firma:** Equitania Software GmbH
- **E-Mail:** info@equitania.de
- **Website:** https://www.equitania.de

---

## English Documentation

### Project Overview

**odoodev** is a unified CLI tool for native Odoo development environment management across versions (v16–v19). It replaces a variety of manual scripts, shell functions, and configuration files with a consistent tool providing complete lifecycle management.

**Key Features:**
- Multi-version support (v16, v17, v18, v19)
- Automatic version detection from current directory
- **Interactive setup wizard** for first-time configuration
- Native development with UV virtual environments
- Repository management (Odoo, OCA, Enterprise, Custom)
- Database backup restoration (ZIP, 7z, tar, SQL)
- Docker service management (PostgreSQL, Mailpit)
- Shell integration (Fish, Bash, Zsh)
- Odoo configuration generation with template system

### Quick Setup

#### 1. Installation

**Option A: Install as permanent CLI tool (recommended)**

```bash
# Install as global CLI tool permanently
uv tool install odoodev-equitania

# Or install directly from GitLab/GitHub (latest version)
uv tool install git+https://github.com/equitania/odoo-dev.git

# Update to latest version
uv tool upgrade odoodev-equitania

# Run once without installing
uvx odoodev-equitania --help
```

After `uv tool install`, `odoodev` is available system-wide — no virtual environment needed.

**Option B: Development installation (for contributors)**

```bash
# Clone repository
git clone https://github.com/equitania/odoo-dev.git
cd odoo-dev

# Create and activate virtual environment
uv venv && source .venv/bin/activate.fish  # Fish
# or: source .venv/bin/activate             # Bash/Zsh

# Install package in development mode
uv pip install -e ".[dev]"
```

#### 2. Setup Wizard

On the first invocation of any `odoodev` command, a hint is shown automatically:

```
[INFO] No configuration found. Tip: run 'odoodev setup' (using defaults)
```

Start the interactive wizard:

```bash
# Interactive setup wizard (recommended for first-time users)
odoodev setup
```

The wizard guides you through 4 steps:

| Step | Question | Default |
|------|----------|---------|
| 1 | Base directory for Odoo projects | `~/gitbase` |
| 2 | Active Odoo versions (multi-select) | v16, v17, v18, v19 |
| 3 | PostgreSQL user and password | `ownerp` / `CHANGE_AT_FIRST` |
| 4 | Summary and confirmation | — |

The configuration is saved to `~/.config/odoodev/config.yaml`:

```yaml
# Generated by: odoodev setup
base_dir: ~/projects/odoo      # Custom base path
database:
  user: ownerp
  password: CHANGE_AT_FIRST
active_versions:
  - '18'
  - '19'
```

**Additional setup options:**

```bash
# Save defaults without interaction (e.g. for CI/scripts)
odoodev setup --non-interactive

# Reset configuration to defaults
odoodev setup --reset

# Show current configuration
odoodev config show
```

**What `base_dir` does:** All version paths from `versions.yaml` are automatically rebased. If `base_dir` is set to `~/projects/odoo`, then `~/gitbase/v18` becomes `~/projects/odoo/v18`. Automatic version detection (`odoodev start` without version argument) also works in the new base directory.

**Backwards compatibility:**
- Without `config.yaml`, odoodev uses the original defaults (`~/gitbase`)
- Existing `versions-override.yaml` continues to work unchanged
- Paths with explicit overrides are **not** rebased by `base_dir`

#### 3. Initialize and Start

```bash
# Initialize new Odoo 18 environment
odoodev init 18

# Start Odoo in development mode
odoodev start 18 --dev

# Install shell integration
odoodev shell-setup
```

### Prerequisites and Required Files

#### System Prerequisites in Detail

| Tool | Check | Required | Note |
|------|-------|----------|------|
| UV | `uv --version` | Yes | Python package manager — replaces pip |
| Docker | `docker info` | Yes | For PostgreSQL and Mailpit containers |
| Docker Compose V2 | `docker compose version` | Yes | Service orchestration |
| wkhtmltopdf | Path detection (platform-specific) | Yes | macOS: `/usr/local/bin`, `/opt/homebrew/bin`; Linux: `/usr/local/bin`, `/usr/bin` |
| PostgreSQL tools | `pg_dump`, `psql` | For DB operations | macOS: `/opt/homebrew/opt/libpq/bin` |
| Git | SSH access | Yes | For repository cloning |
| Python packages | babel, psycopg2, lxml, PIL, werkzeug, dateutil | Yes | In .venv via requirements.txt |

Installing system prerequisites:
```bash
# macOS
brew install uv
brew install libpq && brew link libpq --force
# wkhtmltopdf: download 'patched qt' version from https://wkhtmltopdf.org/downloads.html
# Note: brew install wkhtmltopdf lacks patched Qt — Odoo PDF rendering may not work correctly

# Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
sudo apt-get install -y postgresql-client
# wkhtmltopdf: download 'patched qt' version from https://wkhtmltopdf.org/downloads.html
# Note: apt-get install wkhtmltopdf lacks patched Qt — Odoo PDF rendering may not work correctly
```

#### User-Provided Files

| File | Path | Purpose |
|------|------|---------|
| `repos.yaml` | `vXX-dev/scripts/repos.yaml` | Defines all repositories to clone |
| `requirements.txt` | `vXX-dev/devXX_native/requirements.txt` | Python dependencies for Odoo |
| `odoo_template.conf` | `vXX-dev/conf/odooXX_template.conf` | Template for Odoo configuration generation |
| SSH keys | `~/.ssh/id_rsa` (or configurable via repos.yaml) | Access to private Git repositories |

These files are **project-specific** and are not generated by odoodev. They must exist in the respective version repository.

#### Files Generated by odoodev

| File | Command | Purpose |
|------|---------|---------|
| `config.yaml` | `odoodev setup` | Global configuration (base path, DB credentials) |
| `.env` | `odoodev env setup` | Environment variables (ports, credentials, paths) |
| `docker-compose.yml` | `odoodev init` | Docker services (PostgreSQL, Mailpit) |
| `.venv/` | `odoodev venv setup` | Python virtual environment via UV |
| `odoo_YYMMDD.conf` | `odoodev repos` | Odoo configuration with addons_path |
| `odoodev-activate.fish/.sh` | `odoodev shell-setup` | Shell integration |

### Directory Structure in Detail

Complete view of all directories and files, showing what odoodev generates vs. what must be provided:

```
~/.config/odoodev/
├── config.yaml                      # [GENERATED] odoodev setup — Global configuration
└── versions-override.yaml           # [MANUAL] Optional version overrides

~/gitbase/vXX/                       # (or custom base_dir from config.yaml)
├── vXX-server/                      # [REPOS] Git clone of Odoo server
│   ├── odoo-bin                     # Odoo executable (expected by odoodev start)
│   ├── odoo/addons/                 # Core addons
│   └── addons/                      # Standard addons
├── vXX-dev/
│   ├── devXX_native/                # [INIT] Created by odoodev
│   │   ├── .env                     # [GENERATED] odoodev env setup
│   │   ├── docker-compose.yml       # [GENERATED] odoodev init
│   │   ├── .venv/                   # [GENERATED] odoodev venv setup
│   │   └── requirements.txt         # [MANUAL] Must be provided!
│   ├── conf/
│   │   └── odooXX_template.conf     # [MANUAL] Template for config generation
│   └── scripts/
│       └── repos.yaml               # [MANUAL] Repository definitions
├── myconfs/                         # [GENERATED] odoodev repos
│   └── odoo_YYMMDD.conf            # Generated Odoo configuration
├── vXX-addons/                      # [REPOS] Cloned by odoodev repos
├── vXX-oca/                         # [REPOS] Cloned by odoodev repos
└── ...additional addon repos...     # [REPOS] According to repos.yaml
```

**Legend:**
- `[GENERATED]` — Automatically created by odoodev
- `[REPOS]` — Created by `odoodev repos` via git clone
- `[INIT]` — Directory created by `odoodev init`
- `[MANUAL]` — Must be provided by the user

### Data Flow

The complete workflow from first-time setup to server start:

```
odoodev setup (one-time)
    ├── Set base directory (default: ~/gitbase)
    ├── Select active versions
    ├── Configure DB credentials
    └── Save config.yaml → ~/.config/odoodev/config.yaml

odoodev init
    ├── Create directories (devXX_native/)
    ├── Generate .env (from Jinja2 template + versions.yaml + config.yaml)
    ├── Generate docker-compose.yml (PostgreSQL + Mailpit)
    ├── Create .venv (UV + requirements.txt)
    └── Run repos (optional, --skip-repos skips this)
            │
            ├── Load repos.yaml
            ├── Verify SSH access
            ├── git clone/pull for all repositories
            └── Generate odoo_YYMMDD.conf
                    │
                    ├── Read template (odooXX_template.conf)
                    ├── Build addons_path from repo paths
                    │   (grouped by: Odoo, OCA, Enterprise,
                    │    Syscoon, 3rd-party, Equitania, Customer, Other)
                    └── Save config to myconfs/

odoodev start
    ├── Load .env (DB_PORT, PGUSER, ODOO_PORT...)
    ├── Check prerequisites:
    │   ├── .venv exists?
    │   ├── odoo-bin exists?
    │   ├── odoo_*.conf exists?
    │   └── PostgreSQL port reachable?
    ├── Check requirements.txt freshness (SHA256)
    └── Start odoo-bin (with odoo_YYMMDD.conf)
```

### Usage

#### Command Reference

| Command | Description |
|---------|-------------|
| `odoodev setup` | **Interactive setup wizard** for first-time configuration |
| `odoodev init [VERSION]` | Initialize new development environment |
| `odoodev start [VERSION]` | Start Odoo server |
| `odoodev stop [VERSION]` | Stop Odoo server and Docker services |
| `odoodev repos [VERSION]` | Clone/update repositories |
| `odoodev pull [VERSION]` | Quick `git pull` across all existing repos |
| `odoodev db [SUBCOMMAND] [VERSION]` | Database operations (backup, restore, list, drop) |
| `odoodev env [SUBCOMMAND] [VERSION]` | .env file management |
| `odoodev venv [SUBCOMMAND] [VERSION]` | Virtual environment management |
| `odoodev docker [SUBCOMMAND] [VERSION]` | Docker service control |
| `odoodev config [SUBCOMMAND]` | Configuration and versions |
| `odoodev run [PLAYBOOK] [OPTIONS]` | Run YAML playbook or inline steps |
| `odoodev shell-setup` | Install shell wrapper functions |

#### Setup Wizard

```bash
# Interactive wizard (recommended)
odoodev setup

# Save defaults without interaction
odoodev setup --non-interactive

# Reset configuration to defaults
odoodev setup --reset
```

#### Initialize Environment

```bash
# Interactive (with confirmation prompts)
odoodev init 18

# Non-interactive (with defaults)
odoodev init 18 --non-interactive

# Skip repository cloning
odoodev init 18 --skip-repos

# Skip Docker services
odoodev init 18 --skip-docker
```

#### Start Server

```bash
# Development mode (hot-reload)
odoodev start 18 --dev

# Interactive shell
odoodev start 18 --shell

# Run tests
odoodev start 18 --test

# Activate venv without starting server
odoodev start 18 --prepare

# Pass additional Odoo arguments
odoodev start 18 -- -d mydb -u my_module
```

**Start Modes Overview:**

| Mode | Flag | Description |
|------|------|-------------|
| **Normal** | *(no flag)* | Production-like start. Views are loaded from the database, no auto-reload. |
| **Development** | `--dev` | Development mode (`--dev=all`): load views from XML files, auto-reload on code changes, pdb debugger on exceptions. **Development only!** |
| **Shell** | `--shell` | Interactive Odoo Python shell with full ORM API access. |
| **Test** | `--test` | Starts Odoo with `--test-enable --stop-after-init` — runs unit tests and exits. |
| **Prepare** | `--prepare` | Only activates the virtual environment and opens a shell without starting Odoo. |

> **Note:** `--dev=all` enables all developer features (XML reload, Python auto-reload, pdb debugger). Individual features can be selected comma-separated, e.g. `--dev=reload,xml`. Never use in production!

#### Stop Server

```bash
# Stop Odoo process and Docker services
odoodev stop 18

# Stop only Odoo process (keep Docker running)
odoodev stop 18 --keep-docker

# Immediate kill without graceful shutdown
odoodev stop 18 --force
```

The `stop` command discovers the running Odoo process by configured port (via `lsof`) and terminates it with SIGTERM first, then SIGKILL if needed.

#### Repository Management

```bash
# Clone/update all repositories
odoodev repos 18

# Process only Odoo server
odoodev repos 18 --server-only

# Generate Odoo config only
odoodev repos 18 --config-only

# Use custom repos.yaml
odoodev repos 18 -c /path/to/repos.yaml
```

#### Quick Pull All Repos

```bash
# Update all existing repos (no clone, no access check)
odoodev pull 18

# With custom repos.yaml
odoodev pull 18 -c /path/to/repos.yaml
```

#### Database Operations

```bash
# List databases
odoodev db list 18

# Create backup (interactive)
odoodev db backup 18

# Backup as SQL dump
odoodev db backup 18 -n v18_exam -t sql -o /tmp

# Backup as ZIP with filestore
odoodev db backup 18 -n v18_exam -t zip -o /tmp

# Restore backup
odoodev db restore 18 -n v18_test -z backup.zip

# Drop database
odoodev db drop 18 -n v18_test

# Drop database without confirmation prompt
odoodev db drop 18 -n v18_test --yes
```

#### Playbook Automation (run)

```bash
# Execute YAML playbook
odoodev run playbook.yaml

# Dry-run — show steps without executing
odoodev run playbook.yaml --dry-run

# JSON output (NDJSON) for machine processing
odoodev run playbook.yaml --output json

# Inline steps without YAML file
odoodev run --step docker.up --step pull -V 18

# Override version
odoodev run playbook.yaml -V 19
```

**Playbook format:**

```yaml
version: "18"
on_error: stop          # stop | continue

steps:
  - name: "Start Docker"
    command: docker.up
  - name: "Pull code"
    command: pull
  - name: "Generate config"
    command: repos
    args:
      config-only: true
```

**Available commands:** `docker.up`, `docker.down`, `docker.status`, `pull`, `repos`, `start`, `stop`, `db.list`, `db.backup`, `db.restore`, `db.drop`, `env.check`, `venv.check`, `venv.setup`

Example playbooks in `odoodev/data/examples/playbooks/`: `daily-update.yaml`, `start-dev.yaml`, `full-refresh.yaml`, `restore-db.yaml`

#### Docker Services

```bash
# Start services
odoodev docker up 18

# Stop services
odoodev docker down 18

# Show status
odoodev docker status 18

# View logs
odoodev docker logs 18 -f
```

### repos.yaml Format

The file `repos.yaml` controls which repositories are cloned and how they are organized in the Odoo configuration. Expected at `vXX-dev/scripts/repos.yaml`:

```yaml
version: "18"
branch: "develop"
ssh_key: "~/.ssh/id_rsa"

paths:
  base: ~/gitbase/v18
  template: ~/gitbase/v18/v18-dev/conf/odoo18_template.conf
  config_dir: ~/gitbase/v18/myconfs

base_addons:
  - $HOME/gitbase/v18/v18-server/odoo/addons
  - $HOME/gitbase/v18/v18-server/addons

addons:
  - key: eq_module
    path: v18-addons
    git_url: git@gitlab.ownerp.io:v18/v18-addons.git
    section: Equitania       # Odoo|OCA|Enterprise|Syscoon|3rd-party|Equitania|Customer|Other
    commented: false          # false=active, true=commented out in odoo.conf
    suffix: ""                # Subdirectory for modules (e.g. /modules)

customers:
  - key: v18-customer
    path: v18-customer
    git_url: git@gitlab.ownerp.io:customer/v18-customer.git
    section: Customer
    commented: true           # Commented out in odoo.conf until activated
```

**Field Reference:**

| Field | Required | Description |
|-------|----------|-------------|
| `version` | Yes | Odoo version (e.g. "18") |
| `branch` | Yes | Git branch for all repositories |
| `ssh_key` | No | Path to SSH key (default: system default) |
| `paths.base` | Yes | Base directory of the Odoo version |
| `paths.template` | Yes | Path to odoo_template.conf |
| `paths.config_dir` | Yes | Target directory for generated configs |
| `base_addons` | Yes | Odoo core and standard addon paths |
| `addons[].key` | Yes | Unique identifier for the repository |
| `addons[].path` | Yes | Target directory (relative to paths.base) |
| `addons[].git_url` | Yes | Git repository URL |
| `addons[].section` | No | Grouping in odoo.conf (default: "Other") |
| `addons[].commented` | No | true = as comment in odoo.conf (default: false) |
| `addons[].suffix` | No | Subdirectory suffix for addons_path |

**Sections in addons_path** (order in generated odoo.conf):
1. Odoo (Core)
2. OCA
3. Enterprise
4. Syscoon
5. 3rd-party
6. Equitania
7. Customer
8. Other

**Repository sections in repos.yaml:** `addons`, `additional`, `special`, `customers` — all processed identically.

### Supported Versions

| Version | Python | PostgreSQL | DB Port | Odoo Port | Gevent | Mailpit | SMTP |
|---------|--------|------------|---------|-----------|--------|---------|------|
| v16 | 3.12 | 16.11 | 16432 | 16069 | 16072 | 16025 | 11025 |
| v17 | 3.12 | 16.11 | 17432 | 17069 | 17072 | 17025 | 11725 |
| v18 | 3.13 | 16.11 | 18432 | 18069 | 18072 | 18025 | 1025 |
| v19 | 3.13 | 17.4 | 19432 | 19069 | 19072 | 19025 | 1925 |

Port schema: `{version}{service}` — e.g. v18: DB=18432, Odoo=18069, Gevent=18072

### Configuration

#### Global Configuration (`odoodev setup`)

The global configuration is stored in `~/.config/odoodev/config.yaml` and controls:

| Setting | Default | Description |
|---------|---------|-------------|
| `base_dir` | `~/gitbase` | Base directory for all Odoo versions |
| `database.user` | `ownerp` | Default PostgreSQL user |
| `database.password` | `CHANGE_AT_FIRST` | Default PostgreSQL password |
| `active_versions` | `16, 17, 18, 19` | Active Odoo versions |

DB credentials from `config.yaml` are automatically used in `.env` files and database operations.

#### Version-Specific Overrides (`versions-override.yaml`)

Users can override version-specific settings without modifying `versions.yaml` in the package:

**File:** `~/.config/odoodev/versions-override.yaml`

```yaml
versions:
  "18":
    ports:
      db: 15432          # Custom PostgreSQL port
      odoo: 8069         # Standard Odoo port instead of 18069
    paths:
      base: "~/projects/odoo18"   # Different base path
    git:
      branch: "main"     # Different default branch
```

The override file is automatically merged when loading the version registry. Only specified fields are overridden — all others retain their default values.

**Priority:**
1. `versions-override.yaml` (highest — version-specific paths are **not** rebased by `base_dir`)
2. `config.yaml` (global settings like `base_dir`)
3. `versions.yaml` in the package (defaults)

### Obsolete Components

odoodev replaces the following artifacts from existing vXX-dev repositories:

| Obsolete File/Component | Replaced by | Note |
|--------------------------|-------------|------|
| `start-native.sh` | `odoodev start` | All start modes covered (dev, shell, test, prepare) |
| `.env.template` | `odoodev env setup` | Template is built into the tool (Jinja2) |
| `docker-compose.yml` (manual) | `odoodev init` | Generated from internal template |
| Fish functions (`odoo-env`, `odoo-start`, `odoo-stop`) | `odoodev` CLI | All commands consolidated |
| Fish aliases (`dev16`, `dev18`) | `odoodev-activate` | Shell integration via `odoodev shell-setup` |
| Manual `git clone` per repo | `odoodev repos` | Controlled via repos.yaml |
| Manual config generation | `odoodev repos --config-only` | Automatic from repos.yaml + template |
| `docker-compose-arm64.yml` | `odoodev init` | Platform is automatically detected |

**Still required** (not replaced):

| File | Reason |
|------|--------|
| `repos.yaml` | Project-specific — defines which repos to clone |
| `requirements.txt` | Version-specific — Odoo dependencies + custom packages |
| `odooXX_template.conf` | Version-specific — base for configuration generation |
| SSH keys | Access to private Git repositories |

### Filestore Management

During database restoration, odoodev also manages the Odoo filestore:

**Filestore path:** `~/odoo-share/filestore/{db_name}/`

This path is hardcoded in the tool and automatically used by `odoodev db restore`:

1. Backup is extracted (ZIP, 7z, tar, gz, SQL)
2. SQL dump is imported into new database
3. Filestore is copied to `~/odoo-share/filestore/{db_name}/`
4. **Post-restore deactivations:**
   - Cron jobs (`ir_cron.active = false`)
   - Mail servers (`ir_mail_server.active = false`)
   - Fetchmail servers (`fetchmail_server.active = false`)
   - Nextcloud integration (config parameters cleared)
   - Office365 integration (config parameters cleared)

### Architecture

```
odoodev/
├── cli.py                  # CLI entry point (Click) + first-run hint
├── output.py               # Rich console output
├── commands/
│   ├── setup_cmd.py        # Setup wizard (questionary)
│   ├── init_cmd.py         # Environment initialization
│   ├── start.py            # Server startup
│   ├── repos.py            # Repository management
│   ├── db.py               # Database operations
│   ├── env.py              # .env management
│   ├── venv.py             # Virtual environment
│   ├── docker.py           # Docker services
│   ├── config.py           # Configuration
│   └── shell_setup.py      # Shell integration
├── core/
│   ├── global_config.py    # Global configuration (config.yaml)
│   ├── version_registry.py # Version management + base_dir rebasing
│   ├── environment.py      # Platform detection
│   ├── git_ops.py          # Git operations
│   ├── database.py         # PostgreSQL operations
│   ├── odoo_config.py      # Config generation
│   ├── venv_manager.py     # UV venv management
│   ├── docker_compose.py   # Docker Compose operations
│   ├── prerequisites.py    # Prerequisite checks
│   └── shell_integration.py# Shell activation
├── templates/              # Jinja2 templates
│   ├── docker-compose.yml.j2
│   ├── env.template.j2
│   └── shell/              # Shell activation scripts
└── data/
    └── versions.yaml       # Version registry
```

### Development

```bash
# Set up development environment
uv venv && source .venv/bin/activate.fish
uv pip install -e ".[dev]"

# Run tests
pytest

# Linting
ruff check . && ruff format --check .

# Apply formatting
ruff check --fix . && ruff format .

# Type checking
mypy odoodev

# Build package
uv build
```

### License

This project is licensed under [AGPL-3.0-or-later](LICENSE).

### Contact

- **Company:** Equitania Software GmbH
- **Email:** info@equitania.de
- **Website:** https://www.equitania.de
