Einzel Files

Kalender
This commit is contained in:
jopster 2024-07-22 11:12:17 +02:00
parent e7ae0f6481
commit 789df92466
28 changed files with 3259 additions and 1673 deletions

View File

@ -35,6 +35,7 @@
'views/menu.xml', 'views/menu.xml',
'views/company_view.xml', 'views/company_view.xml',
'views/google_map.xml', 'views/google_map.xml',
'views/dss_report_invoice.xml',
], ],
'demo': [], 'demo': [],
'installable': True, 'installable': True,

View File

@ -1,6 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details. # Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import http from odoo import http
import os
import os.path
import base64
import logging import logging
from odoo.http import request from odoo.http import request
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@ -24,12 +28,12 @@ class GoogleMap(http.Controller):
directives ``width`` and ``height``. directives ``width`` and ``height``.
''' '''
@http.route(['/google_map'], type='http', auth="public", website=True, sitemap=False) @http.route(['/google_map'], type='http', auth="none", website=True, sitemap=False, db='odoo_db')
def google_map(self, *arg, **post): def google_map(self, *arg, **post):
projects = request.env['dss.projects'].sudo().search([('standort_visible', '=', True)]) projects = request.env['dss.projects'].sudo().search([('standort_visible', '=', True)])
settings = (request.env['dss.settings'].search([],limit=1)) settings = (request.env['dss.settings'].sudo().search([],limit=1))
google_maps_api_key = settings.google_maps_key google_maps_api_key = settings.google_maps_key
_logger.info("Google Maps " + str(projects)+ " and Record : "+str(len(projects))) _logger.info("Google Maps " + str(projects)+ " and Record : "+str(len(projects)))
projects_data = { projects_data = {
@ -37,14 +41,30 @@ class GoogleMap(http.Controller):
"projects": [] "projects": []
} }
for project in projects.with_context(show_address=True): for project in projects:
if project.maps_image:
fname=settings.os_webimg_path+'/img_'+str(project.id)+'_b.jpg';
if os.path.isfile(fname):
os.remove(fname)
fileobj = open(fname, "xb")
fileobj.write(base64.decodebytes(project.maps_image))
fileobj.close()
maps_image_url="/DigitalSignage/static/src/img/img_"+str(project.id)+"_b.jpg";
else:
maps_image_url=""
projects_data["projects"].append({ projects_data["projects"].append({
'id': project.id, 'id': project.id,
'name': project.projektname, 'name': project.projektname,
'google_name': project.maps_name,
'google_typ':project.maps_type,
'google_marker': project.maps_marker,
'google_image':maps_image_url,
'google_text':project.maps_text,
'latitude': str(project.standort_lati) if project.standort_lati else False, 'latitude': str(project.standort_lati) if project.standort_lati else False,
'longitude': str(project.standort_long) if project.standort_long else False, 'longitude': str(project.standort_long) if project.standort_long else False,
}) })
partner_url = "" partner_url = "/google_map"
values = { values = {
'project_url': partner_url, 'project_url': partner_url,
@ -53,3 +73,7 @@ class GoogleMap(http.Controller):
'google_maps_api_key': google_maps_api_key, 'google_maps_api_key': google_maps_api_key,
} }
return request.render("DigitalSignage.google_map", values) return request.render("DigitalSignage.google_map", values)
@http.route(['/google_map/info'], type='http', auth="public", website=True, sitemap=False)
def google_map_info(self, *arg, **post):
return "Hello World"

View File

@ -1,3 +1,13 @@
from . import dss_settings
from . import dss_contract
from . import dss_projects
from . import dss_geraetetypen
from . import dss_systemtypen
from . import dss_software
from . import dss_systems
from . import dss_eventdays
from . import dss_advertisefields
from . import dss_ads
from . import dss from . import dss
from . import company from . import company

View File

@ -50,11 +50,11 @@ class ResCompany(models.Model):
# return res # return res
@api.onchange('name') # @api.onchange('name')
def onchange_name(self): # def onchange_name(self):
if not self.dsspartner_name : # if not self.dsspartner_name :
self.dsspartner_name = self.name[self.name.index(' '):] # self.dsspartner_name = self.name[self.name.index(' '):]
if not self.dsspartner_vorname : # if not self.dsspartner_vorname :
self.dsspartner_vorname = self.name[0:self.name.index(' ')] # self.dsspartner_vorname = self.name[0:self.name.index(' ')]
# self.dsspartner_werbung = self.company_type == 'dss_client' # self.dsspartner_werbung = self.company_type == 'dss_client'
# return res # return res

File diff suppressed because it is too large Load Diff

576
models/dss_ads.py Normal file
View File

@ -0,0 +1,576 @@
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
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 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)
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.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')
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, tracking=True)
adtype = fields.Selection(
[('MAIN', 'Ersteinrichtung'), ('KCHN', 'Änderung durch Kunde'), ('LCHN', 'Änderung durch Logumedia'),
('SONS', 'Sonstige Änderung')], tracking=True)
adpos = fields.Integer('Reihenfolge', default=lambda self: self._default_adpos(),
tracking=True)
ad_is_lastpos = fields.Boolean('Letzte Aktion', tracking=True)
start_date = fields.Date('gew. Ausstrahl.Begin', tracking=True)
end_date = fields.Date('gew. Ausstrahl.Ende', tracking=True)
contract = fields.Many2one('dss.contracts', store=True, tracking=True)
contract_id = fields.Char(related='contract.contract_id')
contract_name = fields.Char(related='contract.contract_name')
contract_need_media = fields.Many2many(related='contract.need_media', tracking=True)
project = fields.Many2one('dss.projects', string='Project', store=True, 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')
amount = fields.Float('Extrakosten', tracking=True)
order = fields.Integer('Reihenfolge', tracking=True)
# need_media = fields.Many2many('dss.mediarelations','ad',string='Medien')
need_media = fields.One2many('dss.mediarelations', 'ad', 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')
work_state_info = fields.Char('Zusatzinfo')
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')
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_add_directory = fields.Char('Cloud KundenKampagnen Ordner', tracking=True)
date_zuarbeit = fields.Date(string='Zuarbeit Datum', help='Zuarbeit gesendet am', tracking=True)
date_korrekturabzug = fields.Date(string='K.Abzug Datum', help='Korrekturabzug gesendet am')
date_korrekturfreigabe = fields.Date(string='K.Freigabe Datum', help='Korrekturfreigabe erhalten am',
tracking=True)
date_korrekturfreigabe_frist = fields.Date(string='K.Freigabe bis Datum', help='Korrekturfreigabe sollte bis .... erfolgen')
freigabe_durch_ablauf = fields.Boolean(string='Zeitablauf',help='Freigabe wurde durch Zeitablauf erreicht ?', 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('ad_state')
def _onchange_ad_state(self):
for record in self:
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
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):
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 = []
for feld in self.contract.werbe_feld_selected:
for media in feld.mediastructure.medias:
if not media:
_logger.info('Prüfe Medien : C_' + str(self.contract.id) + 'K_' + str(
newkampagne.id) + ' Kein Medium in MedienStructur von F_' + str(feld.id) + 'M_' + str(
media.id))
else:
newmedia = self.env['dss.mediarelations'].create(
{'field': feld.id, 'contract': self.contract.id, 'project': self.project.id,
'field_uuid': feld.uuid, 'ad': newkampagne.id, 'relname': media.medianame,
'mediatype': media.id})
_logger.info('Prüfe Medien : C_' + str(self.contract.id) + 'K_' + str(
newkampagne.id) + ' setze Vertrag für Medium : ' + str(newmedia.contract) + '/' + str(
newmedia.ad))
mediaids.append(newmedia.id)
newkampagne.write({'need_media': [(6, 0, mediaids)]})
_logger.info('Click auf Werbekampagne : C_' + str(self.contract.id) + 'A_' + str(
newkampagne.id) + ' setze Media ')
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]")]'
}
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)
if text:
self.write({'description': text.description})
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)
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.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')
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, tracking=True)
adtype = fields.Selection(
[('MAIN', 'Ersteinrichtung'), ('KCHN', 'Änderung durch Kunde'), ('LCHN', 'Änderung durch Logumedia'),
('SONS', 'Sonstige Änderung')], tracking=True)
adpos = fields.Integer('Reihenfolge', default=lambda self: self._default_adpos(),
tracking=True)
ad_is_lastpos = fields.Boolean('Letzte Aktion', tracking=True)
start_date = fields.Date('gew. Ausstrahl.Begin', tracking=True)
end_date = fields.Date('gew. Ausstrahl.Ende', tracking=True)
contract = fields.Many2one('dss.contracts', store=True, tracking=True)
contract_id = fields.Char(related='contract.contract_id')
contract_name = fields.Char(related='contract.contract_name')
contract_need_media = fields.Many2many(related='contract.need_media', tracking=True)
project = fields.Many2one('dss.projects', string='Project', store=True, 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')
amount = fields.Float('Extrakosten', tracking=True)
order = fields.Integer('Reihenfolge', tracking=True)
# need_media = fields.Many2many('dss.mediarelations','ad',string='Medien')
need_media = fields.One2many('dss.mediarelations', 'ad', 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')
work_state_info = fields.Char('Zusatzinfo')
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')
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_add_directory = fields.Char('Cloud KundenKampagnen Ordner', tracking=True)
date_zuarbeit = fields.Date(string='Zuarbeit Datum', help='Zuarbeit gesendet am',
tracking=True)
date_korrekturabzug = fields.Date(string='K.Abzug Datum', help='Korrekturabzug gesendet am',
track_visibility='onchange', tracking=True)
date_korrekturfreigabe = fields.Date(string='K.Freigabe Datum', help='Korrekturfreigabe erhalten am',
track_visibility='onchange', 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('ad_state')
def _onchange_ad_state(self):
for record in self:
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
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):
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 = []
for feld in self.contract.werbe_feld_selected:
for media in feld.mediastructure.medias:
if not media:
_logger.info('Prüfe Medien : C_' + str(self.contract.id) + 'K_' + str(
newkampagne.id) + ' Kein Medium in MedienStructur von F_' + str(feld.id) + 'M_' + str(
media.id))
else:
newmedia = self.env['dss.mediarelations'].create(
{'field': feld.id, 'contract': self.contract.id, 'project': self.project.id,
'field_uuid': feld.uuid, 'ad': newkampagne.id, 'relname': media.medianame,
'mediatype': media.id})
_logger.info('Prüfe Medien : C_' + str(self.contract.id) + 'K_' + str(
newkampagne.id) + ' setze Vertrag für Medium : ' + str(newmedia.contract) + '/' + str(
newmedia.ad))
mediaids.append(newmedia.id)
newkampagne.write({'need_media': [(6, 0, mediaids)]})
_logger.info('Click auf Werbekampagne : C_' + str(self.contract.id) + 'A_' + str(
newkampagne.id) + ' setze Media ')
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]")]'
}
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)
if text:
self.write({'description': text.description})

View File

