import ast import datetime import json import re import uuid import logging import base64 import subprocess import tempfile import easywebdav import os import os.path import requests import hashlib from odoo import api, fields, models, _ from odoo import tools from odoo.exceptions import ValidationError from datetime import date from datetime import datetime from dateutil.relativedelta import relativedelta from pyffmpeg import FFmpeg from tuya_iot import TuyaOpenAPI, TUYA_LOGGER from tuya_connector import TuyaOpenAPI, TUYA_LOGGER import sys TUYA_LOGGER.setLevel(logging.DEBUG) _logger = logging.getLogger(__name__) class dssadvertisefields(models.Model): @api.model def create(self,vals): result = super().create(vals) result.issaved = True return result _name = "dss.advertisefields" _description = "DigitalSignage Werbefelder" _inherit = ['mail.thread','mail.activity.mixin'] _rec_name = "auto_feldname" # _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') issaved = fields.Boolean('ist gespeichert') isblocked = fields.Boolean('Nach Nutzung sperren',tracking=True, default=True) # uuid = fields.Char('UUID', required=True, translate=True) auto_feldname = fields.Char('Projekt_Feldname', default=lambda self: self._default_projektfeld(), required=True) display = fields.Char('Designname',tracking=True) feldname = fields.Char('Feldname', required=True,tracking=True) project = fields.Many2one('dss.projects' , string='Project', store=True,tracking=True) project_id = fields.Integer(related='project.projectid', string='Project ID',tracking=True) contract = fields.Many2many('dss.contracts' , string='Vertrag', store=True,tracking=True) contract_save = fields.Many2one('dss.contracts' , string='Vertrag', store=True,tracking=True) contract_project_id = fields.Integer(related='contract.project_id', string='Project ID',tracking=True) color_used = fields.Char(string='Color Index',tracking=True) color_unused = fields.Char(string='Color Index',tracking=True) mediastructure = fields.Many2one('dss.adstructures',string='Feldaufbau',tracking=True) mediastructure_medias = fields.Many2many(related='mediastructure.medias',string='Inhalt') mediarelations = fields.One2many('dss.mediarelations','relname',tracking=True) is_btn = fields.Boolean('Feld ist Button',help="Feld hat einen Button auf eineen TSS System ?",tracking=True, default=True) btn_displaytemplate = fields.Many2one('dss.display.templates',string="Bildschirmvorlage",tracking=True) btn_fromtemplate = fields.Many2one('dss.advertisefields.templates',string="Buttonvorlage",tracking=True) btn_pos_x = fields.Integer('Position im Display X (px)', tracking=True) btn_pos_y = fields.Integer('Position im Display Y (px)', tracking=True) btn_pos_w = fields.Integer('Breite des Feldes (px)', tracking=True) btn_pos_h = fields.Integer('Höhe des Feldes (px)', tracking=True) btn_name = fields.Char('Button name',tracking=True) btn_image = fields.Char('Button Bild Pfad',tracking=True) btn_image_hash = fields.Char('Button Bild Hash',tracking=True) btn_image_bin = fields.Binary('Button Bild Binary',tracking=True) btn_image_bin_base64 = fields.Char('Button Bild Base64',tracking=True,compute='_compute_base64', store=True) btn_fieldname = fields.Char('Feldname',tracking=True) btn_visible = fields.Boolean('Feld wird angezeigt',tracking=True, default=True) btn_active = fields.Boolean('Feld ist bedienbar/aktiv',tracking=True, default=True) btn_action_inactive = fields.Integer('Inaktiv Klickaktion',help='Aktion die ausgeführt wird bei click auf inaktiven Button - >0 und nicht activ = Baustellenbild bringen', tracking=True) btn_action_active = fields.Selection([('9','Spezialfenster'),('16','Internetfenster'),('3','Storry ausführen'),('2','Gallerie anzeigen'),('5','normales Verhalten'),('12','im Specialfenster das Fenster schliessen'),('14','im Specialfenster ein Bild anzeigen')],string='Aktive Klickaktion',help='Aktion die ausgeführt wird bei click auf Aktiven Button', tracking=True) btn_playlist_filename = fields.Char('Playlistendatei',help='Bei Aktion-Story = Storrydatei', tracking=True) btn_playlist_zuordnung = fields.Selection([('1','Standard Zuordnung - Pfad+SchemaID+File'),('20','Kunden Zuordnung - Pfad+KundenID+File'),('50','Gallerie Zuordnung - Pfad+GallerieID+File')], tracking=True) btn_gallery_filename = fields.Char('Galleriedatei',help="Gallerie Datei - Ohne Pfad, und Ohne .GAL",tracking=True) btn_gallery_id = fields.Char('Gallerie ID', tracking=True) btn_gallery_rows = fields.Integer('Zeilen der Gallery', tracking=True) btn_gallery_cols = fields.Integer('Spalten der Gallery', tracking=True) btn_gallery_prv_w = fields.Integer('Gallery Bildpreview Breite', tracking=True) btn_gallery_prv_h = fields.Integer('Gallery Bildpreview Höhe', tracking=True) btn_has_timer = fields.Boolean('Button Timeout',tracking=True, default=True) btn_has_timer_time = fields.Integer('Button Timer-Zeit', tracking=True) btn_editable = fields.Boolean('Button Editierbar',tracking=True, default=True) btn_special_actionimage = fields.Char('Anzeigebild Spezialform ', tracking=True) btn_special_actionimage_x = fields.Integer('X-Position Anzeigebild', tracking=True) btn_special_actionimage_y = fields.Integer('Y-Position Anzeigebild', tracking=True) btn_special_actionimage_w = fields.Integer('Breite Anzeigebild', tracking=True) btn_special_actionimage_h = fields.Integer('Hoehe Anzeigebild', tracking=True) btn_special_actionimage_time = fields.Integer('Anzeigezeit Anzeigebild', tracking=True) btn_center_video_1 = fields.Char('Zentralvideo 1', tracking=True) btn_center_video_2 = fields.Char('Zentralvideo 1', tracking=True) btn_center_video_3 = fields.Char('Zentralvideo 1', tracking=True) btn_center_video_4 = fields.Char('Zentralvideo 1', tracking=True) btn_text_1 = fields.Char('Textzeile 1', tracking=True) btn_text_2 = fields.Char('Textzeile 2', tracking=True) btn_text_3 = fields.Char('Textzeile 3', tracking=True) btn_text_4 = fields.Char('Textzeile 4', tracking=True) btn_text_1_visible = fields.Boolean('Textzeile 1 anzeigen',tracking=True, default=False) btn_text_2_visible = fields.Boolean('Textzeile 1 anzeigen',tracking=True, default=False) btn_text_3_visible = fields.Boolean('Textzeile 1 anzeigen',tracking=True, default=False) btn_text_4_visible = fields.Boolean('Textzeile 1 anzeigen',tracking=True, default=False) btn_text_1_pos_x = fields.Integer('Textzeile 1 X-Pos',help="xxxx direkter Zahlenwert , +/-xxxx relativ zu Button",tracking=True) btn_text_1_pos_y = fields.Integer('Textzeile 1 Y-Pos',help="xxxx direkter Zahlenwert , +/-xxxx relativ zu Button",tracking=True) btn_text_2_pos_x = fields.Integer('Textzeile 2 X-Pos',help="xxxx direkter Zahlenwert , +/-xxxx relativ zu Button",tracking=True) btn_text_2_pos_y = fields.Integer('Textzeile 2 Y-Pos',help="xxxx direkter Zahlenwert , +/-xxxx relativ zu Button",tracking=True) btn_text_3_pos_x = fields.Integer('Textzeile 3 X-Pos',help="xxxx direkter Zahlenwert , +/-xxxx relativ zu Button",tracking=True) btn_text_3_pos_y = fields.Integer('Textzeile 3 Y-Pos',help="xxxx direkter Zahlenwert , +/-xxxx relativ zu Button",tracking=True) btn_text_4_pos_x = fields.Integer('Textzeile 4 X-Pos',help="xxxx direkter Zahlenwert , +/-xxxx relativ zu Button",tracking=True) btn_text_4_pos_y = fields.Integer('Textzeile 4 Y-Pos',help="xxxx direkter Zahlenwert , +/-xxxx relativ zu Button",tracking=True) btn_text_1_font = fields.Char('Textzeile 1 Schriftart', tracking=True) btn_text_2_font = fields.Char('Textzeile 2 Schriftart', tracking=True) btn_text_3_font = fields.Char('Textzeile 3 Schriftart', tracking=True) btn_text_4_font = fields.Char('Textzeile 4 Schriftart', tracking=True) Field_notinCloud = fields.Boolean('Feld im Cloudname',tracking=True, default=True) loopfiles = fields.Char('Durchlaufdateien', tracking=True) def _default_projektfeld(self): return "000_unbekannt" def _default_create_date(self): return str(date.today()) def _default_create_user(self): self.issaved = True return str(self.env.user.name) @api.onchange('project') def _onchange_project(self): autoid = "" autoid = str(self.project_id)+"_"+str(self.feldname) self.auto_feldname = autoid @api.onchange('contract') def _onchange_contract(self): autoid = "" _logger.info('Contract Änderung prüfe Projekte !' + str(self.project_id) + ' / ' + str(self.contract_project_id)) if not self.project_id == self.contract_project_id: _logger.info('Contract Änderung unterschiedliche Projekte !'+str(self.project_id)+' / '+str(self.contract_project_id)) raise ValidationError(_("Gewähltes Projekt und Projekt des Vertrages sind unterschiedlich !")) else: autoid = str(self.project_id)+"_"+str(self.feldname) self.auto_feldname =autoid @api.onchange('mediastructure') def _onchange_mediastructure_id(self): restr = 'keine' for record in self : resstr = record.mediastructure.uuid mtyp = self.env['dss.adstructures'].search([("uuid","=",str(record.mediastructure.uuid))]) _logger.info(resstr) if mtyp: resstr = mtyp.structurename _logger.info(resstr + ' uuid : '+record.mediastructure.uuid) foundused = self.env['dss.mediarelations'].search_count(["&",('field_uuid','=',record.uuid),'|',('secured_ro','=',True),('used_ro','=',True)]) if foundused != 0 : _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 @api.model def _default_uuid(self): return str(uuid.uuid4()) def check_contract_multi_Values(self): for record in self: if not record.contract: record.contract = record.contract_save def pyactiontaketemplate(self): action = (self.env["confirmation.wizard"].confirm_message(_("Das Template wirklich übernehmen ?"),title="Bitte bestätigen",method="taketemplate",records=self,callback_params={"template":self.id}) ) if action: return action def taketemplate(self,template): self.btn_pos_x = self.btn_fromtemplate.btn_pos_x self.btn_pos_y = self.btn_fromtemplate.btn_pos_y self.btn_pos_w = self.btn_fromtemplate.btn_pos_w self.btn_pos_h = self.btn_fromtemplate.btn_pos_h self.btn_name = self.btn_fromtemplate.btn_name self.btn_fieldname = self.btn_fromtemplate.btn_fieldname self.btn_visible = self.btn_fromtemplate.btn_visible self.btn_active = self.btn_fromtemplate.btn_active self.btn_action_inactive = self.btn_fromtemplate.btn_action_inactive self.btn_action_active = self.btn_fromtemplate.btn_action_active self.btn_playlist_zuordnung = self.btn_fromtemplate.btn_playlist_zuordnung self.btn_gallery_rows = self.btn_fromtemplate.btn_gallery_rows self.btn_gallery_cols = self.btn_fromtemplate.btn_gallery_cols self.btn_gallery_prv_w = self.btn_fromtemplate.btn_gallery_prv_w self.btn_gallery_prv_h = self.btn_fromtemplate.btn_gallery_prv_h self.btn_has_timer = self.btn_fromtemplate.btn_has_timer self.btn_has_timer_time = self.btn_fromtemplate.btn_has_timer_time self.btn_editable = self.btn_fromtemplate.btn_editable self.btn_special_actionimage = self.btn_fromtemplate.btn_special_actionimage self.btn_special_actionimage_x = self.btn_fromtemplate.btn_special_actionimage_x self.btn_special_actionimage_y = self.btn_fromtemplate.btn_special_actionimage_y self.btn_special_actionimage_w = self.btn_fromtemplate.btn_special_actionimage_w self.btn_special_actionimage_h = self.btn_fromtemplate.btn_special_actionimage_h self.btn_special_actionimage_time = self.btn_fromtemplate.btn_special_actionimage_time self.btn_text_1_visible = self.btn_fromtemplate.btn_text_1_visible self.btn_text_2_visible = self.btn_fromtemplate.btn_text_2_visible self.btn_text_3_visible = self.btn_fromtemplate.btn_text_3_visible self.btn_text_4_visible = self.btn_fromtemplate.btn_text_4_visible self.btn_text_1_pos_x = self.btn_fromtemplate.btn_text_1_pos_x self.btn_text_1_pos_y = self.btn_fromtemplate.btn_text_1_pos_y self.btn_text_2_pos_x = self.btn_fromtemplate.btn_text_2_pos_x self.btn_text_2_pos_y = self.btn_fromtemplate.btn_text_2_pos_y self.btn_text_3_pos_x = self.btn_fromtemplate.btn_text_3_pos_x self.btn_text_3_pos_y = self.btn_fromtemplate.btn_text_3_pos_y self.btn_text_4_pos_x = self.btn_fromtemplate.btn_text_4_pos_x self.btn_text_4_pos_y = self.btn_fromtemplate.btn_text_4_pos_y self.btn_text_1_font = self.btn_fromtemplate.btn_text_1_font self.btn_text_2_font = self.btn_fromtemplate.btn_text_2_font self.btn_text_3_font = self.btn_fromtemplate.btn_text_3_font self.btn_text_4_font = self.btn_fromtemplate.btn_text_4_font def py_openadvfield(self): action = self.env["ir.actions.actions"]._for_xml_id("DigitalSignage.action_dss_advertisefields_fill") action['context']='{"active_id":'+str(self.id)+'}' action['res_id']=self.id return action def btn_image_import(self): action = self.env["confirmation.wizard"].confirm_message(_("Das Bild wirklich importieren ?"),title="Bitte bestätigen",method="btn_image_import_do",records=self,callback_params={"template":self.id}) if action: return action def btn_image_import_do(self,template): try: response = requests.get(self.btn_image, stream=True) if response.status_code == 200: # Encode the image content to base64 image_data = base64.b64encode(response.content) # Save the image to the Binary field self.btn_image_bin = image_data # Calculate the hash of the image image_hash = hashlib.sha256(response.content).hexdigest() # Save the hash to the hash field self.btn_image_hash = image_hash else: raise ValidationError(_("Failed to download the image. HTTP Status: %s") % response.status_code) except requests.exceptions.RequestException as e: raise ValidationError(_("An error occurred while downloading the image: %s") % str(e)) def btn_image_import_local(self): action = self.env["confirmation.wizard"].confirm_message(_("Das Bild wirklich importieren ?"),title="Bitte bestätigen",method="btn_image_import_do_local",records=self,callback_params={"template":self.id}) if action: return action @api.depends('btn_image_bin') def _compute_base64(self): for record in self: if record.btn_image_bin: record.btn_image_bin_base64 = 'data:image/png;base64,'+str(record.btn_image_bin) else: record.btn_image_bin_base64 = False