diff --git a/__manifest__.py b/__manifest__.py
index 09451e7..6c4b2e5 100755
--- a/__manifest__.py
+++ b/__manifest__.py
@@ -14,7 +14,14 @@
'security/groups.xml',
'security/ir.model.access.csv',
'views/menu.xml',
- 'views/dss.xml',
+ 'views/dss_projectstate.xml',
+ 'views/dss_systemtypen.xml',
+ 'views/dss_projects.xml',
+ 'views/dss_ads.xml',
+ 'views/dss_contracts.xml',
+ 'views/dss_mediafiles.xml',
+ 'views/dss_addstructures.xml',
+ 'views/dss_texts.xml',
'views/mainsystem_view.xml',
'views/company_view.xml',
],
diff --git a/models/__pycache__/dss.cpython-311.pyc b/models/__pycache__/dss.cpython-311.pyc
index e5951ed..2249ac0 100644
Binary files a/models/__pycache__/dss.cpython-311.pyc and b/models/__pycache__/dss.cpython-311.pyc differ
diff --git a/models/dss.py b/models/dss.py
index 1e643bb..375e79b 100755
--- a/models/dss.py
+++ b/models/dss.py
@@ -1,15 +1,33 @@
# -*- coding: utf-8 -*-
+
import ast
import json
import re
import uuid
import logging
+import base64
+import subprocess
+import tempfile
+import easywebdav
+import os
+import os.path
from odoo import api, fields, models, _
+from odoo import tools
from odoo.exceptions import ValidationError
+from datetime import date
_logger = logging.getLogger(__name__)
+def _generate_preview_from_binary(self, videofile_file):
+ cmd = ['ffmpeg', '-i','-','-ss','00:00:01','-vframes','1','-f','image2','-']
+ p = subprocess.Popen(cmd,stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out,err = p.communicate(videofile_file)
+ if p.returncode != 0:
+ pass
+
+ return base64.b64encode(out)
+
class dsscontracts(models.Model):
@api.model
@@ -39,69 +57,94 @@ class dsscontracts(models.Model):
_name = "dss.contracts"
_description = "DigitalSignage Vertraege"
_rec_name = "contract_auto_name"
- _inherit = ['mail.thread']
+ _inherit = ['mail.thread','mail.activity.mixin']
uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID')
- contract_id = fields.Char("Kundennummer",store=True)
- contract_name = fields.Char('Kurzbezeichnung', required=True)
- contract_state = fields.Many2one('dss.contractstate',group_expand='_read_group_stage_ids')
+ contract_id = fields.Char("Kundennummer",store=True,tracking=True)
+ contract_name = fields.Char('Kurzbezeichnung', required=True,tracking=True)
+ contract_state = fields.Many2one('dss.contractstate',group_expand='_read_group_stage_ids',tracking=True)
contract_state_order = fields.Integer(related='contract_state.order',store=True)
- contract_auto_id = fields.Char("Kundennummer")
- contract_auto_name = fields.Char('Vertragskennug')
- project = fields.Many2one('dss.projects' , string='Project', store=True)
+ contract_auto_id = fields.Char("Kundennummer",tracking=True)
+ contract_auto_name = fields.Char('Vertragskennug',tracking=True)
+ project = fields.Many2one('dss.projects' , string='Project', store=True,tracking=True)
project_id = fields.Integer(related='project.projectid', string='Project ID')
- projectIid = fields.Integer('Project IID')
- client = fields.Many2one('res.partner',domain="['&',('dsspartner','=',True),('dsspartner_werbung','=',True)]")
- client_id = fields.Char("Kundenid")
+ projectIid = fields.Integer('Project IID',tracking=True)
+ client = fields.Many2one('res.partner',domain="['&',('dsspartner','=',True),('dsspartner_werbung','=',True)]",tracking=True)
+ client_id = fields.Char("Kundenid",tracking=True)
client_uuid = fields.Char(related="client.dss_uuid")
- parent_id = fields.Many2one('dss.contracts', string='Parent Task', index=True)
+ parent_id = fields.Many2one('dss.contracts', string='Parent Task', index=True,tracking=True)
- client_short_company = fields.Char('Firmenname Kunde')
- client_short_vorname = fields.Char('Vorname Kunde')
- client_short_name = fields.Char('Name Kunde')
- client_short_strasse = fields.Char('Strasse Kunde')
- client_short_plz = fields.Char('PLZ Kunde')
- client_short_ort = fields.Char('Ort Kunde')
- client_short_land = fields.Many2one('res.country','Land Kunde')
- client_short_email = fields.Char('Email Kunde')
- client_short_telefon = fields.Char('Telefon Kunde')
- client_short_mobil = fields.Char('Mobilfunk Kunde')
- client_short_website = fields.Char('Webseite Kunde')
+ client_short_company = fields.Char('Firmenname Kunde',tracking=True)
+ client_short_vorname = fields.Char('Vorname Kunde',tracking=True)
+ client_short_name = fields.Char('Name Kunde',tracking=True)
+ client_short_strasse = fields.Char('Strasse Kunde',tracking=True)
+ client_short_plz = fields.Char('PLZ Kunde',tracking=True)
+ client_short_ort = fields.Char('Ort Kunde',tracking=True)
+ client_short_land = fields.Many2one('res.country','Land Kunde',tracking=True)
+ client_short_email = fields.Char('Email Kunde',tracking=True)
+ client_short_telefon = fields.Char('Telefon Kunde',tracking=True)
+ client_short_mobil = fields.Char('Mobilfunk Kunde',tracking=True)
+ client_short_website = fields.Char('Webseite Kunde',tracking=True)
- client_other_projects = fields.Many2many('dss.projects',string='Weitere Projekte')
+ client_other_projects = fields.Many2many('dss.projects',string='Weitere Projekte',tracking=True)
- werbe_feld_selected = fields.Many2many('dss.advertisefields',string='Werbefelder')
+ werbe_feld_selected = fields.Many2many('dss.advertisefields',string='Werbefelder',tracking=True)
- main_runtime = fields.Integer('Gesamtlaufzeit')
- split_runtime_count = fields.Integer('Laufzeit Teilungen')
- split_runtime_time = fields.Integer('Laufzeit Sekunden')
+ main_runtime = fields.Integer('Gesamtlaufzeit',tracking=True)
+ split_runtime_count = fields.Integer('Laufzeit Teilungen',tracking=True)
+ split_runtime_time = fields.Integer('Laufzeit Sekunden',tracking=True)
- contract_date = fields.Date('Vertragsdatum')
- start_date = fields.Date('Ausstrahlungsdatum')
+ contract_date = fields.Date('Vertragsdatum',tracking=True)
+ start_date = fields.Date('Ausstrahlungsdatum',tracking=True)
- runtimesystem = fields.Selection([('M','Monatslaufzeit'),('T','Tagelaufzeit'), ('E','Eventlaufzeit'), ('S','Sonderlaufzeit')])
- runtime_m = fields.Integer('Laufzeit')
- runtime_t = fields.Integer('Laufzeit')
- runtime_events = fields.Many2many('dss.eventdays')
- runtime_divers = fields.Char('Laufzeit')
+ runtimesystem = fields.Selection([('M','Monatslaufzeit'),('T','Tagelaufzeit'), ('E','Eventlaufzeit'), ('S','Sonderlaufzeit')],tracking=True)
+ runtime_m = fields.Integer('Laufzeit',tracking=True)
+ runtime_t = fields.Integer('Laufzeit',tracking=True)
+ runtime_events = fields.Many2many('dss.eventdays',tracking=True)
+ runtime_divers = fields.Char('Laufzeit',tracking=True)
-
- info_account_changes = fields.Boolean('Benarichtigen bei Accountänderungen')
- info_spot_changes = fields.Boolean('Benarichtigen bei Spotänderungen')
- info_contract_changes = fields.Boolean('Benarichtigen bei Vertragsänderungen')
- info_partner_changes = fields.Boolean('Benarichtigen bei Partneränderungen')
- info_partner = fields.Many2one('res.partner','Benarichtigung an : ')
+ paymentsystems = fields.Many2one('dss.paysystems',tracking=True)
+ intern_info_payment_off = fields.Boolean('Keine Zahl-Benachrichtigungen',tracking=True)
- work_state = fields.Many2one('dss.workstate',default=_default_work_state)
+ base_ad = fields.Many2one('dss.ads',tracking=True)
+ ads = fields.One2many('dss.ads','contract',tracking=True)
+
+ vnnox_zugang_erstellt = fields.Boolean('Vnnox Zugang ?',tracking=True)
+ vnnox_zugang_username = fields.Char('Vnnox Username',tracking=True)
+ vnnox_zugang_password = fields.Char('Vnnox Passwort',tracking=True)
+ vnnox_zugang_gesendet = fields.Boolean('Vnnox Zugang gesendet?',tracking=True)
+
+ xibo_zugang_erstellt = fields.Boolean('Xibo Zugang ?',tracking=True)
+ xibo_zugang_username = fields.Char('Xibo Username',tracking=True)
+ xibo_zugang_password = fields.Char('Xibo Passwort',tracking=True)
+ vnnox_zugang_gesendet = fields.Boolean('Xibo Zugang gesendet?',tracking=True)
+
+ lmw_zugang_erstellt = fields.Boolean('LMW Zugang ?',tracking=True)
+ lmw_zugang_username = fields.Char('LMW Username',tracking=True)
+ lmw_zugang_password = fields.Char('LMW Passwort',tracking=True)
+ lmw_zugang_gesendet = fields.Boolean('LMW Zugang gesendet?',tracking=True)
+
+ wflow_korrekturabzug = fields.Boolean('Korekturabzug gesendet ?',tracking=True)
+ wflow_ausstahlung = fields.Boolean('Eingespielt/Ausgestahlt ?',tracking=True)
+ wflow_aenderung = fields.Boolean('Änderung durchgeführt ?',tracking=True)
+
+ info_account_changes = fields.Boolean('Benachrichtigen bei Accountänderungen',tracking=True)
+ info_spot_changes = fields.Boolean('Benachrichtigen bei Spotänderungen',tracking=True)
+ info_contract_changes = fields.Boolean('Benachrichtigen bei Vertragsänderungen',tracking=True)
+ info_partner_changes = fields.Boolean('Benachrichtigen bei Partneränderungen',tracking=True)
+ info_partner = fields.Many2one('res.partner','Benachrichtigung an : ',tracking=True)
+
+ work_state = fields.Many2one('dss.workstate',default=_default_work_state,tracking=True)
work_state_color = fields.Char(related='work_state.color')
work_state_text = fields.Char(related='work_state.statusname')
- work_state_info = fields.Char('Zusatzinfo')
+ work_state_info = fields.Char('Zusatzinfo',tracking=True)
- todo_state = fields.Many2one('dss.todostate',default=_default_todo_state)
+ todo_state = fields.Many2one('dss.todostate',default=_default_todo_state,tracking=True)
todo_state_color = fields.Char(related='todo_state.color')
todo_state_text = fields.Char(related='todo_state.statusname')
- todo_state_info = fields.Char('Zusatzinfo')
- todo_state_until = fields.Date('Abarbeiten bis')
+ todo_state_info = fields.Char('Zusatzinfo',tracking=True)
+ todo_state_until = fields.Date('Abarbeiten bis',tracking=True)
+ cloud_contract_directory = fields.Char('Cloud Kunden Ordner',tracking=True)
@api.constrains('client_id')
def _check_client_id(self) :
@@ -192,6 +235,28 @@ class dsscontracts(models.Model):
# action['context'] = context
return action
+ def tokampagne(self):
+ action = self.env['ir.actions.act_window'].with_context({'default_contractid': self.id})._for_xml_id('DigitalSignage.action_dss_ads_view')
+ context = action['context']
+ kampagne=self.env['dss.ads'].search([('contract','=',self.id)],limit=1)
+ if not kampagne :
+ defadstate = self.env['dss.adstate'].search([('default','=',True)],limit=1).id
+ if not defadstate :
+ defadstate == 1
+ kampagne = self.env['dss.ads'].create({'contract': self.id, 'project': self.project.id, 'adname': 'WK '+self.contract_auto_name,'adtype':'MAIN','ad_state':defadstate})
+ kampagne.parent_ad = kampagne.id
+ return {
+ 'type': 'ir.actions.act_window',
+ 'view_type':'form',
+ 'view_mode':'form,tree',
+ 'res_model':'dss.ads',
+ 'target':'current',
+ 'context':'',
+ 'res_id':kampagne.id,
+ 'display_name' : 'Änderung zur Werbekampagne '+kampagne.parent_ad.adname,
+ 'domain':'[("id","=","context[kampagne.id]")]'
+ }
+
@api.model
def pyaction_view_contract(self):
@@ -231,28 +296,31 @@ class dssmain(models.Model):
_name = "dss.projects"
_description = "DigitalSignage Projekte"
_rec_name = "projektname"
- _inherit = ['mail.thread']
+ _inherit = ['mail.thread','mail.activity.mixin']
projektname = fields.Char('Projektname', required=True)
uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID')
- projectid = fields.Integer('Projekt ID')
- color = fields.Integer('Color Index')
- active = fields.Boolean('Active', default=True)
- name = fields.Char('Interner Name', required=True)
- aktstatus = fields.Many2one('dss.projectstate',string='Aktueller Status:')
- aktstatus_color = fields.Integer(related='aktstatus.color')
+ projectid = fields.Integer('Projekt ID',tracking=True)
+ color = fields.Char('Color Index',tracking=True)
+ active = fields.Boolean('Active', default=True,tracking=True)
+ name = fields.Char('Interner Name', required=True,tracking=True)
+ aktstatus = fields.Many2one('dss.projectstate',string='Aktueller Status:',tracking=True)
+ aktstatus_typ = fields.Selection(related='aktstatus.typ')
+ aktstatus_color = fields.Char(related='aktstatus.color')
aktstatus_icon = fields.Image(related='aktstatus.icon')
- description = fields.Text('Beschreibung')
- systemname = fields.Many2one('dss.systems')
- grundsystemname = fields.Many2one('dss.systemtypen')
- grundsystemicon = fields.Image(related='grundsystemname.icon')
+ description = fields.Text('Beschreibung',tracking=True)
+ systemname = fields.Many2one('dss.systems',tracking=True)
+ grundsystemname = fields.Many2one('dss.systemtypen',tracking=True)
+ grundsystemicon = fields.Image(related='grundsystemname.icon',tracking=True)
grundsystemicon5050 = fields.Image(related='grundsystemname.icon_5050')
- vertragsschreiber = fields.Many2one('res.partner',domain="['&',('dsspartner','=',True),('dsspartner_vertrieb','=',True)]")
- standortpartner = fields.Many2one('res.partner',domain="['&',('dsspartner','=',True),('dsspartner_standort','=',True)]")
- vertriebspartner = fields.Many2many('res.partner',domain="['&',('dsspartner','=',True),('dsspartner_vertrieb','=',True)]")
- zeiten_on = fields.Datetime('Einschaltzeit')
- zeiten_off = fields.Datetime('Ausschaltzeit')
- errichtet_am = fields.Datetime('Errichtungstag')
- standort_inout = fields.Selection([('indoor','im Gebäude'), ('outdoor','Aussenbereich'), ('semiindoor','Überdachter Aussenbereich'),('Divers','Andere Art')]);
+ vertragsschreiber = fields.Many2one('res.partner',domain="['&',('dsspartner','=',True),('dsspartner_vertrieb','=',True)]",tracking=True)
+ standortpartner = fields.Many2one('res.partner',domain="['&',('dsspartner','=',True),('dsspartner_standort','=',True)]",tracking=True)
+ vertriebspartner = fields.Many2many('res.partner',domain="['&',('dsspartner','=',True),('dsspartner_vertrieb','=',True)]",tracking=True)
+ zeiten_on = fields.Datetime('Einschaltzeit',tracking=True)
+ zeiten_off = fields.Datetime('Ausschaltzeit',tracking=True)
+ errichtet_am = fields.Datetime('Errichtungstag',tracking=True)
+ standort_inout = fields.Selection([('indoor','im Gebäude'), ('outdoor','Aussenbereich'), ('semiindoor','Überdachter Aussenbereich'),('Divers','Andere Art')],tracking=True);
+
+ cloud_main_directory = fields.Char('Cloud Projekt Ordner',tracking=True)
@api.model
def _default_uuid(self):
@@ -277,66 +345,66 @@ class dssmain(models.Model):
class dssgeraetetypen(models.Model):
_name = "dss.geraetetypen"
_description = "DigitalSignage Geraetetypen"
- _inherit = ['mail.thread']
+ _inherit = ['mail.thread','mail.activity.mixin']
_rec_name = "geraetename"
geraetename = fields.Char('Geraetename', required=True)
uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID')
- geraetetyp = fields.Selection([('SYS','Systemgerät'), ('STE','Steuergerät'), ('DIV','Anderes'), ('ANZ','Anzeigegerät'), ('PLY','Abspielgerät')])
- grundsystem = fields.Many2one('dss.systemtypen', string="Gerät ist nutzbar für")
- grundsystem_kennung = fields.Char(string='Kennung', related='grundsystem.kennung')
+ geraetetyp = fields.Selection([('SYS','Systemgerät'), ('STE','Steuergerät'), ('DIV','Anderes'), ('ANZ','Anzeigegerät'), ('PLY','Abspielgerät')],tracking=True)
+ grundsystem = fields.Many2one('dss.systemtypen', string="Gerät ist nutzbar für",tracking=True)
+ grundsystem_kennung = fields.Char(string='Kennung', related='grundsystem.kennung',tracking=True)
- farbe = fields.Char('Grundfarbe')
+ farbe = fields.Char('Grundfarbe',tracking=True)
- has_heizung = fields.Boolean('Mit Heizsystem')
- has_klima = fields.Boolean('Mit Klimasystem')
- has_fan = fields.Boolean('Mit Ventiltorensystem')
+ has_heizung = fields.Boolean('Mit Heizsystem',tracking=True)
+ has_klima = fields.Boolean('Mit Klimasystem',tracking=True)
+ has_fan = fields.Boolean('Mit Ventiltorensystem',tracking=True)
- stromzaehler = fields.Many2one('dss.geraetetypen')
- stromverbrauch_avg = fields.Integer('Stromverbrauch AVG in W')
+ stromzaehler = fields.Many2one('dss.geraetetypen',tracking=True)
+ stromverbrauch_avg = fields.Integer('Stromverbrauch AVG in W',tracking=True)
- osvorhanden = fields.Boolean('Mit Betriebssystem')
- osname = fields.Char('Betriebssystem')
- ostyp = fields.Selection([('Win','Windows'), ('Lin','Linux'), ('And','Android'),('Ras','Raspberry PI'),('Non','Keines bekannt'),('Div','Anderes')]);
+ osvorhanden = fields.Boolean('Mit Betriebssystem',tracking=True)
+ osname = fields.Char('Betriebssystem',tracking=True)
+ ostyp = fields.Selection([('Win','Windows'), ('Lin','Linux'), ('And','Android'),('Ras','Raspberry PI'),('Non','Keines bekannt'),('Div','Anderes')],tracking=True);
- lcd_ausrichtung = fields.Selection([('quer','Horizontal/Querformat'), ('hoch','Vertikal/Hochformat'),('Divers','Andere Art')],'LCD Ausrichtung');
- lcd_touch = fields.Boolean('Touchsystem')
- lcd_montage = fields.Selection([('WAN','Wandmontage'), ('FUS','Standfuss rollbar'), ('FI1','Boden verankert 1 Fuss'),('FI2','Boden verankert 2 Füsse'),('FIX','Bodenverankert Blockfuss'),('XXX','Sonstige')],'Montage/Befestigung');
- lcd_montage_sonstige = fields.Char('Sonstige Montageart')
- lcd_size = fields.Selection([('42','42 Zoll'), ('55','55 Zoll'), ('65','65 Zoll'),('75','75 Zoll'),('10','10.x Zoll'),('00','Sonstige')],'LCD Größe');
- lcd_size_sonstige = fields.Char('LCD Sondergröße')
+ lcd_ausrichtung = fields.Selection([('quer','Horizontal/Querformat'), ('hoch','Vertikal/Hochformat'),('Divers','Andere Art')],'LCD Ausrichtung',tracking=True);
+ lcd_touch = fields.Boolean('Touchsystem',tracking=True)
+ lcd_montage = fields.Selection([('WAN','Wandmontage'), ('FUS','Standfuss rollbar'), ('FI1','Boden verankert 1 Fuss'),('FI2','Boden verankert 2 Füsse'),('FIX','Bodenverankert Blockfuss'),('XXX','Sonstige')],'Montage/Befestigung',tracking=True);
+ lcd_montage_sonstige = fields.Char('Sonstige Montageart',tracking=True)
+ lcd_size = fields.Selection([('42','42 Zoll'), ('55','55 Zoll'), ('65','65 Zoll'),('75','75 Zoll'),('10','10.x Zoll'),('00','Sonstige')],'LCD Größe',tracking=True);
+ lcd_size_sonstige = fields.Char('LCD Sondergröße',tracking=True)
- led_geraetetyp = fields.Selection([('MOD','LED Modul'),('NET','Netzgerät'), ('REC','Receiving Karte'), ('STE','Steuerkarte'),('LFT','Lüftertyp')])
- led_module_pixelpitch = fields.Float('Modulpixelpitch')
- led_module_breite = fields.Integer('Modulbreite mm')
- led_module_hoehe = fields.Integer('Modulhoehe mm')
- led_module_pixel_breite = fields.Integer('Modulbreite px')
- led_module_pixel_hoehe = fields.Integer('Modulhoehe px')
+ led_geraetetyp = fields.Selection([('MOD','LED Modul'),('NET','Netzgerät'), ('REC','Receiving Karte'), ('STE','Steuerkarte'),('LFT','Lüftertyp')],tracking=True)
+ led_module_pixelpitch = fields.Float('Modulpixelpitch',tracking=True)
+ led_module_breite = fields.Integer('Modulbreite mm',tracking=True)
+ led_module_hoehe = fields.Integer('Modulhoehe mm',tracking=True)
+ led_module_pixel_breite = fields.Integer('Modulbreite px',tracking=True)
+ led_module_pixel_hoehe = fields.Integer('Modulhoehe px',tracking=True)
- led_module_system = fields.Selection([('FIX1','Fix Verschraubt'), ('MAG1','Magnetisch haltend'), ('RIG1','Imbus Veriegelt (vorn)'),('SONS','Sonstige')],'Modul Montage/Befestigung');
- led_module_system_sonstige = fields.Char('Modulbefestigung Sonstige')
- led_module_kennung = fields.Char('Modulbezeichnung')
- led_module_serial = fields.Char('Modulseriennummer')
- led_module_vendor = fields.Many2one('res.partner','Modul Hersteller')
+ led_module_system = fields.Selection([('FIX1','Fix Verschraubt'), ('MAG1','Magnetisch haltend'), ('RIG1','Imbus Veriegelt (vorn)'),('SONS','Sonstige')],'Modul Montage/Befestigung',tracking=True);
+ led_module_system_sonstige = fields.Char('Modulbefestigung Sonstige',tracking=True)
+ led_module_kennung = fields.Char('Modulbezeichnung',tracking=True)
+ led_module_serial = fields.Char('Modulseriennummer',tracking=True)
+ led_module_vendor = fields.Many2one('res.partner','Modul Hersteller',tracking=True)
led_receivingcard_vendor = fields.Many2one('res.partner','Receivingcard Hersteller')
led_receivingcard_kennung = fields.Char('Receivingcardtyp')
- led_netzteil_typ = fields.Selection([('SNT','Schaltnetzteil'), ('STN','Steckernetzteil'), ('HNT','Hutschienennetzteil'),('INT','Internes Netzteil')],'Netzteil Bauart');
- led_netzteil_vendor = fields.Many2one('res.partner','Netzteil Hersteller')
- led_netzteil_kennung = fields.Char('Netzteilkennung')
- led_netzteil_spannung = fields.Char('Netzteil Spannung V')
- led_netzteil_leistung = fields.Char('Netzteil Leistung W')
+ led_netzteil_typ = fields.Selection([('SNT','Schaltnetzteil'), ('STN','Steckernetzteil'), ('HNT','Hutschienennetzteil'),('INT','Internes Netzteil')],'Netzteil Bauart',tracking=True);
+ led_netzteil_vendor = fields.Many2one('res.partner','Netzteil Hersteller',tracking=True)
+ led_netzteil_kennung = fields.Char('Netzteilkennung',tracking=True)
+ led_netzteil_spannung = fields.Char('Netzteil Spannung V',tracking=True)
+ led_netzteil_leistung = fields.Char('Netzteil Leistung W',tracking=True)
- lcd_montage = fields.Selection([('WAN','Wandmontage'), ('FUS','Standfuss rollbar'), ('FI1','Boden verankert 1 Fuss'),('FI2','Boden verankert 2 Füsse'),('FIX','Bodenverankert Blockfuss'),('XXX','Sonstige')],'Montage/Befestigung');
- lcd_montage_sonstige = fields.Char('Sonstige Montageart')
+ lcd_montage = fields.Selection([('WAN','Wandmontage'), ('FUS','Standfuss rollbar'), ('FI1','Boden verankert 1 Fuss'),('FI2','Boden verankert 2 Füsse'),('FIX','Bodenverankert Blockfuss'),('XXX','Sonstige')],'Montage/Befestigung',tracking=True);
+ lcd_montage_sonstige = fields.Char('Sonstige Montageart',tracking=True)
- hw_anzeige = fields.Many2one('dss.geraetetypen',domain="[('geraetetyp','=','ANZ')]")
- hw_steuerung = fields.Many2one('dss.geraetetypen',domain="['&',('geraetetyp','=','STE'),('grundsystem_kennung','=','LED')]")
- hw_player = fields.Many2one('dss.geraetetypen',domain="[('geraetetyp','=','PLY')]")
- hw_umwelt = fields.Many2one('dss.geraetetypen',domain="['|',('geraetetyp','=','SYS'),('geraetetyp','=','DIV')]")
+ hw_anzeige = fields.Many2one('dss.geraetetypen',domain="[('geraetetyp','=','ANZ')]",tracking=True)
+ hw_steuerung = fields.Many2one('dss.geraetetypen',domain="['&',('geraetetyp','=','STE'),('grundsystem_kennung','=','LED')]",tracking=True)
+ hw_player = fields.Many2one('dss.geraetetypen',domain="[('geraetetyp','=','PLY')]",tracking=True)
+ hw_umwelt = fields.Many2one('dss.geraetetypen',domain="['|',('geraetetyp','=','SYS'),('geraetetyp','=','DIV')]",tracking=True)
- zusatz_integrationen = fields.Many2one('dss.geraetetypen')
+ zusatz_integrationen = fields.Many2one('dss.geraetetypen',tracking=True)
@api.model
def _default_uuid(self):
@@ -349,6 +417,8 @@ class dssgeraetetypen(models.Model):
syst.grundsystem_kennung = syst.grundsystem.kennung
class dsssystemtypen(models.Model):
+
+
_name = "dss.systemtypen"
_inherit = ['mail.thread']
_description = "DigitalSignage Systemtypen"
@@ -356,20 +426,35 @@ class dsssystemtypen(models.Model):
uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID')
systemname = fields.Char('Systemname', required=True)
kennung = fields.Char('Kurzkennung', required=True)
- farbe = fields.Integer('Grundfarbe')
+ farbe = fields.Char('Grundfarbe')
icon = fields.Image()
- icon_5050 = fields.Image("Icon 50")
-
+ icon_5050 = fields.Image("Icon 50",compute='_compute_icon_5050')
+ default_adstructure = fields.Many2one('dss.adstructures',String='Standard-Werbeaufbau')
@api.model
def _default_uuid(self):
return str(uuid.uuid4())
+ @api.depends('icon')
+ def _compute_icon_5050(self):
+ for rec in self:
+ if rec.icon != False:
+ _logger.info('compute 50x50 icon for '+rec.uuid)
+# rec.mediafile_preview = self._generate_preview_from_binary(base64.decodebytes(rec.mediafile))
+# rec.icon_5050 = tools.image_resize_image(rec.icon,size=(50,50),avoid_if_small=True)
+ rec.icon_5050 = rec.icon
+# if rec.mediafile != False:
+# rec.mediafile_preview = self._generate_preview_from_binary(base64.decodebytes(rec.mediafile))
+# rec.mediafile_preview = None
+ else:
+ _logger.info('alternative compute '+rec.uuid)
+ rec.icon_5050 = rec.icon
+ return
class dsssoftware(models.Model):
_name = "dss.software"
_description = "Softwaresysteme"
- _inherit = ['mail.thread']
+ _inherit = ['mail.thread','mail.activity.mixin']
_rec_name = "softwarename"
# _inherit = ['mail.thread', 'mail.activity.mixin']
uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID')
@@ -385,7 +470,7 @@ class dsssoftware(models.Model):
class dsssystems(models.Model):
_name = "dss.systems"
_description = "DigitalSignage Systemtypen"
- _inherit = ['mail.thread']
+ _inherit = ['mail.thread','mail.activity.mixin']
_rec_name = "systemname"
# _inherit = ['mail.thread', 'mail.activity.mixin']
uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID')
@@ -440,13 +525,14 @@ class dsssystems(models.Model):
class dsspprojektstatus(models.Model):
_name = "dss.projectstate"
_description = "DigitalSignage Projektstatus"
- _inherit = ['mail.thread']
+ _inherit = ['mail.thread','mail.activity.mixin']
_rec_name = "statusname"
# _inherit = ['mail.thread', 'mail.activity.mixin']
uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID')
# uuid = fields.Char('UUID', required=True, translate=True)
statusname = fields.Char('Statusname', required=True)
- color = fields.Integer(string='Color Index')
+ color = fields.Char(string='Color Index')
+ typ = fields.Selection([('NEU','In Bearbeitung'),('WORK','fertig/laufend'),('ERROR','Fehlerhaft/Defekt'),('ARCHIV','veraltet/archiviert')],'Systemzuordnung')
icon = fields.Image()
@api.model
@@ -456,13 +542,31 @@ class dsspprojektstatus(models.Model):
class dsscontractstatus(models.Model):
_name = "dss.contractstate"
_description = "DigitalSignage Vertragsstatus"
- _inherit = ['mail.thread']
+ _inherit = ['mail.thread','mail.activity.mixin']
_rec_name = "statusname"
# _inherit = ['mail.thread', 'mail.activity.mixin']
uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID')
# uuid = fields.Char('UUID', required=True, translate=True)
statusname = fields.Char('Statusname', required=True)
- color = fields.Integer(string='Color Index')
+ color = fields.Char(string='Color Index')
+ icon = fields.Image()
+ order = fields.Integer('Reihenfolge')
+
+ @api.model
+ def _default_uuid(self):
+ return str(uuid.uuid4())
+
+class dssadstatus(models.Model):
+ _name = "dss.adstate"
+ _description = "DigitalSignage Werbeaktions-Status"
+ _inherit = ['mail.thread','mail.activity.mixin']
+ _rec_name = "statusname"
+# _inherit = ['mail.thread', 'mail.activity.mixin']
+ uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID')
+# uuid = fields.Char('UUID', required=True, translate=True)
+ statusname = fields.Char('Statusname', required=True)
+ color = fields.Char(string='Color Index')
+ default = fields.Boolean('Standardwert ?')
icon = fields.Image()
order = fields.Integer('Reihenfolge')
@@ -474,7 +578,7 @@ class dsscontractstatus(models.Model):
class dssworkstatus(models.Model):
_name = "dss.workstate"
_description = "DigitalSignage Bearbeitungsstatus"
- _inherit = ['mail.thread']
+ _inherit = ['mail.thread','mail.activity.mixin']
_rec_name = "statusname"
# _inherit = ['mail.thread', 'mail.activity.mixin']
uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID')
@@ -490,7 +594,7 @@ class dssworkstatus(models.Model):
class dsseventdays(models.Model):
_name = "dss.eventdays"
_description = "DigitalSignage EventSpieltage"
- _inherit = ['mail.thread']
+ _inherit = ['mail.thread','mail.activity.mixin']
_rec_name = "eventname"
# _inherit = ['mail.thread', 'mail.activity.mixin']
uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID')
@@ -509,7 +613,7 @@ class dsseventdays(models.Model):
class dsstodostatus(models.Model):
_name = "dss.todostate"
_description = "DigitalSignage Bearbeitungsschritte"
- _inherit = ['mail.thread']
+ _inherit = ['mail.thread','mail.activity.mixin']
_rec_name = "statusname"
# _inherit = ['mail.thread', 'mail.activity.mixin']
uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID')
@@ -526,7 +630,7 @@ class dsstodostatus(models.Model):
class dssadvertisefields(models.Model):
_name = "dss.advertisefields"
_description = "DigitalSignage Werbefelder"
- _inherit = ['mail.thread']
+ _inherit = ['mail.thread','mail.activity.mixin']
_rec_name = "feldname"
# _inherit = ['mail.thread', 'mail.activity.mixin']
uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID')
@@ -542,5 +646,386 @@ class dssadvertisefields(models.Model):
def _default_uuid(self):
return str(uuid.uuid4())
+class dsstexts(models.Model):
+ _name = "dss.texts"
+ _description = "DigitalSignage Standard texte"
+ _inherit = ['mail.thread','mail.activity.mixin']
+ _rec_name = "textname"
+# _inherit = ['mail.thread', 'mail.activity.mixin']
+ uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID')
+# uuid = fields.Char('UUID', required=True, translate=True)
+ text_id = fields.Char('Kennung', required=True)
+ textname = fields.Char('Textname', required=True)
+ description = fields.Text('Text')
+
+ @api.model
+ def _default_uuid(self):
+ return str(uuid.uuid4())
+
+class dsspaysystemfields(models.Model):
+ _name = "dss.paysystem_fields"
+ _description = "DigitalSignage Abrechnungsarten_felder"
+ _inherit = ['mail.thread','mail.activity.mixin']
+ _rec_name = "feldname"
+# _inherit = ['mail.thread', 'mail.activity.mixin']
+ uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID')
+# uuid = fields.Char('UUID', required=True, translate=True)
+ feldname = fields.Char('Abrechnungs_Feldname', required=True)
+ payonfieldset = fields.Selection([('VE','Vertragseingang'),('KA','Korrekturabzug'),('ES','Einspielung'),('CH','Jede Änderung'),('XH','X, Änderung')])
+ changecount = fields.Integer('Änderungsnummer')
+ description = fields.Text('EventBeschreibung')
+ amount = fields.Float('Kosten')
+
+ @api.model
+ def _default_uuid(self):
+ return str(uuid.uuid4())
+class dssmediatypes(models.Model):
+ _name = "dss.mediatypes"
+ _description = "DigitalSignage Datei-Medientypen"
+ _inherit = ['mail.thread','mail.activity.mixin']
+ _rec_name = "medianame"
+# _inherit = ['mail.thread', 'mail.activity.mixin']
+ uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID')
+# uuid = fields.Char('UUID', required=True, translate=True)
+ medianame = fields.Char('Medien Name', required=True)
+ mediatype = fields.Selection([('IMG_J','Bild'),('VID_4','MP4 Video'),('FIL_X','belieb. Datei')])
+ description = fields.Text('Medien Beschreibung')
+ cloudlink = fields.Char('Cloud Urverzeichnis')
+ maxsize_kb = fields.Integer('Maximale Größe KB')
+ maxsize_w = fields.Integer('Maximale Pixel W')
+ maxsize_h = fields.Integer('Maximale Pixel H')
+
+ @api.model
+ def _default_uuid(self):
+ return str(uuid.uuid4())
+
+class dssmediarelations(models.Model):
+
+ def _generate_preview_from_binary(self, videofile_file):
+ cmd = ['ffmpeg', '-i','-','-ss','00:00:01','-vframes','1','-f','image2','-']
+ p = subprocess.Popen(cmd,stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out,err = p.communicate(videofile_file)
+ if p.returncode != 0:
+ pass
+
+ return base64.b64encode(out)
+
+ def _generate_preview_and_save_from_binary(self, videofile_file, videofile_file_name:str):
+ cmd = ['ffmpeg', '-i','-','-ss','00:00:01','-vframes','1','-f','image2','-']
+ p = subprocess.Popen(cmd,stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ out,err = p.communicate(videofile_file)
+ if p.returncode != 0:
+ _logger.info(videofile_file_name)
+ fileobj = open(videofile_file_name,"xb")
+ fileobj.write(out)
+ fileobj.close()
+ pass
+
+ return base64.b64encode(out)
+
+
+ _name = "dss.mediarelations"
+ _description = "DigitalSignage Kampagne-Medien-Zuordnung"
+ _inherit = ['mail.thread','mail.activity.mixin']
+ _rec_name = "relname"
+# _inherit = ['mail.thread', 'mail.activity.mixin']
+ uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID')
+# uuid = fields.Char('UUID', required=True, translate=True)
+ kampagne = fields.Many2one('dss.ads',string='Kampagne')
+ mediatype = fields.Many2one('dss.mediatypes',string='Medientyp')
+ mediatype_type = fields.Selection(related='mediatype.mediatype',string='Medientyp')
+ relname = fields.Char('Relationsname')
+ kampagnen_uuid = fields.Char('Kampagne')
+ mediatype_uuid = fields.Char('Medientyp')
+ mediafile = fields.Binary('Datei',attachment=True)
+ mediafile_attachment = fields.Many2one('ir.attachment',string='Datei')
+ mediafile_file = fields.Char('Dateiname')
+ mediafile_preview = fields.Binary('Datei Vorschau',compute='_compute_media_preview')
+ secured_ro = fields.Boolean('Gesperrt ro')
+ used_ro = fields.Boolean('Benutzt ro')
+
+ @api.onchange('mediafile')
+ def _onchange_mediafile(self):
+ restr = 'keine'
+ for record in self :
+ resstr = record.uuid
+ _logger.info(record.mediafile)
+ if record.mediafile != False :
+ _logger.info('Generating File '+resstr)
+ if os.path.isfile(record.mediafile_file) :
+ os.remove(record.mediafile_file)
+ fileobj = open(record.mediafile_file,"xb")
+ fileobj.write(base64.decodebytes(record.mediafile))
+ fileobj.close()
+ _logger.info(resstr+' File generated')
+ _logger.info(' Projekt : '+record.kampagne.contract.project.uuid)
+ _logger.info(' Keine Datei ')
+ return
+
+ @api.model
+ def _default_uuid(self):
+ return str(uuid.uuid4())
+
+ @api.depends('mediafile_file')
+ def _compute_media_preview(self):
+ for rec in self:
+ if rec.mediafile != False:
+ _logger.info('compute image for '+rec.uuid)
+# rec.mediafile_preview = self._generate_preview_from_binary(base64.decodebytes(rec.mediafile))
+ rec.mediafile_preview = self._generate_preview_and_save_from_binary(base64.decodebytes(rec.mediafile),rec.mediafile_file+'_prv')
+# if rec.mediafile != False:
+# rec.mediafile_preview = self._generate_preview_from_binary(base64.decodebytes(rec.mediafile))
+# rec.mediafile_preview = None
+ else:
+ _logger.info('alternative compute '+rec.uuid)
+ rec.mediafile_preview = rec.mediafile
+ return
+
+class dssadstructures(models.Model):
+ _name = "dss.adstructures"
+ _description = "DigitalSignage Werbestrukturen"
+ _inherit = ['mail.thread','mail.activity.mixin']
+ _rec_name = "structurename"
+# _inherit = ['mail.thread', 'mail.activity.mixin']
+ uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID')
+# uuid = fields.Char('UUID', required=True, translate=True)
+ structurename = fields.Char('Struktur Name', required=True)
+ kampagnen_uuid = fields.Char('Kampagne')
+ description = fields.Text('Struktur Beschreibung')
+ medias = fields.Many2many('dss.mediatypes',string='Enthaltene Dateien')
+
+ @api.model
+ def _default_uuid(self):
+ return str(uuid.uuid4())
+
+
+class dsspaysystems(models.Model):
+ _name = "dss.paysystems"
+ _description = "DigitalSignage Abrechnungsarten"
+ _inherit = ['mail.thread','mail.activity.mixin']
+ _rec_name = "payname"
+# _inherit = ['mail.thread', 'mail.activity.mixin']
+ uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID')
+# uuid = fields.Char('UUID', required=True, translate=True)
+ payname = fields.Char('Abrechnungsname', required=True)
+ payonset = fields.Many2many('dss.paysystem_fields')
+ description = fields.Text('EventBeschreibung')
+ send_info = fields.Boolean('Informationsemail senden ?')
+ send_info_to = fields.Many2one('res.users')
+ send_info_template = fields.Many2one('mail.template')
+ amount = fields.Float('Kosten')
+ icon = fields.Image()
+
+ @api.model
+ def _default_uuid(self):
+ return str(uuid.uuid4())
+
+
+class dsscontractads(models.Model):
+
+
+ def _default_work_state(self):
+ ds=self.env['dss.workstate'].search([('statusname','=','Neu')],limit=1).id
+ _logger.debug(ds)
+ return ds
+
+ def _default_work_state_color(self):
+ ds=self.env['dss.workstate'].search([('statusname','=','Neu')],limit=1).color
+ _logger.info(ds)
+ return ds
+
+ def _default_todo_state(self):
+ ds=self.env['dss.todostate'].search([('statusnr','=','0')],limit=1).id
+ if not ds : ds = 1
+ _logger.debug(ds)
+# ds =
+ return ds
+
+ @api.model
+ def create(self,vals):
+ result = super().create(vals)
+ self['date_create'] = date.today()
+ self['user_create'] = self.env.user.name
+ return result
+
+ _name = "dss.ads"
+ _description = "DigitalSignage Werbekampagnen Phasen"
+ _inherit = ['mail.thread','mail.activity.mixin']
+ _rec_name = "adname"
+# _inherit = ['mail.thread', 'mail.activity.mixin']
+ uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID')
+
+ date_create = fields.Date('Erstellungsdatum',default=lambda self: self._default_create_date())
+ date_lastedit = fields.Date('Änderungsdatum')
+ user_create = fields.Char('Erstellungsuser',default=lambda self: self._default_create_user())
+ user_lastedit = fields.Char('Änderungsuser')
+# uuid = fields.Char('UUID', required=True, translate=True)
+ adname = fields.Char('Kampagnenname', required=True,track_visibility='onchange',tracking=True)
+ adtype = fields.Selection([('MAIN','Ersteinrichtung'),('KCHN','Änderung durch Kunde'),('LCHN','Änderung durch Logumedia'),('SONS','Sonstige Änderung')],track_visibility='onchange',tracking=True)
+ adpos = fields.Integer('Reihenfolge',default=lambda self: self._default_adpos(),track_visibility='onchange',tracking=True)
+
+ contract = fields.Many2one('dss.contracts',store=True,track_visibility='onchange',tracking=True)
+ contract_id = fields.Char(related='contract.contract_id')
+ contract_name = fields.Char(related='contract.contract_name')
+
+ project = fields.Many2one('dss.projects' , string='Project', store=True,track_visibility='onchange',tracking=True)
+ project_id = fields.Integer(related='project.projectid', string='Project ID')
+
+ parent_ad = fields.Many2one('dss.ads' , string='UrsprungsWerbung', store=True)
+ parent_ad_uuid = fields.Char(related='parent_ad.uuid')
+ description = fields.Text('Beschreibung',track_visibility='onchange')
+ amount = fields.Float('Extrakosten')
+ order = fields.Integer('Reihenfolge')
+
+ work_state = fields.Many2one('dss.workstate',default=_default_work_state,tracking=True)
+ work_state_color = fields.Char(related='work_state.color')
+ work_state_text = fields.Char(related='work_state.statusname')
+ work_state_info = fields.Char('Zusatzinfo')
+
+ ad_state = fields.Many2one('dss.adstate',tracking=True)
+ ad_state_color = fields.Char(related='ad_state.color')
+
+ todo_state = fields.Many2one('dss.todostate',default=_default_todo_state,tracking=True)
+ todo_state_color = fields.Char(related='todo_state.color')
+ todo_state_text = fields.Char(related='todo_state.statusname')
+ todo_state_info = fields.Char('Zusatzinfo')
+ todo_state_until = fields.Date('Abarbeiten bis')
+
+ mediastructure = fields.Many2one('dss.adstructures',string='Systemaufbau',tracking=True)
+ mediarelations = fields.One2many('dss.mediarelations','kampagne',tracking=True)
+
+ cloud_add_directory = fields.Char('Cloud KundenKampagnen Ordner',tracking=True)
+
+ @api.model
+ def _default_uuid(self):
+ return str(uuid.uuid4())
+
+
+ def _default_create_date(self):
+ return str(date.today())
+
+ def _default_create_user(self):
+ return str(self.env.user.name)
+
+ def _default_adpos(self):
+ pos = self.env['dss.ads'].search_count([('contract_id','=',self.contract.id)]) + 1
+ return str(pos)
+
+ @api.onchange('mediastructure')
+ def _onchange_mediastructure_id(self):
+ restr = 'keine'
+ for record in self :
+ resstr = record.mediastructure.uuid
+ _logger.info(resstr)
+ mtyp = self.env['dss.adstructures'].search([("uuid","=",str(record.mediastructure.uuid))])
+ resstr = mtyp.structurename
+ _logger.info(resstr)
+ _logger.info(record.mediastructure.uuid)
+ foundused = self.env['dss.mediarelations'].search_count(["&",('kampagnen_uuid','=',record.uuid),'|',('secured_ro','=',True),('used_ro','=',True)])
+ if foundused == 0 :
+ self.env['dss.mediarelations'].search([('kampagnen_uuid','=',record.uuid)]).unlink()
+ for media in mtyp.medias :
+ resstr = media.medianame
+ self.env['dss.mediarelations'].create({'kampagne': record.id,'relname':resstr,'mediatype':media.id,'kampagnen_uuid':record.uuid})
+ _logger.info(resstr)
+ else :
+ _logger.info('change - Canceled !')
+ raise ValidationError(_("Datensatz kann nicht gewechselt werden ! Es sind benutzt Medien in der Kampagne ! Bitte erst diese freigeben !"))
+ self.date_lastedit = str(date.today())
+ self.mediastructure = mtyp
+
+ def pyaction_view_ad_details(self):
+ action = self.env['ir.actions.act_window'].with_context({'default_adid': self.id})._for_xml_id('DigitalSignage.action_dss_ads_view')
+# action['display_name'] = self.ad_name
+# action['domain'] = '[["projectid","=","4"]]'
+# context = action['context'].replace('', str(self.id))
+# context = ast.literal_eval(context)
+# context.update({
+# 'create': self.active,
+# 'active_test': self.active
+# })
+# action['context'] = context
+ return {
+ 'type': 'ir.actions.act_window',
+ 'view_type':'form',
+ 'view_mode':'form,tree',
+ 'res_model':'dss.ads',
+ 'target':'current',
+ 'context':'',
+ 'res_id':self.id,
+ 'display_name' : ' '+self.adname,
+ 'domain':''
+ }
+
+ return action
+
+ def pydoviewallads(self):
+ action = self.env['ir.actions.act_window'].with_context({'default_adid': self.id})._for_xml_id('DigitalSignage.act_dss_ads_view_full')
+ action['display_name'] = self.contract_name
+# action['domain'] = '[["projectid","=","4"]]'
+# context = action['context'].replace('', str(self.id))
+# context = ast.literal_eval(context)
+# context.update({
+# 'create': self.active,
+# 'active_test': self.active
+# })
+# action['context'] = context
+# return {
+# 'type': 'ir.actions.act_window',
+# 'view_type':'form',
+# 'view_mode':'form,tree',
+# 'res_model':'dss.ads',
+# 'target':'current',
+# 'context':'',
+# 'res_id':kampagne.id,
+# 'display_name' : 'Werbekampagne '+kampagne.adname,
+# 'domain':'[("contract","=","context[active_id]")]'
+# }
+# return action
+ return {
+ 'type': 'ir.actions.act_window',
+ 'view_type':'kanban',
+ 'view_mode':'kanban',
+ 'res_model':'dss.ads',
+ 'target':'current',
+ 'context':'{"group_by":["parent_ad"]}',
+# 'res_id':self.parent_ad,
+ 'display_name' : 'Übersicht für '+self.adname,
+ 'domain':[("contract","=",self.contract.id)]
+ }
+
+ def pydonewad(self):
+ defadstate = self.env['dss.adstate'].search([('default','=',True)],limit=1).id
+ if not defadstate :
+ defadstate == 1
+ newkampagne = self.env['dss.ads'].create({'contract': self.contract.id, 'project': self.project.id, 'adname': 'AD_'+self.adname,'parent_ad':self.id, 'adtype':'KCHN','ad_state':defadstate })
+# action = self.env['ir.actions.act_window'].with_context({'default_contractid': newkampagne.id})._for_xml_id('DigitalSignage.act_dss_ads_view_contract')
+# action['display_name'] = self.contract_name
+# action['domain'] = '[["projectid","=","4"]]'
+# context = action['context'].replace('', str(self.id))
+# context = ast.literal_eval(context)
+# context.update({
+# 'create': self.active,
+# 'active_test': self.active
+# })
+# action['context'] = context
+ return {
+ 'type': 'ir.actions.act_window',
+ 'view_type':'form',
+ 'view_mode':'form,tree',
+ 'res_model':'dss.ads',
+ 'target':'current',
+ 'context':'',
+ 'res_id':newkampagne.id,
+ 'display_name' : 'Änderung zur Werbekampagne '+newkampagne.parent_ad.adname,
+ 'domain':'[("id","=","context[newkampagne.id]")]'
+ }
+
+ return action
+
+ def setStandardText(self,tid):
+ text = self.env['dss.texts'].search([('text_id','=',tid)], limit=1)
+ if text:
+ self.write({'description':text.description})
diff --git a/security/ir.model.access.csv b/security/ir.model.access.csv
index fca5190..e0cf7c4 100755
--- a/security/ir.model.access.csv
+++ b/security/ir.model.access.csv
@@ -9,5 +9,13 @@ digitalsignage_dss_contractstate_group_user,access.dss.contractstate,model_dss_c
digitalsignage_dss_workstate_group_user,access.dss.workstate,model_dss_workstate,base.group_user,1,1,1,1
digitalsignage_dss_todostate_group_user,access.dss.todostate,model_dss_todostate,base.group_user,1,1,1,1
digitalsignage_dss_contracts_group_user,access.dss.contracts,model_dss_contracts,base.group_user,1,1,1,1
+digitalsignage_dss_adstate_group_user,access.dss.adstate,model_dss_adstate,base.group_user,1,1,1,1
digitalsignage_dss_eventdays_group_user,access.dss.eventdays,model_dss_eventdays,base.group_user,1,1,1,1
+digitalsignage_dss_paysystems_group_user,access.dss.paysystems,model_dss_paysystems,base.group_user,1,1,1,1
+digitalsignage_dss_paysystem_fields_group_user,access.dss.paysystem_fields,model_dss_paysystem_fields,base.group_user,1,1,1,1
+digitalsignage_dss_ads_fields_group_user,access.dss.ads,model_dss_ads,base.group_user,1,1,1,1
+digitalsignage_dss_adstructures_group_user,access.dss.adstructures,model_dss_adstructures,base.group_user,1,1,1,1
+digitalsignage_dss_mediatypes_group_user,access.dss.mediatypes,model_dss_mediatypes,base.group_user,1,1,1,1
+digitalsignage_dss_texts_group_user,access.dss.texts,model_dss_texts,base.group_user,1,1,1,1
+digitalsignage_dss_mediarelations_group_user,access.dss.mediarelations,model_dss_mediarelations,base.group_user,1,1,1,1
digitalsignage_dss_advertisefields_group_user,access.dss.advertisefields,model_dss_advertisefields,base.group_user,1,1,1,1
\ No newline at end of file
diff --git a/static/images/tree_r.png b/static/images/tree_r.png
new file mode 100644
index 0000000..dfbb593
Binary files /dev/null and b/static/images/tree_r.png differ
diff --git a/static/images/tree_ud.png b/static/images/tree_ud.png
new file mode 100644
index 0000000..ccb30fc
Binary files /dev/null and b/static/images/tree_ud.png differ
diff --git a/views/.mc.menu b/views/.mc.menu
new file mode 100644
index 0000000..f82ee7a
--- /dev/null
+++ b/views/.mc.menu
@@ -0,0 +1,379 @@
+shell_patterns=0
+
+##############################################################################
+# %% The % character
+# %f The current file (if non-local vfs, file will be copied locally and
+# %f will be full path to it)
+# %p The current file
+# %d The current working directory
+# %s "Selected files"; the tagged files if any, otherwise the current file
+# %t Tagged files
+# %u Tagged files (and they are untagged on return from expand_format)
+# %view Runs the commands and pipes standard output to the view command
+# If %view is immediately followed by '{', recognize keywords
+# ascii, hex, nroff and unform
+#
+# If the format letter is in uppercase, it refers to the other panel
+#
+# With a number followed the % character you can turn quoting on (default)
+# and off. For example:
+# %f quote expanded macro
+# %1f ditto
+# %0f don't quote expanded macro
+##############################################################################
+
++ ! t t
+@ Do something on the current file
+ CMD=%{Enter command}
+ $CMD %f
+
++ t t
+@ Do something on the tagged files
+ CMD=%{Enter command}
+ for i in %t ; do
+ $CMD "$i"
+ done
+
+0 Edit a bug report and send it to root
+ I=`mktemp "${MC_TMPDIR:-/tmp}/mail.XXXXXX"` || exit 1
+ ${EDITOR-vi} "$I"
+ test -r "$I" && mail root < "$I"
+ rm -f "$I"
+
+=+ f \.1$ | f \.3$ | f \.4$ | f \.5$ | f \.6$ | f \.7$ | f \.8$ | f \.man$ & t r
+1 Display the file with roff -man
+ %view{ascii,nroff} roff -c -Tlatin1 -mandoc %f
+
+2 Call the info hypertext browser
+ info
+
+= t d
+3 Compress the current subdirectory (tar.gz)
+ Pwd=`basename %d /`
+ echo -n "Name of the compressed file (without extension) [$Pwd]: "
+ read tar
+ [ "$tar"x = x ] && tar="$Pwd"
+ cd .. && \
+ tar cf - "$Pwd" | gzip -f9 > "$tar.tar.gz" && \
+ echo "../$tar.tar.gz created."
+
+4 Compress the current subdirectory (tar.bz2)
+ Pwd=`basename %d /`
+ echo -n "Name of the compressed file (without extension) [$Pwd]: "
+ read tar
+ [ "$tar"x = x ] && tar="$Pwd"
+ cd .. && \
+ tar cf - "$Pwd" | bzip2 -f > "$tar.tar.bz2" && \
+ echo "../$tar.tar.bz2 created."
+
+5 Compress the current subdirectory (tar.7z)
+ Pwd=`basename %d /`
+ echo -n "Name of the compressed file (without extension) [$Pwd]: "
+ read tar
+ [ "$tar"x = x ] && tar="$Pwd"
+ cd .. && \
+ tar cf - "$Pwd" | 7za a -si "$tar.tar.7z" && \
+ echo "../$tar.tar.7z created."
+
+6 Compress the current subdirectory (tar.xz)
+ Pwd=`basename %d /`
+ echo -n "Name of the compressed file (without extension) [$Pwd]: "
+ read tar
+ [ "$tar"x = x ] && tar="$Pwd"
+ cd .. && \
+ tar cf - "$Pwd" | xz -f > "$tar.tar.xz" && \
+ echo "../$tar.tar.xz created."
+
+7 Compress the current subdirectory (tar.zst)
+ Pwd=`basename %d /`
+ echo -n "Name of the compressed file (without extension) [$Pwd]: "
+ read tar
+ [ "$tar"x = x ] && tar="$Pwd"
+ cd .. && \
+ tar cf - "$Pwd" | zstd -f > "$tar.tar.zst" && \
+ echo "../$tar.tar.zst created."
+
+= f \.c$ & t r
++ f \.c$ & t r & ! t t
+c Compile and link current .c file
+ make "`basename %f .c`" 2>/dev/null || cc -O -o "`basename %f .c`" %f
+
++ t r & ! t t
+a Append file to opposite
+ cat %f >> %D/%f
+
++ t t
+A Append files to opposite files
+ for i in %t ; do
+ cat "$i" >> %D/"$i"
+ done
+
++ t r & ! t t
+d Delete file if a copy exists in the other directory.
+ if [ %d = %D ]; then
+ echo "The two directories must be different."
+ exit 1
+ fi
+ if [ -f %D/%f ]; then # if two of them, then
+ if cmp -s %D/%f %f; then
+ rm %f && echo %f": DELETED."
+ else
+ echo %f" and "%D/%f" differ: NOT deleted."
+ echo -n "Press RETURN "
+ read key
+ fi
+ else
+ echo %f": No copy in "%D/%f": NOT deleted."
+ fi
+
++ t t
+D Delete tagged files if a copy exists in the other directory.
+ if [ %d = %D ]; then
+ echo "The two directores must be different."
+ exit 1
+ fi
+ for i in %t ; do
+ if [ -f %D/"$i" ]; then
+ SUM1=`sum "$i"`
+ SUM2=`sum %D/"$i"`
+ if [ "$SUM1" = "$SUM2" ]; then
+ rm "$i" && echo "${i}: DELETED."
+ else
+ echo "$i and "%D"/$i differ: NOT deleted."
+ fi
+ else
+ echo "$i has no copy in "%D": NOT deleted."
+ fi
+ done
+
+m View manual page
+ MAN=%{Enter manual name}
+ %view{ascii,nroff} MANROFFOPT='-c -Tlatin1' MAN_KEEP_FORMATTING=1 man -P cat "$MAN"
+
+= f \.gz$ & t r
++ ! t t
+n Inspect gzip'ed newsbatch file
+ dd if=%f bs=1 skip=12 | zcat | ${PAGER-more}
+ # assuming the cunbatch header is 12 bytes long.
+
+= t r &
++ ! t t
+h Strip headers from current newsarticle
+ CHECK=`awk '{print $1 ; exit}' %f` 2>/dev/null
+ case "$CHECK" in
+ Newsgroups:|Path:)
+ I=`mktemp "${MC_TMPDIR:-/tmp}/news.XXXXXX"` || exit 1
+ cp %f "$I" && sed '/^'"$CHECK"' /,/^$/d' "$I" > %f
+ [ "$?" = "0" ] && rm "$I"
+ echo %f": header removed."
+ ;;
+ *)
+ echo %f" is not a news article."
+ ;;
+ esac
+
++ t t
+H Strip headers from the marked newsarticles
+ for i in %t ; do
+ CHECK=`awk '{print $1 ; exit}' "$i"` 2>/dev/null
+ WFILE=`mktemp "${MC_TMPDIR:-/tmp}/news.XXXXXX"` || exit 1
+ case "$CHECK" in
+ Newsgroups:|Path:)
+ cp "$i" "$WFILE" && sed '/^'"$CHECK"' /,/^$/d' "$WFILE" > "$i"
+ if [ "$?" = "0" ]; then
+ rm "$WFILE"; echo "$i header removed. OK."
+ else
+ echo "Oops! Please check $i against $WFILE."
+ fi
+ ;;
+ *)
+ echo "$i skipped: Not a news article."
+ ;;
+ esac
+ done
+
+= t r
++ ! t t
+r Copy file to remote host
+ echo -n "To which host?: "
+ read Host
+ echo -n "To which directory on $Host?: "
+ read Dir
+ rcp -p %f "${Host}:${Dir}"
+
++ t t
+R Copy files to remote host (no error checking)
+ echo -n "Copy files to which host?: "
+ read Host
+ echo -n "To which directory on $Host? :"
+ read Dir
+ rcp -pr %u "${Host}:${Dir}"
+
+= f \.tex$ & t r
++ f \.tex$ & t r & ! t t
+t Run latex on file and show it with xdvi
+ latex %f && xdvi "`basename %f .tex`".dvi
+
+=+ f ^part | f ^Part | f uue & t r
++ t t
+U Uudecode marked news articles (needs work)
+ (
+ for i in %t ; do # strip headers
+ FIRST=`awk '{print $1 ; exit}' "$i"`
+ cat "$i" | sed '/^'"$FIRST"' /,/^$/d'
+ done
+ ) | sed '/^$/d' | sed -n '/^begin 6/,/^end$/p' | uudecode
+ if [ "$?" != "0" ]; then
+ echo "Cannot decode "%t"."
+ fi
+ echo "Please test the output file before deleting anything."
+
+=+ f \.tar\.gz$ | f \.tar\.z$ | f \.tgz$ | f \.tpz$ | f \.tar\.lz$ | f \.tar\.lz4$ | f \.tar\.lzma$ | f \.tar\.7z$ | f \.tar\.xz$ | f \.tar\.zst | f \.tar\.Z$ | f \.tar\.bz2$ & t rl
+x Extract the contents of a compressed tar file
+ unset PRG
+ case %f in
+ *.tar.7z) PRG="7za e -so";;
+ *.tar.bz2) PRG="bunzip2 -c";;
+ *.tar.gz|*.tar.z|*.tgz|*.tpz|*.tar.Z) PRG="gzip -dc";;
+ *.tar.lz) PRG="lzip -dc";;
+ *.tar.lz4) PRG="lz4 -dc";;
+ *.tar.lzma) PRG="lzma -dc";;
+ *.tar.xz) PRG="xz -dc";;
+ *.tar.zst) PRG="zstd -dc";;
+ *) exit 1;;
+ esac
+ $PRG %f | tar xvf -
+
+= t r
++ ! t t
+y Gzip or gunzip current file
+ unset DECOMP
+ case %f in
+ *.gz|*.[zZ]) DECOMP=-d;;
+ esac
+ # Do *not* add quotes around $DECOMP!
+ gzip $DECOMP -v %f
+
++ t t
+Y Gzip or gunzip tagged files
+ for i in %t ; do
+ unset DECOMP
+ case "$i" in
+ *.gz|*.[zZ]) DECOMP=-d;;
+ esac
+ gzip $DECOMP -v "$i"
+ done
+
++ ! t t
+b Bzip2 or bunzip2 current file
+ unset DECOMP
+ case %f in
+ *.bz2) DECOMP=-d;;
+ esac
+ bzip2 $DECOMP -v %f
+
++ t t
+B Bzip2 or bunzip2 tagged files
+ for i in %t ; do
+ unset DECOMP
+ case "$i" in
+ *.bz2) DECOMP=-d;;
+ esac
+ bzip2 $DECOMP -v "$i"
+ done
+
++ f \.tar.gz$ | f \.tgz$ | f \.tpz$ | f \.tar.Z$ | f \.tar.z$ | f \.tar.bz2$ | f \.tar.F$ & t r & ! t t
+z Extract compressed tar file to subdirectory
+ unset D
+ set gzip -cd
+ case %f in
+ *.tar.F) D=`basename %f .tar.F`; set freeze -dc;;
+ *.tar.Z) D=`basename %f .tar.Z`;;
+ *.tar.bz2) D=`basename %f .tar.bz2`; set bunzip2 -c;;
+ *.tar.gz) D=`basename %f .tar.gz`;;
+ *.tar.z) D=`basename %f .tar.z`;;
+ *.tgz) D=`basename %f .tgz`;;
+ *.tpz) D=`basename %f .tpz`;;
+ esac
+ mkdir "$D"; cd "$D" && ("$1" "$2" ../%f | tar xvf -)
+
++ t t
+Z Extract compressed tar files to subdirectories
+ for i in %t ; do
+ set gzip -dc
+ unset D
+ case "$i" in
+ *.tar.F) D=`basename "$i" .tar.F`; set freeze -dc;;
+ *.tar.Z) D=`basename "$i" .tar.Z`;;
+ *.tar.bz2) D=`basename "$i" .tar.bz2`; set bunzip2 -c;;
+ *.tar.gz) D=`basename "$i" .tar.gz`;;
+ *.tar.z) D=`basename "$i" .tar.z`;;
+ *.tgz) D=`basename "$i" .tgz`;;
+ *.tpz) D=`basename "$i" .tpz`;;
+ esac
+ mkdir "$D"; (cd "$D" && "$1" "$2" "../$i" | tar xvf -)
+ done
+
++ f \.gz$ | f \.tgz$ | f \.tpz$ | f \.Z$ | f \.z$ | f \.bz2$ & t r & ! t t
+c Convert gz<->bz2, tar.gz<->tar.bz2 & tgz->tar.bz2
+ unset D
+ unset EXT
+ case %f in
+ *.Z) EXT=Z;;
+ *.bz2) EXT=bz2;;
+ *.gz) EXT=gz;;
+ *.tgz) EXT=tgz;;
+ *.tpz) EXT=tpz;;
+ *.z) EXT=z;;
+ esac
+ case "$EXT" in
+ bz2|Z|gz|z) D=`basename %f ."$EXT"`;;
+ tgz|tpz) D=`basename %f ."$EXT"`.tar;;
+ esac
+ if [ "$EXT" = "bz2" ]; then
+ bunzip2 -v %f
+ gzip -f9 -v "$D"
+ else
+ gunzip -v %f
+ bzip2 -v "$D"
+ fi
+
++ t t
+C Convert gz<->bz2, tar.gz<->tar.bz2 & tgz->tar.bz2
+ for i in %t ; do
+ unset D
+ unset EXT
+ case "$i" in
+ *.Z) EXT=Z;;
+ *.bz2) EXT=bz2;;
+ *.gz) EXT=gz;;
+ *.tgz) EXT=tgz;;
+ *.tpz) EXT=tpz;;
+ *.z) EXT=z;;
+ esac
+ case "$EXT" in
+ bz2|Z|gz|z) D=`basename "$i" ."$EXT"`;;
+ tgz|tpz) D=`basename "$i" ."$EXT"`.tar;;
+ esac
+ if [ "$EXT" = "bz2" ]; then
+ bunzip2 -v "$i"
+ gzip -f9 -v "$D"
+ else
+ gunzip -v "$i"
+ bzip2 -v "$D"
+ fi
+ done
+
++ x /usr/bin/open | x /usr/local/bin/open & x /bin/sh
+o Open next a free console
+ open -s -- sh
+
++ x /usr/bin/open | x /usr/local/bin/open & x /bin/sh
+O Odoo Refresh
+ sh /root/refresh_odoo.sh
+
++ x /usr/bin/open | x /usr/local/bin/open & x /bin/sh
+G git push
+ git push -u origin main
+
+
diff --git a/views/dss_addstructures.xml b/views/dss_addstructures.xml
new file mode 100755
index 0000000..046b7f9
--- /dev/null
+++ b/views/dss_addstructures.xml
@@ -0,0 +1,72 @@
+
+
+ Neuen Medienfiletyp erstellen
+
+ Neue Werbekampagne erstellen
+
+