@ -0,0 +1,115 @@
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
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', required=True)
display = fields.Char('Designname')
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.Many2many('dss.contracts' , string='Vertrag', store=True)
contract_save = fields.Many2one('dss.contracts' , string='Vertrag', store=True)
contract_project_id = fields.Integer(related='contract.project_id', string='Project ID')
color_used = fields.Char(string='Color Index')
color_unused = fields.Char(string='Color Index')
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('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

698
models/dss_contract.py Normal file
View File

@ -0,0 +1,698 @@
# -*- coding: utf-8 -*
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
from odoo import api, fields, models, _
from odoo import tools
from . import dss_settings
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 dsscontracts(models.Model):
@api.model
def _get_default_project(self):
_logger.debug("Ermittelte Id aus Context : %s" % (self.env.context.get('active_id')))
ds = self.env['dss.projects'].search([('id','=',self.env.context.get('active_id'))],limit=1)
return ds
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
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_color = fields.Char(related='contract_state.color',store=True)
contract_state_order = fields.Integer(related='contract_state.order',store=True)
contract_auto_id = fields.Char("Kundennummer",tracking=True,help="Wird berechnet aus Projektnummer + Kunden ID")
contract_auto_name = fields.Char('Vertragskennug',tracking=True,help="Wird berechnet aus Kundennummer + Vertragskennung")
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',string="Kunde (wenn angelegt)",domain="['&',('dsspartner','=',True),('dsspartner_werbung','=',True)]",tracking=True,help="Nur zu Benutzen wenn Kunden als Kontakt angelegt wurde")
client_id = fields.Char(string="KundenID (2Stellen)",help="Nur der 2 stellige letzte Teil der Kundennummer",tracking=True)
client_uuid = fields.Char(related="client.dss_uuid")
contact_street = fields.Char(related="client.street")
contact_street2 = fields.Char(related="client.street2")
contact_zip = fields.Char(related="client.zip")
contact_city = fields.Char(related="client.city")
contact_state_id = fields.Many2one(related="client.state_id")
contact_country_id = fields.Many2one(related="client.country_id")
contact_telefon = fields.Char(related="client.phone")
contact_mobil = fields.Char(related="client.mobile")
contact_email = fields.Char(related="client.email")
contact_web = fields.Char(related="client.website")
contact_company_name = fields.Char(related="client.name")
contact_name = fields.Char(related="client.company_name")
contact_dsspartner_vorname = fields.Char(related="client.dsspartner_name")
contact_dsspartner_name = fields.Char(related="client.dsspartner_vorname")
parent_id = fields.Many2one('dss.contracts', string='Parent Task', index=True,tracking=True)
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',tracking=True)
werbe_feld_selected = fields.Many2many('dss.advertisefields',string='Werbefelder',tracking=True)
shortwerbe_feld_selected = fields.Char(related='werbe_feld_selected.feldname',string='Werbefelder',tracking=True)
cutshortwerbe_feld_selected = fields.Char(string='gekürzte Felder',compute='_compute_cutshort')
# need_media = fields.Many2many('dss.mediarelations','mediarelations_contract_rel','contract_id','mediarelations_id',string='benötigte Medien')
last_media = fields.Many2many('dss.mediarelations',string='Medien',domain="[('isreference','=',False)]")
# last_media = fields.Many2many('dss.mediarelations','mediarelations_ad_relations','contract_id','mediarelations_id',string='Medien')
need_media = fields.Many2many('dss.mediarelations','contract',string='Medien',domain="[('isreference','=',True)]")
# 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)
split_runtime_time = fields.Integer('Laufzeit Sekunden',tracking=True)
contract_date = fields.Date('Vertragsdatum',tracking=True)
start_date = fields.Date('Start/Auslief.datum',tracking=True)
contract_auto_extend = fields.Boolean('autom. V.Verlängerung',tracking=True)
contract_auto_extend_time = fields.Char('Verl. Monate',tracking=True)
runtimesystem = fields.Selection([('M','Monatslaufzeit'),('T','Tagelaufzeit'), ('E','Eventlaufzeit'), ('S','Sonderlaufzeit')],tracking=True)
runtime_m = fields.Integer('Laufzeit',tracking=True)
runtime_bonus_m = fields.Integer('zusätzl. Laufzeit',tracking=True)
runtime_t = fields.Integer('Laufzeit',tracking=True)
runtime_bonus_t = fields.Integer('zusätzl. Laufzeit',tracking=True)
runtime_events = fields.Many2many('dss.eventdays',tracking=True)
runtime_bonus_e = fields.Integer('zusätzl. Events',tracking=True)
runtime_divers = fields.Char('Laufzeit',tracking=True)
runtime_finish = fields.Date('LaufzeitEnde',tracking=True)
runtime_calendar_event = fields.Integer('Kalendereintrag ID',tracking=True)
paymentsystems = fields.Many2one('dss.paysystems',tracking=True)
intern_info_payment_off = fields.Boolean('Keine Zahl-Benachrichtigungen',tracking=True)
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', string="Zuständigkeit letzt Kamp",help="Zuständigkeit/Status des letzten Werbekampagnen Eintrags",store=True,readonly=False,group_expand='_expand_ads_last_state')
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',store=True,readonly=False)
ads_last_work_state = fields.Many2one(related='ads_last_ad.work_state', string="Arbeitschritt letzt Kamp",help="Arbeitsstatus des letzten Werbekampagnen Eintrags",store=True,readonly=False,group_expand='_expand_ads_last_work_state')
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',store=True,readonly=False)
ads_last_work_state_info = fields.Char(related='ads_last_ad.work_state_info')
ads_last_todo_state = fields.Many2one(related='ads_last_ad.todo_state',string="Aufgabe letzt Kamp", help="Aufgabenstatus des letzten Werbekampagnen Eintrags",store=True,readonly=False,group_expand='_expand_ads_last_todo_state')
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',store=True,readonly=False)
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',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)
cloudlink = fields.Char('Cloud Verzeichnis',help='Verzeichnis für den Kunde innerhalb des Projekt Ordners')
@api.model
def _expand_ads_last_work_state(self,states,domain,order):
if dss_settings.dssSettings._get_settingvalue(self,'show_expand_contract_group_ad_work_state'):
state_ids = self.env['dss.workstate'].search([])
return state_ids
else:
return self.ads_last_work_state
@api.model
def _expand_ads_last_todo_state(self,states,domain,order):
if dss_settings.dssSettings._get_settingvalue(self,'show_expand_contract_group_ad_todo_state'):
state_ids = self.env['dss.todostate'].search([])
return state_ids
else:
return self.ads_last_todo_state
@api.model
def _expand_ads_last_state(self,states,domain,order):
if dss_settings.dssSettings._get_settingvalue(self,'show_expand_contract_group_ad_state'):
state_ids = self.env['dss.adstate'].search([])
return state_ids
else:
return self.ads_last_state
@api.constrains('client_id')
def _check_client_id(self) :
for record in self :
if len(record.client_id) != 2 :
_logger.debug("Kundenid muss 2 Stellen haben %s" % (record.client_id))
raise ValidationError(_("KundenID muss 2 Stellen haben"))
@api.onchange('client_id')
def _onchange_client_id(self):
for record in self :
if record.contract_name == '' :
cname = 'unbekannter Kunden'
else:
cname = record.contract_name
resstr = "%s%s %s" % (record.project_id,record.client_id,cname)
cidstr = "%s%s" % (record.project_id,record.client_id)
if resstr is None :
resstr = 'nicht ermittelbar'
_logger.info('Contract_client_id_change : C_' + str(self.id) + ' - '+str(cidstr)+' vs. '+str(self.contract_auto_id)+'/'+str(resstr)+' vs '+str(self.contract_auto_name));
if not self.contract_auto_name:
self.contract_auto_name = resstr
if not self.contract_auto_id:
self.contract_auto_id = cidstr
if self.contract_auto_id == "":
self.contract_auto_id = cidstr
@api.onchange('project_id')
def _onchange_project_id(self):
for record in self :
if record.contract_name == '' :
cname = 'unbekannter Kunden'
else:
cname = record.contract_name
resstr = "%s%s %s" % (record.project_id,record.client_id,cname)
cidstr = "%s%s" % (record.project_id,record.client_id)
if resstr is None :
resstr = 'nicht ermittelbar'
_logger.info('project_id_change : C_' + str(self.id) + ' - '+str(cidstr)+' vs. '+str(self.contract_auto_id)+'/'+str(resstr)+' vs '+str(self.contract_auto_name));
if not self.contract_auto_name:
self.contract_auto_name = resstr
if not self.contract_auto_id:
self.contract_auto_id = cidstr
if self.contract_auto_id == "":
self.contract_auto_id = cidstr
@api.onchange('contract_name')
def _onchange_contract_name(self):
for record in self :
if record.contract_name == '' :
cname = 'unbekannter Kunden'
else:
cname = record.contract_name
resstr = "%s%s %s" % (record.project_id,record.client_id,cname)
cidstr = "%s%s" % (record.project_id, record.client_id)
if resstr is None :
resstr = 'nicht ermittelbar'
_logger.info('Contract_Name_Change : C_' + str(self.id) + ' - '+str(cidstr)+' vs. '+str(self.contract_auto_id)+'/'+str(resstr)+' vs '+str(self.contract_auto_name));
if not self.contract_auto_name:
self.contract_auto_name = resstr
if not self.contract_auto_id:
self.contract_auto_id = cidstr
if self.contract_auto_id == "":
self.contract_auto_id = cidstr
@api.onchange('contract_auto_id')
def _onchange_contract_auto_id(self):
for record in self :
if record.contract_name == '' :
cname = 'unbekannter Kunden'
else:
cname = record.contract_name
resstr = "%s%s %s" % (record.project_id,record.client_id,cname)
cidstr = "%s%s" % (record.project_id, record.client_id)
if resstr is None:
resstr = 'nicht ermittelbar'
_logger.info('Contract_auto_id_change : C_' + str(self.id) + ' - '+str(cidstr)+' vs. '+str(self.contract_auto_id)+'/'+str(resstr)+' vs '+str(self.contract_auto_name));
if not self.contract_auto_name:
self.contract_auto_name = resstr
if not self.contract_auto_id:
self.contract_auto_id = cidstr
if self.contract_auto_id == "":
self.contract_auto_id = cidstr
# @api.model
# def create(self,vals):
# vals['projectid'] = self.env.context.get('active_id')
# project = self.env('dss.projects').search(['id','=',vals['projectid']])
# vals['project'] = project('projektname');
# contract=super().create(vals)
# return contract
@api.model
def _default_uuid(self):
return str(uuid.uuid4())
@api.model
def _getdefwscolor(self):
return str('#ffffff')
@api.model
def _default_client_id(self):
return str("00")
@api.model
def _read_group_stage_ids(self,stages,domain,order):
contract_state_ids = self.env['dss.contractstate'].search([],order='order')
return contract_state_ids
def pyaction_dss_contract_goto_partner(self):
fullname = str(self.client_short_vorname) + ' ' +str(self.client_short_name)
def pyaction_dss_contract_make_partner(self):
fullname = str(self.client_short_vorname) + ' ' +str(self.client_short_name)
myplz=self.client_short_plz
result = self.env['res.partner'].create({'name':fullname,
'company_name': self.client_short_company,
'dsspartner_vorname':self.client_short_vorname,
'dsspartner_name':self.client_short_name,
'dsspartner':True,
'dsspartner_werbung':True,
'street':self.client_short_strasse,
'city':self.client_short_ort,
'zip':myplz,
'phone':self.client_short_telefon,
'mobile':self.client_short_mobil,
'email':self.client_short_email,
'is_company':False})
result.country_id = self.client_short_land
_logger.info('Creating Contact ' + str(result) + ' ' + str(fullname))
self.client = result
# 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_dss_contract_addcalendar_runtime(self):
event = {
'start': self.runtime_finish.strftime('%Y-%m-%d %H:%M:%S'),
'stop': self.runtime_finish.strftime('%Y-%m-%d %H:%M:%S'),
'duration': 24,
'allday': True,
'partner_ids': (4,self.env['dss.settings'].search([],limit=1).contact_runtime_user.partner_id.id),
'name': 'Vertragsablauf '+self.contract_auto_name,
'description': 'Vertragsablauf '+self.contract_auto_name+' im Projekt '+self.project.projektname,
'user_id': self.env['dss.settings'].search([],limit=1).contact_runtime_user.id
}
_logger.debug('linking new event ' + str(event) + ' ' + str(self.uuid))
self.runtime_calendar_event=self.env['calendar.event'].create(event).id
return ""
def pyaction_dss_contract_addcalendar_rf_runtime(self):
self.runtime_calendar_event.unlink()
event = {
'start': self.runtime_finish.strftime('%Y-%m-%d %H:%M:%S'),
'stop': self.runtime_finish.strftime('%Y-%m-%d %H:%M:%S'),
'duration': 24,
'allday': True,
'partner_ids': (4,self.env['dss.settings'].search([],limit=1).contact_runtime_user.partner_id.id),
'name': 'Vertragsablauf '+self.contract_auto_name,
'description': 'Vertragsablauf '+self.contract_auto_name+' im Projekt '+self.project.projektname,
'user_id': self.env['dss.settings'].search([],limit=1).contact_runtime_user.id
}
_logger.debug('linking new event ' + str(event) + ' ' + str(self.uuid))
self.runtime_calendar_event=self.env['calendar.event'].create(event).id
return ""
def pyaction_dss_contract_calc_runtime(self):
if self.start_date:
startdatum= self.start_date
else:
startdatum= self.contract_date
if startdatum :
if self.runtimesystem == "M":
bmonths = 0
bmonths = self.runtime_m+self.runtime_bonus_m
if bmonths > 12:
addyears=bmonths//12
else:
addyears = 0
addmonths = bmonths - (addyears*12)
enddatum = startdatum + relativedelta(months=addmonths,years=addyears)
elif self.runtimesystem == "T":
enddatum = startdatum + relativedelta(days=self.runtime_t)
enddatum = enddatum + relativedelta(days=self.runtime_t)
elif self.runtimesystem == "E":
enddatum = startdatum
if self.runtime_events:
mydate = startdatum
for event in self.runtime_events:
if mydate.strftime('%Y-%m-%d') < event.eventenddate.strftime('%Y-%m-%d'):
mydate = event.eventenddate
enddatum = mydate
elif self.runtimesystem == "S":
enddatum = self.runtime_finish
self.runtime_finish = enddatum
def tokampagne(self):
_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 Contract_autoname
resstr = ''
if not self.contract_auto_name:
_logger.info('Click auf Werbekampagne : C_'+str(self.id)+'A_'+str(ds.id)+' - Kein Contract_autoname ')
if self.contract_name == '':
cname = 'unbekannter Kunden'
else:
cname = self.contract_name
resstr = "%s%s %s" % (self.project_id, self.client_id, cname)
if not resstr:
resstr = 'nicht ermittelbar'
_logger.debug(resstr)
self.contract_auto_name = resstr
_logger.info('Click auf Werbekampagne : C_' + str(self.id) + 'A_' + str(ds.id) + ' - Contract_autoname gesetzt '+ str(resstr)+'/'+str(cidstr))
# 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
_logger.info('Click auf Werbekampagne : C_'+str(self.id)+' Suche Kampagne allgemein ')
kampagne=self.env['dss.ads'].search([('contract','=',self.id)],limit=1)
if not kampagne:
_logger.info('Click auf Werbekampagne : C_'+str(self.id)+' kein kampagne')
defadstate = self.env['dss.adstate'].search([('func','=','STD')],limit=1)
if not defadstate :
_logger.info('Click auf Werbekampagne : C_'+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 : C_'+str(self.id)+' Kampagne erstellt A_'+str(kampagne.id))
kampagne.parent_ad = kampagne.id
mediaids = []
if not self.werbe_feld_selected:
_logger.info('Prüfe Medien : C_' + str(self.id) + 'A_' + str(
kamp.id) + ' Keine Felder im Vertrag')
raise ValidationError(_("Vertrag hat keine Felder ! Kampagnen benötigen Felder - auch virtuelle"))
else:
for feld in self.werbe_feld_selected:
if not feld:
_logger.info('Prüfe Medien : C_' + str(self.id) + 'A_' + str(
kamp.id) + ' Keine Felder im Vertrag')
raise ValidationError(_("Vertrag hat keine Felder ! Kampagnen benötigen Felder - auch virtuelle"))
else:
for media in feld.mediastructure.medias:
if not media:
_logger.info('Prüfe Medien : C_'+str(self.id)+'K_'+str(kampagne.id)+' Kein Medium in MedienStructur von F_'+str(feld.id)+'M_'+str(media.id))
else:
newmedia=self.env['dss.mediarelations'].create({'field':feld.id,'contract':self.id,'project':self.project.id,'field_uuid':feld.uuid,'ad':kampagne.id, 'relname': media.medianame,
'mediatype': media.id})
_logger.info('Prüfe Medien : C_'+str(self.id)+'K_'+str(kampagne.id)+' setze Vertrag für Medium : '+str(newmedia.contract)+'/'+str(newmedia.ad))
mediaids.append(newmedia.id)
kampagne.write({'need_media': [(6,0,mediaids)]})
_logger.info('Click auf Werbekampagne : C_'+str(self.id)+'/'+str(kampagne.id)+' setze Media '+str(kampagne.need_media))
else:
_logger.info('Click auf Werbekampagne : C_'+str(self.id)+' mind. 1 Kampagne vorhanden A_'+str(kampagne.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)+'A_'+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)+'A_'+str(kamp.id)+' keine Medien gefunden !')
if not self.werbe_feld_selected:
_logger.info('Prüfe Medien : C_' + str(self.id) + 'A_' + str(
kamp.id) + ' Keine Felder im Vertrag')
raise ValidationError(
_("Vertrag hat keine Felder ! Kampagnen benötigen Felder - auch virtuelle"))
else:
for feld in self.werbe_feld_selected:
if not feld:
_logger.info('Prüfe Medien : C_' + str(self.id) + 'A_' + str(
kamp.id) + ' Keine Felder im Vertrag')
raise ValidationError(_("Vertrag hat keine Felder ! Kampagnen benötigen Felder - auch virtuelle"))
else:
for media in feld.mediastructure.medias:
if not media:
_logger.info('Prüfe Medien : C_'+str(self.id)+'A_'+str(kamp.id)+' Kein Medium in der Struktur F_'+str(feld.id)+'M_'+str(feld.mediastructure.id))
else:
newmedi = self.env['dss.mediarelations'].create(
{ 'field': feld.id, 'contract': self.id, 'project': self.project.id,
'field_uuid': feld.uuid, 'ad': kamp.id, 'relname':media.medianame,'mediatype':media.id})
_logger.info('Prüfe Medien : C_'+str(self.id)+'A_'+str(kamp.id)+' Erstelle Medium : M_'+str(media.id)+' -> '+str(newmedi.id))
_logger.info('Prüfe Medien : C_'+str(self.id)+'A_'+str(kamp.id)+' Medien evtl erstellt ! ')
medias = self.env['dss.mediarelations'].search([('ad','=',kamp.id)])
_logger.info('Click auf Werbekampagne : C_'+str(self.id)+'A_'+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)+'A_'+str(kamp.id)+' Medien gefunden !')
if not self.werbe_feld_selected:
_logger.info('Prüfe Medien : C_' + str(self.id) + 'A_' + str(
kamp.id) + ' Keine Felder im Vertrag')
raise ValidationError(
_("Vertrag hat keine Felder ! Kampagnen benötigen Felder - auch virtuelle"))
else:
for feld in self.werbe_feld_selected:
_logger.info('Prüfe Medien : C_' + str(self.id) + 'A_' + str(kamp.id)+'F_'+str(feld.id))
if not feld:
_logger.info('Prüfe Medien : C_' + str(self.id) + 'A_' + str(
kamp.id) + ' Keine Felder im Vertrag')
raise ValidationError(_("Vertrag hat keine Felder ! Kampagnen benötigen Felder - auch virtuelle"))
else:
for media in feld.mediastructure.medias:
if not media:
_logger.info('Prüfe Medien : C_' + str(self.id) + 'A_' + str(
kamp.id) + ' Kein Medium in der Struktur F_' + str(feld.id) + 'M_' + str(
feld.mediastructure.id))
else:
_logger.info('Prüfe Medien : C_' + str(self.id) + 'A_' + str(kamp.id) + 'F_' + str(
feld.id) + 'M_' + str(media.id))
existmedia = self.env['dss.mediarelations'].search(['&',('ad','=',kamp.id),('mediatype','=',media.id),('field','=',feld.id)])
if not existmedia:
newmedi = self.env['dss.mediarelations'].create(
{'field': feld.id, 'contract': self.id, 'project': self.project.id,
'field_uuid': feld.uuid, 'ad': kamp.id, 'relname': media.medianame,
'mediatype': media.id})
_logger.info('Prüfe Medien : C_' + str(self.id) + 'A_' + str(
kamp.id) + ' Erstelle Medium : M_' + str(media.id) + ' -> ' + str(
newmedi.id))
# mediaids.append(medias.ids)
_logger.info('Click auf Werbekampagne : C_'+str(self.id)+'A_'+str(kamp.id)+' gefundene Media '+str(mediaids))
kampagne=self.env['dss.ads'].browse(kamp.id)
_logger.info('Click auf Werbekampagne : C_'+str(self.id)+'A_'+str(kamp.id)+' gefundene Media '+str(mediaids)+' Kampagne '+str(kampagne))
if kampagne.need_media != medias:
_logger.info('Click auf Werbekampagne : C_'+str(self.id)+'A_'+str(kamp.id)+' Media unterschiede - setze Media '+str(mediaids)+'/'+str(kampagne.need_media))
else:
_logger.info('Click auf Werbekampagne : C_'+str(self.id)+'A_'+str(kamp.id)+' Media gleich '+str(kampagne.need_media))
else:
_logger.info('Prüfe Medien : C_'+str(self.id)+'A_'+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]")]'
}
def setFirstKampagne(self):
for record in self:
if record.contract_auto_id:
record.tokampagne()
def setTreeStandardValues(self):
for record in self:
if record.contract_name == '':
cname = 'unbekannter Kunden'
else:
cname = record.contract_name
resstr = "%s%s %s" % (record.project_id, record.client_id, cname)
cidstr = "%s%s" % (record.project_id, record.client_id)
if resstr is None:
resstr = 'nicht ermittelbar'
_logger.info('Set Standard Values : C_' + str(record.id) + ' - ' + str(cidstr) + ' vs. ' + str(
record.contract_auto_id) + '/' + str(resstr) + ' vs ' + str(record.contract_auto_name));
if not record.contract_auto_name:
record.contract_auto_name = resstr
if not record.contract_auto_id:
record.contract_auto_id = cidstr
if record.contract_auto_id == "":
record.contract_auto_id = cidstr
def setStandardValues(self):
for record in self:
if record.contract_name == '':
cname = 'unbekannter Kunden'
else:
cname = record.contract_name
resstr = "%s%s %s" % (record.project_id, record.client_id, cname)
cidstr = "%s%s" % (record.project_id, record.client_id)
if resstr is None:
resstr = 'nicht ermittelbar'
_logger.info('Set Standard Values : C_' + str(self.id) + ' - ' + str(cidstr) + ' vs. ' + str(
self.contract_auto_id) + '/' + str(resstr) + ' vs ' + str(self.contract_auto_name));
if not self.contract_auto_name:
self.contract_auto_name = resstr
if not self.contract_auto_id:
self.contract_auto_id = cidstr
if self.contract_auto_id == "":
self.contract_auto_id = cidstr
@api.depends('shortwerbe_feld_selected')
@api.onchange('werbe_feld_selected')
def _compute_cutshort(self):
for rec in self:
if rec.werbe_feld_selected:
shorty = ""
for f in rec.werbe_feld_selected:
try:
if not shorty:
shorty = str(f.feldname)
else:
shorty = shorty+','+str(f.feldname)
except:
_logger.info('Werbefeldberechnung Exception : C_' + str(rec.id))
rec.cutshortwerbe_feld_selected = str(shorty)
else:
rec.cutshortwerbe_feld_selected = 'unb.'
_logger.info('Werbefeldberechnung kein Inhalt für : C_' + str(rec.id) + ' - ' + str(rec.shortwerbe_feld_selected))
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')
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_dss_project_make_contract(self):
action = self.env['ir.actions.act_window'].with_context({'default_projectid': self.id})._for_xml_id('DigitalSignage.action_dss_project_view_contract')
return action
def py_jump_last_ad(self):
for record in self:
self.tokampagne()

