import ast import datetime import json import re from .dsslogger import OdooCustomLogger import logging import uuid import base64 import subprocess import tempfile import requests #from symbol import return_stmt import json from types import SimpleNamespace import easywebdav import os import os.path from odoo import api, fields, models, _ from odoo import tools from odoo.exceptions import ValidationError from . import dss_settings 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) logging.setLoggerClass(OdooCustomLogger) _logger = logging.getLogger(__name__) class dssprojects(models.Model): _name = "dss.projects" _description = "DigitalSignage Projekte" _rec_name = "projektname" _inherit = ['mail.thread','mail.activity.mixin','dss.triggermodel'] 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',tracking=True) color = fields.Char('Color Index',tracking=True) active = fields.Boolean('Active', default=True,tracking=True) invisible = fields.Boolean('Ausgeblendet', default=False,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',tracking=True) short_partner_description = fields.Char('Kurz-Beschreibung für Kunden',tracking=True) partner_description = fields.Text('Beschreibung für Kunden',tracking=True) systemname = fields.Many2one('dss.systems',tracking=True) grundsystemname = fields.Many2one('dss.systemtypen',group_expand='_read_group_system_ids',tracking=True) grundsystem_typ = fields.Char(related='grundsystemname.kennung',tracking=True) grundsystemnameuuid = fields.Char(related='grundsystemname.uuid',tracking=True) grundsystemicon = fields.Image(related='grundsystemname.icon',tracking=True) grundsystem_default_adstructure = fields.Many2one(related='grundsystemname.default_adstructure',tracking=True) grundsystemicon5050 = fields.Image(related='grundsystemname.icon_5050') grundsystem_ordner = fields.Char(related='grundsystemname.default_cloud_path') grundsystem_showonlinestate = fields.Boolean(related='grundsystemname.showonlinestate') grundsystem_showonlinestate_type = fields.Selection(related='grundsystemname.showonlinestate_type') standort = fields.Char('Beschreibung des Standortes') standort_strasse = fields.Char('Strasse des Projektes',tracking=True) standort_plz = fields.Char('PLZ des Projektes',tracking=True) standort_ort = fields.Char('Ort des Projektes',tracking=True) standort_bundesland = fields.Many2one('res.country.state',string='Bundesland des Projektes',tracking=True) standort_land = fields.Many2one('res.country',string='Land des Projektes',tracking=True) standort_long = fields.Char('Standort Longitude',tracking=True) standort_lati = fields.Char('Standort Latitude',tracking=True) standort_visible = fields.Boolean('Auf Projekt-Karte sichtbar',tracking=True) zahlungsvorlauf = fields.Integer('Wochen Zahlungsvorlauf', tracking=True) maps_name = fields.Char('Name in Google',tracking=True) maps_type = fields.Char('Type in Google',tracking=True) maps_marker = fields.Selection([('m1.png','Marker 1'),('m2.png','Marker 2'),('m3.png','Marker 3'),('m4.png','Marker 4'),('m5.png','Marker 5'),('pin.png','Marker Pin'),('pin2.png','3D Marker Pin'),('pin_display.png','Displpay Pin'),('pin_display_touch.png','TouchDisplpay Pin'),('pin_led.png','LEDWand Pin')],'Marker in Google',tracking=True) maps_image = fields.Binary('Google Bild',tracking=True) maps_image_2 = fields.Binary('Google Bild 2',tracking=True) maps_image_3 = fields.Binary('Google Bild 3',tracking=True) maps_text = fields.Html('Google Beschreibung',tracking=True) maps_typ_interactive = fields.Boolean('Ist Interactive ?', tracking=True) maps_visitors = fields.Integer('Besucher pro Tag', tracking=True) maps_displaytyp = fields.Char('Anzeigetyp in Google', tracking=True) maps_displaysize = fields.Char('Anzeigegroesse in Google',tracking=True) maps_werbeflaechen_a_free = fields.Boolean('Werbeflächen 1 Frei', tracking=True) maps_werbeflaechen_a = fields.Char('Werbeflächenbeschreibung 1',tracking=True) maps_werbeflaechen_b_free = fields.Boolean('Werbeflächen 2 Frei', tracking=True) maps_werbeflaechen_b = fields.Char('Werbeflächenbeschreibung 2',tracking=True) maps_werbemedien = fields.Char('Werbeflächen-Dateien',tracking=True) maps_freespaces_b_show = fields.Boolean('Freie Flächen zeigen ?', tracking=True) maps_freespaces_b = fields.Char('Freie Werbeflächen',tracking=True) 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) project_grafiker = fields.Many2one('res.partner',domain="['&',('dssinternpartner','=',True),('dssinternpartner_grafik','=',True)]",tracking=True) zeiten_on = fields.Datetime('veraltet',tracking=True) zeiten_off = fields.Datetime('veraltet',tracking=True) zeitenf_on = fields.Float('Einschaltzeit',tracking=True) zeitenf_off = fields.Float('Ausschaltzeit',tracking=True) zeiten_notiz = fields.Char('Schaltzeiten Notizen', tracking=True) errichtet_am = fields.Date('Errichtungstag',tracking=True) standort_inout = fields.Selection([('indoor','im Gebäude'), ('outdoor','Aussenbereich'), ('semiindoor','Überdachter Aussenbereich'),('Divers','Andere Art')],tracking=True) date_start_compute = fields.Date('Kalender Start intern',compute='_compute_calendar_start') cloudlink = fields.Char('Cloud Verzeichnis',help='Verzeichnis für das Project innerhalb des Cloud Struktur') maintains = fields.Many2many('dss.maintaintask',string="Einsätze am Projekt") marker_list = fields.Many2many('dss.marker', string='vorhandene Marker', tracking=True) onlinestate_1 = fields.Char('OnlineColor_1') playername_1 = fields.Char('Name des Players_1', tracking=True) onlinestate_2 = fields.Char('OnlineColor_2') playername_2 = fields.Char('Name des Players_2', tracking=True) onlinestate_3 = fields.Char('OnlineColor_3') playername_3 = fields.Char('Name des Players_3', tracking=True) Rportid_1 = fields.Char('RPort ID 1', tracking=True) Rportid_2 = fields.Char('RPort ID 2', tracking=True) Rportid_3 = fields.Char('RPort ID 3', tracking=True) issim = fields.Boolean('Sim Karte genutzt ?', tracking=True) simid_1 = fields.Char('Simkarte Nr 1', tracking=True) simstart_1 = fields.Char('Simkarte 1 Vertr.start', tracking=True) simstart_DVEmpty_1 = fields.Boolean('Simkarte 1 DV leer', tracking=True) simstart_DVEmpty_1_lastdate = fields.Date('Simkarte 1 Leerdatum', tracking=True) simid_2 = fields.Char('Simkarte Nr 2', tracking=True) simstart_2 = fields.Char('Simkarte 2 Vertr.start', tracking=True) simstart_DVEmpty_2 = fields.Boolean('Simkarte 2 DV leer', tracking=True) simstart_DVEmpty_2_lastdate = fields.Date('Simkarte 2 Leerdatum', tracking=True) simid_3 = fields.Char('Simkarte Nr 3', tracking=True) simstart_3 = fields.Char('Simkarte 3 Vertr.start', tracking=True) simstart_DVEmpty_3 = fields.Boolean('Simkarte 3 DV leer', tracking=True) simstart_DVEmpty_3_lastdate = fields.Date('Simkarte 3 Leerdatum', tracking=True) @api.model def _read_group_system_ids(self, stages, domain, order): project_system_ids = self.env['dss.systemtypen'].search([('open_close_standard_state','=',False)], order='order') return project_system_ids def jumpcloud(self): urlbase=str(self.env['dss.settings'].search([], limit=1).def_cloud_url_base) _logger.info("Cloud Open Link Urlbase DB " + str(urlbase)) if not urlbase: urlbase = 'https://cloud.logumedia.de/index.php/apps/files/?dir='; _logger.info("Cloud Open Link Urlbase Used " + str(urlbase)) url=str(urlbase)+str(dss_settings.dssSettings._get_path_converted(self,self.cloudlink,self)) _logger.info("Cloud Open Link " + str(url)) return { 'type': 'ir.actions.act_url', 'url': str(url), 'target': 'new', } @api.model def _compute_calendar_start(self): for record in self: if record.errichtet_am: record.date_start_compute=record.errichtet_am else: record.date_start_compute=date.today() @api.model def _default_uuid(self): return str(uuid.uuid4()) def _track_template(self, changes): res = super()._track_template(changes) if self.run_trigger: self.trigger_track_template(changes, self) return res def pyaction_view_contracts(self): # action = self.env['ir.actions.act_window'].with_context({'default_project': self.id})._for_xml_id('DigitalSignage.action_dss_project_contracts') # action['display_name'] = self.projektname # context = action['context'].replace('active_id', str(self.id)) # domain = action['domain'].replace('active_id', str(self.id)) # _logger.info('Vertraege fuer : '+str(self.id)) return { 'type': 'ir.actions.act_window', 'view_type':'kanban', 'view_mode':'kanban,tree', 'res_model':'dss.contracts', 'target':'current', 'context':'{"default_project":'+str(self.id)+',"show_project_update":True}', 'res_id':self.id, 'display_name' : self.name, 'domain':'[("project","=",'+str(self.id)+')]' } # context = ast.literal_eval(context) # context = "{ # 'create': self.active, # 'active_test': self.active # }7 # action['context'] = context # action['domain'] = domain # return action @api.onchange('cloudlink') def _onchange_cloudlink(self): _logger.info("Project "+str(self.id)+" Cloudpath changed") if (self.cloudlink == ''): if (self._origin.cloudlink != ''): _logger.info("Project " + str(self.id) + " deleted - using standard path") self.cloudlink = dss_settings.dssSettings._get_path_converted(self,self.env['dss.settings'].search([],limit=1).def_project_cloudpath,self) def switch_invislbe(self): return { 'type': 'ir.actions.act_window', 'view_type':'kanban', 'view_mode':'kanban,tree', 'res_model':'dss.contracts', 'target':'current', 'context':'{"default_project":'+str(self.id)+',"show_project_update":True}', 'res_id':self.id, 'display_name' : self.projektname, 'domain':'[("project","=",'+str(self.id)+')]' } @api.model def _geo_localize(self, street='', zip='', city='', state='', country=''): geo_obj = self.env['base.geocoder'] search = geo_obj.geo_query_address(street=street, zip=zip, city=city, state=state, country=country) result = geo_obj.geo_find(search, force_country=country) if result is None: search = geo_obj.geo_query_address(city=city, state=state, country=country) result = geo_obj.geo_find(search, force_country=country) return result def dss_geo_localize(self): # We need country names in English below result = self._geo_localize(self.standort_strasse, self.standort_plz, self.standort_ort, self.standort_bundesland.name, self.standort_land.name) if result: self.write({ 'standort_lati': result[0], 'standort_long': result[1] }) else: partners_not_geo_localized |= partner return True def pyaction_dss_project_set_def_cloud(self): self.cloudlink = str(self.env['dss.settings'].search([], limit=1).def_project_cloudpath) return True @api.model def _compute_getonlinestate(self): colorval = "#a0a0a0" self.onlinestate = colorval @api.model def compute_getonlinestate2(self,project): projekte = self.env['dss.projects'].search([('grundsystem_showonlinestate','=',True)]) for pro in projekte: self.compute_getonlinestate_single(pro) def compute_getonlinestate_single(self,project): #proj = self.env['dss.projects'].search([('id',"=",project.id)]) proj = project colorOn = str(self.env['dss.settings'].search([], limit=1).systemonline_color) colorOff = str(self.env['dss.settings'].search([], limit=1).systemoffline_color) _logger.info("Projekt Online Settings Check "+str(proj.grundsystem_showonlinestate_type)+' '+str(self)+' '+str(project)) if (proj.grundsystem_showonlinestate_type == 'RPORT'): playername = proj["Rportid_1"] _logger.info("Projekt RPORT Settings "+str(playername) ) if playername!=False: rporturl = str(self.env['dss.settings'].search([], limit=1).rporturl)+'/api/v1/clients/' rportusername = str(self.env['dss.settings'].search([], limit=1).rportusername) rporttoken = str(self.env['dss.settings'].search([], limit=1).rporttoken) auth = (rportusername, rporttoken) for plnr in range(1,4): playername = proj["Rportid_"+str(plnr)] if playername: _logger.info("RPORT request :"+str(rporturl)+str(playername)) r = requests.get(str(rporturl)+str(playername), auth=auth, verify=False) _logger.info("RPORT answere :"+str(r.status_code)+' - '+str(r.content)) if (str(r.status_code) == "200"): content = str(r.json()) index = content.find("connection_state") content = content[index+20:] index = content.find("',") token = content[:index] if (self.env['dss.onlinestate'].search([("project","=",proj.id),("number","=",plnr)], order="date_create desc", limit=1) == False): self.env['dss.onlinestate'].create({'project':proj.id,'number':plnr,'online':False}) laststate = self.env['dss.onlinestate'].search([("project","=",proj.id),("number","=",plnr)], order="date_create desc", limit=1).online _logger.info("RPORT answere :"+str(token)+"/"+str(laststate)) if token == 'connected': colorval = colorOn if not laststate: self.env['dss.onlinestate'].create({'project':proj.id,'number':plnr,'online':True}) else: colorval = colorOff if laststate: self.env['dss.onlinestate'].create({'project':proj.id,'number':plnr,'online':False}) else: colorval = colorOff else: colorval = 0 proj['onlinestate_'+str(plnr)]=colorval else: colorval = 0 proj['onlinestate_1']=colorval elif (proj.grundsystem_showonlinestate_type == 'VNNOX'): vnurl = str(self.env['dss.settings'].search([], limit=1).vnnoxurl)+'/Rest/Logon' vnusername = str(self.env['dss.settings'].search([], limit=1).vnnoxusername) vnpassword = str(self.env['dss.settings'].search([], limit=1).vnnoxpassword) # _logger.info("Projekt VNNOX Settings " + str(vnurl)) r = requests.post(vnurl, json={"password": vnpassword,"username": vnusername}) if (str(r.status_code) == "200"): content = str(r.json()) index = content.find("token") content = content[index+9:] index = content.find("',") token = content[:index] for plnr in range(1,4): playername = proj["playername_"+str(plnr)] if playername!=False: # _logger.info("Projekt VNNOX Settings Token : /" + str(token)+"/") vnurl_getPlayer = str(self.env['dss.settings'].search([], limit=1).vnnoxurl)+'/Rest/Player?offset=0&limit=10&sort=name&sortType=asc&search='+str(playername) headers = {'token': token} r = requests.get(vnurl_getPlayer, headers=headers) if (str(r.status_code) == "200"): _logger.info("Projekt VNNOX Settings Data : /" + str(r.content)+"/") resj = json.loads(r.content) if resj["data"]["count"] == "1": if (self.env['dss.onlinestate'].search([("project","=",proj.id),("number","=",plnr)], order="date_create desc", limit=1) == False): self.env['dss.onlinestate'].create({'project':proj.id,'number':plnr,'online':False}) laststate = self.env['dss.onlinestate'].search([("project","=",proj.id),("number","=",plnr)], order="date_create desc", limit=1).online _logger.info("Projekt VNNOX Settings Data : /" + str(resj["data"]["playerInfo"][0]["online"])+"/"+str(laststate)) if resj["data"]["playerInfo"][0]["online"] == "1": colorval = colorOn if not laststate: self.env['dss.onlinestate'].create({'project':proj.id,'number':plnr,'online':True}) else: colorval = colorOff if laststate: self.env['dss.onlinestate'].create({'project':proj.id,'number':plnr,'online':False}) else: colorval = "#a0a0a0" else: colorval = "#a0a0a0" proj['onlinestate_'+str(plnr)]=colorval else: colorval = "0" proj['onlinestate_'+str(plnr)]=colorval else: colorval = "#a0a0a0" proj['onlinestate_1']=colorval else: colorval = "#a0a0a0" proj['onlinestate_1']=colorval def method(self): return ( self.env["confirmation.wizard"] .with_context(hide_cancel=True) .confirm_no_action_message( message="Message", title="Notification" ) )