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/company_view.xml',
'views/google_map.xml',
'views/dss_report_invoice.xml',
],
'demo': [],
'installable': True,

View File

@ -1,6 +1,10 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import http
import os
import os.path
import base64
import logging
from odoo.http import request
_logger = logging.getLogger(__name__)
@ -24,12 +28,12 @@ class GoogleMap(http.Controller):
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):
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
_logger.info("Google Maps " + str(projects)+ " and Record : "+str(len(projects)))
projects_data = {
@ -37,14 +41,30 @@ class GoogleMap(http.Controller):
"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({
'id': project.id,
'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,
'longitude': str(project.standort_long) if project.standort_long else False,
})
partner_url = ""
partner_url = "/google_map"
values = {
'project_url': partner_url,
@ -53,3 +73,7 @@ class GoogleMap(http.Controller):
'google_maps_api_key': google_maps_api_key,
}
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 company

View File

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

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

View File

@ -46,6 +46,7 @@
<div class="col-20">
<group>
<field name="description" string="Kurzbeschreibung" widget="text"/>
<field name="work_state_info" string="Aktuelle Hinweise" widget="text"/>
</group>
</div>
</div>
@ -123,45 +124,88 @@
</div>
<hr></hr>
<notebook>
<page name="informations" string="Dateien">
-- <field name="need_media">
<tree string="Dateien" editable="False" create="False">
<field name="field" string="von Feld"/>
<field name="mediatype_name" string=" Verwendung "/>
<field name="mediafile" string=" Datei " filename="mediafile_file"/>
<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 name="zuarbeiten" string="Ablauf">
<div class="row">
<div class="col-4">
<group>
<field name="date_zuarbeit" widget="date"/>
</group>
</div>
<div class="col-4">
<group>
<field name="date_korrekturabzug" widget="date"/>
</group>
</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 name="informations" string="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"/>
</group>
<page name="informations" string="Sonderlaufzeiten">
<div class="row">
<div class="col-4">
<group>
<field name="start_date" widget="date"/>
</group>
</div>
<div class="col-4">
<group>
<field name="end_date" widget="date"/>
</group>
</div>
</div>
</page>
<page name="createhistory" string="DSInformation">
<group>
<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 name="informations" string="entahltene Dateien">
<field name="need_media">
<tree string="Dateien" editable="False" create="False">
<field name="field" string="von Feld"/>
<field name="mediatype_name" string=" Verwendung "/>
<field name="mediafile" string=" Datei " filename="mediafile_file"/>
<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>
</notebook>
</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_ids"/>
<field name="activity_ids"/>
</div>-->
</div>
</form>
</field>
</record>
@ -252,25 +296,26 @@
</div>
</div>
<div class="row" style="--gutter-x:10px;" attrs="{'invisible': [('adtype','==','MAIN')]}">
<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 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 class="row" style="--gutter-x:10px;">
<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 class="col-11">
<div class="row" style="--gutter-x:10px;">
<div class="col-11">
<strong style="font-size:20px;font-weight:bold"><field name="adname"/></strong>
</div>
<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="ad_is_lastpos" widget="boolean_toggle" /></strong>
</div>
</div>
<div class="row" style="--gutter-x:10px;">
<div class="col-1">
<div class="row" style="--gutter-x:10px;">
<div class="col-11">
<strong style="font-size:20px;font-weight:bold"><field name="adname"/></strong>
</div>
<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="ad_is_lastpos" widget="boolean_toggle" /></strong>
</div>
</div>
<div class="row" style="--gutter-x:10px;">
<div class="col-1">
</div>
<div class="col-7">
<strong style="font-size:12px"><field name="description"/></strong>
</div>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="dss_advertisefields_view_tree" model="ir.ui.view">
<field name="name">dss_advertisefields_tree</field>
<field name="model">dss.advertisefields</field>
@ -10,7 +9,9 @@
<tree string="Werbefelder">
<field name="feldname"/>
<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_unused" widget="color"/>
</tree>
@ -28,11 +29,18 @@
<field name="feldname" string="Feldname"/>
<field name="project" string="Projekt"/>
<field name="auto_feldname" string="Projekt_Feld" readonly="1"/>
<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>
<field name="mediastructure" attrs="{'invisible': [('issaved','!=',True)]}" />
<field name="color_used" widget="color"/>
<field name="color_unused" widget="color"/>
<field name="contract" string="Vertrag">
<tree string="Verträge">
<field name="contract_auto_name"/>
<field name="contract_auto_id"/>
<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>
<notebook>
@ -81,4 +89,13 @@
</field>
</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>

