diff --git a/__manifest__.py b/__manifest__.py index 6c4b2e5..05a87f1 100755 --- a/__manifest__.py +++ b/__manifest__.py @@ -13,16 +13,18 @@ 'data': [ 'security/groups.xml', 'security/ir.model.access.csv', - 'views/menu.xml', + 'views/dss_contracts.xml', 'views/dss_projectstate.xml', 'views/dss_systemtypen.xml', + 'views/dss_mediarelations.xml', + 'views/dss_advertisementfields.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/menu.xml', 'views/company_view.xml', ], 'demo': [], diff --git a/models/__pycache__/dss.cpython-311.pyc b/models/__pycache__/dss.cpython-311.pyc index 2249ac0..922504d 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 375e79b..2160b0d 100755 --- a/models/dss.py +++ b/models/dss.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# -*- coding: utf-8 -* import ast import json @@ -12,10 +12,12 @@ 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 +from pyffmpeg import FFmpeg _logger = logging.getLogger(__name__) @@ -28,6 +30,15 @@ def _generate_preview_from_binary(self, videofile_file): return base64.b64encode(out) +def _generate_preview_from_binary_2(self, videofile_file): + ff=FFmpeg() + 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 @@ -53,21 +64,33 @@ class dsscontracts(models.Model): # ds = return ds + def _default_get_ads_last_ad(self): + _logger.info('finding Standard ad '+self.id) + ds = self.env['dss.ads'].search([('contract','=',self.id),('ad_is_lastpos','=',True)],limit=1) + if not ds: + ds = self.env['dss.ads'].search([('contract','=',self.id)],limit=1) + return ds _name = "dss.contracts" _description = "DigitalSignage Vertraege" _rec_name = "contract_auto_name" _inherit = ['mail.thread','mail.activity.mixin'] uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID') + cruuid = fields.Char(related='uuid') 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",tracking=True) contract_auto_name = fields.Char('Vertragskennug',tracking=True) + + contract_remark = fields.Html('Vertragshinweise',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',tracking=True) + project_ad_structure = fields.Many2one(related='project.grundsystem_default_adstructure', string='Aufbau') + 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") @@ -87,7 +110,14 @@ class dsscontracts(models.Model): client_other_projects = fields.Many2many('dss.projects',string='Weitere Projekte',tracking=True) - werbe_feld_selected = fields.Many2many('dss.advertisefields',string='Werbefelder',tracking=True) + werbe_feld_selected = fields.One2many('dss.advertisefields','contract',string='Werbefelder',tracking=True) + + need_media = fields.Many2many('dss.mediarelations','mediarelations_contract_rel','contract_id','mediarelations_id',string='benötigte Medien') + last_media = fields.One2many('dss.mediarelations','contract',string='Medien') +# last_media = fields.Many2many('dss.mediarelations','mediarelations_ad_relations','contract_id','mediarelations_id',string='Medien') +# need_media = fields.Many2many('dss.mediarelations','contract',string='Medien') +# need_media_computed = fields.One2many('dss.mediarelations','field',compute='_get_media_list') +# need_media_computed = fields.One2many('dss.mediarelations','uuid',domain="[('field','in',werbe_feld_selected)]") main_runtime = fields.Integer('Gesamtlaufzeit',tracking=True) split_runtime_count = fields.Integer('Laufzeit Teilungen',tracking=True) @@ -107,6 +137,17 @@ class dsscontracts(models.Model): base_ad = fields.Many2one('dss.ads',tracking=True) ads = fields.One2many('dss.ads','contract',tracking=True) + ads_last_ad = fields.Many2one('dss.ads', help="letzte Werbekampagne",computed='_default_get_ads_last_ad',store=True) + ads_last_state = fields.Many2one(related='ads_last_ad.ad_state', help="Status des letzten Werbekampagnen Eintrags") + ads_last_state_color = fields.Char(related='ads_last_ad.ad_state_color') + ads_last_state_text = fields.Char(related='ads_last_ad.ad_state_text') + ads_last_work_state = fields.Many2one(related='ads_last_ad.work_state', help="Arbeitsstatus des letzten Werbekampagnen Eintrags") + ads_last_work_state_color = fields.Char(related='ads_last_ad.work_state_color') + ads_last_work_state_text = fields.Char(related='ads_last_ad.work_state_text') + ads_last_todo_state = fields.Many2one(related='ads_last_ad.todo_state', help="Aufgabenstatus des letzten Werbekampagnen Eintrags") + ads_last_todo_state_until = fields.Date(related='ads_last_ad.todo_state_until') + ads_last_todo_state_color = fields.Char(related='ads_last_ad.todo_state_color') + ads_last_todo_state_text = fields.Char(related='ads_last_ad.todo_state_text') vnnox_zugang_erstellt = fields.Boolean('Vnnox Zugang ?',tracking=True) vnnox_zugang_username = fields.Char('Vnnox Username',tracking=True) @@ -133,18 +174,35 @@ class dsscontracts(models.Model): 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 = 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',tracking=True) - 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',tracking=True) - todo_state_until = fields.Date('Abarbeiten bis',tracking=True) +# 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',tracking=True) +# todo_state_until = fields.Date('Abarbeiten bis',tracking=True) - cloud_contract_directory = fields.Char('Cloud Kunden Ordner',tracking=True) + cloudlink = fields.Char('Cloud Verzeichnis',help='Verzeichnis für das Project innerhalb des Projekt Ordners') + + @api.onchange('werbe_feld_selected') + def _onchange_werbe_feld_selected(self) : + for record in self : +# self.write({'need_media': [(5,0,0)]}) + medias_ids = [] + for feld in record.werbe_feld_selected: + _logger.info("Feld : %s %s" % (record._origin.id,feld._origin.id)) + medias = self.env['dss.mediarelations'].search([('field','=',feld._origin.id)]) + for med in medias: + med.contract=record._origin.id + medias_ids.append(med.id) + self.write({'need_media': [(6,0,medias_ids)]}) + _logger.info("Media : "+str(record.need_media)) +# mrelobj.write({'field': feldid }) +# mrelobj.write({'project': record.project.id}) + @api.constrains('client_id') def _check_client_id(self) : @@ -195,7 +253,6 @@ class dsscontracts(models.Model): resstr = 'nicht ermittelbar' _logger.debug(resstr) self.contract_auto_name = resstr - # @api.model # def create(self,vals): @@ -205,10 +262,12 @@ class dsscontracts(models.Model): # contract=super().create(vals) # return contract + @api.model def _default_uuid(self): return str(uuid.uuid4()) + @api.model def _getdefwscolor(self): return str('#ffffff') @@ -236,41 +295,115 @@ class dsscontracts(models.Model): 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'] + _logger.info('Click auf Werbekampagne : C_'+str(self.id)+' - prüfe Letzte Aktuelle Kampagne') +# action = self.env['ir.actions.act_window'].with_context({'default_contractid': self.id})._for_xml_id('DigitalSignage.action_dss_ads_view') +# context = action['context'] + ds = self.env['dss.ads'].search([('contract','=',self.id),('ad_is_lastpos','=',True)],limit=1) + if not ds: + _logger.info('Click auf Werbekampagne : C_'+str(self.id)+' - keine letzte Kampagne') + ds = self.env['dss.ads'].search([('contract','=',self.id)],limit=1) + else: + _logger.info('Click auf Werbekampagne : C_'+str(self.id)+'A_'+str(ds.id)+' - Kampagne gefunden ') + self.ads_last_ad = ds +# prüfen ob LetzteKampagne medien hat + _logger.info('Click auf Werbekampagne : C_'+str(self.id)+'A_'+str(ds.id)+' - Suche evtl Medien der Kampagne ') + medias = self.env['dss.mediarelations'].search(['&',('contract','=',self.id),('ad','=',ds.id)]) + if medias: + _logger.info('Click auf Werbekampagne : C_'+str(self.id)+'A_'+str(ds.id)+' - Medien gefunden '+str(medias.ids)) + self.write({'last_media': [(6,0,medias.ids)]}) + else: + _logger.info('Click auf Werbekampagne : C_'+str(self.id)+'A_'+str(ds.id)+' - Keine Medien gefunden ') + +# Medien erzeugen wenn nicht vorhanden 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 + _logger.info('Click auf Werbekampagne : '+str(self.id)+' 3') + if not kampagne: + _logger.info('Click auf Werbekampagne : '+str(self.id)+' kein kampagne') + defadstate = self.env['dss.adstate'].search([('func','=','STD')],limit=1) + if not defadstate : + _logger.info('Click auf Werbekampagne : '+str(self.id)+' kein defstate') + defadstateid = 1 + else: + defadstateid = defadstate.id + kampagne = self.env['dss.ads'].create({'contract': self.id, 'project': self.project.id, 'adname': 'WK '+self.contract_auto_name,'adtype':'MAIN','ad_state':defadstateid}) + self.ads_last_ad = kampagne.id + _logger.info('Click auf Werbekampagne : '+str(self.id)+' Kampagne erstellt '+str(kampagne.id)) + kampagne.parent_ad = kampagne.id + mediaids = [] + for singlemedi in self.need_media: + if not singlemedi: + _logger.info('Prüfe Medien : C_'+str(self.id)+'K_'+str(kampagne.id)+' Kein Medium in NEED_MEDIA') + else: + newmedi=singlemedi.copy({'contract':self.id,'ad':kampagne.id}) + _logger.info('Prüfe Medien : C_'+str(self.id)+'K_'+str(kampagne.id)+' setze Vertrag für Medium : '+str(newmedi.contract)+'/'+str(newmedi.ad)) + mediaids.append(newmedi.id) + kampagne.write({'need_media': [(6,0,mediaids)]}) + _logger.info('Click auf Werbekampagne : '+str(self.id)+'/'+str(kampagne.id)+' setze Media '+str(kampagne.need_media)) + else: + _logger.info('Click auf Werbekampagne : '+str(self.id)+' mind. 1 Kampagne vorhanden '+str(kampagne.id)) + _logger.info('Prüfe Medien : C_'+str(self.id)) + kampagnen=self.env['dss.ads'].search([('contract','=',self.id)]) + _logger.info('Prüfe Medien : C_'+str(self.id)+' alle Kamp : '+str(kampagnen)) + for kamp in kampagnen: + _logger.info('Prüfe Medien : C_'+str(self.id)+'K_'+str(kamp.id)) + if kamp: + mediaids = [] + medias = self.env['dss.mediarelations'].search([('ad','=',kamp.id)]) + if not medias: + _logger.info('Prüfe Medien : C_'+str(self.id)+'K_'+str(kamp.id)+' keine Medien gefunden !') + for singlemedi in self.need_media: + if not singlemedi: + _logger.info('Prüfe Medien : C_'+str(self.id)+'K_'+str(kamp.id)+' Kein Medium in NEED_MEDIA') + else: + newmedi=singlemedi.copy({'ad':kamp.id}) + _logger.info('Prüfe Medien : C_'+str(self.id)+'K_'+str(kamp.id)+' Kopiere Medium : '+str(singlemedi)+' -> '+str(newmedi)) + _logger.info('Prüfe Medien : C_'+str(self.id)+'K_'+str(kamp.id)+' Medien evtl erstellt !') + medias = self.env['dss.mediarelations'].search([('ad','=',kamp.id)]) + _logger.info('Click auf Werbekampagne : C_'+str(self.id)+'K_'+str(kamp.id)+' neue Media '+str(mediaids)) + kamp.write({'need_media': [(6,0,medias.ids)]}) +# self.write({'need_media': [(5,0,0)]}) +# _logger.info('Click auf Werbekampagne : C_'+str(self.id)+'K_'+str(kamp.id)+' setze Media '+str(kamp.need_media)) + else: + _logger.info('Prüfe Medien : C_'+str(self.id)+'K_'+str(kamp.id)+' Medien gefunden !') + medias = self.env['dss.mediarelations'].search([('ad','=',kamp.id)]) +# mediaids.append(medias.ids) + _logger.info('Click auf Werbekampagne : C_'+str(self.id)+'K_'+str(kamp.id)+' gefundene Media '+str(mediaids)) + kampagne=self.env['dss.ads'].browse(kamp.id) + _logger.info('Click auf Werbekampagne : C_'+str(self.id)+'K_'+str(kamp.id)+' gefundene Media '+str(mediaids)+' Kampagne '+str(kampagne)) + if kampagne.need_media != medias: + _logger.info('Click auf Werbekampagne : C_'+str(self.id)+'K_'+str(kamp.id)+' Media unterschiede - setze Media '+str(mediaids)+'/'+str(kampagne.need_media)) + else: + _logger.info('Click auf Werbekampagne : C_'+str(self.id)+'K_'+str(kamp.id)+' Media gleich '+str(kampagne.need_media)) + else: + _logger.info('Prüfe Medien : C_'+str(self.id)+'K_'+str(kamp.id)+' Keine Kampagne gefunden !') +# _logger.info('Click auf Werbekampagne : '+str(self.id)+' 4 '+str(kampagne.id)) return { 'type': 'ir.actions.act_window', 'view_type':'form', 'view_mode':'form,tree', 'res_model':'dss.ads', 'target':'current', + 'context':'{"kampagne_id":'+str(kampagne.id)+',"show_project_update":True}', 'context':'', 'res_id':kampagne.id, 'display_name' : 'Änderung zur Werbekampagne '+kampagne.parent_ad.adname, - 'domain':'[("id","=","context[kampagne.id]")]' + 'domain':'[("id","=","context[kampagne_id]")]' } - @api.model - def pyaction_view_contract(self): - action = self.env['ir.actions.act_window'].with_context({'default_contractid': self.id})._for_xml_id('DigitalSignage.act_dss_project_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 action + def pyaction_view_contract(self): + view = self.env.ref('DigitalSignage.dss_main_contracts_form') + _logger.debug('Click auf Vertrag : '+str(self.id)) + return { + 'type': 'ir.actions.act_window', + 'view_mode': 'form' , + 'view_id': view.id, + 'res_model': 'dss.contracts' , + 'target': 'current' , + 'display_name' : self.contract_name, + 'views':[(view.id,'form')], + 'res_id': self.id , + } def pyaction_new_contract_kanban(self): action = self.env['ir.actions.act_window'].with_context({'default_contractid': self.id})._for_xml_id('DigitalSignage.action_dss_project_new_contract_kanban') @@ -311,6 +444,7 @@ class dssmain(models.Model): systemname = fields.Many2one('dss.systems',tracking=True) grundsystemname = fields.Many2one('dss.systemtypen',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') 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) @@ -320,23 +454,37 @@ class dssmain(models.Model): 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) + cloudlink = fields.Char('Cloud Verzeichnis',help='Verzeichnis für das Project innerhalb des Cloud Struktur') @api.model def _default_uuid(self): return str(uuid.uuid4()) 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)) +# 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.projektname, + 'domain':'[("project","=",'+str(self.id)+')]' + } # context = ast.literal_eval(context) # context = "{ # 'create': self.active, # 'active_test': self.active # } - action['context'] = context - return action +# action['context'] = context +# action['domain'] = domain +# return action @@ -566,7 +714,7 @@ class dssadstatus(models.Model): # uuid = fields.Char('UUID', required=True, translate=True) statusname = fields.Char('Statusname', required=True) color = fields.Char(string='Color Index') - default = fields.Boolean('Standardwert ?') + func = fields.Selection([('STD','Standard'), ('FIN','Endzustand'), ('WOR','Arbeitszustand')]) icon = fields.Image() order = fields.Integer('Reihenfolge') @@ -619,7 +767,7 @@ class dsstodostatus(models.Model): 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) - statusnr = fields.Integer('Litenpostion', required=True) + statusnr = fields.Integer(default=lambda self: self._default_statusnr(),string='Listenpostion', required=True) color = fields.Char(string='Color Index') icon = fields.Image() @@ -627,20 +775,74 @@ class dsstodostatus(models.Model): def _default_uuid(self): return str(uuid.uuid4()) + @api.model + def _default_statusnr(self): + return str(1) + 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 = "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') # uuid = fields.Char('UUID', required=True, translate=True) feldname = fields.Char('Feldname', required=True) project = fields.Many2one('dss.projects' , string='Project', store=True) project_id = fields.Integer(related='project.projectid', string='Project ID') + contract = fields.Many2one('dss.contracts' , string='Vertrag', store=True) color_used = fields.Char(string='Color Index') color_unused = fields.Char(string='Color Index') - icon = fields.Image() + 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) + + 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('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 : + self.env['dss.mediarelations'].search([('field_uuid','=',record.uuid)]).unlink() + for media in mtyp.medias : + resstr = media.medianame + _logger.info('Erstellung : '+str(self._origin.id)+'/'+str(record.id)+'('+str(record._origin.id)+')/'+str(media.id)+'/'+str(record.project.id)+' '+str(restr)) + mrelobj = self.env['dss.mediarelations'].create({'field':record.id,'relname':resstr,'mediatype': media.id,'field_uuid':record.uuid,'project':record.project.id}) + feldid = self._origin.id + mrelobj.write({'field': feldid }) + mrelobj.write({'project': record.project.id}) + _logger.info('Erzeugt : '+str(mrelobj)+' - '+str(mrelobj.project)+' - '+str(mrelobj.field)) + 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 @api.model def _default_uuid(self): @@ -692,10 +894,12 @@ class dssmediatypes(models.Model): 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') + cloudlink = fields.Char('Cloud Verzeichnis',help='Verzeichnis für diese Datei innerhalb des Vertrags-Ordners') + filepartname = fields.Char('Part.Dateiname',help='Teil des Dateinamens. Wird ergaenzt durch KampagnenID und MedienID. Beispiel : PNAME_34_544.jpg') maxsize_kb = fields.Integer('Maximale Größe KB') maxsize_w = fields.Integer('Maximale Pixel W') maxsize_h = fields.Integer('Maximale Pixel H') + standard_image = fields.Image() @api.model def _default_uuid(self): @@ -703,55 +907,52 @@ class dssmediatypes(models.Model): 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'] + _inherit = [] _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') + field = fields.Many2one('dss.advertisefields',string='Feld') + contract = fields.Many2one(related='field.contract',string='Vertrag') + ad = fields.Many2one('dss.ads',string='Werbekampagne') + project = fields.Many2one('dss.projects',string='Werbeprojekt') mediatype = fields.Many2one('dss.mediatypes',string='Medientyp') mediatype_type = fields.Selection(related='mediatype.mediatype',string='Medientyp') + mediatype_name = fields.Char(related='mediatype.medianame',string='Medienname') relname = fields.Char('Relationsname') - kampagnen_uuid = fields.Char('Kampagne') + field_uuid = fields.Char('Feld') 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('field') +# def _onchange_field(self): +# for record in self: +# if record.field='': +# record.contract='' +# else: +# record.contrect=record.field_contract + + def unlink(self): + _logger.info('unlinking '+str(self)) + for record in self: + _logger.info('unlinking '+str(record)+' '+str(record.ad)) + if record.ad != False: + super(dssmediarelations,record).unlink() + else: + _logger.info('not unlinking '+str(record)+' '+str(record.ad)) + @api.onchange('mediafile') def _onchange_mediafile(self): restr = 'keine' for record in self : resstr = record.uuid - _logger.info(record.mediafile) + _logger.info(record.mediafile_file) if record.mediafile != False : _logger.info('Generating File '+resstr) if os.path.isfile(record.mediafile_file) : @@ -760,28 +961,34 @@ class dssmediarelations(models.Model): fileobj.write(base64.decodebytes(record.mediafile)) fileobj.close() _logger.info(resstr+' File generated') - _logger.info(' Projekt : '+record.kampagne.contract.project.uuid) + _logger.info(' Projekt : P_'+str(record.project)+'C_'+str(record.contract)+'A_'+str(record.ad)+' F : '+restr+' created ') _logger.info(' Keine Datei ') return + def dload(self): + for record in self : + _logger.info('Download pressed : '+str(record)) + + 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) +# @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') +# 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 +# else: +# _logger.info('alternative compute '+rec.uuid) +# rec.mediafile_preview = rec.mediafile +# return class dssadstructures(models.Model): _name = "dss.adstructures" @@ -846,16 +1053,42 @@ class dsscontractads(models.Model): @api.model def create(self,vals): result = super().create(vals) - self['date_create'] = date.today() - self['user_create'] = self.env.user.name + resstr = result.uuid + _logger.info(resstr) + for n_record in result: + resstr = n_record.uuid + _logger.info(resstr) + n_record.date_create = date.today() + n_record.user_create = self.env.user.name + allads = n_record.contract.ads + _logger.info(allads) + if allads != False: + for ad in allads: + ad.ad_is_lastpos = False + n_record.ad_is_lastpos = True + contract = n_record.contract + contract.ads_last_ad = n_record return result + @api.depends('need_media') + def _getmedialist(self): + mlist = [] + mlist = self.env['dss.mediarelations'].search([('ad','=',self.id)]) + if mlist != False: + _logger.info('AD Need_Medias A_'+str(self)+' - Computed Medias '+str(mlist)) + self.need_media = mlist.ids + else: + self.need_media = False + _name = "dss.ads" _description = "DigitalSignage Werbekampagnen Phasen" - _inherit = ['mail.thread','mail.activity.mixin'] +# _inherit = ['mail.thread','mail.activity.mixin'] + _inherit = ['mail.activity.mixin'] +#'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') + aduuid = fields.Char(related='uuid') date_create = fields.Date('Erstellungsdatum',default=lambda self: self._default_create_date()) date_lastedit = fields.Date('Änderungsdatum') @@ -865,10 +1098,12 @@ class dsscontractads(models.Model): 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) + ad_is_lastpos = fields.Boolean('Letzte Aktion') 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') + contract_need_media = fields.Many2many('contract.need_media',tracking=True) project = fields.Many2one('dss.projects' , string='Project', store=True,track_visibility='onchange',tracking=True) project_id = fields.Integer(related='project.projectid', string='Project ID') @@ -879,6 +1114,9 @@ class dsscontractads(models.Model): amount = fields.Float('Extrakosten') order = fields.Integer('Reihenfolge') +# need_media = fields.Many2many('dss.mediarelations','ad',string='Medien') + need_media = fields.Many2many('dss.mediarelations','mediarelations_ad_relations','ad_id','mediarelations_id',string='Medien') + 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') @@ -886,6 +1124,8 @@ class dsscontractads(models.Model): ad_state = fields.Many2one('dss.adstate',tracking=True) ad_state_color = fields.Char(related='ad_state.color') + ad_state_text = fields.Char(related='ad_state.statusname') + ad_state_func = fields.Selection(related='ad_state.func') todo_state = fields.Many2one('dss.todostate',default=_default_todo_state,tracking=True) todo_state_color = fields.Char(related='todo_state.color') @@ -893,16 +1133,14 @@ class dsscontractads(models.Model): 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()) @@ -913,28 +1151,18 @@ class dsscontractads(models.Model): 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' + + @api.onchange('ad_state') + def _onchange_ad_state(self): 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 !")) + if record.ad_is_lastpos == True: + contract = record.contract + contract.ads_last_state = record.ad_state +# mtyp = self.env['dss.adstructures'].search([("uuid","=",str(record.mediastructure.uuid))]) +# buildmediarelations(self) self.date_lastedit = str(date.today()) - self.mediastructure = mtyp +# 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') @@ -997,21 +1225,49 @@ class dsscontractads(models.Model): } 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 { + for n_record in self: + resstr = n_record.uuid + _logger.info(resstr) + allads = n_record.contract.ads + _logger.info(allads) + abort = False + if allads != False: + for ad in allads: + if ad.ad_state.func != 'FIN': + abort = True + if abort == False: + defadstate = self.env['dss.adstate'].search([('func','=','STD')],limit=1).id + if not defadstate : + defadstate = 1 + if self.ad_state.func == 'STD': + parent_id = self.id + else: + parent_id = self.parent_ad.id + newkampagne = self.env['dss.ads'].create({'contract': self.contract.id, 'project': self.project.id, 'adname': 'AD_'+self.contract.contract_auto_name+' '+str(date.today()),'parent_ad':parent_id, 'adtype':'KCHN','ad_state':defadstate }) + _logger.info('C_'+str(self.id)+' Kampagne erzeugt : '+str(newkampagne)) + _logger.info('Prüfe Medien : C_'+str(self.id)+'K_'+str(newkampagne.id)) + mediaids = [] + medias = self.env['dss.mediarelations'].search([('ad','=',newkampagne.id)]) + if not medias: + _logger.info('Prüfe Medien : C_'+str(self.id)+'K_'+str(newkampagne.id)+' keine Medien gefunden !') + medias = self.env['dss.mediarelations'].search(['&',('contract','=',self.contract.id),('ad','=',False)]) + if not medias: + _logger.info('Prüfe Medien : C_'+str(self.id)+'K_'+str(newkampagne.id)+' keine Medien im vertrag gefunden !') + else: + for singlemedi in medias: + if not singlemedi: + _logger.info('Prüfe Medien : C_'+str(self.id)+'K_'+str(newkampagne.id)+' Kein Medium') + else: + newmedi=singlemedi.copy({'ad':newkampagne.id}) + mediaids.append(newmedi.id) + _logger.info('Prüfe Medien : C_'+str(self.id)+'K_'+str(newkampagne.id)+' Kopiere Medium : '+str(singlemedi)+' -> '+str(newmedi)) + medias = self.env['dss.mediarelations'].search([('ad','=',newkampagne.id)]) + _logger.info('Click auf Werbekampagne : C_'+str(self.id)+'K_'+str(newkampagne.id)+' neue Media '+str(mediaids)) + newkampagne.write({'need_media': [(6,0,medias.ids)]}) +# self.write({'need_media': [(5,0,0)]}) +# _logger.info('Click auf Werbekampagne : C_'+str(self.id)+'K_'+str(kamp.id)+' setze Media '+str(kamp.need_media)) +# _logger.info('Click auf Werbekampagne : '+str(self.id)+' 4 '+str(kampagne.id)) + return { 'type': 'ir.actions.act_window', 'view_type':'form', 'view_mode':'form,tree', @@ -1021,9 +1277,10 @@ class dsscontractads(models.Model): 'res_id':newkampagne.id, 'display_name' : 'Änderung zur Werbekampagne '+newkampagne.parent_ad.adname, 'domain':'[("id","=","context[newkampagne.id]")]' - } - - return action + } + else: + raise ValidationError(_("Kann neue Aktualisierung erst anlegen wenn alle vorherigen Schritte beendet wurden !")) + def setStandardText(self,tid): text = self.env['dss.texts'].search([('text_id','=',tid)], limit=1) diff --git a/views/dss_ads.xml b/views/dss_ads.xml index 40d3503..6893124 100755 --- a/views/dss_ads.xml +++ b/views/dss_ads.xml @@ -9,7 +9,7 @@