288 lines
11 KiB
Python
288 lines
11 KiB
Python
# -*- coding: utf-8 -*-
|
|
# ows_models.py
|
|
# Part of Odoo Open Workshop
|
|
|
|
from odoo import models, fields, api
|
|
import logging
|
|
_logger = logging.getLogger(__name__)
|
|
_logger.info("✅ ows_models.py geladen")
|
|
|
|
class ResPartner(models.Model):
|
|
_inherit = 'res.partner'
|
|
_logger.info("✅ ows ResPartner geladen")
|
|
|
|
ows_user_id = fields.One2many('ows.user', 'partner_id', string="OWS Benutzerdaten")
|
|
|
|
# ✳️ Zugriff auf Felder aus ows.user per compute + inverse (statt related)
|
|
birthday = fields.Date(
|
|
string="Geburtstag",
|
|
compute='_compute_ows_user_fields',
|
|
inverse='_inverse_ows_user_fields',
|
|
store=False
|
|
)
|
|
|
|
rfid_card = fields.Text(
|
|
string="RFID Card ID",
|
|
compute='_compute_ows_user_fields',
|
|
inverse='_inverse_ows_user_fields',
|
|
store=False
|
|
)
|
|
|
|
security_briefing = fields.Boolean(
|
|
string="Haftungsausschluss",
|
|
compute='_compute_ows_user_fields',
|
|
inverse='_inverse_ows_user_fields',
|
|
store=False
|
|
)
|
|
|
|
security_id = fields.Text(
|
|
string="Haftungsausschluss ID",
|
|
compute='_compute_ows_user_fields',
|
|
inverse='_inverse_ows_user_fields',
|
|
store=False
|
|
)
|
|
|
|
|
|
@api.depends('ows_user_id')
|
|
def _compute_ows_user_fields(self):
|
|
for partner in self:
|
|
user = partner.ows_user_id[0] if partner.ows_user_id else False
|
|
partner.birthday = user.birthday if user else False
|
|
partner.rfid_card = user.rfid_card if user else False
|
|
partner.security_briefing = user.security_briefing if user else False
|
|
partner.security_id = user.security_id if user else False
|
|
|
|
def _inverse_ows_user_fields(self):
|
|
for partner in self:
|
|
user = partner.ows_user_id[0] if partner.ows_user_id else False
|
|
if user:
|
|
user.birthday = partner.birthday
|
|
user.rfid_card = partner.rfid_card
|
|
user.security_briefing = partner.security_briefing
|
|
user.security_id = partner.security_id
|
|
|
|
@api.model_create_multi
|
|
def create(self, vals_list):
|
|
partners = super().create(vals_list)
|
|
for partner in partners:
|
|
self.env['ows.user'].create({'partner_id': partner.id})
|
|
return partners
|
|
|
|
machine_access_ids = fields.One2many(
|
|
'ows.machine.access',
|
|
'partner_id',
|
|
string='Maschinenfreigaben'
|
|
)
|
|
|
|
machine_access_html = fields.Html(
|
|
string="Maschinenfreigaben",
|
|
compute="_compute_machine_access_html",
|
|
sanitize=False
|
|
)
|
|
|
|
@api.depends('machine_access_ids')
|
|
def _compute_machine_access_html(self):
|
|
areas = self.env['ows.machine.area'].search([], order="name")
|
|
for partner in self:
|
|
html = "<div style='display: grid; grid-template-columns: repeat(3, 1fr); gap: 2rem;'>"
|
|
for area in areas:
|
|
html += f"<div class='o_group' style='margin-bottom: 1em;'>"
|
|
html += f"<table class='o_group o_inner_group'>"
|
|
html += f"<thead><tr><th>{area.name}</th><th></th><th>Datum</th><th>Gültig bis</th></tr></thead><tbody>"
|
|
machines = self.env['ows.machine'].search([('area_id', '=', area.id)], order="name")
|
|
for machine in machines:
|
|
access = self.env['ows.machine.access'].search([
|
|
('partner_id', '=', partner.id),
|
|
('machine_id', '=', machine.id),
|
|
], limit=1)
|
|
icon = "<span class='fa fa-check text-success'></span>" if access else "<span class='fa fa-times text-danger'></span>"
|
|
date_granted = access.date_granted.strftime('%Y-%m-%d') if access and access.date_granted else ""
|
|
date_expiry = access.date_expiry.strftime('%Y-%m-%d') if access and access.date_expiry else ""
|
|
html += f"""
|
|
<tr>
|
|
<td class='o_td_label'><label>{machine.name}</label></td>
|
|
<td class='o_td_field'>{icon}</td>
|
|
<td class='o_td_field'>{date_granted}</td>
|
|
<td class='o_td_field'>{date_expiry}</td>
|
|
</tr>
|
|
"""
|
|
html += "</tbody></table></div>"
|
|
html += "</div>"
|
|
partner.machine_access_html = html
|
|
|
|
@api.model
|
|
def migrate_existing_partners(self):
|
|
"""
|
|
Erstellt für alle vorhandenen res.partner einen ows.user,
|
|
wenn noch keiner existiert, und übernimmt alte vvow_* Felder.
|
|
Führt am Ende automatisch einen commit durch.
|
|
|
|
Verwendung in der odoo shell:
|
|
env['res.partner'].migrate_existing_partners()
|
|
env['ows.user'].search_count([])
|
|
env['ows.user'].search([]).mapped('partner_id.name')
|
|
"""
|
|
migrated = 0
|
|
skipped = 0
|
|
|
|
partners = self.env['res.partner'].search([])
|
|
for partner in partners:
|
|
if partner.ows_user_id:
|
|
skipped += 1
|
|
continue
|
|
|
|
# Werte lesen (werden evtl. durch _inherit hinzugefügt)
|
|
vals = {
|
|
'partner_id': partner.id,
|
|
'birthday': getattr(partner, 'vvow_birthday', False),
|
|
'rfid_card': getattr(partner, 'vvow_rfid_card', False),
|
|
'security_briefing': getattr(partner, 'vvow_security_briefing', False),
|
|
'security_id': getattr(partner, 'vvow_security_id', False),
|
|
}
|
|
self.env['ows.user'].create(vals)
|
|
migrated += 1
|
|
_logger.info(f"Erzeuge ows.user für Partner {partner.id} ({partner.name}) mit Werten: {vals}")
|
|
|
|
_logger.info(f"[OWS Migration] ✅ Migriert: {migrated}, ❌ Übersprungen: {skipped}")
|
|
|
|
# 🔐 Commit am Ende
|
|
self.env.cr.commit()
|
|
|
|
return {
|
|
'type': 'ir.actions.client',
|
|
'tag': 'display_notification',
|
|
'params': {
|
|
'title': "Migration abgeschlossen",
|
|
'message': f"{migrated} Partner migriert, {skipped} übersprungen.",
|
|
'sticky': False,
|
|
}
|
|
}
|
|
|
|
|
|
class OwsUser(models.Model):
|
|
_name = 'ows.user'
|
|
_description = 'OWS: Benutzerdaten'
|
|
_table = 'ows_user'
|
|
_logger.info("✅ ows_user geladen")
|
|
|
|
partner_id = fields.Many2one(
|
|
'res.partner',
|
|
required=True,
|
|
ondelete='cascade',
|
|
string='Kontakt'
|
|
)
|
|
|
|
birthday = fields.Date('Geburtstag')
|
|
rfid_card = fields.Text('RFID Card ID')
|
|
security_briefing = fields.Boolean('Haftungsausschluss', default=False)
|
|
security_id = fields.Text('Haftungsausschluss ID')
|
|
|
|
_sql_constraints = [
|
|
('partner_unique', 'unique(partner_id)', 'Jeder Partner darf nur einen OWS-Datensatz haben.')
|
|
]
|
|
|
|
|
|
class OwsMachineArea(models.Model):
|
|
_name = 'ows.machine.area'
|
|
_table = "ows_machine_area"
|
|
_description = 'OWS: Maschinenbereich'
|
|
_order = 'name'
|
|
|
|
name = fields.Char(required=True, translate=True)
|
|
#color = fields.Integer(string="Farbe")
|
|
color_hex = fields.Char(string="Farbe (Hex)", help="Hex-Farbcode wie #FF0000 für Rot")
|
|
|
|
|
|
class OwsMachine(models.Model):
|
|
_name = 'ows.machine'
|
|
_table = 'ows_machine'
|
|
_description = 'OWS: Maschine'
|
|
|
|
name = fields.Char(required=True, translate=True)
|
|
code = fields.Char(required=True, help="Eindeutiger Kurzcode, z.B. 'lasercutter'")
|
|
description = fields.Text()
|
|
active = fields.Boolean(default=True)
|
|
area_id = fields.Many2one('ows.machine.area', string='Bereich')
|
|
product_ids = fields.One2many('ows.machine.product', 'machine_id', string="Nutzungsprodukte")
|
|
product_names = fields.Char(string="Nutzungsprodukte Liste", compute="_compute_product_using_names", store=False,)
|
|
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,)
|
|
|
|
@api.depends('product_ids.product_id.name')
|
|
def _compute_product_using_names(self):
|
|
for machine in self:
|
|
names = machine.product_ids.mapped('product_id.name')
|
|
machine.product_names = ", ".join(names)
|
|
|
|
@api.depends('training_ids.training_id.name')
|
|
def _compute_product_training_names(self):
|
|
for machine in self:
|
|
names = machine.training_ids.mapped('training_id.name')
|
|
machine.training_names = ", ".join(names)
|
|
|
|
_sql_constraints = [
|
|
('code_unique', 'unique(code)', 'Maschinencode muss eindeutig sein.')
|
|
]
|
|
|
|
def name_get(self):
|
|
return [(rec.id, f"{rec.name} ({rec.code})") for rec in self]
|
|
|
|
@api.model
|
|
def get_access_list_grouped(self, 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 = []
|
|
for area in areas:
|
|
machines = self.search([('area_id', '=', area.id)], order="name")
|
|
machine_list = []
|
|
for machine in machines:
|
|
has_access = bool(self.env['ows.machine.access'].search([
|
|
('partner_id', '=', partner_id),
|
|
('machine_id', '=', machine.id),
|
|
], limit=1))
|
|
machine_list.append({
|
|
'name': machine.name,
|
|
'has_access': has_access,
|
|
})
|
|
res.append({
|
|
'area': area.name,
|
|
'color_hex': area.color_hex or '#000000',
|
|
'machines': machine_list
|
|
})
|
|
return res
|
|
|
|
|
|
class OwsMachineAccess(models.Model):
|
|
_name = 'ows.machine.access'
|
|
_table = 'ows_machine_access'
|
|
_description = 'OWS: Maschinenfreigabe'
|
|
_order = 'partner_id, machine_id'
|
|
|
|
partner_id = fields.Many2one('res.partner', required=True, ondelete='cascade')
|
|
machine_id = fields.Many2one('ows.machine', required=True)
|
|
date_granted = fields.Date(default=fields.Date.today)
|
|
date_expiry = fields.Date(string="Ablaufdatum")
|
|
granted_by_pos = fields.Boolean(default=True)
|
|
|
|
_sql_constraints = [
|
|
('partner_machine_unique', 'unique(partner_id, machine_id)', 'Der Kunde hat diese Freigabe bereits.')
|
|
]
|
|
|
|
|
|
class OwsMachineProduct(models.Model):
|
|
_name = 'ows.machine.product'
|
|
_table = 'ows_machine_product'
|
|
_description = 'OWS: Zurordnung Produkt der Nutzung zur die Maschine'
|
|
|
|
product_id = fields.Many2one('product.product', required=True, domain=[('available_in_pos', '=', True)], ondelete='cascade')
|
|
machine_id = fields.Many2one('ows.machine', required=True, ondelete='cascade')
|
|
|
|
class OwsMachineTraining(models.Model):
|
|
_name = 'ows.machine.training'
|
|
_table = 'ows_machine_training'
|
|
_description = 'OWS: Zurordnung Produkt der Einweisung zur die Maschine'
|
|
|
|
training_id = fields.Many2one('product.product', required=True, domain=[('available_in_pos', '=', True)], ondelete='cascade')
|
|
machine_id = fields.Many2one('ows.machine', required=True, ondelete='cascade')
|