28
models/dss_dialog.py Normal file
View File

@ -0,0 +1,28 @@
# Confirmation msg box for ORIC
from openerp.osv import fields,osv
from openerp.tools.translate import _
class dssDialog(osv.osv_memory):
_name = "dss.dialog"
_columns={
'text': fields.text(),
}
thesis_approval_message_oric()
@api.multi
def btn_approve(self):
text = """The case """ + str(self.case_no) + """ will be forward to VC for further Approval. Are you want to proceed."""
query = 'delete from thesis_approval_message_oric'
self.env.cr.execute(query)
value = self.env['thesis.approval.message.oric'].sudo().create({'text': text})
return {
'type': 'ir.actions.act_window',
'name': 'Message',
'res_model': 'dss.dialog',
'view_type': 'form',
'view_mode': 'form',
'target': 'new',
# 'context':{'thesis_obj':self.id,'flag':'course Work completed'},
'res_id': value.id
}

69
models/dss_eventdays.py Normal file
View File

@ -0,0 +1,69 @@
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
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 dsseventdays(models.Model):
_name = "dss.eventdays"
_description = "DigitalSignage EventSpieltage"
_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')
# uuid = fields.Char('UUID', required=True, translate=True)
eventname = fields.Char('Eventname', required=True)
description = fields.Text('EventBeschreibung')
eventstartdate = fields.Datetime('EventDatum', required=True)
eventenddate = fields.Datetime('EventDatum', required=True)
color = fields.Char(string='Color Index')
username = fields.Many2one('res.users',string="Kalendercontact")
calendarevent = fields.Integer('Kalenderevent ID')
@api.model
def _default_uuid(self):
return str(uuid.uuid4())
@api.model
def create(self,vals):
result = super().create(vals)
return result
def pydocalendarEntry(self):
event = {
'start': self.eventstartdate.strftime('%Y-%m-%d %H:%M:%S'),
'stop': self.eventenddate.strftime('%Y-%m-%d %H:%M:%S'),
'duration': 24,
'allday': False,
'partner_ids': (4,self.username.partner_id.id),
'name': self.eventname,
'description': self.description,
'user_id': self.username.id,
}
_logger.debug('linking new event ' + str(event) + ' ' + str(self.uuid))
self.calendarevent=self.env['calendar.event'].create(event)

169
models/dss_geraetetypen.py Normal file
View File

@ -0,0 +1,169 @@
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
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 dssgeraetetypen(models.Model):
_name = "dss.geraetetypen"
_description = "DigitalSignage Geraetetypen"
_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')],tracking=True)
# grundsystem = fields.Many2one('dss.systemtypen', string="Gerät ist nutzbar für",tracking=True)
grundsystem = fields.Many2many('dss.systemtypen', string="Gerät ist nutzbar für",tracking=True)
grundsystem_kennung = fields.Char(string='Kennung', related='grundsystem.kennung',tracking=True)
standort = fields.Char('Hauptstandort des Gerätes',tracking=True)
farbe = fields.Char('Grundfarbe',tracking=True)
has_heizung = fields.Boolean('Mit Heizsystem',tracking=True)
has_klima = fields.Boolean('Mit Klimasystem',tracking=True)
has_fan = fields.Boolean('Mit Ventiltorensystem',tracking=True)
has_tuya = fields.Boolean('Mit Tuyasteuerung',tracking=True)
stromzaehler = fields.Many2one('dss.geraetetypen',tracking=True)
stromverbrauch_avg = fields.Integer('Stromverbrauch AVG in W',tracking=True)
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',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')],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',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',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',tracking=True);
lcd_montage_sonstige = fields.Char('Sonstige Montageart',tracking=True)
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',tracking=True)
zusatz_zubehoer = fields.Char('Sonstiges Zubehör',tracking=True)
tuya_Geraete_uid = fields.Char('Tuya Geräte UID',tracking=True)
tuya_Geraete_id = fields.Char('Tuya Geräte ID', tracking=True)
tuya_can_switch = fields.Boolean('Tuya mit Schalter',tracking=True)
tuya_has_powervalue = fields.Boolean('Tuya mit Stromzähler',tracking=True)
tuya_last_totalpower = fields.Char('Stromzähler Gesamt',tracking=True,readonly=True)
tuya_last_lastpower = fields.Char('Stromzähler Aktuell',tracking=True,readonly=True)
tuya_last_switchstate = fields.Char('Schalter Aktuell ',tracking=True,readonly=True)
@api.model
def _default_uuid(self):
return str(uuid.uuid4())
@api.depends('grundsystem')
def _compute_grundsystem_kennung(self):
for syst in self:
if syst.grundsystem:
syst.grundsystem_kennung = syst.grundsystem.kennung
def get_value_from_tuyaresult(self,dataset,valuename):
result=''
_logger.info('Resultanfrage:' + str(dataset)+' Feld : '+str(valuename))
for singlepart in dataset:
if singlepart:
if (singlepart['code'] == valuename):
result = singlepart['value']
break
return result
def pyaction_tuya_readout(self):
_logger.info('Tuya Schaltanfrage : Endpoint - ' + str(dssSettings._get_settingvalue(self,'tuya_endpoint')) + ' AccessID ' + str(dssSettings._get_settingvalue(self,'tuya_access_id')) + ' AccessKEY ' + str(dssSettings._get_settingvalue(self,'tuya_access_key')))
openapi = TuyaOpenAPI(dssSettings._get_settingvalue(self,'tuya_endpoint'),dssSettings._get_settingvalue(self,'tuya_access_id'),dssSettings._get_settingvalue(self,'tuya_access_key'))
openapi.connect()
switchcode = eval('True')
commands = {'commands':[{'code':'switch','value': switchcode}]}
# result = openapi.post('/v1.0/iot-03/devices/{}/commands'.format(self.tuya_Geraete_id),commands)
result = openapi.get('/v1.0/iot-03/devices/{}/status'.format(self.tuya_Geraete_id))
_logger.info('Erfolg ? :' + str(result['success']))
success = result['success']
if success:
_logger.info('Erfolgreiche Anfrage :' + str(result['result']))
if self.tuya_has_powervalue:
self.tuya_last_totalpower = self.get_value_from_tuyaresult(result['result'],'forward_energy_total')
self.tuya_last_lastpower = self.get_value_from_tuyaresult(result['result'],'phase_a')
if self.tuya_can_switch:
self.tuya_last_switchstate = self.get_value_from_tuyaresult(result['result'],'switch')
else:
_logger.info('Fehlerhafte Anfrage :' + str(result['msg']))
def pyaction_tuya_switch(self):
_logger.info('Tuya Schaltanfrage : Endpoint - ' + str(
dssSettings._get_settingvalue(self, 'tuya_endpoint')) + ' AccessID ' + str(
dssSettings._get_settingvalue(self, 'tuya_access_id')) + ' AccessKEY ' + str(
dssSettings._get_settingvalue(self, 'tuya_access_key')))
openapi = TuyaOpenAPI(dssSettings._get_settingvalue(self, 'tuya_endpoint'),
dssSettings._get_settingvalue(self, 'tuya_access_id'),
dssSettings._get_settingvalue(self, 'tuya_access_key'))
openapi.connect()
commands = {'commands': [{'code': 'switch', 'value': not self.tuya_last_switchstate}]}
# result = openapi.post('/v1.0/iot-03/devices/{}/commands'.format(self.tuya_Geraete_id),commands)
result = openapi.post('/v1.0/iot-03/devices/{}/commands'.format(self.tuya_Geraete_id),commands)
_logger.info('Erfolg ? :' + str(result['success']))
success = result['success']
if success:
_logger.info('Erfolgreiche Anfrage :' + str(result['result']))
self.pyaction_tuya_readout()
else:
_logger.info('Fehlerhafte Anfrage :' + str(result['msg']))

155
models/dss_projects.py Normal file
View File

@ -0,0 +1,155 @@
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
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)
_logger = logging.getLogger(__name__)
class dssprojects(models.Model):
_name = "dss.projects"
_description = "DigitalSignage Projekte"
_rec_name = "projektname"
_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',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)
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')
grundsystem_ordner = fields.Char(related='grundsystemname.default_cloud_path')
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)
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_text = fields.Html('Google Beschreibung',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)
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)
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);
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))
# 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
# }
# 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

110
models/dss_settings.py Normal file
View File

