Merge branch 'feature/pos_notice' into 18.0

This commit is contained in:
Matthias Lotz 2026-06-06 14:53:48 +02:00
commit 5fb425fb85
7 changed files with 188 additions and 5 deletions

View File

@ -0,0 +1,141 @@
# Feature Request: POS Partner Interne Notizen
## Ziel:
In der POS-Oberfläche des Moduls open_workshop_pos soll für die akuelle eingebuchten Kunden angezeigt werden, ob in res.partner interne Notizen vorhanden sind. Diese Notizen sollen durch anklicken eines Symbols im Kassiererbereich sichtbar und per Klick abrufbar sein.
## Anforderung:
1. Prüfe beim aktuell ausgewählten Partner, ob das Feld Interne Notizen in res.partner einen Inhalt hat.
2. Wenn das Feld nicht leer ist, zeige rechts neben dem Partnernamen ein Symbol an.
3. Klickt der Benutzer auf das Symbol, soll der Inhalt der internen Notiz in einem Popup angezeigt werden.
4. Wenn keine interne Notiz vorhanden ist, soll kein Symbol angezeigt werden.
##Technische Vorgabe:
Die Anzeige und das Verhalten sollen in extra-addons/open_workshop/open_workshop_pos/static/src/js/ows_pos_customer_sidebar.js umgesetzt werden.
## Akzeptanzkriterien:
- Partner mit interner Notiz zeigen ein Symbol neben dem Namen.
- Partner ohne Notiz zeigen kein Symbol.
- Ein Klick auf das Symbol öffnet ein Popup mit dem Notiztext.
- Die bestehende POS-Oberfläche soll dabei nicht gestört werden.
---
## Implementierungsplan
### Analyse-Ergebnis
Das Feld `comment` (Interne Notizen aus `res.partner`) wird von Odoo POS standardmäßig **nicht** an den Browser übertragen. Die Methode `_load_pos_data_fields` in `point_of_sale/models/res_partner.py` listet explizit die zu ladenden Felder auf `comment` fehlt dort.
Das bedeutet: Es sind Änderungen auf **zwei Ebenen** nötig Backend (Python) und Frontend (JS + XML).
---
### Schritt 1 Backend: `comment`-Feld in POS-Datenübertragung aufnehmen
**Datei:** `open_workshop_pos/models/res_partner.py` *(neu anlegen)*
Das Modul muss `res.partner` erweitern und `_load_pos_data_fields` überschreiben, um das Feld `comment` in die Liste der an den POS-Client gesendeten Felder aufzunehmen.
> **Warum nicht `pos_access.py` aus `open_workshop_base`?**
> Der Controller `pos_access.py` liefert Daten **on-demand per RPC-Aufruf** (async, pro Partnerwechsel). Das ist sinnvoll für volatile Daten wie Maschinenfreigaben. Das Feld `comment` ist dagegen ein statisches Partnerfeld es reicht aus, es einmalig beim POS-Start zu laden. Der `_load_pos_data_fields`-Ansatz erfordert keinen extra Netzwerk-Request, keinen `useState` und keinen async-Code in der Sidebar-Komponente.
```python
# -*- coding: utf-8 -*-
from odoo import models
class ResPartner(models.Model):
_inherit = 'res.partner'
def _load_pos_data_fields(self, config_id):
fields = super()._load_pos_data_fields(config_id)
if 'comment' not in fields:
fields.append('comment')
return fields
```
**Datei:** `open_workshop_pos/models/__init__.py`
Den neuen Import hinzufügen:
```python
from . import res_partner
```
---
### Schritt 2 Frontend JS: Logik und Popup in `ows_pos_customer_sidebar.js`
**Datei:** `open_workshop_pos/static/src/js/ows_pos_customer_sidebar.js`
Zwei neue Methoden in der Klasse `OwsPosCustomerSidebar` hinzufügen:
1. `getPartnerComment(order)` gibt den Wert des `comment`-Feldes des aktuellen Partners zurück oder `null`.
2. `showPartnerComment(order)` öffnet einen Dialog mit dem Notizinhalt. Dafür kann der bereits vorhandene `this.dialog`-Service genutzt werden.
```js
getPartnerComment(order) {
return order.get_partner()?.comment || null;
}
showPartnerComment(order) {
const comment = this.getPartnerComment(order);
if (!comment) return;
this.dialog.add(/* AlertDialog oder ConfirmationDialog aus @web/core */, {
title: _t("Interne Notizen"),
body: comment,
});
}
```
> Hinweis: Als Dialog-Komponente eignet sich `AlertDialog` aus `@web/core/confirmation_dialog/confirmation_dialog`, da dieser nur einen „OK"-Button benötigt.
---
### Schritt 3 Frontend XML: Symbol in Template einbauen
**Datei:** `open_workshop_pos/static/src/xml/ows_pos_customer_sidebar.xml`
Im bestehenden Template `open_workshop_pos.OwsPosCustomerSidebar` innerhalb der `.sidebar-line` ein Symbol (z. B. `` oder ein Bootstrap-Icon) **konditional** anzeigen:
```xml
<span t-if="getPartnerComment(order)"
class="partner-note-icon ms-1"
title="Interne Notiz vorhanden"
t-on-click.stop="() => this.showPartnerComment(order)">
<!-- Bootstrap Icon: bi-chat-square-text oder einfaches Unicode-Symbol -->
📋
</span>
```
Das `t-on-click.stop` verhindert, dass gleichzeitig der Click-Handler der übergeordneten `.order-entry` ausgelöst wird.
---
### Schritt 4 (Optional) CSS: Icon-Darstellung anpassen
**Datei:** `open_workshop_pos/static/src/css/` *(vorhandene CSS-Datei oder neue)*
```css
.partner-note-icon {
cursor: pointer;
font-size: 0.85em;
opacity: 0.7;
}
.partner-note-icon:hover {
opacity: 1;
}
```
---
### Zusammenfassung der betroffenen Dateien
| Datei | Aktion |
|---|---|
| `models/res_partner.py` | Neu anlegen `comment`-Feld in POS-Daten aufnehmen |
| `models/__init__.py` | `res_partner`-Import hinzufügen |
| `static/src/js/ows_pos_customer_sidebar.js` | Methoden `getPartnerComment` und `showPartnerComment` ergänzen |
| `static/src/xml/ows_pos_customer_sidebar.xml` | Symbol-Icon konditional in `.sidebar-line` einfügen |
| `static/src/css/` | (optional) Styling für Icon |

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
{
'name': 'Open Workshop POS',
'version': '18.0.1.0.2',
'version': '18.0.1.0.3',
'category': 'Point of Sale',
'summary': 'POS Integration für Open Workshop - Machine Access & Customer UI',
'description': """

View File

@ -1,2 +1,3 @@
# -*- coding: utf-8 -*-
from . import pos_order
from . import res_partner

View File

@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
from odoo import models
class ResPartner(models.Model):
_inherit = 'res.partner'
def _load_pos_data_fields(self, config_id):
fields = super()._load_pos_data_fields(config_id)
if 'comment' not in fields:
fields.append('comment')
return fields

View File

@ -7,7 +7,7 @@
.ows-sidebar {
flex: 1 1 auto;
width: 220px;
width: 300px;
display: flex;
flex-direction: column;
overflow: hidden;
@ -50,12 +50,24 @@
}
.sidebar-name {
flex-shrink: 1;
flex: 1;
text-align: right;
overflow: hidden;
text-overflow: ellipsis;
}
.partner-note-icon {
flex-shrink: 0;
width: 1.4em;
text-align: center;
cursor: pointer;
font-size: 0.85em;
opacity: 0.7;
}
.partner-note-icon:hover {
opacity: 1;
}
.bg-200, .text-bg-200 {
--background-color: rgb(122, 122, 122);

View File

@ -1,10 +1,10 @@
// @odoo-module ows_pos_customer_sidebar.js
import { Component } from "@odoo/owl";
import { Component, markup } from "@odoo/owl";
import { useService } from "@web/core/utils/hooks";
import { usePos } from "@point_of_sale/app/store/pos_hook";
import { _t } from "@web/core/l10n/translation";
import { ask } from "@web/core/confirmation_dialog/confirmation_dialog";
import { ask, AlertDialog } from "@web/core/confirmation_dialog/confirmation_dialog";
export class OwsPosCustomerSidebar extends Component {
static template = "open_workshop_pos.OwsPosCustomerSidebar";
@ -61,4 +61,17 @@ export class OwsPosCustomerSidebar extends Component {
this.pos.set_order(order);
this.env.bus.trigger('partner-changed');
}
getPartnerComment(order) {
return order.get_partner()?.comment || null;
}
showPartnerComment(order) {
const comment = this.getPartnerComment(order);
if (!comment) return;
this.dialog.add(AlertDialog, {
title: _t("Interne Notizen"),
body: markup(comment),
});
}
}

View File

@ -18,6 +18,10 @@
<div class="sidebar-line">
<span class="sidebar-date"><t t-esc="getDate(order)"/></span>
<span class="sidebar-name" t-att-title="getPartner(order)"><t t-esc="getPartner(order)"/></span>
<span class="partner-note-icon"
t-att-style="getPartnerComment(order) ? '' : 'visibility: hidden'"
title="Interne Notiz vorhanden"
t-on-click.stop="() => this.showPartnerComment(order)">&#128203;</span>
</div>
</div>
</t>