atlas-academy/docs/ODOO.md
Atlas Developer 03829a38b2 feat: Atlas Academy — Odoo eLearning platform, full fusion
9-course Dutch e-learning platform fused onto atlasacademy.nl via Caddy
reverse proxy. Odoo 19 Community as course engine (website_slides), static
HTML for marketing front. Single Odoo account system.

- static/: 8 marketing pages (index, pricing, coaching, leerpad, over, shop, bisl, esf)
- backend/odoo_relay.py: lead relay Flask service (POST /academy-lead → Odoo CRM)
- caddy/academy.caddyfile: full Caddy config with Odoo proxy + auth rewrites
- docs/: ARCHITECTURE, USERFLOW, COURSES, DEPLOYMENT, SECURITY, ODOO

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 00:48:45 +02:00

160 lines
4.7 KiB
Markdown

# Odoo eLearning Setup — Atlas Academy
## Installatie
`website_slides` is geïnstalleerd als onderdeel van Odoo 19 Community op atlas-01.
```bash
# Verificatie
ssh atlas-01 "docker exec atlas-odoo odoo --list-db 2>/dev/null"
# DB: atlas
# Module status
ssh atlas-01 "docker exec -i atlas-odoo odoo shell -d atlas --no-http" <<'EOF'
m = env['ir.module.module'].sudo().search([('name','=','website_slides')])
print(m.name, m.state) # verwacht: website_slides installed
EOF
```
---
## Multi-website configuratie
Atlas Academy draait op **website 3** (apart van de Atlas Corporation-website op website 1).
| | Website 1 | Website 3 |
|--|-----------|-----------|
| Naam | Atlas Corporation | Atlas Academy |
| Domein | *(default)* | `https://atlasacademy.nl` |
| Signup | `b2b` (gesloten) | `b2c` (open) |
| Taal | NL | NL |
| Logo | Atlas Corp | Atlas Academy icon |
### Kritische gotcha's
**1. Caching van website-routing**
`_get_current_website_id` is ORM-gecached. Na aanmaken/wijzigen van een website:
```bash
ssh atlas-01 "docker restart atlas-odoo"
```
**2. X-Forwarded-Host verplicht**
Caddy moet `X-Forwarded-Host {host}` doorgeven, anders serveert Odoo altijd website 1:
```caddyfile
reverse_proxy 100.93.16.81:8069 {
header_up Host {host}
header_up X-Forwarded-Host {host}
header_up X-Forwarded-Proto https
}
```
**3. `proxy_mode = True`**
Controleer `/opt/atlas-odoo/config/odoo.conf`:
```ini
proxy_mode = True
```
**4. Signup is per-website, niet globaal**
De globale `auth_signup.allow_uninvited` parameter wordt **genegeerd** als `website` module actief is. Gebruik altijd:
```python
env['website'].sudo().browse(3).write({'auth_signup_uninvited': 'b2c'})
env.cr.commit()
```
---
## Website 3 aanmaken (referentie)
```python
env = env # Odoo shell
w3 = env['website'].sudo().create({
'name': 'Atlas Academy',
'domain': 'https://atlasacademy.nl',
'company_id': env.company.id,
'language_ids': [(4, env.ref('base.lang_nl').id)],
'default_lang_id': env.ref('base.lang_nl').id,
'auth_signup_uninvited': 'b2c',
})
# Stel logo in
import base64, requests
logo_data = requests.get('https://atlasacademy.nl/atlas-icon.png').content
w3.write({'logo': base64.b64encode(logo_data).decode()})
env.cr.commit()
print(f"Website aangemaakt: ID={w3.id}")
# Vervolgens: docker restart atlas-odoo
```
---
## Cursus website-toewijzing
Alle cursussen (`slide.channel`) moeten `website_id=3` hebben:
```python
channels = env['slide.channel'].sudo().search([])
for c in channels:
if not c.website_id or c.website_id.id != 3:
c.sudo().write({'website_id': 3})
env.cr.commit()
print(f"{len(channels)} cursussen toegewezen aan website 3")
```
---
## Email base-URL
Odoo gebruikt `website.get_base_url()` voor links in e-mails (wachtwoord reset etc.).
Dankzij multi-website:
- Website 3 → `get_base_url()` = `https://atlasacademy.nl`
- Website 1 → `get_base_url()` = corp-domein ✅
De globale `web.base.url` parameter wordt **niet** gewijzigd (zou corp-emails breken).
---
## Odoo backend bereikbaarheid
| Route | Bereikbaar? | Via |
|-------|-------------|-----|
| `atlasacademy.nl/slides` | ✅ Publiek | Caddy proxy |
| `atlasacademy.nl/web/login` | ✅ Publiek | Caddy proxy |
| `atlasacademy.nl/web` (backend) | ❌ Niet geproxied | — |
| `http://100.93.16.81:8069` | ✅ Tailnet only | Direct |
| `odoo.atlascorporation.nl` | ✅ SSO only | Authentik + Caddy |
---
## Veelgebruikte ORM-commando's
```bash
# Shell openen
ssh atlas-01 "docker exec -i atlas-odoo odoo shell -d atlas --no-http"
# Alle cursussen tonen
for c in env['slide.channel'].sudo().search([]): print(c.id, c.name, c.website_slug)
# Cursuspagina URL genereren
c = env['slide.channel'].sudo().browse(2)
print(f"https://atlasacademy.nl/slides/{c.website_slug}")
# Lessen van een cursus tonen
slides = env['slide.slide'].sudo().search([('channel_id','=',2),('is_category','=',False)])
for s in slides: print(s.sequence, s.name, len(s.question_ids), 'vragen')
# Website-instellingen inspecteren
w = env['website'].sudo().browse(3)
print(w.name, w.domain, w.auth_signup_uninvited, w.get_base_url())
```
---
## Bekende issues & oplossingen
| Issue | Oorzaak | Oplossing |
|-------|---------|-----------|
| `/web/signup` → 404 | `auth_signup_uninvited` niet op `b2c` | ORM shell: `w.write({'auth_signup_uninvited':'b2c'})` |
| Courses tonen op corp-website | `website_id=None` op channels | Script: set alle channels op `website_id=3` |
| Wachtwoord-reset e-mail heeft wrong URL | `web.base.url` verkeerd OF website 3 geen domein | Controleer `w3.domain` en `w3.get_base_url()` |
| Odoo toont corp-logo op academy-domein | Website-cache niet geleegd | `docker restart atlas-odoo` |
| `/slides` geeft 502 | Odoo container down | `docker start atlas-odoo && docker logs atlas-odoo` |