@ -0,0 +1,110 @@
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
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 dssSettings(models.Model):
_name = "dss.settings"
_description = "DigitalSignage Einstellungen"
_inherit = ['mail.thread','mail.activity.mixin']
uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID')
def_project_cloudpath = fields.Char('Standard Projekt Pfad',tracking=True)
def_project_cloudpath_sample = fields.Char('Projekt Beispiel :',store=True,tracking=True)
def_contract_cloudpath = fields.Char('Standard Kunden Pfad',tracking=True)
def_contract_cloudpath_sample = fields.Char('Projekt Beispiel :',tracking=True)
def_ad_cloudpath = fields.Char('Standard Kampagnen Pfad',tracking=True)
def_ad_cloudpath_sample = fields.Char('Kampagnen Beispiel :',tracking=True)
tuya_access_id = fields.Char('Tuya Access ID',tracking=True)
tuya_access_key = fields.Char('Tuya Access KEY',tracking=True)
tuya_endpoint = fields.Char('Tuya Access Endpoint',tracking=True)
google_maps_key = fields.Char('Google API Key (Maps)',tracking=True)
os_webimg_path = fields.Char('Verzeichnis für Bilder im Odooweb',tracking=True)
contact_runtime_user = fields.Many2one('res.users',string="Kalenderkontact",help="Kalenderkontakt für Ablauf von Verträgen")
runtime_auto_calandar_entry = fields.Boolean('Autom. Vertragsende Kalendereintrag ?',help='Jeden berechneten Vertrag-Ablaufzeitpunkt automatisch in Kalender eintragen ?',tracking=True)
show_expand_contract_group_ad_state = fields.Boolean('Jeden Kampagnen-Status anzeigen ?',help='im Groupierungsmodus der Verträge nach Kampagnenstatus alle (auch unbenutzte) Statusspalten anzeigen ?',tracking=True)
show_expand_contract_group_ad_work_state = fields.Boolean('Jeden Kampagnen-Arbeitsstatus anzeigen ?',help='im Groupierungsmodus der Verträge nach Kampagnen-Arbeitsstatus alle (auch unbenutzte) Statusspalten anzeigen ?',tracking=True)
show_expand_contract_group_ad_todo_state = fields.Boolean('Jeden Kampagnen-Aufgabenschritt anzeigen ?',help='im Groupierungsmodus der Verträge nach Kampagnen-Aufgabenschritt alle (auch unbenutzte) Aufgabenspalten anzeigen ?',tracking=True)
def _get_settingvalue(self,valuename):
settings = (self.env['dss.settings'].search([],limit=1))
wert = settings._origin.read([valuename])[0][valuename]
return wert
def _get_path_converted(self,path,record):
alls = ''
_logger.info("GetPath with " + str(path)+ " and Record : "+str(record.id))
if path:
for parts in path.split(','):
if parts[0] == '$':
fels = parts[1:]
parts = record._origin.read([fels])
_logger.info("Default Cloudpath Setzen - MusterProjekt gefunden " + str(parts))
if parts:
value = str(parts[0][fels])
else:
value = ''
_logger.info("Default Cloudpath Setzen - MusterProjekt gefunden " + str(value))
alls = alls + value
else:
alls = alls + str(parts)
return alls
@api.onchange('def_project_cloudpath')
def _onchange_def_project_cloudpath(self):
_logger.info("Default Project Cloudpath Setzen")
project_1 = self.env['dss.projects'].search([('uuid','=ilike','%')],limit=1)
if not project_1:
_logger.info("Default Cloudpath Setzen - kein MusterProjekt gefunden")
else:
_logger.info("Default Cloudpath Setzen - MusterProjekt gefunden "+str(project_1.id))
alls = self._get_path_converted(self.def_project_cloudpath,project_1)
self.def_project_cloudpath_sample = alls
@api.onchange('def_contract_cloudpath')
def _onchange_def_contract_cloudpath(self):
_logger.info("Default Contract Cloudpath Setzen")
contract_1 = self.env['dss.contracts'].search([('uuid','=ilike','%')],limit=1)
if not contract_1:
_logger.info("Default Cloudpath Setzen - kein MusterProjekt gefunden")
else:
_logger.info("Default Cloudpath Setzen - MusterProjekt gefunden "+str(contract_1.id))
alls = self._get_path_converted(self.def_contract_cloudpath,contract_1)
self.def_contract_cloudpath_sample = alls
@api.onchange('def_ad_cloudpath')
def _onchange_def_ad_cloudpath(self):
_logger.info("Default ad Cloudpath Setzen")
ad_1 = self.env['dss.ads'].search([('uuid','=ilike','%')],limit=1)
if not ad_1:
_logger.info("Default Cloudpath Setzen - kein MusterProjekt gefunden")
else:
_logger.info("Default Cloudpath Setzen - MusterProjekt gefunden "+str(ad_1.id))
alls = self._get_path_converted(self.def_ad_cloudpath,ad_1)
self.def_ad_cloudpath_sample = alls
def _default_uuid(self):
return str(uuid.uuid4())

43
models/dss_software.py Normal file
View File

@ -0,0 +1,43 @@
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
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 dsssoftware(models.Model):
_name = "dss.software"
_description = "Softwaresysteme"
_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')
# uuid = fields.Char('UUID', required=True, translate=True)
softwarename = fields.Char('Softwarename', required=True)
version = fields.Char('Version')
hersteller = fields.Char('Hersteller')
@api.model
def _default_uuid(self):
return str(uuid.uuid4())

85
models/dss_systems.py Normal file
View File

@ -0,0 +1,85 @@
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
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 dsssystems(models.Model):
_name = "dss.systems"
_description = "DigitalSignage Systemtypen"
_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')
# uuid = fields.Char('UUID', required=True, translate=True)
systemname = fields.Char('Systemname', required=True)
grundsystem = fields.Many2one('dss.systemtypen', string="Gerät ist nutzbar für")
grundsystem_kennung = fields.Char(string='Kennung', related='grundsystem.kennung')
standort = fields.Char('Hauptstandort des Systems',tracking=True)
farbe = fields.Integer('Grundfarbe')
has_heizung = fields.Boolean('Mit Heizsystem')
has_klima = fields.Boolean('Mit Klimasystem')
has_fan = fields.Boolean('Mit Ventiltorensystem')
stromzaehler = fields.Many2one('dss.geraetetypen')
stromverbrauch_avg = fields.Integer('Stromverbrauch AVG in W')
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')]);
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_panel = fields.Many2one('dss.geraetetypen',domain="['&',('grundsystem_kennung','=','LCD'),('led_geraetetyp','=','ANZ')]")
lcd_mainboard = fields.Many2one('dss.geraetetypen',domain="['&',('grundsystem_kennung','=','LCD'),('led_geraetetyp','=','STE')]")
lcd_touchcontroler = fields.Many2one('dss.geraetetypen',domain="['&',('grundsystem_kennung','=','LCD'),('led_geraetetyp','=','SYS')]")
lcd_netzteil = fields.Many2one('dss.geraetetypen',domain="['&',('grundsystem_kennung','=','LCD'),('led_geraetetyp','=','NET')]")
led_pixelpitch = fields.Char('Pixelabstand')
led_breite = fields.Integer('LED Breite mm')
led_hoehe = fields.Integer('LED Hoehe mm')
led_pixel_breite = fields.Integer('LED Breite px')
led_pixel_hoehe = fields.Integer('LED Hoehe px')
led_receivingcard = fields.Many2one('dss.geraetetypen',domain="['&',('grundsystem_kennung','=','LED'),('led_geraetetyp','=','REC')]")
led_netzteile = fields.Many2one('dss.geraetetypen',domain="['&',('grundsystem_kennung','=','LED'),('led_geraetetyp','=','NET')]")
led_module = fields.Many2one('dss.geraetetypen',domain="['&',('grundsystem_kennung','=','LED'),('led_geraetetyp','=','MOD')]")
led_montage = fields.Selection([('WAN','Wandmontage'), ('FUS','1 standFuss zentral'), ('FU2','2 Standfüsse Aussen'),('FU3','1 Standfuss dezentral'),('MO1','manuell Mobil bewegbar'),('MO2','Mobil bewegbar Container'),('XXX','Sonstige')],'Montage/Befestigung');
led_montage_sonstige = fields.Char('Sonstige Montageart')
zusatz_integrationen = fields.Many2many('dss.geraetetypen')
@api.model
def _default_uuid(self):
return str(uuid.uuid4())

64
models/dss_systemtypen.py Normal file
View File

@ -0,0 +1,64 @@
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
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 dsssystemtypen(models.Model):
_name = "dss.systemtypen"
_inherit = ['mail.thread']
_description = "DigitalSignage Systemtypen"
_rec_name = "systemname"
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.Char('Grundfarbe')
icon = fields.Image()
icon_5050 = fields.Image("Icon 50",compute='_compute_icon_5050')
default_adstructure = fields.Many2one('dss.adstructures',String='Standard-Werbeaufbau')
default_cloud_path = fields.Char('Standard Cloud Path')
@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

View File

@ -22,3 +22,18 @@ width:90px;
height:20px; height:20px;
width:20px; width:20px;
} }
.dss_dd {
max-height: 70vh;
overflow: auto;
background-clip: border-box;
background-color: #ffe9c7 !important;
box-shadow: 0 1rem 1.1rem rgba(0, 0, 0, 0.5) !important;
}
.o_FormRenderer_chatterContainer.oe_chatter.o-aside
{
max-width: 20%; // The width in pixels
}

View File

