Merge pull request '13.0_dev' (#6) from 13.0_dev into 13.0

Reviewed-on: #6
This commit is contained in:
Matthias Lotz 2025-06-26 17:48:09 +02:00
commit adbb4f2f56
5 changed files with 147 additions and 36 deletions

View File

@ -378,17 +378,56 @@ class OwsUser(models.Model):
('partner_unique', 'unique(partner_id)', 'Jeder Partner darf nur einen OWS-Datensatz haben.') ('partner_unique', 'unique(partner_id)', 'Jeder Partner darf nur einen OWS-Datensatz haben.')
] ]
AVAILABLE_COLORS = [
('#000000', 'schwarz'),
('#ff0000', 'Rot'),
('#E91E63', 'Pink'),
('#9C27B0', 'Lila'),
('#3F51B5', 'Indigo'),
('#0000ff', 'Blau'),
('#008000', 'Grün'),
('#ffff00', 'Gelb'),
('#FF9800', 'Orange'),
('#795548', 'Braun'),
('#1f1f1f', 'Grau'),
]
class OwsMachineArea(models.Model): class OwsMachineArea(models.Model):
_name = 'ows.machine.area' _name = 'ows.machine.area'
_table = "ows_machine_area" _table = 'ows_machine_area'
_description = 'OWS: Maschinenbereich' _description = 'OWS: Maschinenbereich'
_order = 'name' _order = 'name'
name = fields.Char(required=True, translate=True) name = fields.Char(string="Name", required=True, translate=True)
#color = fields.Integer(string="Farbe")
color_hex = fields.Char(string="Farbe (Hex)", help="Hex-Farbcode wie #FF0000 für Rot")
color_hex = fields.Selection(
selection=AVAILABLE_COLORS,
string="Farbe (Hex)",
required=True,
)
color_hex_value = fields.Char(
string="Farbcode",
compute='_compute_color_hex_value',
store=False
)
color_name = fields.Char(
string="Farbname",
compute='_compute_color_name',
store=False
)
@api.depends('color_hex')
def _compute_color_hex_value(self):
for rec in self:
rec.color_hex_value = rec.color_hex or ''
@api.depends('color_hex')
def _compute_color_name(self):
label_dict = dict(AVAILABLE_COLORS)
for rec in self:
rec.color_name = label_dict.get(rec.color_hex, 'Unbekannt')
class OwsMachine(models.Model): class OwsMachine(models.Model):
_name = 'ows.machine' _name = 'ows.machine'
@ -397,13 +436,37 @@ class OwsMachine(models.Model):
name = fields.Char(required=True, translate=True) name = fields.Char(required=True, translate=True)
code = fields.Char(required=True, help="Eindeutiger Kurzcode, z.B. 'lasercutter'") code = fields.Char(required=True, help="Eindeutiger Kurzcode, z.B. 'lasercutter'")
description = fields.Text() category = fields.Selection([
active = fields.Boolean(default=True) ('green', 'Kategorie 1: grün'),
area_id = fields.Many2one('ows.machine.area', string='Bereich') ('yellow', 'Kategorie 2: gelb'),
product_ids = fields.One2many('ows.machine.product', 'machine_id', string="Nutzungsprodukte") ('red', 'Kategorie 3: rot'),
product_names = fields.Char(string="Nutzungsprodukte Liste", compute="_compute_product_using_names", store=False,) ], string="Sicherheitskategorie", required=True, default='red', help="Sicherheitsrelevante Maschinenkategorie:\n"
"- grün: keine Einweisungspflicht\n"
"- gelb: empfohlene Einweisung\n"
"- rot: Einweisung zwingend erforderlich")
category_icon = fields.Char(string="Kategorie-Symbol", compute="_compute_category_icon", store=False)
@api.depends('category')
def _compute_category_icon(self):
for rec in self:
icon_map = {
'green': '🟢',
'yellow': '🟡',
'red': '🔴',
}
rec.category_icon = icon_map.get(rec.category, '')
description = fields.Text(string="Gerätebeschreibung", translate=True, help="Beschreibung der Maschine oder des Geräts.")
active = fields.Boolean(string="Aktive", default=True, help="Ist die Maschine oder das Gerät aktiv? Inaktive Maschinen werden nicht mehr in der POS-Ansicht angezeigt.")
area_id = fields.Many2one('ows.machine.area', string='Bereich', help="Bereich in der Werkstatt, in dem die Maschine oder das Gerät steht.")
product_ids = fields.One2many('ows.machine.product', 'machine_id', string="Nutzungsprodukte", help="Dies ist das zugehörige Produkt, falls die Maschine oder das Geräte eine zeitliche Nutzungsgebühr hat.")
product_names = fields.Char(string="Liste der Nutzungsprodukte", compute="_compute_product_using_names", store=False,)
training_ids = fields.One2many('ows.machine.training', 'machine_id', string="Einweisungsprodukte") training_ids = fields.One2many('ows.machine.training', 'machine_id', string="Einweisungsprodukte")
training_names = fields.Char(string="Einweisungsprodukte Liste", compute="_compute_product_training_names", store=False,) training_names = fields.Char(string="Liste der Einweisungsprodukte", compute="_compute_product_training_names", store=False,)
storage_location = fields.Char(string="Lagerort", help="Lagerort der Maschine oder des Geräts.")
purchase_price = fields.Float(string="Kaufpreis", help="Kaufpreis der Maschine oder des Geräts.")
purchase_date = fields.Date(string="Kaufdatum", help="Kaufdatum der Maschine oder des Geräts.")
@api.depends('product_ids.product_id.name') @api.depends('product_ids.product_id.name')
def _compute_product_using_names(self): def _compute_product_using_names(self):
@ -426,12 +489,34 @@ class OwsMachine(models.Model):
@api.model @api.model
def get_access_list_grouped(self, partner_id): def get_access_list_grouped(self, partner_id):
"""
Gibt eine gruppierte Liste von Maschinenzugängen für einen bestimmten Partner zurück. Diese Funktion wird in
Odoo POS Frontend verwendet um die Ansicht zu erzeugen auf Welche Maschinen der Partner Zugriff hat.
Für einen gegebenen Partner (über die partner_id) werden alle Maschinenbereiche (areas) abgefragt.
Für jeden Bereich wird geprüft, auf welche Maschinen der Partner Zugriff hat. Das Ergebnis wird
als Liste von Bereichen mit jeweils zugehörigen Maschinen und Zugriffsstatus zurückgegeben.
Zusätzlich werden sicherheitsrelevante Informationen des Partners (wie Sicherheitsunterweisung,
Sicherheits-ID, RFID-Karte und Geburtstag) aus dem zugehörigen ows_user ermittelt und mitgeliefert.
Args:
partner_id (int): Die ID des Partners, für den die Zugriffsübersicht erstellt werden soll.
Returns:
dict: Ein Dictionary mit folgenden Schlüsseln:
- 'access_by_area': Liste von Bereichen mit Maschinen und Zugriffsstatus.
- 'security_briefing': Sicherheitsunterweisung des Nutzers (bool oder False).
- 'security_id': Sicherheits-ID des Nutzers (str oder '').
- 'rfid_card': RFID-Kartennummer des Nutzers (str oder '').
- 'birthday': Geburtstag des Nutzers (str oder '').
"""
partner = self.env['res.partner'].browse(partner_id)
areas = self.env['ows.machine.area'].search([], order="name") areas = self.env['ows.machine.area'].search([], order="name")
_logger.info("🔍 Maschinenbereiche: %s", areas.mapped('name'))
_logger.info("🔍 Partner_id: %s", partner_id) access_by_area = []
res = []
for area in areas: for area in areas:
machines = self.search([('area_id', '=', area.id)], order="name") machines = self.search([('area_id', '=', area.id), ('category', '=', 'red')], order="name")
machine_list = [] machine_list = []
for machine in machines: for machine in machines:
has_access = bool(self.env['ows.machine.access'].search([ has_access = bool(self.env['ows.machine.access'].search([
@ -442,12 +527,21 @@ class OwsMachine(models.Model):
'name': machine.name, 'name': machine.name,
'has_access': has_access, 'has_access': has_access,
}) })
res.append({ if machine_list:
access_by_area.append({
'area': area.name, 'area': area.name,
'color_hex': area.color_hex or '#000000', 'color_hex': area.color_hex or '#000000',
'machines': machine_list 'machines': machine_list
}) })
return res
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): class OwsMachineAccess(models.Model):

View File

@ -8,9 +8,9 @@ _logger = logging.getLogger(__name__)
_logger.info("✅ pos_order.py geladen") _logger.info("✅ pos_order.py geladen")
# debugpy.listen(("0.0.0.0", 5678)) # debugpy.listen(("0.0.0.0", 5678))
print("✅ debugpy wartet auf Verbindung (Port 5678) ...") # print("✅ debugpy wartet auf Verbindung (Port 5678) ...")
# Optional: Starte erst, wenn VS Code verbunden ist # Optional: Starte erst, wenn VS Code verbunden ist
#debugpy.wait_for_client() # debugpy.wait_for_client()
class PosOrder(models.Model): class PosOrder(models.Model):
_inherit = 'pos.order' _inherit = 'pos.order'

View File

@ -1609,6 +1609,9 @@ td {
.order-selector { .order-selector {
display: none !important; display: none !important;
} }
.machine-access-sidebar {
display: none !important;
}
.blockUI { .blockUI {
display: none !important; display: none !important;
} }

View File

@ -53,7 +53,7 @@ odoo.define('open_workshop.machine_access_sidebar', function (require) {
}).then(function (result) { }).then(function (result) {
partner.create_date = partner.create_date && partner.create_date.substring(0, 10); partner.create_date = partner.create_date && partner.create_date.substring(0, 10);
var html = QWeb.render('PartnerMachineAccessList', { var html = QWeb.render('PartnerMachineAccessList', {
areas: result || [], areas: result.access_by_area || [],
partner: partner, partner: partner,
}); });
self.$('.access-content').html(html); self.$('.access-content').html(html);

View File

@ -6,18 +6,23 @@
<field name="model">ows.machine</field> <field name="model">ows.machine</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree> <tree>
<field name="category_icon" string="⚙" readonly="1"/>
<field name="name"/> <field name="name"/>
<field name="category"/>
<field name="code"/> <field name="code"/>
<field name="area_id" widget="many2one_color"/> <field name="area_id" widget="many2one_color"/>
<field name="product_names"/> <field name="product_names"/>
<field name="training_names"/> <field name="training_names"/>
<field name="storage_location"/>
<field name="purchase_price"/>
<field name="purchase_date"/>
<field name="active"/> <field name="active"/>
</tree> </tree>
</field> </field>
</record> </record>
<!-- Maschinen Formularansicht --> <!-- Maschinen Formularansicht -->
<record id="view_machine_form" model="ir.ui.view"> <record id="view_machine_form" model="ir.ui.view">
<field name="name">ows.machine.form</field> <field name="name">ows.machine.form</field>
<field name="model">ows.machine</field> <field name="model">ows.machine</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
@ -25,9 +30,18 @@
<sheet> <sheet>
<group> <group>
<field name="name"/> <field name="name"/>
<field name="category"/>
<field name="category_icon" string="⚙" readonly="1"/>
<field name="code"/> <field name="code"/>
<field name="area_id"/> <field name="area_id"/>
</group>
<group>
<field name="description"/> <field name="description"/>
<field name="storage_location"/>
<field name="purchase_price"/>
<field name="purchase_date"/>
<field name="active"/> <field name="active"/>
</group> </group>