View File

@ -1,6 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<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">
<field name="name">DigitalSignage Projekt Vertraege</field>
<field name="type">ir.actions.act_window</field>
@ -38,7 +52,10 @@
<field name="project_id"/>
<field name="client_short_vorname"/>
<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>
</field>
</record>
@ -142,256 +159,366 @@
<field eval="2" name="priority"/>
<field name="arch" type="xml">
<form>
<header>
<button name="tokampagne" string="Zur Werbekampagne" type="object" class="oe_hightlight"/>
</header>
<header>
<button name="tokampagne" string="Zur Werbekampagne" type="object" class="oe_hightlight"/>
</header>
<sheet>
<div class="row">
<h1>
<field name="contract_auto_name" string="Autom. Vertragskennung"/>
</h1>
<div class="row">
<h1>
<field name="contract_auto_name" string="Autom. Vertragskennung"/>
</h1>
</div>
<div class="row">
<hr></hr>
<div class="row">
<hr></hr>
</div>
<div class="row">
<div class="col-7">
<div class="row">
<div class="col-3">
<group>
<field name="project_id" string="Projekt ID"/>
</group>
</div>
<div class="col-7">
<group>
<field name="project" string="Projekt"/>
</group>
</div>
</div>
<div class="row">
<div class="col-3">
<group>
<field name="client_id" string="Kunden ID"/>
</group>
</div>
</div>
<hr></hr>
<div class="row">
<div class="col-20">
<div class="row">
<div class="col-4">
<group>
<field name="contract_auto_id" string="Kundennummer"/>
</group>
</div>
<div class="col-8">
<group>
<field name="contract_name" string="Vertragskennung"/>
</group>
</div>
<div class="col-7">
<div class="row">
<div class="col-3">
<group>
<field name="project_id" string="Projekt ID"/>
</group>
</div>
<div class="col-7">
<group>
<field name="project" string="Projekt"/>
</group>
</div>
</div>
<div class="row">
<div class="col-3">
<group>
<field name="client_id" string="Kunden ID"/>
</group>
</div>
</div>
<hr></hr>
<div class="row">
<div class="col-20">
<div class="row">
<div class="col-4">
<group>
<field name="contract_auto_id" string="Kundennummer"/>
</group>
</div>
<div class="col-8">
<group>
<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 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)]"/>
</group>
</div>
</div>
</div>
</div>
</div>
<div class="col-5" style="border-style:solid;border-width:1px;border-color:lightgray">
<div class="col-5" style="border-style:solid;border-width:1px;border-color:lightgray">
<!-- <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>
<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 class="row">
<div class="col-5" style="height:20px;">
</div>
<div class="row">
<div class="col-5" style="height:20px;">
</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 class="row">
<group>
<field name="contract_state" string="Status"/>
</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">
<hr></hr>
<div class="row">
<div class="col-15">
<group>
<field name="client" string="Kunde"/>
</group>
</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">
<div class="col-3">
<group>
<field name="client_short_land"/>
</group>
</div>
<div class="col-3">
<group>
<field name="client_short_plz"/>
</group>
</div>
<div class="col-6">
<group>
<field name="client_short_ort"/>
</group>
</div>
</div>
<div class="row">
<div class="col-3">
<group>
<field name="client_short_telefon"/>
</group>
</div>
<div class="col-3">
<group>
<field name="client_short_mobil"/>
</group>
</div>
<div class="col-5">
<group>
<field name="client_short_email"/>
</group>
</div>
</div>
<div class="row">
<div class="col-10">
<group>
<field name="client_short_website"/>
</group>
</div>
<button string="Kunde anlegen" name="pyaction_dss_contract_make_partner" type="object" class="btn-primary o_open_tasks" data-hotkey="m"/>
<div class="col-2">
</div>
</div>
<hr></hr>
<div class="row" string="Kundendaten Kundenverwaltung" name="contact_edit" attrs="{'invisible':[('client','=',False)]}">
<div class="mw-sm-100">
<button string="zum Kunde wechseln" name="pyaction_dss_contract_goto_partner" type="object" class="btn-primary o_open_tasks" data-hotkey="m"/>
</div>
<br></br>
<br></br>
<hr></hr>
<br></br>
<div class="row">
<div class="col-10">
<group>
<field name="contact_company_name" string="Firmenname Kunde²"/>
</group>
</div>
</div>
<div class="row">
<div class="col-4">
<group>
<field name="contact_dsspartner_vorname" string="Vorname Kunde²"/>
</group>
</div>
<div class="col-8">
<group>
<field name="contact_dsspartner_name" string="Name Kunde²"/>
</group>
</div>
</div>
<div class="row">
<div class="col-13">
<group>
<field name="contact_street" string="Strasse Kunde²"/>
</group>
</div>
</div>
<div class="row">
<div class="col-13">
<group>
<field name="contact_street2" string="Strasse 2 Kunde²"/>
</group>
</div>
</div>
<div class="row">
<div class="col-3">
<group>
<field name="contact_country_id" string="Land Kunde²"/>
</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>
<page name="grundsettings" string="Grundeinstellungen">
<div class="row">
<group string="Werbeaufbau">
<field name="project_ad_structure"/>
</group>
</div>
<div class="row">
<div class="col-4">
<group>
<field name="main_runtime" string="Gesamtlaufzeit Sekunden (Vertrag)"/>
<field name="main_runtime" string="Gesamtlaufzeit Sekunden (Vertrag)" placeholder="Gesamte LZ lt. Vertrag"/>
</group>
</div>
<div class="col-3">
<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>
</div>
<div class="col-3">
<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>
</div>
</div>
</page>
<page name="contractsettings" string="Vertragsdaten">
<div class="row">
<div class="col-4">
<group>
<field name="contract_date" string="Vertragsdatum"/>
</group>
</div>
<div class="col-4">
<group>
<field name="start_date"/>
</group>
</div>
</div>
<div class="col-4">
<group>
<field name="contract_date" string="Vertragsdatum"/>
</group>
</div>
<div class="col-4">
<group>
<field name="start_date"/>
</group>
</div>
</div>
<div class="row">
<div class="col-8">
<group>
<field name="runtimesystem" string="Laufzeitmodel"/>
</group>
</div>
</div>
<div class="row" >
<div class="col-8">
<group attrs="{'invisible': [('runtimesystem','!=','M')]}" >>
<field name="runtime_m" string="Laufzeit Monate"/>
</group>
<group attrs="{'invisible': [('runtimesystem','!=','T')]}" >>
<field name="runtime_t" string="Laufzeit Tage"/>
</group>
<group attrs="{'invisible': [('runtimesystem','!=','E')]}" >>
<field name="runtime_events" string="Laufzeit EventTage"/>
</group>
<group attrs="{'invisible': [('runtimesystem','!=','S')]}" >>
<field name="runtime_divers" string="Laufzeit sontige"/>
</group>
</div>
</div>
<div class="row" >
<div class="col-8">
<group>
<field name="runtime_finish" string="Laufzeit Ende"/>
<button icon="DigitalSignage/static/src/img/dsscalc.png" name="pyaction_dss_contract_make_partner" type="object" class="dss-smallbutton" data-hotkey="c"/>
</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>
<div class="col-8">
<group>
<field name="runtimesystem" string="Laufzeitmodel"/>
</group>
</div>
</div>
<div class="row" >
<div class="col-8">
<group attrs="{'invisible': [('runtimesystem','!=','M')]}" >
<field name="runtime_m" string="Laufzeit Monate"/>
<field name="runtime_bonus_m" string="Bonus Monate"/>
</group>
<group attrs="{'invisible': [('runtimesystem','!=','T')]}" >
<field name="runtime_t" string="Laufzeit Tage"/>
<field name="runtime_bonus_t" string="Bonus Tage"/>
</group>
<group attrs="{'invisible': [('runtimesystem','!=','E')]}" >
<field name="runtime_events" string="Laufzeit EventTage"/>
<field name="runtime_bonus_e" string="Bonus Events"/>
</group>
<group attrs="{'invisible': [('runtimesystem','!=','S')]}" >
<field name="runtime_divers" string="Laufzeit sontige"/>
</group>
</div>
</div>
<div class="row" >
<div class="col-6">
<group>
<field name="runtime_finish" string="Laufzeit Ende"/>
</group>
</div>
<div class="col-2">
<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 !"/>
<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)]}"/>
<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)]}"/>
</div>
</div>
<div class="row" >
<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 name="contractsettings" string="Kampagnen/Verlauf">
<group>
@ -426,20 +553,19 @@
<field name="client_other_projects" string="Weitere Projekte"/>
</group>
</page>-->
<page name="informations" string="Informationen">
<page name="informations" string="Interne Informationen">
<group>
<field name="cloudlink"/>
</group>
</page>
<page name="informations" string="Informationen">
<group>
<field name="contract_id" string="Kunden/Vert.nummer" 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="projectIid" string="Project IId" readonly="1"/>
<field name="uuid" string="Datensatz UUID"/>
<field name="project_ad_structure" string="Project Aufbau" readonly="1"/>
<field name="runtime_calendar_event" string="zum Ablauf-KalenderEvent"/>
</group>
</page>
</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">-->
<field name="contract_name"/>
<field name="contract_state"/>
<field name="contract_state_color"/>
<field name="contract_state_order"/>
<field name="ads_last_work_state_color"/>
<field name="ads_last_todo_state_color"/>
@ -480,26 +607,77 @@
<templates>
<t t-name="kanban-box">
<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="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 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>
<!-- <t t-esc="record.work_state_color"/>
<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>
</div>
<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>
</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>
</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>
</div>
</div>
@ -508,15 +686,6 @@
<strong><field name="ads_last_work_state_color" invisible="1"/></strong>
</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="col-10" style="padding-left: 1px">
<span style="font-size:9px">Status : <field name="ads_last_work_state_text"/></span>
@ -524,7 +693,7 @@
</div>
<div class="row" style="--gutter-x:10px;">
<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 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>
</group>
</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)">
<div class="row">
<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">
<span class="fa fa-ellipsis-h"/>
</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>
<div role="separator" class="dropdown-divider"></div>
<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="active" 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>
<search>
<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"/>
</group>
</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>
</form>
</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
id="menu_dss_mediarelations_systems"
name="MediaRelationen"
parent="menu_dss_internsetup"
parent="menu_dss_div_internsetup"
action="action_dss_mediarelations_view"
sequence="60"/>
@ -126,43 +126,43 @@
<menuitem
id="menu_dss_configuration_systemtypen"
name="Grundsystemtypen"
parent="menu_dss_internsetup"
name="Projektarten verwalten"
parent="menu_dss_stati_internsetup"
action="action_dss_systemtypen_view"
sequence="20"/>
<menuitem
id="menu_dss_configuration_projectstate"
name="Projektstati verwalten"
name="Projektstatus verwalten"
parent="menu_dss_stati_internsetup"
action="action_dss_projectstate_view"
sequence="50"/>
<menuitem
id="menu_dss_configuration_contractstate"
name="Vertragsstati verwalten"
name="Vertragsstatus verwalten"
parent="menu_dss_stati_internsetup"
action="action_dss_contractstate_view"
sequence="60"/>
<menuitem
id="menu_dss_configuration_ads"
name="Kampagnenstati verwalten"
name="Zuständigkeiten verwalten"
parent="menu_dss_stati_internsetup"
action="action_dss_adstate_view"
sequence="65"/>
<menuitem
id="menu_dss_configuration_workstate"
name="Bearbeitungsstände verwalten"
name="Bearbeitungsschritte verwalten"
parent="menu_dss_stati_internsetup"
action="action_dss_workstate_view"
sequence="70"/>
<menuitem
id="menu_dss_configuration_todostate"
name="Bearbeitungsschritte verwalten"
parent="menu_dss_internsetup"
name="Aufgabenschritte verwalten"
parent="menu_dss_stati_internsetup"
action="action_dss_todostate_view"
sequence="80"/>
@ -180,16 +180,23 @@
action="action_dss_eventdays_view"
sequence="100"/>
<menuitem
id="menu_dss_div_internsetup"
name="Diverses"
parent="menu_dss_internsetup"
sequence="60"/>
<menuitem
id="menu_dss_configuration_paysystem_fields"
name="Zahlungsfelder verwalten"
parent="menu_dss_internsetup"
parent="menu_dss_div_internsetup"
action="action_dss_paysystem_fields_view"
sequence="110"/>
<menuitem
id="menu_dss_configuration_paysystems"
name="Zahlungsarten verwalten"
parent="menu_dss_internsetup"
parent="menu_dss_div_internsetup"
action="action_dss_paysystems_view"
sequence="120"/>
@ -221,6 +228,7 @@
action="action_dss_trigger_view"
sequence="52"/>
<menuitem
id="menu_dss_openprojectimport"
name="OpenProject-Import via API"