@ -4,8 +4,8 @@ function initialize_map() {
// MAP CONFIG AND LOADING // MAP CONFIG AND LOADING
var map = new google.maps.Map(document.getElementById('odoo-google-map'), { var map = new google.maps.Map(document.getElementById('odoo-google-map'), {
zoom: 1, zoom: 10,
center: {lat: 0.0, lng: 0.0}, center: {lat: 50.98, lng: 12.98},
mapTypeId: google.maps.MapTypeId.ROADMAP mapTypeId: google.maps.MapTypeId.ROADMAP
}); });
@ -14,11 +14,11 @@ function initialize_map() {
// INFO BUBBLES // INFO BUBBLES
var infoWindow = new google.maps.InfoWindow(); var infoWindow = new google.maps.InfoWindow();
var partners = new google.maps.MarkerImage('/website_google_map/static/src/img/partners.png', new google.maps.Size(25, 25)); var partners = new google.maps.MarkerImage('/DigitalSignage/static/src/img/pin.png', new google.maps.Size(55, 55));
var partner_url = document.body.getAttribute('data-partner-url') || ''; var partner_url = document.body.getAttribute('data-partner-url') || '';
var markers = []; var markers = [];
var options = { var options = {
imagePath: '/website_google_map/static/src/lib/images/m' imagePath: '/DigitalSignage/static/src/img/m'
}; };
google.maps.event.addListener(map, 'click', function() { google.maps.event.addListener(map, 'click', function() {
@ -28,43 +28,27 @@ function initialize_map() {
// Display the bubble once clicked // Display the bubble once clicked
var onMarkerClick = function() { var onMarkerClick = function() {
var marker = this; var marker = this;
var p = marker.partner; var p = marker.project;
infoWindow.setContent( infoWindow.setContent(
'<div class="marker">'+ '<div class="marker">'+
(partner_url.length ? '<a target="_top" href="'+partner_url+p.id+'"><b>'+p.name +'</b></a>' : '<b>'+p.name+'</b>' )+ (partner_url.length ? '<a target="_top" href="'+partner_url+'?id='+p.id+'"><b>'+p.google_name +'</b></a>' : '<b>'+p.google_name+'</b></br> : ' )+
(p.type ? ' <b>' + p.type + '</b>' : '')+ (p.google_typ ? ' </br><b>' + p.google_typ + '</b></br></br>' : '')+
' <pre>' + p.address + '</pre>'+ (p.google_image ? ' </br><img src="'+ p.google_image + '" width="200px"/></br></br>' : '')+
(p.google_text ? ' </br><span> ' + p.google_text + '</span>' : '')+
'</div>' '</div>'
); );
infoWindow.open(map, marker); infoWindow.open(map, marker);
}; };
// Create a bubble for a partner // Create a bubble for a partner
var set_marker = function(partner) { var set_marker = function(project) {
// If no lat & long, geocode address // If no lat & long, geocode address
// TODO: a server cronjob that will store these coordinates in database instead of resolving them on-the-fly // TODO: a server cronjob that will store these coordinates in database instead of resolving them on-the-fly
if (!partner.latitude && !partner.longitude) { if (project.latitude && project.longitude) {
Geocoder.geocode({'address': partner.address}, function(results, status) { var latLng = new google.maps.LatLng(project.latitude, project.longitude);
if (status === google.maps.GeocoderStatus.OK) { var partners = new google.maps.MarkerImage('/DigitalSignage/static/src/img/'+project.google_marker, new google.maps.Size(55, 55));
var location = results[0].geometry.location;
partner.latitude = location.ob;
partner.longitude = location.pb;
var marker = new google.maps.Marker({
partner: partner,
map: map,
icon: partners,
position: location
});
google.maps.event.addListener(marker, 'click', onMarkerClick);
markers.push(marker);
} else {
console.debug('Geocode was not successful for the following reason: ' + status);
}
});
} else {
var latLng = new google.maps.LatLng(partner.latitude, partner.longitude);
var marker = new google.maps.Marker({ var marker = new google.maps.Marker({
partner: partner, project: project,
icon: partners, icon: partners,
map: map, map: map,
position: latLng position: latLng
@ -76,9 +60,9 @@ function initialize_map() {
/* eslint-disable no-undef */ /* eslint-disable no-undef */
// Create the markers and cluster them on the map // Create the markers and cluster them on the map
if (odoo_partner_data){ /* odoo_partner_data special variable should have been defined in google_map.xml */ if (odoo_projects_data){ /* odoo_partner_data special variable should have been defined in google_map.xml */
for (var i = 0; i < odoo_partner_data.counter; i++) { for (var i = 0; i < odoo_projects_data.counter; i++) {
set_marker(odoo_partner_data.partners[i]); set_marker(odoo_projects_data.projects[i]);
} }
new MarkerClusterer(map, markers, options); new MarkerClusterer(map, markers, options);
} }

View File

@ -46,6 +46,7 @@
<div class="col-20"> <div class="col-20">
<group> <group>
<field name="description" string="Kurzbeschreibung" widget="text"/> <field name="description" string="Kurzbeschreibung" widget="text"/>
<field name="work_state_info" string="Aktuelle Hinweise" widget="text"/>
</group> </group>
</div> </div>
</div> </div>
@ -123,45 +124,88 @@
</div> </div>
<hr></hr> <hr></hr>
<notebook> <notebook>
<page name="informations" string="Dateien"> <page name="zuarbeiten" string="Ablauf">
-- <field name="need_media"> <div class="row">
<tree string="Dateien" editable="False" create="False"> <div class="col-4">
<field name="field" string="von Feld"/> <group>
<field name="mediatype_name" string=" Verwendung "/> <field name="date_zuarbeit" widget="date"/>
<field name="mediafile" string=" Datei " filename="mediafile_file"/> </group>
<field name="mediafile" string=" Inhalt " options="{'size':[150]}" widget="image"/> </div>
<field name="mediafile_file"/> <div class="col-4">
<field name="secured_ro" string=" Gesperrt " widget="boolean_toggle"/> <group>
<field name="used_ro" string=" Benutzt " widget="boolean_toggle"/> <field name="date_korrekturabzug" widget="date"/>
</tree> </group>
</field> </div>
<div class="col-4">
<group>
<field name="date_korrekturfreigabe" widget="date"/>
</group>
</div>
</div>
<div class="row">
<div class="col-4">
<group>
</group>
</div>
<div class="col-4">
<group>
</group>
</div>
<div class="col-4">
<group>
</group>
</div>
</div>
</page> </page>
<page name="informations" string="Informationen"> <page name="informations" string="Sonderlaufzeiten">
<group> <div class="row">
<field name="contract" string="Vertrag" readonly="1"/> <div class="col-4">
<field name="contract_id" string="Kunden/Vert.nummer" readonly="1"/> <group>
<field name="id" string="Vertrags Interne Id" readonly="1"/> <field name="start_date" widget="date"/>
<field name="uuid" string="Datensatz UUID" readonly="1"/> </group>
<field name="adpos" string="Reihenfolge" readonly="1"/> </div>
<field name="ad_is_lastpos" string="ist Letzte" readonly="1"/> <div class="col-4">
<field name="ad_state_func" string="Status" readonly="1"/> <group>
</group> <field name="end_date" widget="date"/>
</group>
</div>
</div>
</page> </page>
<page name="createhistory" string="DSInformation"> <page name="informations" string="entahltene Dateien">
<group> <field name="need_media">
<field name="date_create" string="Erstellt am :" readonly="1"/> <tree string="Dateien" editable="False" create="False">
<field name="user_create" string="Erstell von :" readonly="1"/> <field name="field" string="von Feld"/>
<field name="date_lastedit" string="letzte Änderung am :" readonly="1"/> <field name="mediatype_name" string=" Verwendung "/>
<field name="user_lastedit" string="letzte Änderung von :" readonly="1"/> <field name="mediafile" string=" Datei " filename="mediafile_file"/>
</group> <field name="mediafile" string=" Inhalt " options="{'size':[150]}" widget="image"/>
<field name="mediafile_file"/>
<field name="secured_ro" string=" Gesperrt " widget="boolean_toggle"/>
<field name="used_ro" string=" Benutzt " widget="boolean_toggle"/>
</tree>
</field>
</page>
<page name="informations" string="Interne Informationen">
<group>
<field name="contract" string="Vertrag" readonly="1"/>
<field name="contract_id" string="Kunden/Vert.nummer" readonly="1"/>
<field name="id" string="Vertrags Interne Id" readonly="1"/>
<field name="uuid" string="Datensatz UUID" readonly="1"/>
<field name="adpos" string="Reihenfolge" readonly="1"/>
<field name="ad_is_lastpos" string="ist Letzte" readonly="1"/>
<field name="ad_state_func" string="Status" readonly="1"/>
<field name="date_create" string="Erstellt am :" readonly="1"/>
<field name="user_create" string="Erstell von :" readonly="1"/>
<field name="date_lastedit" string="letzte Änderung am :" readonly="1"/>
<field name="user_lastedit" string="letzte Änderung von :" readonly="1"/>
</group>
</page> </page>
</notebook> </notebook>
</sheet> </sheet>
<!-- <div class="oe_chatter"> <div class="oe_chatter">
<field name="message_follower_ids" options="{'post_refresh':True}" help="Follow this project to automatically track the events associated to tasks and issues of this project." groups="base.group_user"/> <field name="message_follower_ids" options="{'post_refresh':True}" help="Follow this project to automatically track the events associated to tasks and issues of this project." groups="base.group_user"/>
<field name="message_ids"/> <field name="message_ids"/>
<field name="activity_ids"/> <field name="activity_ids"/>
</div>--> </div>
</form> </form>
</field> </field>
</record> </record>
@ -252,25 +296,26 @@
</div> </div>
</div> </div>
<div class="row" style="--gutter-x:10px;" attrs="{'invisible': [('adtype','==','MAIN')]}"> <div class="row" style="--gutter-x:10px;" attrs="{'invisible': [('adtype','==','MAIN')]}">
<div style="height:10px;width:90%"></div> <div style="height:10px;width:90%"></div>
<div t-attf-style="background-color:{{record.ad_state_color.value}};padding-left: 1px;width:10%;height:10px;border-style:solid;border-width:0.2px;"></div> <div t-attf-style="background-color:{{record.ad_state_color.value}};padding-left: 1px;width:10%;height:10px;border-style:solid;border-width:0.2px;"></div>
<div class="row" style="--gutter-x:10px;"> <div class="row" style="--gutter-x:10px;">
<div class="col-1"> <div class="col-1">
<img src="/DigitalSignage/static/images/tree_ud.png" width="20px" height="72px"/> <img alt="tree" src="/DigitalSignage/static/images/tree_ud.png" width="20px" height="72px"/>
</div> </div>
<div class="col-11"> <div class="col-11">
<div class="row" style="--gutter-x:10px;"> <div class="row" style="--gutter-x:10px;">
<div class="col-11"> <div class="col-11">
<strong style="font-size:20px;font-weight:bold"><field name="adname"/></strong> <strong style="font-size:20px;font-weight:bold"><field name="adname"/></strong>
</div> </div>
<div class="col-1"> <div class="col-1">
<strong style="font-size:8px;text-align:right;"><field name="create_date"/></strong> <strong style="font-size:8px;text-align:right;"><field name="create_date"/></strong>
<strong style="font-size:8px;text-align:right;"><field name="ad_is_lastpos" widget="boolean_toggle" /></strong> <strong style="font-size:8px;text-align:right;"><field name="ad_is_lastpos" widget="boolean_toggle" /></strong>
</div> </div>
</div>
<div class="row" style="--gutter-x:10px;">
<div class="col-1">
</div> </div>
<div class="row" style="--gutter-x:10px;">
<div class="col-1">
</div>
<div class="col-7"> <div class="col-7">
<strong style="font-size:12px"><field name="description"/></strong> <strong style="font-size:12px"><field name="description"/></strong>
</div> </div>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<record id="dss_advertisefields_view_tree" model="ir.ui.view"> <record id="dss_advertisefields_view_tree" model="ir.ui.view">
<field name="name">dss_advertisefields_tree</field> <field name="name">dss_advertisefields_tree</field>
<field name="model">dss.advertisefields</field> <field name="model">dss.advertisefields</field>
@ -10,7 +9,9 @@
<tree string="Werbefelder"> <tree string="Werbefelder">
<field name="feldname"/> <field name="feldname"/>
<field name="project"/> <field name="project"/>
<field name="contract"/> <field name="contract">
</field>
<field name="isblocked" widget="boolean_toggle"/>
<field name="color_used" widget="color"/> <field name="color_used" widget="color"/>
<field name="color_unused" widget="color"/> <field name="color_unused" widget="color"/>
</tree> </tree>
@ -28,11 +29,18 @@
<field name="feldname" string="Feldname"/> <field name="feldname" string="Feldname"/>
<field name="project" string="Projekt"/> <field name="project" string="Projekt"/>
<field name="auto_feldname" string="Projekt_Feld" readonly="1"/> <field name="auto_feldname" string="Projekt_Feld" readonly="1"/>
<field name="contract" string="Vertrag"/> <field name="contract" string="Vertrag">
<div colspan="2" style="font-color:#E00000;"><p>Die Struktur kann erst nach Speichern der Grunddaten eingerichtet werden !</p></div> <tree string="Verträge">
<field name="mediastructure" attrs="{'invisible': [('issaved','!=',True)]}" /> <field name="contract_auto_name"/>
<field name="color_used" widget="color"/> <field name="contract_auto_id"/>
<field name="color_unused" widget="color"/> <field name="contract_name" />
</tree>
</field>
<div colspan="2" style="font-color:#E00000;"><p>Die Struktur kann erst nach Speichern der Grunddaten eingerichtet werden !</p></div>
<field name="mediastructure" attrs="{'invisible': [('issaved','!=',True)]}" />
<field name="color_used" widget="color"/>
<field name="color_unused" widget="color"/>
<field name="isblocked" widget="boolean_toggle"/>
</group> </group>
</group> </group>
<notebook> <notebook>
@ -81,4 +89,13 @@
</field> </field>
</record> </record>
<record id="action_check_fieldcontract_multi_values" model="ir.actions.server">
<field name="name">Verträge prüfen ob dort Vertrag beinhaltet!</field>
<field name="model_id" ref="model_dss_advertisefields"/>
<field name="binding_model_id" ref="model_dss_advertisefields"/>
<field name="binding_view_types">tree</field>
<field name="state">code</field>
<field name="code">action = records.check_contract_multi_Values()</field>
</record>
</odoo> </odoo>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<record id="dss_contract_view_search" model="ir.ui.view">
<field name="name">dss_contracts_form</field>
<field name="model">dss.contracts</field>
<field name="arch" type="xml">
<search string="Verträge">
<group expand="0" string="Systeme">
<filter string="Nach letzt Kamp. - Zuständigkeit" name="letz_ads_last_state" context="{'group_by' : 'ads_last_state'}"/>
<filter string="Nach letzt Kamp. - akt. Schritt" name="letz_ads_last_work_state" context="{'group_by' : 'ads_last_work_state'}"/>
<filter string="Nach letzt Kamp. - näch. Aufgabe" name="letz_ads_last_todo_state" context="{'group_by' : 'ads_last_todo_state'}"/>
</group>
</search>
</field>
</record>
<record id="action_dss_project_contracts" model="ir.actions.act_window"> <record id="action_dss_project_contracts" model="ir.actions.act_window">
<field name="name">DigitalSignage Projekt Vertraege</field> <field name="name">DigitalSignage Projekt Vertraege</field>
<field name="type">ir.actions.act_window</field> <field name="type">ir.actions.act_window</field>
@ -38,7 +52,10 @@
<field name="project_id"/> <field name="project_id"/>
<field name="client_short_vorname"/> <field name="client_short_vorname"/>
<field name="client_short_name"/> <field name="client_short_name"/>
<field name="werbe_feld_selected"/> <field name="werbe_feld_selected" widget="many2many_tags"/>
<field name="ads_last_state"/>
<field name="ads_last_work_state"/>
<field name="ads_last_todo_state"/>
</tree> </tree>
</field> </field>
</record> </record>
@ -142,256 +159,366 @@
<field eval="2" name="priority"/> <field eval="2" name="priority"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form> <form>
<header> <header>
<button name="tokampagne" string="Zur Werbekampagne" type="object" class="oe_hightlight"/> <button name="tokampagne" string="Zur Werbekampagne" type="object" class="oe_hightlight"/>
</header> </header>
<sheet> <sheet>
<div class="row"> <div class="row">
<h1> <h1>
<field name="contract_auto_name" string="Autom. Vertragskennung"/> <field name="contract_auto_name" string="Autom. Vertragskennung"/>
</h1> </h1>
</div> </div>
<div class="row"> <div class="row">
<hr></hr> <hr></hr>
</div> </div>
<div class="row">
<div class="col-7">
<div class="row"> <div class="row">
<div class="col-3"> <div class="col-7">
<group> <div class="row">
<field name="project_id" string="Projekt ID"/> <div class="col-3">
</group> <group>
</div> <field name="project_id" string="Projekt ID"/>
<div class="col-7"> </group>
<group> </div>
<field name="project" string="Projekt"/> <div class="col-7">
</group> <group>
</div> <field name="project" string="Projekt"/>
</div> </group>
<div class="row"> </div>
<div class="col-3"> </div>
<group> <div class="row">
<field name="client_id" string="Kunden ID"/> <div class="col-3">
</group> <group>
</div> <field name="client_id" string="Kunden ID"/>
</div> </group>
<hr></hr> </div>
<div class="row"> </div>
<div class="col-20"> <hr></hr>
<div class="row"> <div class="row">
<div class="col-4"> <div class="col-20">
<group> <div class="row">
<field name="contract_auto_id" string="Kundennummer"/> <div class="col-4">
</group> <group>
</div> <field name="contract_auto_id" string="Kundennummer"/>
<div class="col-8"> </group>
<group> </div>
<field name="contract_name" string="Vertragskennung"/> <div class="col-8">
</group> <group>
</div> <field name="contract_name" string="Vertragskennung"/>
</group>
</div>
</div>
<div class="row">
<div class="col-8">
<group>
<field name="werbe_feld_selected" string="Werbefeld" widget="many2many_tags" option="{'not_delete': True}" domain="[('project','=',project),'|',('contract','=',False),('isblocked','=',False)]"/>
</group>
</div>
</div>
</div>
</div>
</div> </div>
<div class="row"> <div class="col-5" style="border-style:solid;border-width:1px;border-color:lightgray">
<div class="col-8">
<group>
<field name="werbe_feld_selected" string="Werbefeld" widget="many2many_tags" option="{'not_delete': True}" domain="[('project','=',project),('contract','=',False)]"/>
</group>
</div>
</div>
</div>
</div>
</div>
<div class="col-5" style="border-style:solid;border-width:1px;border-color:lightgray">
<!-- <div class="row"> <!-- <div class="row">
<div class="col-1" t-attf-style="background-color:{{work_state_color}};padding-left: 1px;height:20px;border-style:solid;border-width:0.2px;"> <div class="col-1" t-attf-style="background-color:{{work_state_color}};padding-left: 1px;height:20px;border-style:solid;border-width:0.2px;">
</div> </div>
<div class="col-1" t-attf-style="background-color:{{todo_state_color}};padding-left: 1px;height:20px;border-style:solid;border-width:0.2px;"> <div class="col-1" t-attf-style="background-color:{{todo_state_color}};padding-left: 1px;height:20px;border-style:solid;border-width:0.2px;">
</div> </div>
</div>--> </div>-->
<div class="row"> <div class="row">
<div class="col-5" style="height:20px;"> <div class="col-5" style="height:20px;">
</div> </div>
</div>
<div class="row">
<group>
<field name="contract_state" string="Vertragsstatus"/>
</group>
</div>
<div class="row">
<group>
<field name="ads_last_state" string="Zuständigkeit (letzte Kamp.)"/>
</group>
</div>
<div class="row">
<group>
<field name="ads_last_work_state" string="Arbeitsstand (letzte Kamp.)"/>
</group>
</div>
<field name="ads_last_work_state_text" invisible="1"/>
<div class="row" attrs="{'invisible': [('ads_last_work_state_text','!=','Sonstiges')]}" >
<group>
<field name="work_state_info"/>
</group>
</div>
<div class="row">
<group>
<field name="ads_last_todo_state" string="nächste Aufgabe (letzte Kamp.)"/>
</group>
</div>
<div class="row">
<group>
<field name="ads_last_todo_state_until" string="Aufgabe bis"/>
</group>
</div>
</div>
</div> </div>
<div class="row"> <hr></hr>
<group> <div class="row">
<field name="contract_state" string="Status"/> <div class="col-15">
</group>
</div>
<div class="row">
<group>
<field name="ads_last_work_state" string="Arbeitsstand"/>
</group>
</div>
<field name="ads_last_work_state_text" invisible="1"/>
<div class="row" attrs="{'invisible': [('ads_last_work_state_text','!=','Sonstiges')]}" >
<group>
<field name="work_state_info"/>
</group>
</div>
<div class="row">
<group>
<field name="ads_last_todo_state" string="nächste Aufgabe"/>
</group>
</div>
<div class="row">
<group>
<field name="ads_last_todo_state_until" string="Aufgabe bis"/>
</group>
</div>
</div>
</div>
<hr></hr>
<div class="row">
<div class="col-15">
<group> <group>
<field name="client" string="Kunde"/> <field name="client" string="Kunde"/>
</group> </group>
</div> </div>
</div>
<hr></hr>
<div class="row">
<div class="col-10">
<group>
<field name="client_short_company"/>
</group>
</div>
</div>
<div class="row">
<div class="col-4">
<group>
<field name="client_short_vorname"/>
</group>
</div>
<div class="col-8">
<group>
<field name="client_short_name"/>
</group>
</div>
</div>
<div class="row">
<div class="col-13">
<group>
<field name="client_short_strasse"/>
</group>
</div> </div>
</div> <div class="row" string="Kundendaten Kundenverwaltung" name="contact_edit" attrs="{'invisible':[('client','=',False)]}">
<div class="row"> <div class="mw-sm-100">
<div class="col-3"> <button string="zum Kunde wechseln" name="pyaction_dss_contract_goto_partner" type="object" class="btn-primary o_open_tasks" data-hotkey="m"/>
<group> </div>
<field name="client_short_land"/> <br></br>
</group> <br></br>
</div> <hr></hr>
<div class="col-3"> <br></br>
<group> <div class="row">
<field name="client_short_plz"/> <div class="col-10">
</group> <group>
</div> <field name="contact_company_name" string="Firmenname Kunde²"/>
<div class="col-6"> </group>
<group> </div>
<field name="client_short_ort"/> </div>
</group> <div class="row">
</div> <div class="col-4">
</div> <group>
<div class="row"> <field name="contact_dsspartner_vorname" string="Vorname Kunde²"/>
<div class="col-3"> </group>
<group> </div>
<field name="client_short_telefon"/> <div class="col-8">
</group> <group>
</div> <field name="contact_dsspartner_name" string="Name Kunde²"/>
<div class="col-3"> </group>
<group> </div>
<field name="client_short_mobil"/> </div>
</group> <div class="row">
</div> <div class="col-13">
<div class="col-5"> <group>
<group> <field name="contact_street" string="Strasse Kunde²"/>
<field name="client_short_email"/> </group>
</group> </div>
</div> </div>
</div> <div class="row">
<div class="row"> <div class="col-13">
<div class="col-10"> <group>
<group> <field name="contact_street2" string="Strasse 2 Kunde²"/>
<field name="client_short_website"/> </group>
</group> </div>
</div> </div>
<button string="Kunde anlegen" name="pyaction_dss_contract_make_partner" type="object" class="btn-primary o_open_tasks" data-hotkey="m"/> <div class="row">
<div class="col-2"> <div class="col-3">
</div> <group>
</div> <field name="contact_country_id" string="Land Kunde²"/>
<hr></hr> </group>
</div>
<div class="col-3">
<group>
<field name="contact_zip" string="PLZ Kunde²"/>
</group>
</div>
<div class="col-6">
<group>
<field name="contact_city" string="Ort Kunde²"/>
</group>
</div>
</div>
<div class="row">
<div class="col-3">
<group>
<field name="contact_telefon" string="Telefon Kunde²"/>
</group>
</div>
<div class="col-3">
<group>
<field name="contact_mobil" string="Mobile Kunde²"/>
</group>
</div>
<div class="col-5">
<group>
<field name="contact_email" string="Email Kunde²"/>
</group>
</div>
</div>
<div class="row">
<span><bold>² - Kunde wird über Kontaktmanager verwaltet .. Bitte Daten dort ändern ... </bold></span>
</div>
</div>
<div class="row" string="Kundendaten Schnellanlage" name="client_short_edit" attrs="{'invisible':[('client','!=',False)]}">
<hr></hr>
<div class="row">
<div class="col-10">
<group>
<field name="client_short_company" string="Firmenname Kunde"/>
</group>
</div>
</div>
<div class="row">
<div class="col-4">
<group>
<field name="client_short_vorname" string="Vorname Kunde"/>
</group>
</div>
<div class="col-8">
<group>
<field name="client_short_name" string="Name Kunde"/>
</group>
</div>
</div>
<div class="row">
<div class="col-13">
<group>
<field name="client_short_strasse" string="Strasse Kunde"/>
</group>
</div>
</div>
<div class="row">
<div class="col-3">
<group>
<field name="client_short_land" string="Land Kunde"/>
</group>
</div>
<div class="col-3">
<group>
<field name="client_short_plz" string="PLZ Kunde"/>
</group>
</div>
<div class="col-6">
<group>
<field name="client_short_ort" string="Ort Kunde"/>
</group>
</div>
</div>
<div class="row">
<div class="col-3">
<group>
<field name="client_short_telefon" string="Telefon Kunde"/>
</group>
</div>
<div class="col-3">
<group>
<field name="client_short_mobil" string="Mobil Kunde"/>
</group>
</div>
<div class="col-5">
<group>
<field name="client_short_email" string="Email Kunde"/>
</group>
</div>
</div>
<div class="row">
<div class="col-10">
<group>
<field name="client_short_website" string="Webseite Kunde"/>
</group>
</div>
<button string="Kunde anlegen" name="pyaction_dss_contract_make_partner" type="object" class="btn-primary o_open_tasks" data-hotkey="m" confirm="Sicher das ein Kunde erstellt werden soll ? Spätere Änderungen dann nur im Kunde möglich !"/>
<div class="col-2">
</div>
</div>
</div>
<hr></hr>
<notebook> <notebook>
<page name="grundsettings" string="Grundeinstellungen"> <page name="grundsettings" string="Grundeinstellungen">
<div class="row">
<group string="Werbeaufbau">
<field name="project_ad_structure"/>
</group>
</div>
<div class="row"> <div class="row">
<div class="col-4"> <div class="col-4">
<group> <group>
<field name="main_runtime" string="Gesamtlaufzeit Sekunden (Vertrag)"/> <field name="main_runtime" string="Gesamtlaufzeit Sekunden (Vertrag)" placeholder="Gesamte LZ lt. Vertrag"/>
</group> </group>
</div> </div>
<div class="col-3"> <div class="col-3">
<group> <group>
<field name="split_runtime_count" string="Laufzeit Anzahl"/> <field name="split_runtime_count" string="Laufzeit Teilung - Anzahl" placeholder="LZ Teilung" help="Bei Teilung der Gesamtlaufzeit hier bitte die Anzahl eingeben !"/>
</group> </group>
</div> </div>
<div class="col-3"> <div class="col-3">
<group> <group>
<field name="split_runtime_time" string="Laufzeit Sekunden"/> <field name="split_runtime_time" string="Laufzeit Teilung - Sekunden" placeholder="LZ je Teilung" help="Bei Teilung der Gesamtlaufzeit hier bitte die Teillaufzeit eingeben !"/>
</group> </group>
</div> </div>
</div> </div>
</page> </page>
<page name="contractsettings" string="Vertragsdaten"> <page name="contractsettings" string="Vertragsdaten">
<div class="row"> <div class="row">
<div class="col-4"> <div class="col-4">
<group> <group>
<field name="contract_date" string="Vertragsdatum"/> <field name="contract_date" string="Vertragsdatum"/>
</group> </group>
</div> </div>
<div class="col-4"> <div class="col-4">
<group> <group>
<field name="start_date"/> <field name="start_date"/>
</group> </group>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-8"> <div class="col-8">
<group> <group>
<field name="runtimesystem" string="Laufzeitmodel"/> <field name="runtimesystem" string="Laufzeitmodel"/>
</group> </group>
</div> </div>
</div> </div>
<div class="row" > <div class="row" >
<div class="col-8"> <div class="col-8">
<group attrs="{'invisible': [('runtimesystem','!=','M')]}" >> <group attrs="{'invisible': [('runtimesystem','!=','M')]}" >
<field name="runtime_m" string="Laufzeit Monate"/> <field name="runtime_m" string="Laufzeit Monate"/>
</group> <field name="runtime_bonus_m" string="Bonus Monate"/>
<group attrs="{'invisible': [('runtimesystem','!=','T')]}" >> </group>
<field name="runtime_t" string="Laufzeit Tage"/> <group attrs="{'invisible': [('runtimesystem','!=','T')]}" >
</group> <field name="runtime_t" string="Laufzeit Tage"/>
<group attrs="{'invisible': [('runtimesystem','!=','E')]}" >> <field name="runtime_bonus_t" string="Bonus Tage"/>
<field name="runtime_events" string="Laufzeit EventTage"/> </group>
</group> <group attrs="{'invisible': [('runtimesystem','!=','E')]}" >
<group attrs="{'invisible': [('runtimesystem','!=','S')]}" >> <field name="runtime_events" string="Laufzeit EventTage"/>
<field name="runtime_divers" string="Laufzeit sontige"/> <field name="runtime_bonus_e" string="Bonus Events"/>
</group> </group>
</div> <group attrs="{'invisible': [('runtimesystem','!=','S')]}" >
</div> <field name="runtime_divers" string="Laufzeit sontige"/>
<div class="row" > </group>
<div class="col-8"> </div>
<group> </div>
<field name="runtime_finish" string="Laufzeit Ende"/> <div class="row" >
<button icon="DigitalSignage/static/src/img/dsscalc.png" name="pyaction_dss_contract_make_partner" type="object" class="dss-smallbutton" data-hotkey="c"/> <div class="col-6">
</group> <group>
</div> <field name="runtime_finish" string="Laufzeit Ende"/>
</div> </group>
<hr>></hr> </div>
<div class="row" > <div class="col-2">
<div class="col-8"> <button icon="DigitalSignage/static/src/img/dsscalc.png" name="pyaction_dss_contract_calc_runtime" type="object" class="dss-smallbutton" data-hotkey="c" help="Berechnet das Laufzeitende des Vertrages und trägt diesen in einen Kalender ein !"/>
<group> <button icon="DigitalSignage/static/src/img/calendar.png" name="pyaction_dss_contract_addcalendar_runtime" type="object" class="dss-smallbutton" data-hotkey="d" help="Trägt den Ablauftag in einen Kalender ein !" attrs="{'invisible': ['|',('runtime_finish','=',False),('runtime_calendar_event','!=',False)]}"/>
<field name="paymentsystems" string="Abrechnung"/> <button icon="DigitalSignage/static/src/img/calendar_rf.png" name="pyaction_dss_contract_addcalendar_rf_runtime" type="object" class="dss-smallbutton" data-hotkey="d" help="Trägt den Ablauftag in einen Kalender ein !" attrs="{'invisible': [('runtime_calendar_event','=',False)]}"/>
<field name="intern_info_payment_off"/> </div>
</group> </div>
</div> <div class="row" >
</div> <div class="col-4">
<group>
<field name="contract_auto_extend" widget="boolean_toggle"/>
</group>
</div>
<div class="col-4">
<group>
<field name="contract_auto_extend_time" attrs="{'invisible': [('contract_auto_extend','!=',True)]}" />
</group>
</div>
</div>
<hr>></hr>
<div class="row" >
<div class="col-8">
<group>
<field name="paymentsystems" string="Abrechnung"/>
<field name="intern_info_payment_off"/>
</group>
</div>
</div>
</page> </page>
<page name="contractsettings" string="Kampagnen/Verlauf"> <page name="contractsettings" string="Kampagnen/Verlauf">
<group> <group>
@ -426,20 +553,19 @@
<field name="client_other_projects" string="Weitere Projekte"/> <field name="client_other_projects" string="Weitere Projekte"/>
</group> </group>
</page>--> </page>-->
<page name="informations" string="Informationen"> <page name="informations" string="Interne Informationen">
<group> <group>
<field name="cloudlink"/> <field name="cloudlink"/>
</group> </group>
</page>
<page name="informations" string="Informationen">
<group> <group>
<field name="contract_id" string="Kunden/Vert.nummer" readonly="1"/> <field name="contract_id" string="Kunden/Vert.nummer" readonly="1"/>
<field name="id" string="Vertrags Interne Id" readonly="1"/> <field name="id" string="Vertrags Interne Id" readonly="1"/>
<field name="ads_last_state" string="letzter Vorgang" readonly="1"/> <field name="ads_last_state" string="letzter Vorgang"/>
<field name="contract_auto_name" string="Autoname"/> <field name="contract_auto_name" string="Autoname"/>
<field name="projectIid" string="Project IId" readonly="1"/> <field name="projectIid" string="Project IId" readonly="1"/>
<field name="uuid" string="Datensatz UUID"/> <field name="uuid" string="Datensatz UUID"/>
<field name="project_ad_structure" string="Project Aufbau" readonly="1"/> <field name="project_ad_structure" string="Project Aufbau" readonly="1"/>
<field name="runtime_calendar_event" string="zum Ablauf-KalenderEvent"/>
</group> </group>
</page> </page>
</notebook> </notebook>
@ -473,6 +599,7 @@
<kanban class="o_kanban_mobile oe_background_gray o_emphasize_colors" on_create="quick_create" quick_create_view="DigitalSignage.dss_project_new_contract_kanbanform" action="pyaction_view_contract" type="object" default_group_by="contract_state">--> <kanban class="o_kanban_mobile oe_background_gray o_emphasize_colors" on_create="quick_create" quick_create_view="DigitalSignage.dss_project_new_contract_kanbanform" action="pyaction_view_contract" type="object" default_group_by="contract_state">-->
<field name="contract_name"/> <field name="contract_name"/>
<field name="contract_state"/> <field name="contract_state"/>
<field name="contract_state_color"/>
<field name="contract_state_order"/> <field name="contract_state_order"/>
<field name="ads_last_work_state_color"/> <field name="ads_last_work_state_color"/>
<field name="ads_last_todo_state_color"/> <field name="ads_last_todo_state_color"/>
@ -480,26 +607,77 @@
<templates> <templates>
<t t-name="kanban-box"> <t t-name="kanban-box">
<div class="oe_kanban_global_click o_has_icon oe_kanban_content oe_kanban_card"> <div class="oe_kanban_global_click o_has_icon oe_kanban_content oe_kanban_card">
<div class="oe_kanban_content" data-toggle="tooltip" title="Informationen zum Vertrag :">
</div>
<div class="oe_kanban_content oe_kanban_global_click o_kanban_get_form"> <div class="oe_kanban_content oe_kanban_global_click o_kanban_get_form">
<div class="row" style="--gutter-x:10px;"> <div class="row" style="--gutter-x:10px;">
<div class="col-3" t-attf-style="background-color:{{record.ads_last_state_color.value}};padding-left: 1px;height:10px;border-style:solid;border-width:0.2px;"> <!-- <div class="col-12" t-attf-style="background-color:#BfBfBf;padding-left: 1px;height:25px;border-style:solid;border-width:0.2px;">
<p style="font-size:14px;margin-bottom:0px"><field name="contract_name"/></p>
</div>-->
<div class="col-8" style="white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">
<p style="font-size:14px;margin-bottom:0px"><strong><field name="contract_name"/></strong></p>
</div> </div>
<div class="col-3" t-attf-style="background-color:{{record.ads_last_work_state_color.value}};padding-left: 1px;height:10px;border-style:solid;border-width:0.2px;"> <div class="col-2" style="padding-left:0px;padding-right:15px;">
<div class="row" style="height:25px">
<!-- <div class="dropdown" t-if="!selection_mode" groups="base.group_user">-->
<div t-if="!selection_mode" groups="base.group_user">
<a role="button" class="dropdown-toggle o-no-caret btn" data-bs-toggle="dropdown" data-bs-display="static" href="#" aria-label="Dropdown menu" title="Dropdown menu">
<span class="fa fa-ellipsis-h"/>
</a>
<div class="dropdown-menu dss_dd" style="background-color:#bfbfbf;" role="menu">
<span><p>aktueller Zustand der Kampagne : </p><field role="menuitem" name="ads_last_state" /></span>
<a name="switch_invisible" role="menuitem" type="action" class="dropdown-item">Akt. Schritt weiter setzen</a>
<a name="switch_invisible" role="menuitem" type="action" class="dropdown-item">Aufgabe weiter setzen</a>
<div role="separator" class="dropdown-divider"></div>
<button name="tokampagne" string="Zur letzten Werbekampagne" type="object" class="oe_hightlight"/>
</div>
</div>
</div>
</div>
</div>
<div class="row" style="--gutter-x:10px;">
<div class="col-7" t-attf-style="background-color:#fabb86;padding-left: 1px;height:25px;border-style:solid;border-width:0.2px;">
<p style="font-size:14px;margin-bottom:0px"><field name="cutshortwerbe_feld_selected"/></p>
</div>
<div class="col-5" t-attf-style="background-color:{{record.contract_state_color.value}};padding-left: 1px;height:25px;border-style:solid;border-width:0.2px;">
<p style="font-size:14px;margin-bottom:0px"><strong><field name="contract_auto_id" string="Kundennummer"/></strong></p>
</div>
</div>
<div class="row" style="--gutter-x:10px;margin-bottom:0px">
<div class="col-12" t-attf-style="background-color:#BfBfBf;padding-left: 1px;height:13px;border-style:solid;border-width:0px;">
<p style="font-size:10px;margin-bottom:0px">Arbeitsstand letzte Kampagne</p>
</div>
</div>
<div class="row" style="--gutter-x:10px;">
<div class="col-4" t-attf-style="background-color:#BfBfBf;padding-left: 1px;height:13px;border-style:solid;border-width:0.2px;">
<p style="font-size:8px;margin-left:10px;margin-bottom:0px">aktuell Zuständig</p>
</div>
<div class="col-4" t-attf-style="background-color:#BfBfBf;padding-left: 1px;height:13px;border-style:solid;border-width:0.2px;">
<p style="font-size:8px;margin-left:10px;margin-bottom:0px">aktueller Schritt</p>
</div>
<div class="col-4" t-attf-style="background-color:#BfBfBf;padding-left: 1px;height:13px;border-style:solid;border-width:0.2px;">
<p style="font-size:8px;margin-left:10px;margin-bottom:0px">nächste Aufgabe</p>
</div>
</div>
<div class="row" style="--gutter-x:10px;">
<div class="col-4" t-attf-style="background-color:{{record.ads_last_state_color.value}};padding-left: 1px;height:10px;border-style:solid;border-width:0.2px;">
</div>
<div class="col-4" t-attf-style="background-color:{{record.ads_last_work_state_color.value}};padding-left: 1px;height:10px;border-style:solid;border-width:0.2px;">
</div> </div>
<!-- <t t-esc="record.work_state_color"/> <!-- <t t-esc="record.work_state_color"/>
<t t-esc="record.work_state_color.value"/>--> <t t-esc="record.work_state_color.value"/>-->
<div class="col-3" t-attf-style="background-color:{{record.ads_last_todo_state_color.value}};padding-left: 1px;height:10px;border-style:solid;border-width:0.2px;"> <div class="col-4" t-attf-style="background-color:{{record.ads_last_todo_state_color.value}};padding-left: 1px;height:10px;border-style:solid;border-width:0.2px;">
<!-- <div class="col-2" t-attf-style="background-color:{{record.work_state_color.value}};padding-left: 1px;height:10px;border-style:solid;border-width:0.2px;">--> <!-- <div class="col-2" t-attf-style="background-color:{{record.work_state_color.value}};padding-left: 1px;height:10px;border-style:solid;border-width:0.2px;">-->
</div> </div>
</div> </div>
<div class="row" style="--gutter-x:10px;"> <div class="row" style="--gutter-x:10px;">
<div class="col-3" t-attf-style="background-color:#ffffff;padding-left: 1px;height:13px;border-style:solid;border-width:0.2px;"> <div class="col-4" t-attf-style="background-color:#ffffff;padding-left: 1px;height:13px;border-style:solid;border-width:0.2px;">
<p style="font-size:7px"><field name="ads_last_state_text"/></p> <p style="font-size:7px"><field name="ads_last_state_text"/></p>
</div> </div>
<div class="col-3" t-attf-style="background-color:#ffffff;padding-left: 1px;height:13px;border-style:solid;border-width:0.2px;"> <div class="col-4" t-attf-style="background-color:#ffffff;padding-left: 1px;height:13px;border-style:solid;border-width:0.2px;">
<p style="font-size:7px"><field name="ads_last_work_state_text"/></p> <p style="font-size:7px"><field name="ads_last_work_state_text"/></p>
</div> </div>
<div class="col-3" t-attf-style="background-color:#ffffff;padding-left: 1px;height:13px;border-style:solid;border-width:0.2px;"> <div class="col-4" t-attf-style="background-color:#ffffff;padding-left: 1px;height:13px;border-style:solid;border-width:0.2px;">
<p style="font-size:7px"><field name="ads_last_todo_state_text"/></p> <p style="font-size:7px"><field name="ads_last_todo_state_text"/></p>
</div> </div>
</div> </div>
@ -508,15 +686,6 @@
<strong><field name="ads_last_work_state_color" invisible="1"/></strong> <strong><field name="ads_last_work_state_color" invisible="1"/></strong>
</div> </div>
</div> </div>
<div class="row" style="--gutter-x:10px;">
<div class="col-2" style="padding-left: 1px">
<strong><field name="contract_auto_id" string="Kundennummer"/></strong>
<!-- <strong><field name="client_id"/></strong>-->
</div>
<div class="col-8" style="white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">
<strong><field name="contract_name"/></strong>
</div>
</div>
<div class="row" style="--gutter-x:10px;"> <div class="row" style="--gutter-x:10px;">
<div class="col-10" style="padding-left: 1px"> <div class="col-10" style="padding-left: 1px">
<span style="font-size:9px">Status : <field name="ads_last_work_state_text"/></span> <span style="font-size:9px">Status : <field name="ads_last_work_state_text"/></span>
@ -524,7 +693,7 @@
</div> </div>
<div class="row" style="--gutter-x:10px;"> <div class="row" style="--gutter-x:10px;">
<div class="col-10" style="padding-left: 1px"> <div class="col-10" style="padding-left: 1px">
<span style="font-size:9px">Info : <field name="work_state_info"/></span> <span style="font-size:9px">Info : <field name="ads_last_work_state_info"/></span>
</div> </div>
</div> </div>
<div class="row" style="--gutter-x:10px;"> <div class="row" style="--gutter-x:10px;">

21
views/dss_dialog.xml Normal file
View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!--Wizard For Raise Apprval Messages Thesis ORIC-->
<record id="wizard_message_form_for_oric" model="ir.ui.view">
<field name="name">Thesis Wizard Message Approval Message ORIC</field>
<field name="model">dss.dialog</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Message" version="7.0">
<separator string="Message" colspan="6"/>
<field name="text" colspan="4" nolabel="1" readonly="1" widget="html"/>
<newline/>
<separator colspan="6"/>
<footer>
<button name="btn_approve_oric" type="object" string="Yes" class="oe_highlight"/>
<button special="cancel" string="No"/>
</footer>
</form>
</field>
</record>
</odoo>

View File

@ -79,6 +79,21 @@
</div> </div>
</group> </group>
</page> </page>
<page name="partnersettings" string="Google Maps">
<group string="Google Maps Informationen">
<label class="o_form_label" string="Inhalt Infofenster" for="standort"/>
<div class="col6">
<field name="standort" invisible="1"/>
<group>
<field name="maps_name"/>
<field name="maps_type"/>
<field name="maps_marker"/>
<field name="maps_image" widget="Binary"/>
<field name="maps_text" widget="html_frame"/>
</group>
</div>
</group>
</page>
<page name="basesettings" string="Details (Zeiten,Standort)"> <page name="basesettings" string="Details (Zeiten,Standort)">
<div class="row"> <div class="row">
<div class="col10"> <div class="col10">
@ -165,7 +180,7 @@
<a role="button" class="dropdown-toggle o-no-caret btn" data-bs-toggle="dropdown" data-bs-display="static" href="#" aria-label="Dropdown menu" title="Dropdown menu"> <a role="button" class="dropdown-toggle o-no-caret btn" data-bs-toggle="dropdown" data-bs-display="static" href="#" aria-label="Dropdown menu" title="Dropdown menu">
<span class="fa fa-ellipsis-h"/> <span class="fa fa-ellipsis-h"/>
</a> </a>
<div class="dropdown-menu" role="menu"> <div class="dropdown-menu dss_dd" role="menu">
<a name="switch_invisible" role="menuitem" type="action" class="dropdown-item">Sichtbarkeit</a> <a name="switch_invisible" role="menuitem" type="action" class="dropdown-item">Sichtbarkeit</a>
<div role="separator" class="dropdown-divider"></div> <div role="separator" class="dropdown-divider"></div>
<a name="%(portal.portal_share_action)d" role="menuitem" type="action" class="dropdown-item">Projekt teilen</a> <a name="%(portal.portal_share_action)d" role="menuitem" type="action" class="dropdown-item">Projekt teilen</a>
@ -209,6 +224,10 @@
<field name="grundsystemname"/> <field name="grundsystemname"/>
<field name="active" widget="boolean_toggle"/> <field name="active" widget="boolean_toggle"/>
<field name="invisible" widget="boolean_toggle"/> <field name="invisible" widget="boolean_toggle"/>
<field name="standort_visible"/>
<field name="maps_name"/>
<field name="maps_type"/>
<field name="maps_marker"/>
</tree> </tree>
<search> <search>
<filter string="Archivierte Projekte" name="archived" domain="[('aktstatus_typ','=','ARCHIV')]"/> <filter string="Archivierte Projekte" name="archived" domain="[('aktstatus_typ','=','ARCHIV')]"/>

View File

@ -0,0 +1,360 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<template id="report_invoice_document">
<t t-call="web.external_layout">
<t t-set="o" t-value="o.with_context(lang=lang)" />
<t t-set="forced_vat" t-value="o.fiscal_position_id.foreign_vat"/> <!-- So that it appears in the footer of the report instead of the company VAT if it's set -->
<div class="row">
<t t-if="o.partner_shipping_id and (o.partner_shipping_id != o.partner_id)">
<div class="col-6">
<t t-set="information_block">
<div groups="account.group_delivery_invoice_address" name="shipping_address_block">
<strong>Shipping Address:</strong>
<div t-field="o.partner_shipping_id" t-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": True}'/>
</div>
</t>
</div>
<div class="col-6" name="address_not_same_as_shipping">
<t t-set="address">
<address class="mb-0" t-field="o.partner_id" t-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": True}'/>
<div t-if="o.partner_id.vat" id="partner_vat_address_not_same_as_shipping">
<t t-if="o.company_id.account_fiscal_country_id.vat_label" t-esc="o.company_id.account_fiscal_country_id.vat_label" id="inv_tax_id_label"/>
<t t-else="">Tax ID</t>: <span t-field="o.partner_id.vat"/>
</div>
</t>
</div>
</t>
<t t-elif="o.partner_shipping_id and (o.partner_shipping_id == o.partner_id)">
<div class="offset-col-6 col-6" name="address_same_as_shipping">
<t t-set="address">
<address class="mb-0" t-field="o.partner_id" t-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": True}'/>
<div t-if="o.partner_id.vat" id="partner_vat_address_same_as_shipping">
<t t-if="o.company_id.account_fiscal_country_id.vat_label" t-esc="o.company_id.account_fiscal_country_id.vat_label" id="inv_tax_id_label"/>
<t t-else="">Tax ID</t>: <span t-field="o.partner_id.vat"/>
</div>
</t>
</div>
</t>
<t t-else="">
<div class="offset-col-6 col-6" name="no_shipping">
<t t-set="address">
<address class="mb-0" t-field="o.partner_id" t-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": True}'/>
<div t-if="o.partner_id.vat" id="partner_vat_no_shipping">
<t t-if="o.company_id.account_fiscal_country_id.vat_label" t-esc="o.company_id.account_fiscal_country_id.vat_label" id="inv_tax_id_label"/>
<t t-else="">Tax ID</t>: <span t-field="o.partner_id.vat"/>
</div>
</t>
</div>
</t>
</div>
<div class="mt-5">
<div class="page">
<h2>
<span t-if="o.move_type == 'out_invoice' and o.state == 'posted'">Invoice</span>
<span t-if="o.move_type == 'out_invoice' and o.state == 'draft'">Draft Invoice</span>
<span t-if="o.move_type == 'out_invoice' and o.state == 'cancel'">Cancelled Invoice</span>
<span t-if="o.move_type == 'out_refund'">Credit Note</span>
<span t-if="o.move_type == 'in_refund'">Vendor Credit Note</span>
<span t-if="o.move_type == 'in_invoice'">Vendor Bill</span>
<span t-if="o.name != '/'" t-field="o.name"/>
</h2>
<div id="informations" class="row mt-4 mb-4">
<div class="col-auto col-3 mw-100 mb-2" t-if="o.invoice_date" name="invoice_date">
<t t-if="o.move_type == 'out_invoice'"><strong>Invoice Date:</strong></t>
<t t-elif="o.move_type == 'out_refund'"><strong>Credit Note Date:</strong></t>
<t t-elif="o.move_type == 'out_receipt'"><strong>Receipt Date:</strong></t>
<t t-else=""><strong>Date:</strong></t>
<p class="m-0" t-field="o.invoice_date"/>
</div>
<div class="col-auto col-3 mw-100 mb-2" t-if="o.invoice_date_due and o.move_type == 'out_invoice' and o.state == 'posted'" name="due_date">
<strong>Due Date:</strong>
<p class="m-0" t-field="o.invoice_date_due"/>
</div>
<div class="col-auto col-3 mw-100 mb-2" t-if="o.invoice_origin" name="origin">
<strong>Source:</strong>
<p class="m-0" t-field="o.invoice_origin"/>
</div>
<div class="col-auto col-3 mw-100 mb-2" t-if="o.partner_id.ref" name="customer_code">
<strong>Customer Code:</strong>
<p class="m-0" t-field="o.partner_id.ref"/>
</div>
<div class="col-auto col-3 mw-100 mb-2" t-if="o.ref" name="reference">
<strong>Reference:</strong>
<p class="m-0" t-field="o.ref"/>
</div>
</div>
<t t-set="display_discount" t-value="any(l.discount for l in o.invoice_line_ids)"/>
<table class="table table-sm o_main_table table-borderless" name="invoice_line_table">
<thead>
<tr>
<th name="th_description" class="text-start"><span>Description</span></th>
<th name="th_quantity" class="text-end"><span>Quantity</span>*menge*</th>
<th name="th_priceunit" t-attf-class="text-end {{ 'd-none d-md-table-cell' if report_type == 'html' else '' }}"><span>Unit Price</span></th>
<th name="th_price_unit" t-if="display_discount" t-attf-class="text-end {{ 'd-none d-md-table-cell' if report_type == 'html' else '' }}">
<span>Disc.%</span>
</th>
<th name="th_taxes" t-attf-class="text-start {{ 'd-none d-md-table-cell' if report_type == 'html' else '' }}"><span>Taxes</span></th>
<th name="th_subtotal" class="text-end">
<span groups="account.group_show_line_subtotals_tax_excluded">Amount</span>
<span groups="account.group_show_line_subtotals_tax_included">Total Price</span>
</th>
</tr>
</thead>
<tbody class="invoice_tbody">
<t t-set="current_subtotal" t-value="0"/>
<t t-set="lines" t-value="o.invoice_line_ids.sorted(key=lambda l: (-l.sequence, l.date, l.move_name, -l.id), reverse=True)"/>
<t t-foreach="lines" t-as="line">
<t t-set="current_subtotal" t-value="current_subtotal + line.price_subtotal" groups="account.group_show_line_subtotals_tax_excluded"/>
<t t-set="current_subtotal" t-value="current_subtotal + line.price_total" groups="account.group_show_line_subtotals_tax_included"/>
<tr t-att-class="'bg-200 fw-bold o_line_section' if line.display_type == 'line_section' else 'fst-italic o_line_note' if line.display_type == 'line_note' else ''">
<t t-if="line.display_type == 'product'" name="account_invoice_line_accountable">
<td name="account_invoice_line_name"><span t-field="line.name" t-options="{'widget': 'text'}"/></td>
<td class="text-end">
<span t-field="line.quantity"/>
<span t-field="line.product_uom_id" groups="uom.group_uom"/>
</td>
<td t-attf-class="text-end {{ 'd-none d-md-table-cell' if report_type == 'html' else '' }}">
<span class="text-nowrap" t-field="line.price_unit"/>
</td>
<td t-if="display_discount" t-attf-class="text-end {{ 'd-none d-md-table-cell' if report_type == 'html' else '' }}">
<span class="text-nowrap" t-field="line.discount"/>
</td>
<td t-attf-class="text-start {{ 'd-none d-md-table-cell' if report_type == 'html' else '' }}">
<span t-esc="', '.join(map(lambda x: (x.description or x.name), line.tax_ids))" id="line_tax_ids"/>
</td>
<td class="text-end o_price_total">
<span class="text-nowrap" t-field="line.price_subtotal" groups="account.group_show_line_subtotals_tax_excluded"/>
<span class="text-nowrap" t-field="line.price_total" groups="account.group_show_line_subtotals_tax_included"/>
</td>
</t>
<t t-if="line.display_type == 'line_section'">
<td colspan="99">
<span t-field="line.name" t-options="{'widget': 'text'}"/>
</td>
<t t-set="current_section" t-value="line"/>
<t t-set="current_subtotal" t-value="0"/>
</t>
<t t-if="line.display_type == 'line_note'">
<td colspan="99">
<span t-field="line.name" t-options="{'widget': 'text'}"/>
</td>
</t>
</tr>
<t t-if="current_section and (line_last or lines[line_index+1].display_type == 'line_section')">
<tr class="is-subtotal text-end">
<td colspan="99">
<strong class="mr16">Subtotal</strong>
<span
t-esc="current_subtotal"
t-options='{"widget": "monetary", "display_currency": o.currency_id}'
/>
</td>
</tr>
</t>
</t>
</tbody>
</table>
<div class="clearfix mb-4">
<div id="total" class="row">
<div t-attf-class="#{'col-6' if report_type != 'html' else 'col-sm-7 col-md-6'} ms-auto">
<table class="table table-sm table-borderless" style="page-break-inside: avoid;">
<!--Tax totals-->
<t t-set="tax_totals" t-value="o.tax_totals"/>
<t t-call="account.document_tax_totals"/>
<!--Payments-->
<t t-if="print_with_payments">
<t t-if="o.payment_state != 'invoicing_legacy'">
<t t-set="payments_vals" t-value="o.sudo().invoice_payments_widget and o.sudo().invoice_payments_widget['content'] or []"/>
<t t-foreach="payments_vals" t-as="payment_vals">
<tr t-if="payment_vals['is_exchange'] == 0">
<td>
<i class="oe_form_field text-end oe_payment_label">Paid on <t t-esc="payment_vals['date']" t-options='{"widget": "date"}'/></i>
</td>
<td class="text-end">
<span t-esc="payment_vals['amount']" t-options='{"widget": "monetary", "display_currency": o.currency_id}'/>
</td>
</tr>
</t>
<t t-if="len(payments_vals) > 0">
<tr class="border-black fw-bold">
<td>Amount Due</td>
<td class="text-end">
<span t-field="o.amount_residual"/>
</td>
</tr>
</t>
</t>
</t>
</table>
</div>
</div>
</div>
<p t-if="o.move_type in ('out_invoice', 'in_refund') and o.payment_reference" name="payment_communication" class="mt-4">
Please use the following communication for your payment : <b><span t-field="o.payment_reference"/></b>
</p>
<t t-set="payment_term_details" t-value="o.payment_term_details"/>
<div t-field="o.invoice_payment_term_id.note" name="payment_term"/>
<t t-if="o.invoice_payment_term_id.display_on_invoice and payment_term_details">
<div t-if='o.show_payment_term_details' id="total_payment_term_details_table" class="row">
<div t-attf-class="#{'col-7' if report_type != 'html' else 'col-sm-7 col-md-6'} mt-2 mb-2">
<table class="table table-sm" style="page-break-inside: avoid;">
<th class="border-black text-start">
Due Date
</th>
<th class="border-black text-end">
Amount Due
</th>
<th t-if="o.show_discount_details" class="border-black text-end">
Discount
</th>
<t t-foreach="payment_term_details" t-as="term">
<tr>
<td t-esc="term.get('date')" class="text-start"/>
<td t-options='{"widget": "monetary", "display_currency": o.currency_id}' t-esc="term.get('amount')" class="text-end"/>
<td t-if="term.get('discount_date')" class="text-end">
<span t-options='{"widget": "monetary", "display_currency": o.currency_id}'
t-esc="term.get('discount_amount_currency')"/> if paid before
<span t-esc="term.get('discount_date')"/>
</td>
</tr>
</t>
</table>
</div>
</div>
</t>
<div t-if="not is_html_empty(o.narration)" name="comment">
<span t-field="o.narration"/>
</div>
<p t-if="not is_html_empty(o.fiscal_position_id.note)" name="note">
<span t-field="o.fiscal_position_id.note"/>
</p>
<p t-if="o.invoice_incoterm_id" name="incoterm">
<strong>Incoterm: </strong><span t-field="o.invoice_incoterm_id.code"/> - <span t-field="o.invoice_incoterm_id.name"/>
</p>
<div id="qrcode" t-if="o.display_qr_code and o.amount_residual > 0">
<t t-set="qr_code_url" t-value="o._generate_qr_code(silent_errors=True)"/>
<p t-if="qr_code_url">
<strong class="text-center">Scan me with your banking app.</strong><br/><br/>
<img class="border border-dark rounded" t-att-src="qr_code_url"/>
</p>
</div>
</div>
</div>
</t>
</template>
<template id="document_tax_totals">
<!--
Generic template to display tax totals in pdf reports.
Used by invoices, SO and PO.
ARGUMENTS:
- tax_totals: dict in the form generated by account.move's _get_tax_totals.
-->
<t t-foreach="tax_totals['subtotals']" t-as="subtotal">
<tr class="border-black o_subtotal">
<td><strong t-esc="subtotal['name']"/></td>
<td class="text-end">
<span
t-att-class="oe_subtotal_footer_separator"
t-esc="subtotal['formatted_amount']"
/>
</td>
</tr>
<t t-set="subtotal_to_show" t-value="subtotal['name']"/>
<t t-call="account.tax_groups_totals"/>
</t>
<t t-if="'formatted_rounding_amount' in tax_totals and tax_totals['rounding_amount'] != 0">
<td>Rounding</td>
<td class="text-end">
<span t-esc="tax_totals['formatted_rounding_amount']"/>
</td>
</t>
<!--Total amount with all taxes-->
<tr class="border-black o_total">
<td><strong>Total</strong></td>
<td class="text-end">
<span t-esc="tax_totals['formatted_amount_total_rounded']" t-if="'formatted_amount_total_rounded' in tax_totals"/>
<span t-esc="tax_totals['formatted_amount_total']" t-else=""/>
</td>
</tr>
</template>
<template id="tax_groups_totals">
<!--
Generic template to display a list of tax groups with the related amounts.
ARGUMENTS:
- tax_totals: dict in the form generated by account.move's _get_tax_totals.
- subtotal_to_show: The subtotal we need to render the groups from
-->
<t t-foreach="tax_totals['groups_by_subtotal'][subtotal_to_show]" t-as="amount_by_group">
<tr>
<t t-if="tax_totals['display_tax_base']">
<td>
<span t-esc="amount_by_group['tax_group_name']"/>
<span class="text-nowrap"> on
<t t-esc="amount_by_group['formatted_tax_group_base_amount']"/>
</span>
</td>
<td class="text-end o_price_total">
<span class="text-nowrap" t-esc="amount_by_group['formatted_tax_group_amount']"/>
</td>
</t>
<t t-else="">
<td><span class="text-nowrap" t-esc="amount_by_group['tax_group_name']"/></td>
<td class="text-end o_price_total">
<span class="text-nowrap" t-esc="amount_by_group['formatted_tax_group_amount']" />
</td>
</t>
</tr>
</t>
</template>
<template id="report_invoice">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="o">
<t t-set="lang" t-value="o.partner_id.lang"/>
<t t-if="o._get_name_invoice_report() == 'account.report_invoice_document'"
t-call="account.report_invoice_document" t-lang="lang"/>
</t>
</t>
</template>
<template id="report_invoice_with_payments">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="o">
<t t-set="lang" t-value="o.partner_id.lang"/>
<t t-set="print_with_payments" t-value="True"/>
<t t-if="o._get_name_invoice_report() == 'account.report_invoice_document'"
t-call="account.report_invoice_document" t-lang="lang"/>
</t>
</t>
</template>
<!--We need to create the following empty report template for the action report
"action_account_original_vendor_bill" to work. The action is merging the
original vendor bill(s) that were used to create the vendor bill(s) into one PDF. -->
<template id="report_original_vendor_bill">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="o">
<div class="article" t-att-data-oe-model="o and o._name" t-att-data-oe-id="o and o.id" t-att-data-oe-lang="o and o.env.context.get('lang')"></div>
</t>
</t>
</template>
</data>
</odoo>

View File

@ -51,6 +51,31 @@
<field name="google_maps_key"/> <field name="google_maps_key"/>
</group> </group>
</div> </div>
<div class="row">
<group name="Dateipfad für WebBilder">
<field name="os_webimg_path"/>
</group>
</div>
<notebook>
<page name="grundsettings" string="Grundeinstellungen">
<div class="col-6">
<group string="Ansichts Einstellungen gültig alle ohne eigene Einstellungen">
<field name="show_expand_contract_group_ad_state" widget="boolean_toggle"></field>
<field name="show_expand_contract_group_ad_work_state" widget="boolean_toggle"></field>
<field name="show_expand_contract_group_ad_todo_state" widget="boolean_toggle"></field>
</group>
</div>
</page>
<page name="calendargrundsettings" string="Benutzer für Kalender">
<div class="col-6">
<group string="Kalender Einstellungen">
<field name="runtime_auto_calandar_entry" widget="boolean_toggle"></field>
<field name="contact_runtime_user"></field>
</group>
</div>
</page>
</notebook>
</sheet> </sheet>
</form> </form>
</field> </field>

103
views/dss_webcalendar.xml Normal file
View File

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<template id="webcalendar" name="Web_Kalender">
&lt;!DOCTYPE html&gt;
<html>
<head>
<title>Open-Source JavaScript Monthly Calendar</title>
<!-- head -->
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="/DigitalSignage/static/src/helpers/v2/main.css?v=2024.3.539" type="text/css" rel="stylesheet"/>
<script src="/DigitalSignage/static/src/js/daypilot-all.min.js?v=2024.3.539"></script>
<!-- /head -->
</head>
<body>
<!-- top -->
<template id="content" data-version="2024.3.539">
<!-- /top -->
<div class="note">
<b>Note:</b>
Customize the component using <a href="https://builder.daypilot.org/month?edition=lite">Monthly Calendar UI Builder</a>
and download a ready-to-run project.
Read more about the <a href="https://javascript.daypilot.org/month/">JavaScript monthly calendar</a>.
</div>
<div id="dp"></div>
<script type="text/javascript">
const dp = new DayPilot.Month("dp", {
startDate: "2022-03-01",
onTimeRangeSelected: async function (args) {
const colors = [
{name: "Blue", id: "#3c78d8"},
{name: "Green", id: "#6aa84f"},
{name: "Yellow", id: "#f1c232"},
{name: "Red", id: "#cc0000"},
];
const form = [
{name: "Text", id: "text"},
{name: "Color", id: "barColor", options: colors}
];
const data = {
text: "Event",
barColor: "#6aa84f"
};
const modal = await DayPilot.Modal.form(form, data);
dp.clearSelection();
if (modal.canceled) {
return;
}
dp.events.add({
start: args.start,
end: args.end,
id: DayPilot.guid(),
text: modal.result.text,
barColor: modal.result.barColor
});
},
});
// generate and load events
for (let i = 0; i < 10; i++) {
const duration = Math.floor(Math.random() * 1.2);
const start = Math.floor(Math.random() * 6) - 3; // -3 to 3
dp.events.add({
start: new DayPilot.Date("2022-03-04T00:00:00").addDays(start),
end: new DayPilot.Date("2022-03-04T12:00:00").addDays(start).addDays(duration),
id: DayPilot.guid(),
text: "Event " + i
});
}
dp.init();
</script>
<!-- bottom -->
</template>
<script src="/DigitalSignage/static/src/helpers/v2/app.js?v=2024.3.539"></script>
<!-- /bottom -->
</body>
</html>
</template>
</odoo>

View File

@ -80,7 +80,7 @@
<menuitem <menuitem
id="menu_dss_mediarelations_systems" id="menu_dss_mediarelations_systems"
name="MediaRelationen" name="MediaRelationen"
parent="menu_dss_internsetup" parent="menu_dss_div_internsetup"
action="action_dss_mediarelations_view" action="action_dss_mediarelations_view"
sequence="60"/> sequence="60"/>
@ -126,43 +126,43 @@
<menuitem <menuitem
id="menu_dss_configuration_systemtypen" id="menu_dss_configuration_systemtypen"
name="Grundsystemtypen" name="Projektarten verwalten"
parent="menu_dss_internsetup" parent="menu_dss_stati_internsetup"
action="action_dss_systemtypen_view" action="action_dss_systemtypen_view"
sequence="20"/> sequence="20"/>
<menuitem <menuitem
id="menu_dss_configuration_projectstate" id="menu_dss_configuration_projectstate"
name="Projektstati verwalten" name="Projektstatus verwalten"
parent="menu_dss_stati_internsetup" parent="menu_dss_stati_internsetup"
action="action_dss_projectstate_view" action="action_dss_projectstate_view"
sequence="50"/> sequence="50"/>
<menuitem <menuitem
id="menu_dss_configuration_contractstate" id="menu_dss_configuration_contractstate"
name="Vertragsstati verwalten" name="Vertragsstatus verwalten"
parent="menu_dss_stati_internsetup" parent="menu_dss_stati_internsetup"
action="action_dss_contractstate_view" action="action_dss_contractstate_view"
sequence="60"/> sequence="60"/>
<menuitem <menuitem
id="menu_dss_configuration_ads" id="menu_dss_configuration_ads"
name="Kampagnenstati verwalten" name="Zuständigkeiten verwalten"
parent="menu_dss_stati_internsetup" parent="menu_dss_stati_internsetup"
action="action_dss_adstate_view" action="action_dss_adstate_view"
sequence="65"/> sequence="65"/>
<menuitem <menuitem
id="menu_dss_configuration_workstate" id="menu_dss_configuration_workstate"
name="Bearbeitungsstände verwalten" name="Bearbeitungsschritte verwalten"
parent="menu_dss_stati_internsetup" parent="menu_dss_stati_internsetup"
action="action_dss_workstate_view" action="action_dss_workstate_view"
sequence="70"/> sequence="70"/>
<menuitem <menuitem
id="menu_dss_configuration_todostate" id="menu_dss_configuration_todostate"
name="Bearbeitungsschritte verwalten" name="Aufgabenschritte verwalten"
parent="menu_dss_internsetup" parent="menu_dss_stati_internsetup"
action="action_dss_todostate_view" action="action_dss_todostate_view"
sequence="80"/> sequence="80"/>
@ -180,16 +180,23 @@
action="action_dss_eventdays_view" action="action_dss_eventdays_view"
sequence="100"/> sequence="100"/>
<menuitem
id="menu_dss_div_internsetup"
name="Diverses"
parent="menu_dss_internsetup"
sequence="60"/>
<menuitem <menuitem
id="menu_dss_configuration_paysystem_fields" id="menu_dss_configuration_paysystem_fields"
name="Zahlungsfelder verwalten" name="Zahlungsfelder verwalten"
parent="menu_dss_internsetup" parent="menu_dss_div_internsetup"
action="action_dss_paysystem_fields_view" action="action_dss_paysystem_fields_view"
sequence="110"/> sequence="110"/>
<menuitem <menuitem
id="menu_dss_configuration_paysystems" id="menu_dss_configuration_paysystems"
name="Zahlungsarten verwalten" name="Zahlungsarten verwalten"
parent="menu_dss_internsetup" parent="menu_dss_div_internsetup"
action="action_dss_paysystems_view" action="action_dss_paysystems_view"
sequence="120"/> sequence="120"/>
@ -221,6 +228,7 @@
action="action_dss_trigger_view" action="action_dss_trigger_view"
sequence="52"/> sequence="52"/>
<menuitem <menuitem
id="menu_dss_openprojectimport" id="menu_dss_openprojectimport"
name="OpenProject-Import via API" name="OpenProject-Import via API"