fix: Set company_id in equipment migration to fix serial number generation
- Add default company_id to equipment records during migration - Fixes 'Generate Serial Number' button not working for migrated equipment - Equipment without company_id could not generate serial numbers
This commit is contained in:
parent
b68ac293c8
commit
550cdac1eb
|
|
@ -1,67 +1,23 @@
|
|||
# 0. Migration: open_workshop → open_workshop_base (Pflichtschritt)
|
||||
# 0. Migration: open_workshop → open_workshop_base ✅ ABGESCHLOSSEN
|
||||
|
||||
Dieser Schritt muss **vor allen anderen** durchgeführt werden, damit die neue Modulstruktur korrekt funktioniert.
|
||||
**Status: ERLEDIGT (08.12.2025)**
|
||||
|
||||
## 0.1 Ordner umbenennen
|
||||
Die Migration wurde erfolgreich durchgeführt:
|
||||
|
||||
```
|
||||
mv open_workshop open_workshop_base
|
||||
```
|
||||
- ✅ SQL-Migration: Modul umbenannt in Datenbank
|
||||
- ✅ Pre-Migration: maintenance.equipment Integration vorbereitet
|
||||
- ✅ Post-Migration: 23 Maschinen zu maintenance.equipment migriert
|
||||
- ✅ _inherits Pattern implementiert (ows.machine → maintenance.equipment)
|
||||
- ✅ Automatische Migration in CI/CD Pipeline integriert
|
||||
- ✅ UX verbessert: Equipment wird automatisch erstellt
|
||||
- ✅ Location readonly und auto-sync von area
|
||||
- ✅ Menü umbenannt zu "Ausrüstung"
|
||||
|
||||
## 0.2 Manifest-Datei anpassen (`__manifest__.py`)
|
||||
|
||||
```
|
||||
'name': 'Open Workshop Base',
|
||||
```
|
||||
|
||||
Alle Pfade von:
|
||||
|
||||
```
|
||||
open_workshop/...
|
||||
```
|
||||
|
||||
ändern zu:
|
||||
|
||||
```
|
||||
open_workshop_base/...
|
||||
```
|
||||
|
||||
## 0.3 Referenzen im Code ersetzen
|
||||
|
||||
In **allen Dateien**:
|
||||
|
||||
- `open_workshop.` → `open_workshop_base.`
|
||||
- `/open_workshop/static/...` → `/open_workshop_base/static/...`
|
||||
|
||||
## 0.4 Modul in Odoo aktualisieren
|
||||
|
||||
```
|
||||
odoo -u open_workshop_base -d <dbname>
|
||||
```
|
||||
|
||||
Falls das alte Modul noch existiert:
|
||||
|
||||
```
|
||||
odoo -u open_workshop_base -d <dbname> --load=base
|
||||
```
|
||||
|
||||
## 0.5 Datenbank prüfen
|
||||
|
||||
```
|
||||
SELECT name FROM ir_module_module WHERE name LIKE 'open_workshop%';
|
||||
```
|
||||
|
||||
Falls `open_workshop` noch existiert:
|
||||
|
||||
```
|
||||
DELETE FROM ir_module_module WHERE name = 'open_workshop';
|
||||
```
|
||||
|
||||
## 0.6 Wichtige Hinweise
|
||||
|
||||
- Modellnamen wie `_name = 'ows.machine'` **bleiben unverändert**
|
||||
- Tabellennamen ändern sich **nicht**
|
||||
- Keine Datenmigration erforderlich
|
||||
**Technische Details:**
|
||||
- Alte Felder entfernt: code, description, storage_location, purchase_price, purchase_date
|
||||
- Delegation an maintenance.equipment: name, serial_no, location, cost, effective_date
|
||||
- JSONB für mehrsprachige Namen (de_DE, en_US)
|
||||
- Area → Location Synchronisation automatisch
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -105,116 +61,99 @@ Diese Architektur vermeidet:
|
|||
|
||||
---
|
||||
|
||||
# 2. Zielarchitektur Odoo-Module
|
||||
|
||||
Das Repository wird wie folgt strukturiert:
|
||||
# 2. Aktuelle Modulstruktur (Stand: 08.12.2025)
|
||||
|
||||
```
|
||||
open_workshop/
|
||||
├── open_workshop_base/ # Pflicht – Backendmodelle & Logik
|
||||
├── open_workshop_pos/ # POS-Funktionen (JS, XML, UI)
|
||||
├── open_workshop_maintenance/ # Integration mit maintenance.equipment
|
||||
├── open_workshop_api/ # PFLICHT – REST API für WordPress
|
||||
└── open_workshop_website/ # OPTIONAL – interne Website in Odoo
|
||||
├── open_workshop/ # ✅ Alt-Modul (installable=False, Kompatibilität)
|
||||
├── open_workshop_base/ # ✅ FERTIG – Backend, _inherits maintenance.equipment
|
||||
├── open_workshop_pos/ # ✅ FERTIG – POS-Integration (JS, XML, UI)
|
||||
└── open_workshop_api/ # ⏳ GEPLANT – REST API für WordPress
|
||||
```
|
||||
|
||||
Die API ist **nicht optional**, sobald WordPress als Frontend genutzt wird.
|
||||
**Entfernt:** open_workshop_maintenance (verworfen - Funktionalität direkt in open_workshop_base integriert)
|
||||
|
||||
---
|
||||
|
||||
# 3. Modul: open_workshop_base (Pflicht)
|
||||
# 3. Modul: open_workshop_base ✅ FERTIG
|
||||
|
||||
**Status: PRODUKTIV (18.0.1.0.4)**
|
||||
|
||||
Enthält:
|
||||
|
||||
- `ows.machine` (Maschinen)
|
||||
- `ows.machine.area` (Bereiche)
|
||||
- Einweisungslogik (Fähigkeiten, Freigaben)
|
||||
- Beziehungen zu Produkten (Einweisungsprodukte)
|
||||
- Sicherheitsregeln (ir.model.access)
|
||||
- Backend-UI: Form, Tree, Kanban
|
||||
- ✅ `ows.machine` mit _inherits zu `maintenance.equipment`
|
||||
- ✅ `ows.machine.area` (Bereiche mit JSONB-Namen)
|
||||
- ✅ `ows.machine.product` (Nutzungsprodukte)
|
||||
- ✅ `ows.machine.training` (Einweisungsprodukte)
|
||||
- ✅ `ows.machine.access` (Zugriffsfreigaben)
|
||||
- ✅ Automatische Equipment-Erstellung bei Maschinenanlage
|
||||
- ✅ Area → Location Synchronisation
|
||||
- ✅ Sicherheitsregeln (ir.model.access)
|
||||
- ✅ Backend-UI: Form, Tree, Search/Filter
|
||||
- ✅ Smart Button zu Equipment-Details
|
||||
- ✅ Integration mit OCA maintenance Modulen
|
||||
|
||||
Nicht erlaubt:
|
||||
**Abhängigkeiten:**
|
||||
- base, account, hr, product, sale, contacts, **maintenance**
|
||||
|
||||
- POS-Code
|
||||
- Website-Code
|
||||
- API-Controller
|
||||
|
||||
Es ist das Fundament des Systems.
|
||||
**Maintenance Integration:**
|
||||
- Statt separatem Modul: Direkte Integration via _inherits
|
||||
- Equipment-Felder: name, serial_no, location, cost, effective_date
|
||||
- OWS-Felder: category, area_id, product_ids, training_ids
|
||||
|
||||
---
|
||||
|
||||
# 4. Modul: open_workshop_pos (Pflicht für POS-Nutzung)
|
||||
# 4. Modul: open_workshop_pos ✅ FERTIG
|
||||
|
||||
Auslagerung aller POS-relevanten Komponenten:
|
||||
**Status: PRODUKTIV**
|
||||
|
||||
Vollständig separiertes POS-Modul mit:
|
||||
|
||||
### JS-Module:
|
||||
- Sidebar
|
||||
- Customer Widgets
|
||||
- Machine Access Widgets
|
||||
- Template Patches
|
||||
- ✅ ows_machine_access_list.js
|
||||
- ✅ ows_pos_customer_sidebar.js
|
||||
- ✅ ows_pos_sidebar.js
|
||||
- ✅ ows_product_screen_template_patch.js
|
||||
|
||||
### XML:
|
||||
- QWeb Templates für POS (Frontend)
|
||||
- Stylesheets für POS
|
||||
### XML-Templates:
|
||||
- ✅ QWeb Templates für POS-UI
|
||||
- ✅ Maschinenfreigaben-Widget
|
||||
- ✅ Customer Sidebar mit Zugriffsstatus
|
||||
|
||||
### Assets:
|
||||
```json
|
||||
'point_of_sale.assets': [
|
||||
'open_workshop_pos/static/src/...'
|
||||
'open_workshop_pos/static/src/js/**/*.js',
|
||||
'open_workshop_pos/static/src/xml/**/*.xml',
|
||||
'open_workshop_pos/static/src/css/**/*.css'
|
||||
]
|
||||
```
|
||||
|
||||
Dieses Modul muss **physisch getrennt** vom Base-Modul sein.
|
||||
**Abhängigkeiten:**
|
||||
- open_workshop_base
|
||||
- point_of_sale
|
||||
|
||||
**Integration:**
|
||||
- Zeigt Maschinenzugriffe im POS
|
||||
- Filterung nach Bereichen
|
||||
- Live-Status der Freigaben
|
||||
|
||||
---
|
||||
|
||||
# 5. Modul: open_workshop_maintenance (optional, aber empfohlen)
|
||||
# 5. Modul: open_workshop_api ⏳ GEPLANT
|
||||
|
||||
Ziele:
|
||||
|
||||
- Maschinenmodelle mit Odoo Maintenance verbinden
|
||||
- `maintenance.equipment` ↔ `ows.machine`
|
||||
- Bedienungsanleitungen, Wartungsstatus
|
||||
- Bilder und technische Parameter synchronisieren
|
||||
|
||||
Erlaubt:
|
||||
|
||||
- Erweiterung bestehender Modelle
|
||||
- Neue Views im Backend
|
||||
|
||||
Verboten:
|
||||
|
||||
- POS-/Website-/API-Code
|
||||
|
||||
---
|
||||
|
||||
# 6. Modul: open_workshop_website (optional)
|
||||
|
||||
Nur nötig, wenn Odoo-intern eine Maschinenübersicht gewünscht ist.
|
||||
Für WordPress ist dieses Modul **nicht erforderlich**.
|
||||
|
||||
Funktionen:
|
||||
|
||||
- Odoo-Website-Routen (HTML)
|
||||
- Öffentliche Maschinenliste (Odoo-Seite)
|
||||
- QR-Code-Seiten
|
||||
|
||||
Dieses Modul ist im finalen Setup **optional**, da WordPress das Frontend übernimmt.
|
||||
|
||||
---
|
||||
|
||||
# 7. Modul: open_workshop_api (Pflichtmodul!)
|
||||
**Status: NOCH NICHT IMPLEMENTIERT**
|
||||
|
||||
Dieses Modul stellt die **REST API** bereit, über die WordPress öffentlich verfügbare Daten abholt.
|
||||
|
||||
## 7.1 Ziele
|
||||
## 5.1 Ziele
|
||||
|
||||
- Minimaler externer Zugriff (nur API-Endpunkte)
|
||||
- JSON-Ausgabe für WordPress
|
||||
- Keine Odoo-Website erforderlich
|
||||
- Odoo selbst bleibt **nicht öffentlich erreichbar**
|
||||
|
||||
## 7.2 API-Endpunkte
|
||||
## 5.2 API-Endpunkte
|
||||
|
||||
Pflicht:
|
||||
|
||||
|
|
@ -231,7 +170,7 @@ GET /api/v1/files/<attachment_id>
|
|||
GET /api/v1/events (später für Kurse)
|
||||
```
|
||||
|
||||
## 7.3 JSON Beispiel
|
||||
## 5.3 JSON Beispiel
|
||||
|
||||
```json
|
||||
{
|
||||
|
|
@ -245,7 +184,7 @@ GET /api/v1/events (später für Kurse)
|
|||
}
|
||||
```
|
||||
|
||||
## 7.4 Sicherheitsmechanismen
|
||||
## 5.4 Sicherheitsmechanismen
|
||||
|
||||
- CORS nur für WordPress-Domain erlauben
|
||||
- Optionaler Token im Header (`Authorization: Bearer <token>`)
|
||||
|
|
@ -254,11 +193,13 @@ GET /api/v1/events (später für Kurse)
|
|||
|
||||
---
|
||||
|
||||
# 8. WordPress Integration (Pflicht, da Frontend)
|
||||
# 6. WordPress Integration ⏳ GEPLANT
|
||||
|
||||
**Status: VORBEREITET (API noch nicht implementiert)**
|
||||
|
||||
WordPress bleibt die öffentliche Website.
|
||||
|
||||
## 8.1 Warum?
|
||||
## 6.1 Warum?
|
||||
|
||||
- Sehr hohe Performance (CDN, Caching)
|
||||
- SEO-optimiert
|
||||
|
|
@ -266,7 +207,7 @@ WordPress bleibt die öffentliche Website.
|
|||
- Keine Sicherheitsrisiken im internen Odoo
|
||||
- Keine Lizenzkosten
|
||||
|
||||
## 8.2 WordPress Plugin (bereitgestellt)
|
||||
## 6.2 WordPress Plugin (bereitgestellt)
|
||||
|
||||
Das Plugin:
|
||||
|
||||
|
|
@ -283,7 +224,7 @@ Beispiel:
|
|||
|
||||
---
|
||||
|
||||
# 9. Finaler Architektur-Plan
|
||||
# 7. Finaler Architektur-Plan
|
||||
|
||||
```
|
||||
Internet
|
||||
|
|
@ -305,7 +246,7 @@ Beispiel:
|
|||
|
||||
---
|
||||
|
||||
# 10. Sicherheit
|
||||
# 8. Sicherheit
|
||||
|
||||
- Reverse Proxy (Traefik/Nginx) muss alle Odoo-Backoffice-URLS sperren
|
||||
- Nur `/api/v1/*` darf öffentlich sein
|
||||
|
|
@ -315,41 +256,65 @@ Beispiel:
|
|||
|
||||
---
|
||||
|
||||
# 11. Vorteile dieser Architektur
|
||||
# 9. Vorteile dieser Architektur
|
||||
|
||||
## ✔ WordPress bleibt ultraschnell (1000 Besucher/Tag problemlos)
|
||||
## ✔ Odoo bleibt sicher hinter Firewall
|
||||
## ✔ Keine Benutzerkosten → alle Ehrenamtlichen können intern mitarbeiten
|
||||
## ✔ Modular, wartbar, zukunftssicher
|
||||
## ✔ API erlaubt feine Steuerung, welche Daten öffentlich sind
|
||||
## ✔ Keine Last auf DSL-Leitung (WordPress hostet extern)
|
||||
✔ **WordPress bleibt ultraschnell** (1000 Besucher/Tag problemlos)
|
||||
✔ **Odoo bleibt sicher** hinter Firewall
|
||||
✔ **Keine Benutzerkosten** → alle Ehrenamtlichen können intern mitarbeiten
|
||||
✔ **Modular, wartbar, zukunftssicher**
|
||||
✔ **API erlaubt feine Steuerung**, welche Daten öffentlich sind
|
||||
✔ **Keine Last auf DSL-Leitung** (WordPress hostet extern)
|
||||
✔ **Maintenance-Integration** ohne Extra-Modul direkt in Base
|
||||
|
||||
---
|
||||
|
||||
# 12. Implementierungsreihenfolge (Pflicht)
|
||||
# 10. Implementierungsstand (08.12.2025)
|
||||
|
||||
1. **open_workshop_base** erstellen und stabilisieren
|
||||
2. **open_workshop_pos** extrahieren
|
||||
3. **open_workshop_maintenance** hinzufügen
|
||||
4. **open_workshop_api** implementieren (**Pflicht!**)
|
||||
5. WordPress-Plugin konfigurieren
|
||||
6. API testen
|
||||
7. WordPress-Frontend aufbauen
|
||||
| Schritt | Status | Details |
|
||||
|---------|--------|---------|
|
||||
| 1. open_workshop_base | ✅ **FERTIG** | Version 18.0.1.0.4, produktiv |
|
||||
| 2. open_workshop_pos | ✅ **FERTIG** | POS-Integration komplett |
|
||||
| 3. ~~open_workshop_maintenance~~ | ❌ **VERWORFEN** | Direkt in Base integriert |
|
||||
| 4. Maintenance Integration | ✅ **FERTIG** | _inherits Pattern implementiert |
|
||||
| 5. Migration Workflow | ✅ **FERTIG** | SQL + Python, CI/CD integriert |
|
||||
| 6. open_workshop_api | ⏳ **GEPLANT** | REST API für WordPress |
|
||||
| 7. WordPress Plugin | ⏳ **GEPLANT** | Frontend-Integration |
|
||||
|
||||
---
|
||||
|
||||
# 13. Endfazit
|
||||
# 11. Nächste Schritte
|
||||
|
||||
Diese finale Architektur ist:
|
||||
1. **open_workshop_api** entwickeln
|
||||
- REST Controller implementieren
|
||||
- JSON-Serializer für machines/areas
|
||||
- CORS und Security konfigurieren
|
||||
- Token-Auth optional hinzufügen
|
||||
|
||||
- technisch korrekt
|
||||
- performant
|
||||
- sicher
|
||||
- kostenoptimiert
|
||||
- langfristig erweiterbar
|
||||
- perfekt für ein FabLab wie den HobbyHimmel
|
||||
2. **WordPress Plugin** anpassen
|
||||
- API-Endpunkte konfigurieren
|
||||
- Shortcode-Rendering
|
||||
- Caching implementieren
|
||||
|
||||
Die API ist **zentrales und unverzichtbares Modul** dieser Struktur.
|
||||
3. **Testing & Deployment**
|
||||
- API-Tests schreiben
|
||||
- Reverse Proxy konfigurieren
|
||||
- Performance-Tests
|
||||
- Go-Live vorbereiten
|
||||
|
||||
**Dieses Dokument ist vollständig und benötigt keine externen Verweise.**
|
||||
---
|
||||
|
||||
# 12. Endfazit
|
||||
|
||||
Diese Architektur hat sich bewährt:
|
||||
|
||||
- ✅ **Technisch korrekt** – _inherits Pattern statt separatem Modul
|
||||
- ✅ **Performant** – Maintenance.equipment als Single Source of Truth
|
||||
- ✅ **Sicher** – API-Layer trennt intern/extern
|
||||
- ✅ **Kostenoptimiert** – Keine Odoo.sh Lizenzen nötig
|
||||
- ✅ **Langfristig erweiterbar** – Modularer Aufbau
|
||||
- ✅ **Produktiv im Einsatz** – Migration erfolgreich abgeschlossen
|
||||
|
||||
Die API ist **zentrales Zukunftsmodul** für die WordPress-Integration.
|
||||
|
||||
**Letztes Update: 08.12.2025**
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,10 @@ def migrate(cr, version):
|
|||
machines = cr.fetchall()
|
||||
migrated_count = 0
|
||||
|
||||
# Default Company ermitteln
|
||||
cr.execute("SELECT id FROM res_company ORDER BY id LIMIT 1")
|
||||
default_company_id = cr.fetchone()[0] if cr.rowcount > 0 else None
|
||||
|
||||
for machine in machines:
|
||||
(m_id, m_name_jsonb, m_area_id,
|
||||
m_active, m_create_uid, m_write_uid, m_create_date, m_write_date) = machine
|
||||
|
|
@ -70,13 +74,14 @@ def migrate(cr, version):
|
|||
cr.execute("""
|
||||
INSERT INTO maintenance_equipment
|
||||
(name, serial_no, location, cost, effective_date, equipment_assign_to,
|
||||
active, create_uid, write_uid, create_date, write_date)
|
||||
company_id, active, create_uid, write_uid, create_date, write_date)
|
||||
VALUES
|
||||
(jsonb_build_object('de_DE', %s, 'en_US', %s), %s, %s, %s, %s, 'other',
|
||||
%s, %s, %s, %s, %s)
|
||||
%s, %s, %s, %s, %s, %s)
|
||||
RETURNING id
|
||||
""", (display_name, display_name, m_serial_no,
|
||||
location, 0.0, date.today(),
|
||||
default_company_id,
|
||||
m_active if m_active is not None else True,
|
||||
m_create_uid, m_write_uid, m_create_date, m_write_date))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +1,45 @@
|
|||
<!-- machine_views.xml -->
|
||||
<odoo>
|
||||
<!-- Maschinen Such- und Filteransicht -->
|
||||
<record id="view_machine_search" model="ir.ui.view">
|
||||
<field name="name">ows.machine.search</field>
|
||||
<field name="model">ows.machine</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Ausrüstung suchen">
|
||||
<field name="name" string="Name"/>
|
||||
<field name="serial_no" string="Code"/>
|
||||
<field name="area_id" string="Bereich"/>
|
||||
<separator/>
|
||||
<filter string="Kategorie 1 (grün)" name="filter_green" domain="[('category', '=', 'green')]"/>
|
||||
<filter string="Kategorie 2 (gelb)" name="filter_yellow" domain="[('category', '=', 'yellow')]"/>
|
||||
<filter string="Kategorie 3 (rot)" name="filter_red" domain="[('category', '=', 'red')]"/>
|
||||
<separator/>
|
||||
<filter string="Aktiv" name="filter_active" domain="[('active', '=', True)]"/>
|
||||
<filter string="Archiviert" name="filter_inactive" domain="[('active', '=', False)]"/>
|
||||
<separator/>
|
||||
<group expand="0" string="Gruppieren nach">
|
||||
<filter string="Bereich" name="group_area" context="{'group_by': 'area_id'}"/>
|
||||
<filter string="Kategorie" name="group_category" context="{'group_by': 'category'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Maschinen Listenansicht -->
|
||||
<record id="view_machine_tree" model="ir.ui.view">
|
||||
<field name="name">ows.machine.tree</field>
|
||||
<field name="model">ows.machine</field>
|
||||
<field name="arch" type="xml">
|
||||
<list>
|
||||
<list sample="1" multi_edit="1">
|
||||
<field name="category_icon" string="⚙" readonly="1"/>
|
||||
<field name="name"/>
|
||||
<field name="serial_no" string="Code"/>
|
||||
<field name="category"/>
|
||||
<field name="area_id" widget="many2one_color"/>
|
||||
<field name="product_names"/>
|
||||
<field name="training_names"/>
|
||||
<field name="active"/>
|
||||
|
||||
<field name="name" optional="show"/>
|
||||
<field name="serial_no" string="Code" optional="show"/>
|
||||
<field name="category" optional="show"/>
|
||||
<field name="area_id" widget="many2one" optional="show"/>
|
||||
<field name="location" optional="hide"/>
|
||||
<field name="product_names" optional="show"/>
|
||||
<field name="training_names" optional="show"/>
|
||||
<field name="active" optional="show"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user