17.0_dev-target #1
|
|
@ -23,6 +23,8 @@
|
|||
'open_workshop/static/src/css/pos.css',
|
||||
'open_workshop/static/src/js/ows_pos_customer_sidebar.js',
|
||||
'open_workshop/static/src/xml/ows_pos_customer_sidebar.xml',
|
||||
'open_workshop/static/src/js/ows_machine_access_list.js',
|
||||
'open_workshop/static/src/xml/ows_machine_access_list.xml',
|
||||
'open_workshop/static/src/xml/ows_product_screen.xml',
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -424,10 +424,10 @@ class OwsMachine(models.Model):
|
|||
|
||||
@api.model
|
||||
def get_access_list_grouped(self, partner_id):
|
||||
partner = self.env['res.partner'].browse(partner_id)
|
||||
areas = self.env['ows.machine.area'].search([], order="name")
|
||||
_logger.info("🔍 Maschinenbereiche: %s", areas.mapped('name'))
|
||||
_logger.info("🔍 Partner_id: %s", partner_id)
|
||||
res = []
|
||||
|
||||
access_by_area = []
|
||||
for area in areas:
|
||||
machines = self.search([('area_id', '=', area.id)], order="name")
|
||||
machine_list = []
|
||||
|
|
@ -440,12 +440,22 @@ class OwsMachine(models.Model):
|
|||
'name': machine.name,
|
||||
'has_access': has_access,
|
||||
})
|
||||
res.append({
|
||||
'area': area.name,
|
||||
'color_hex': area.color_hex or '#000000',
|
||||
'machines': machine_list
|
||||
})
|
||||
return res
|
||||
if machine_list:
|
||||
access_by_area.append({
|
||||
'area': area.name,
|
||||
'color_hex': area.color_hex or '#000000',
|
||||
'machines': machine_list
|
||||
})
|
||||
|
||||
user = partner.ows_user_id[:1]
|
||||
return {
|
||||
'access_by_area': access_by_area,
|
||||
'security_briefing': user.security_briefing if user else False,
|
||||
'security_id': user.security_id if user else '',
|
||||
'rfid_card': user.rfid_card if user else '',
|
||||
'birthday': user.birthday if user else '',
|
||||
}
|
||||
|
||||
|
||||
|
||||
class OwsMachineAccess(models.Model):
|
||||
|
|
|
|||
|
|
@ -1,3 +1,24 @@
|
|||
.ows-sidebar { width: 220px; }
|
||||
.order-entry:hover { cursor: pointer; }
|
||||
.order-entry.selected { background-color: #007bff; color: white; }
|
||||
|
||||
.sidebar-line {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 0.5em;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
padding: 0.2em 0;
|
||||
}
|
||||
|
||||
.sidebar-date {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sidebar-name {
|
||||
flex-shrink: 1;
|
||||
text-align: right;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,132 +0,0 @@
|
|||
/* This file is based on the original code from the OrderWidget in Odoo Point of Sale module (screen.js).
|
||||
* It has been modified to create a sidebar that displays machine access information for the selected customer.*/
|
||||
|
||||
odoo.define('open_workshop.machine_access_sidebar', function (require) {
|
||||
"use strict";
|
||||
|
||||
const DUMMY_PARTNER = {
|
||||
id: 1,
|
||||
name: "AAAA Max Mustermann",
|
||||
security_briefing: false,
|
||||
security_id: null,
|
||||
create_date: null,
|
||||
};
|
||||
|
||||
var rpc = require('web.rpc');
|
||||
var screens = require('point_of_sale.screens');
|
||||
var chrome = require('point_of_sale.chrome');
|
||||
var core = require('web.core');
|
||||
var QWeb = core.qweb;
|
||||
|
||||
|
||||
|
||||
var MachineAccessSidebar = screens.ScreenWidget.extend({
|
||||
template: 'MachineAccessSidebar',
|
||||
|
||||
init: function(parent, options) {
|
||||
this._super(parent, options);
|
||||
this.partner = null;
|
||||
this.pos.bind('change:selectedOrder', this.bind_order_events, this);
|
||||
},
|
||||
|
||||
show: function() {
|
||||
this._super();
|
||||
this.render_access();
|
||||
},
|
||||
|
||||
update_machine_access: function(partner) {
|
||||
console.log("🔁 Sidebar aktualisiert Maschinenfreigaben für Partner:", partner);
|
||||
this.partner = partner;
|
||||
this.render_access();
|
||||
},
|
||||
|
||||
render_access: function() {
|
||||
var self = this;
|
||||
var partner = this.partner || DUMMY_PARTNER;
|
||||
|
||||
|
||||
|
||||
rpc.query({
|
||||
model: 'ows.machine',
|
||||
method: 'get_access_list_grouped',
|
||||
args: [partner.id],
|
||||
}).then(function (result) {
|
||||
partner.create_date = partner.create_date && partner.create_date.substring(0, 10);
|
||||
var html = QWeb.render('PartnerMachineAccessList', {
|
||||
areas: result || [],
|
||||
partner: partner,
|
||||
});
|
||||
self.$('.access-content').html(html);
|
||||
});
|
||||
},
|
||||
|
||||
bind_order_events: function () {
|
||||
var order = this.pos.get_order();
|
||||
if (!order) return;
|
||||
|
||||
/*order.unbind('change:client', this);
|
||||
order.bind('change:client', this, function () {
|
||||
this.update_machine_access(order.get_client());
|
||||
});*/
|
||||
|
||||
this.update_machine_access(order.get_client());
|
||||
}
|
||||
});
|
||||
|
||||
// Sidebar aktualisieren bei Klick im ClientListScreenWidget (Vorschau)
|
||||
screens.ClientListScreenWidget.include({
|
||||
show: function () {
|
||||
this._super();
|
||||
$('.order-selector').hide(); // ← wird hier versteckt
|
||||
},
|
||||
hide: function () {
|
||||
this._super();
|
||||
$('.order-selector').show(); // ← beim Verlassen wieder zeigen
|
||||
},
|
||||
display_client_details: function (visibility, partner, clickpos) {
|
||||
this._super(visibility, partner, clickpos);
|
||||
|
||||
try {
|
||||
if (partner && typeof partner === 'object' && 'id' in partner) {
|
||||
var sidebar = this.pos.chrome.sidebar_widget;
|
||||
if (sidebar) {
|
||||
console.log("👤 ClientListScreen: Vorschau für", partner.name);
|
||||
sidebar.update_machine_access(partner);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn("⚠️ Fehler beim Update der Sidebar nach Kundenauswahl:", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
chrome.Chrome.include({
|
||||
build_widgets: function () {
|
||||
this._super();
|
||||
|
||||
var sidebar = new MachineAccessSidebar(this, {});
|
||||
this.sidebar_widget = sidebar;
|
||||
sidebar.appendTo(this.$el);
|
||||
|
||||
//this.pos.bind('change:selectedOrder', sidebar.bind_order_events, sidebar);
|
||||
|
||||
if (this.pos.get_order()) {
|
||||
sidebar.bind_order_events();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
odoo.define('open_workshop.models', function (require) {
|
||||
"use strict";
|
||||
var models = require('point_of_sale.models');
|
||||
var field_utils = require('web.field_utils');
|
||||
models.load_fields('res.partner', 'create_date');
|
||||
models.load_fields('res.partner', 'birthday');
|
||||
models.load_fields('res.partner', 'security_briefing');
|
||||
models.load_fields('res.partner', 'security_id');
|
||||
models.load_fields('res.partner', 'rfid_card');
|
||||
|
||||
|
||||
});
|
||||
63
static/src/js/ows_machine_access_list.js
Normal file
63
static/src/js/ows_machine_access_list.js
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
// @odoo-module
|
||||
|
||||
import { Component, useState } from "@odoo/owl";
|
||||
import { useBus } from "@web/core/utils/hooks";
|
||||
import { usePos } from "@point_of_sale/app/store/pos_hook";
|
||||
import { jsonrpc } from "@web/core/network/rpc_service";
|
||||
|
||||
export class OwsMachineAccessList extends Component {
|
||||
static template = 'open_workshop.OwsMachineAccessList';
|
||||
|
||||
setup() {
|
||||
this.pos = usePos();
|
||||
|
||||
this.state = useState({
|
||||
grouped_accesses: [],
|
||||
security_briefing: false,
|
||||
security_id: '',
|
||||
rfid_card: '',
|
||||
birthday: '',
|
||||
});
|
||||
|
||||
// 🔁 Reagiere auf Partnerwechsel über den Odoo-Bus
|
||||
useBus(this.env.bus, 'partner-changed', () => {
|
||||
this.updateAccessList();
|
||||
});
|
||||
|
||||
// 🔃 Beim Mounten initiale Daten laden
|
||||
this.updateAccessList();
|
||||
}
|
||||
|
||||
async updateAccessList() {
|
||||
const order = this.pos.get_order();
|
||||
const partner = order?.get_partner?.();
|
||||
|
||||
if (!partner) {
|
||||
this.state.grouped_accesses = [];
|
||||
this.state.security_briefing = false;
|
||||
this.state.security_id = '';
|
||||
this.state.rfid_card = '';
|
||||
this.state.birthday = '';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const data = await jsonrpc("/open_workshop/partner_access", {
|
||||
partner_id: partner.id,
|
||||
});
|
||||
|
||||
this.state.grouped_accesses = data.access_by_area || [];
|
||||
this.state.security_briefing = data.security_briefing;
|
||||
this.state.security_id = data.security_id;
|
||||
this.state.rfid_card = data.rfid_card;
|
||||
this.state.birthday = data.birthday;
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Laden der Einweisungen:", error);
|
||||
this.state.grouped_accesses = [];
|
||||
this.state.security_briefing = false;
|
||||
this.state.security_id = '';
|
||||
this.state.rfid_card = '';
|
||||
this.state.birthday = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ 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 { ConfirmPopup } from "@point_of_sale/app/utils/confirm_popup/confirm_popup";
|
||||
import { deserializeDateTime, formatDateTime, parseDateTime } from "@web/core/l10n/dates";
|
||||
|
||||
export class OwsPosCustomerSidebar extends Component {
|
||||
static template = "open_workshop.OwsPosCustomerSidebar";
|
||||
|
|
@ -12,11 +13,13 @@ export class OwsPosCustomerSidebar extends Component {
|
|||
setup() {
|
||||
this.pos = usePos();
|
||||
this.popup = useService("popup");
|
||||
|
||||
}
|
||||
|
||||
addOrder() {
|
||||
this.pos.add_new_order(); // neue Order wird aktive Order
|
||||
this.pos.selectPartner();
|
||||
this.env.bus.trigger('partner-changed'); // ✅ korrektes Event feuern
|
||||
}
|
||||
|
||||
async removeCurrentOrder() {
|
||||
|
|
@ -45,6 +48,7 @@ export class OwsPosCustomerSidebar extends Component {
|
|||
}
|
||||
|
||||
// Hinweis: Weitere Funktionen wie Sync mit Server (siehe ticket_screen.js) können hier ergänzt werden.
|
||||
this.env.bus.trigger('partner-changed'); // ✅ korrektes Event feuern
|
||||
}
|
||||
|
||||
openTicketScreen() {
|
||||
|
|
@ -56,15 +60,21 @@ export class OwsPosCustomerSidebar extends Component {
|
|||
}
|
||||
|
||||
getDate(order) {
|
||||
const date = new Date(order.creationDate || order.creation_date || Date.now());
|
||||
return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
||||
const date = new Date(order.date_order);
|
||||
const dd = String(date.getDate()).padStart(2, '0');
|
||||
const mm = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const hh = String(date.getHours()).padStart(2, '0');
|
||||
const mi = String(date.getMinutes()).padStart(2, '0');
|
||||
return `${dd}.${mm}. ${hh}:${mi}`;
|
||||
}
|
||||
|
||||
|
||||
getPartner(order) {
|
||||
return order.get_partner()?.name || "Kein Kunde";
|
||||
}
|
||||
|
||||
selectOrder(order) {
|
||||
this.pos.set_order(order);
|
||||
this.env.bus.trigger('partner-changed'); // ✅ korrektes Event feuern
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,12 +3,14 @@
|
|||
import { ProductScreen } from "@point_of_sale/app/screens/product_screen/product_screen";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { OwsPosCustomerSidebar } from "@open_workshop/js/ows_pos_customer_sidebar";
|
||||
import { OwsMachineAccessList } from "@open_workshop/js/ows_machine_access_list";
|
||||
|
||||
export class OwsProductScreen extends ProductScreen {
|
||||
static template = "open_workshop.ProductScreen";
|
||||
static components = {
|
||||
...ProductScreen.components,
|
||||
OwsPosCustomerSidebar,
|
||||
OwsMachineAccessList,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
76
static/src/xml/ows_machine_access_list.xml
Normal file
76
static/src/xml/ows_machine_access_list.xml
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
<t t-name="open_workshop.OwsMachineAccessList">
|
||||
<div class="client-details-grid p-2 small">
|
||||
|
||||
<!-- ✅ Sicherheitsbereich -->
|
||||
<t t-if="state.client">
|
||||
<div class="client-details-header">
|
||||
<ul>
|
||||
<li><span class="client-details-label">Einweisungen</span></li>
|
||||
</ul>
|
||||
|
||||
<div class="client-details-area border" t-att-style="'border: solid 3px #ffffff; margin: 5px;'">
|
||||
<ul>
|
||||
<li class="client-detail">
|
||||
<span class="detail client-details-vvow_briefing">✅</span>
|
||||
<span class="briefinglabel">Werkstatt</span>
|
||||
</li>
|
||||
|
||||
<li class="client-detail">
|
||||
<t t-if="!state.security_briefing">
|
||||
<span class="detail client-details-vvow_briefing_error">❌</span>
|
||||
</t>
|
||||
<t t-if="state.security_briefing">
|
||||
<span class="detail client-details-vvow_briefing">✅</span>
|
||||
</t>
|
||||
<span class="briefinglabel">Haftungsausschluss</span>
|
||||
</li>
|
||||
|
||||
<t t-if="!state.security_briefing">
|
||||
<li class="client-detail">
|
||||
<ul class="subpoints">
|
||||
<span class="detail client-details-vvow_sec_briefing_error">‼️Bitte Prüfen‼️</span>
|
||||
</ul>
|
||||
</li>
|
||||
</t>
|
||||
|
||||
<t t-if="state.security_briefing">
|
||||
<ul class="subpoints">
|
||||
<li class="client-detail">
|
||||
<span class="label">Id:</span>
|
||||
<span class="detail client-details-vvow_security_id">
|
||||
<t t-esc="state.security_id || 'N/A'" />
|
||||
</span>
|
||||
</li>
|
||||
<li class="client-detail">
|
||||
<span class="label">Geburtstag:</span>
|
||||
<span class="detail client-details-vvow_security_id">
|
||||
<t t-esc="state.birthday || 'N/A'" />
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</t>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!-- ✅ Maschinenliste: immer sichtbar, gefiltert -->
|
||||
<t t-foreach="state.grouped_accesses" t-as="area" t-key="area.area">
|
||||
<t t-if="area.machines.length > 0">
|
||||
<div class="client-details-area" t-att-style="'border: solid 3px ' + area.color_hex + '; margin: 5px;'">
|
||||
<ul>
|
||||
<t t-foreach="area.machines" t-as="machine" t-key="machine.name">
|
||||
<li class="client-detail">
|
||||
<span t-attf-class="detail {{ machine.has_access ? 'client-details-vvow_briefing' : 'client-details-vvow_briefing_error' }}">
|
||||
<t t-esc="machine.has_access ? '✅' : '❌'" />
|
||||
</span>
|
||||
<span class="briefinglabel"><t t-esc="machine.name"/></span>
|
||||
</li>
|
||||
</t>
|
||||
</ul>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
</div>
|
||||
</t>
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
<t t-name="MachineAccessSidebar">
|
||||
<div class="machine-access-sidebar">
|
||||
<div class="access-content">
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="PartnerMachineAccessList">
|
||||
<div class="client-details-grid">
|
||||
<div class="client-details-header">
|
||||
<ul>
|
||||
<li><span class="client-details-label">Einweisungen</span></li>
|
||||
</ul>
|
||||
|
||||
<div class="client-details-area" t-att-style="'border: solid 3px #ffffff; margin: 5px;'">
|
||||
<ul>
|
||||
<li class="client-detail">
|
||||
<span class="detail client-details-vvow_briefing">✅</span>
|
||||
<span class="briefinglabel">Werkstatt</span>
|
||||
</li>
|
||||
|
||||
<li class="client-detail">
|
||||
<t t-if="!partner.security_briefing">
|
||||
<span class="detail client-details-vvow_briefing_error">❌</span>
|
||||
</t>
|
||||
<t t-if="partner.security_briefing">
|
||||
<span class="detail client-details-vvow_briefing">✅</span>
|
||||
</t>
|
||||
<span class="briefinglabel">Haftungsausschluss</span>
|
||||
</li>
|
||||
|
||||
|
||||
<t t-if="!partner.security_briefing">
|
||||
<li class="client-detail">
|
||||
<ul class="subpoints"><span class="detail client-details-vvow_sec_briefing_error">‼️Bitte Prüfen‼️</span></ul>
|
||||
</li>
|
||||
</t>
|
||||
|
||||
|
||||
<t t-if="partner.security_briefing">
|
||||
<ul class="subpoints">
|
||||
<li class="client-detail">
|
||||
<span class="label">Id:</span>
|
||||
<t t-if="partner.security_id">
|
||||
<span class="detail client-details-vvow_security_id"><t t-esc="partner.security_id"/></span>
|
||||
</t>
|
||||
<t t-if="!partner.security_id">
|
||||
<span class="detail client-details-vvow_security_id">N/A</span>
|
||||
</t>
|
||||
</li>
|
||||
<li class="client-detail">
|
||||
<span class="label">Erstellt:</span>
|
||||
<t t-if="partner.create_date">
|
||||
<span class="detail client-details-vvow_security_id"><t t-esc="partner.create_date"/></span>
|
||||
</t>
|
||||
<t t-if="!partner.create_date">
|
||||
<span class="detail client-vvow_birthday">N/A</span>
|
||||
</t>
|
||||
</li>
|
||||
</ul>
|
||||
</t>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<t t-foreach="areas" t-as="area">
|
||||
<div class="client-details-area" t-att-style="'border: solid 3px ' + area.color_hex + '; margin: 5px;'">
|
||||
<ul>
|
||||
<t t-foreach="area.machines" t-as="machine">
|
||||
<li class="client-detail">
|
||||
<t t-if="!machine.has_access">
|
||||
<span class="detail client-details-vvow_briefing_error">❌</span>
|
||||
</t>
|
||||
<t t-if="machine.has_access">
|
||||
<span class="detail client-details-vvow_briefing">✅</span>
|
||||
</t>
|
||||
<span class="briefinglabel"><t t-esc="machine.name"/></span>
|
||||
</li>
|
||||
</t>
|
||||
</ul>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
|
@ -15,7 +15,10 @@
|
|||
t-att-class="order === pos.get_order() ? 'bg-primary text-white' : 'bg-white'"
|
||||
t-on-click="() => selectOrder(order)"-->
|
||||
<div t-att-class="'order-entry' + (order === pos.get_order() ? ' selected' : '')" t-on-click="() => this.selectOrder(order)">
|
||||
<div><t t-esc="getDate(order)"/> – <t t-esc="getPartner(order)"/></div>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
<div class="product-screen d-flex h-100 bg-100" t-att-class="{ 'd-none': !props.isShown }">
|
||||
<div class="custompane d-flex flex-column border-end bg-200">
|
||||
<OwsPosCustomerSidebar />
|
||||
<OwsMachineAccessList />
|
||||
</div>
|
||||
|
||||
<div t-if="!ui.isSmall || pos.mobile_pane === 'left'"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user