diff --git a/__manifest__.py b/__manifest__.py index e46a494..ba3dc42 100755 --- a/__manifest__.py +++ b/__manifest__.py @@ -35,6 +35,7 @@ 'views/dss_maintains.xml', 'views/dss_provisionstypen.xml', 'views/dss_provision.xml', + 'views/dss_zahlungen.xml', 'views/mainsystem_view.xml', 'views/menu.xml', 'views/company_view.xml', @@ -50,6 +51,9 @@ 'web.assets_backend': [ 'DigitalSignage/static/src/img/*', 'DigitalSignage/static/src/xml/screenDesignerView.xml', + 'DigitalSignage/static/src/js/form_button.js', + 'DigitalSignage/static/src/js/kanban_button.js', + 'DigitalSignage/static/src/xml/form_button.xml', ], 'web.assets_common': [ 'DigitalSignage/static/images/**/*', diff --git a/controllers/main.py b/controllers/main.py index cf9f7fa..d554b0c 100644 --- a/controllers/main.py +++ b/controllers/main.py @@ -53,6 +53,28 @@ class GoogleMap(http.Controller): maps_image_url="/DigitalSignage/static/src/img/img_"+str(project.id)+"_b.jpg"; else: maps_image_url="" + if project.maps_image_2: + fname=settings.os_webimg_path+'/img_'+str(project.id)+'_b_2.jpg'; + if os.path.isfile(fname): + os.remove(fname) + fileobj = open(fname, "xb") + fileobj.write(base64.decodebytes(project.maps_image_2)) + fileobj.close() + + maps_image_url_2="/DigitalSignage/static/src/img/img_"+str(project.id)+"_b_2.jpg"; + else: + maps_image_url_2="" + if project.maps_image_3: + fname=settings.os_webimg_path+'/img_'+str(project.id)+'_b_3.jpg'; + if os.path.isfile(fname): + os.remove(fname) + fileobj = open(fname, "xb") + fileobj.write(base64.decodebytes(project.maps_image_3)) + fileobj.close() + + maps_image_url_3="/DigitalSignage/static/src/img/img_"+str(project.id)+"_b_3.jpg"; + else: + maps_image_url_3="" projects_data["projects"].append({ 'id': project.id, 'name': project.projektname, @@ -60,7 +82,21 @@ class GoogleMap(http.Controller): 'google_typ':project.maps_type, 'google_marker': project.maps_marker, 'google_image':maps_image_url, + 'google_image_2':maps_image_url_2, + 'google_image_3':maps_image_url_3, 'google_text':project.maps_text, + 'google_typ_interactive': "ja" if project.maps_typ_interactive else "Nein", + 'google_visitors':project.maps_visitors, + 'google_id':project.projectid, + 'google_displaytyp':project.maps_displaytyp, + 'google_displaysize':project.maps_displaysize, + 'google_displayflaechen_a_free': "ja" if project.maps_werbeflaechen_a_free else "Nein", + 'google_displayflaechen_a':project.maps_werbeflaechen_a, + 'google_displayflaechen_b_free': "ja" if project.maps_werbeflaechen_b_free else "Nein", + 'google_displayflaechen_b':project.maps_werbeflaechen_b, + 'google_freiflaechen_b_show':project.maps_freespaces_b_show, + 'google_freiflaechen_b':project.maps_freespaces_b, + 'google_displayfiles':project.maps_werbemedien, 'latitude': str(project.standort_lati) if project.standort_lati else False, 'longitude': str(project.standort_long) if project.standort_long else False, }) diff --git a/models/__init__.py b/models/__init__.py index 23c3689..e89e93e 100755 --- a/models/__init__.py +++ b/models/__init__.py @@ -10,6 +10,7 @@ from . import dss_eventdays from . import dss_advertisefields from . import dss_trigger from . import dss_triggervalues +from . import dss_zahlungen from . import dss from . import dss_maintains from . import dss_provisionstypen diff --git a/models/dss.py b/models/dss.py index c2c306c..be74037 100755 --- a/models/dss.py +++ b/models/dss.py @@ -75,6 +75,7 @@ class dsspprojektstatus(models.Model): color = fields.Char(string='Color Index') typ = fields.Selection([('NEU','In Bearbeitung'),('WORK','fertig/laufend'),('ERROR','Fehlerhaft/Defekt'),('ARCHIV','veraltet/archiviert')],'Systemzuordnung') icon = fields.Image() + order = fields.Integer('Reihenfolge') @api.model def _default_uuid(self): @@ -127,6 +128,7 @@ class dssworkstatus(models.Model): statusname = fields.Char('Statusname', required=True) color = fields.Char(string='Color Index') icon = fields.Image() + order = fields.Integer('Reihenfolge') @api.model def _default_uuid(self): @@ -144,6 +146,7 @@ class dsstodostatus(models.Model): statusnr = fields.Integer(default=lambda self: self._default_statusnr(),string='Listenpostion', required=True) color = fields.Char(string='Color Index') icon = fields.Image() + order = fields.Integer('Reihenfolge') @api.model def _default_uuid(self): @@ -169,25 +172,6 @@ class dsstexts(models.Model): def _default_uuid(self): return str(uuid.uuid4()) -class dsspaysystemfields(models.Model): - _name = "dss.paysystem_fields" - _description = "DigitalSignage Abrechnungsarten_felder" - _inherit = ['mail.thread','mail.activity.mixin'] - _rec_name = "feldname" -# _inherit = ['mail.thread', 'mail.activity.mixin'] - uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID') -# uuid = fields.Char('UUID', required=True, translate=True) - feldname = fields.Char('Abrechnungs_Feldname', required=True) - payonfieldset = fields.Selection([('VE','Vertragseingang'),('KA','Korrekturabzug'),('ES','Einspielung'),('CH','Jede Änderung'),('XH','X, Änderung')]) - changecount = fields.Integer('Änderungsnummer') - description = fields.Text('EventBeschreibung') - amount = fields.Float('Kosten') - - @api.model - def _default_uuid(self): - return str(uuid.uuid4()) - - class dssmediatypes(models.Model): _name = "dss.mediatypes" _description = "DigitalSignage Datei-Medientypen" @@ -314,29 +298,6 @@ class dssadstructures(models.Model): return str(uuid.uuid4()) -class dsspaysystems(models.Model): - _name = "dss.paysystems" - _description = "DigitalSignage Abrechnungsarten" - _inherit = ['mail.thread','mail.activity.mixin'] - _rec_name = "payname" -# _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) - payname = fields.Char('Abrechnungsname', required=True) - payonset = fields.Many2many('dss.paysystem_fields') - description = fields.Text('EventBeschreibung') - send_info = fields.Boolean('Informationsemail senden ?') - send_info_to = fields.Many2one('res.users') - send_info_template = fields.Many2one('mail.template') - amount = fields.Float('Kosten') - icon = fields.Image() - - @api.model - def _default_uuid(self): - return str(uuid.uuid4()) - - - class dssscreendesign(models.Model): _name = "dss.screendesign" _description = "DigitalSignage Screen Designer" @@ -723,17 +684,17 @@ class dsscontractads(models.Model): parent_ad = fields.Many2one('dss.ads', string='UrsprungsWerbung', store=True) parent_ad_uuid = fields.Char(related='parent_ad.uuid') - description = fields.Text('Beschreibung') + description = fields.Text('Beschreibung', tracking=True) 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') + need_media = fields.One2many('dss.mediarelations', 'ad', string='Medien', 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') + work_state_info = fields.Char('Zusatzinfo',tracking=True) ad_state = fields.Many2one('dss.adstate', tracking=True) ad_state_color = fields.Char(related='ad_state.color') diff --git a/models/dss_contract.py b/models/dss_contract.py index 7915a8d..9518372 100755 --- a/models/dss_contract.py +++ b/models/dss_contract.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -* - import ast import datetime import json @@ -74,9 +73,16 @@ class dsscontracts(models.Model): 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_payment_done = fields.Boolean('Zahlungeingang erfolgt',tracking=True) contract_payment_done_date = fields.Date('Zahlungeingang Datum',tracking=True) + contract_receipt_done_multi = fields.Boolean('Mehrere Rechnungen nötig ?', tracking=True) + contract_receipt_done = fields.Boolean('Rechnungstellung erfolgt',tracking=True) + contract_receipt_number = fields.Char("Rechnungsnummer",tracking=True) + contract_receipt_done_date = fields.Date('Rechnungsdatum',tracking=True) + contract_receipt_done_until_date = fields.Date('Zahlungsziel', tracking=True) + remark = fields.Html('Bemerkung',tracking=True) contract_writer = fields.Many2one('res.partner', tracking=True) @@ -163,7 +169,8 @@ class dsscontracts(models.Model): runtime_finish = fields.Date('LaufzeitEnde',tracking=True) runtime_calendar_event = fields.Integer('Kalendereintrag ID',tracking=True) - paymentsystems = fields.Many2one('dss.paysystems',tracking=True) + paymentsystems = fields.Many2one('dss.paysystems',string='Abrechnungsart',tracking=True) + paymentinterval = fields.Many2one('dss.payintervals',string='Abrechnungsinterval',tracking=True) intern_info_payment_off = fields.Boolean('Keine Zahl-Benachrichtigungen',tracking=True) base_ad = fields.Many2one('dss.ads',tracking=True) @@ -219,6 +226,7 @@ class dsscontracts(models.Model): cloudlink = fields.Char('Cloud Verzeichnis',help='Verzeichnis für den Kunde innerhalb des Projekt Ordners') + @api.depends('vertragssumme') def _compute_prov(self): _logger.info('contract Provision Berechnung : C_' + str(self.id)); @@ -327,6 +335,23 @@ class dsscontracts(models.Model): self.contract_auto_id = cidstr if self.contract_auto_id == "": self.contract_auto_id = cidstr + + + def jumpcloud(self): + urlbase=str(self.env['dss.settings'].search([], limit=1).def_cloud_url_base) + _logger.info("Cloud Open Link Urlbase DB " + str(urlbase)) + if not urlbase: + urlbase = 'https://cloud.logumedia.de/index.php/apps/files/?dir='; + _logger.info("Cloud Open Link Urlbase Used " + str(urlbase)) + url=str(urlbase)+str(dss_settings.dssSettings._get_path_converted(self,self.project.cloudlink,self.project))+str(dss_settings.dssSettings._get_path_converted(self,self.cloudlink,self)) + _logger.info("Cloud Open Link " + str(url)) + return { + 'type': 'ir.actions.act_url', + 'url': str(url), + 'target': 'new', + } + + @api.onchange('contract_auto_id') def _onchange_contract_auto_id(self): for record in self : @@ -423,15 +448,15 @@ class dsscontracts(models.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 + @api.model + def _default_client_id(self): + return str("00") + def pyaction_dss_contract_goto_partner(self): fullname = str(self.client_short_vorname) + ' ' +str(self.client_short_name) @@ -856,22 +881,23 @@ class dsscontracts(models.Model): def trigger_action_init(self): _logger.info('Contract Cron Running - Start '+str(self)+' start searching') jobcontracts = self.env['dss.contracts'].search([('run_trigger', '=', True)]) - _logger.info('Contract Cron Running - Start '+str(self)+' Found '+str(len(jobcontracts))+' Trigger') + _logger.info('Contract Cron Running - Start '+str(self)+' '+str(len(jobcontracts))+' Triggergruppen gefunden') for record in jobcontracts: if not record: _logger.info('Contract Cron Running No Contracts Delivered - searching') else: - _logger.info('Contract Cron Running C_' + str(record.id) + ' Check Trigger') + _logger.info('Contract Cron Running C_' + str(record.id) + ' Starte Triggerprüfung') if record.run_trigger: _logger.info('Contract Cron Running C_' + str(record.id) + ' Prüfe Triggergruppe TG_' + str(record.triggergroup.id)) triggergroup = record.triggergroup if not triggergroup: - _logger.info('Contract Cron Running C_' + str(record.id) + ' Triggergruppe TG_' + str(record.triggergroup.id)+' not found') + _logger.info('Contract Cron Running C_' + str(record.id) + ' Triggergruppe TG_' + str(record.triggergroup.id)+' nicht gefunden !') pass else: for trigger in triggergroup.triggers: if not trigger: pass + _logger.info('Contract Cron Running C_' + str(record.id) + ' Triggerprüfung : Keine Trigger in Gruppe !') else: _logger.info('Contract Cron Running C_' + str(record) + ' in Triggergruppe TG_' + str(record.triggergroup)+' Prüfe Trigger T_'+str(trigger)) if trigger._check_trigger(): diff --git a/models/dss_geraetetypen.py b/models/dss_geraetetypen.py index 681a634..f81a0d6 100755 --- a/models/dss_geraetetypen.py +++ b/models/dss_geraetetypen.py @@ -16,6 +16,7 @@ import os.path from odoo import api, fields, models, _ from odoo import tools from odoo.exceptions import ValidationError +from .dss_settings import dssSettings from datetime import date from datetime import datetime from dateutil.relativedelta import relativedelta @@ -88,6 +89,9 @@ class dssgeraetetypen(models.Model): 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) + ledcab_module_breite = fields.Integer('Module in Breite',tracking=True) + ledcab_module_hoehe = fields.Integer('Module in Hoehe',tracking=True) + ledcab_module = fields.Many2one('dss.geraetetypen','Module',tracking=True,domain="['|',('geraetetyp','=','MOD'),('geraetetyp','=','LED')]") 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) @@ -118,7 +122,7 @@ class dssgeraetetypen(models.Model): syst.grundsystem_kennung = syst.grundsystem.kennung def get_value_from_tuyaresult(self,dataset,valuename): - result='' + result='0' _logger.info('Resultanfrage:' + str(dataset)+' Feld : '+str(valuename)) for singlepart in dataset: if singlepart: @@ -141,20 +145,26 @@ class dssgeraetetypen(models.Model): _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') + if self.tuya_last_totalpower == '0': + self.tuya_last_totalpower = str(int(self.get_value_from_tuyaresult(result['result'], 'add_ele'))/1000) self.tuya_last_lastpower = self.get_value_from_tuyaresult(result['result'],'phase_a') + if self.tuya_last_lastpower == '0': + self.tuya_last_lastpower = str(int(self.get_value_from_tuyaresult(result['result'], 'cur_power')) / 10) if self.tuya_can_switch: self.tuya_last_switchstate = self.get_value_from_tuyaresult(result['result'],'switch') + if self.tuya_last_switchstate == '0': + self.tuya_last_switchstate = self.get_value_from_tuyaresult(result['result'], 'switch_1') 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')) + dss_settings.dssSettings._get_settingvalue(self, 'tuya_endpoint')) + ' AccessID ' + str( + dss_settings.dssSettings._get_settingvalue(self, 'tuya_access_id')) + ' AccessKEY ' + str( + dss_settings.dssSettings._get_settingvalue(self, 'tuya_access_key'))) + openapi = TuyaOpenAPI(dss_settings.dssSettings._get_settingvalue(self, 'tuya_endpoint'), + dss_settings.dssSettings._get_settingvalue(self, 'tuya_access_id'), + dss_settings.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) diff --git a/models/dss_mailthreat.py b/models/dss_mailthreat.py new file mode 100644 index 0000000..3011a0d --- /dev/null +++ b/models/dss_mailthreat.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- + +from openerp import models, api, fields + + +class MailThread(models.AbstractModel): + _inherit = 'mail.thread' + + @api.model + def _get_tracked_fields(self, updated_fields): + super(MailThread, self)._get_tracked_fields(updated_fields) + tracked_fields = [] + Model = self.env['ir.model'] + if Model.search([('model', '=', str(self._model))]).track_all_fields: + for name, field in self._fields.items(): + if name not in ['write_date', '__last_update']: + tracked_fields.append(name) + else: + for name, field in self._fields.items(): + if getattr(field, 'track_visibility', False): + tracked_fields.append(name) + + if tracked_fields: + return self.fields_get(tracked_fields) + return {} + + +class IrModel(models.Model): + _inherit = 'ir.model' + + track_all_fields = fields.Boolean(string="Track all fields") diff --git a/models/dss_projects.py b/models/dss_projects.py index 8f59245..cfe25b1 100755 --- a/models/dss_projects.py +++ b/models/dss_projects.py @@ -48,7 +48,7 @@ class dssprojects(models.Model): 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) + grundsystemname = fields.Many2one('dss.systemtypen',group_expand='_read_group_system_ids',tracking=True) grundsystem_typ = fields.Char(related='grundsystemname.kennung',tracking=True) grundsystemicon = fields.Image(related='grundsystemname.icon',tracking=True) grundsystem_default_adstructure = fields.Many2one(related='grundsystemname.default_adstructure',tracking=True) @@ -67,7 +67,20 @@ class dssprojects(models.Model): maps_type = fields.Char('Type in Google',tracking=True) maps_marker = fields.Selection([('m1.png','Marker 1'),('m2.png','Marker 2'),('m3.png','Marker 3'),('m4.png','Marker 4'),('m5.png','Marker 5'),('pin.png','Marker Pin'),('pin2.png','3D Marker Pin'),('pin_display.png','Displpay Pin'),('pin_display_touch.png','TouchDisplpay Pin'),('pin_led.png','LEDWand Pin')],'Marker in Google',tracking=True) maps_image = fields.Binary('Google Bild',tracking=True) + maps_image_2 = fields.Binary('Google Bild 2',tracking=True) + maps_image_3 = fields.Binary('Google Bild 3',tracking=True) maps_text = fields.Html('Google Beschreibung',tracking=True) + maps_typ_interactive = fields.Boolean('Ist Interactive ?', tracking=True) + maps_visitors = fields.Integer('Besucher pro Tag', tracking=True) + maps_displaytyp = fields.Char('Anzeigetyp in Google', tracking=True) + maps_displaysize = fields.Char('Anzeigegroesse in Google',tracking=True) + maps_werbeflaechen_a_free = fields.Boolean('Werbeflächen 1 Frei', tracking=True) + maps_werbeflaechen_a = fields.Char('Werbeflächenbeschreibung 1',tracking=True) + maps_werbeflaechen_b_free = fields.Boolean('Werbeflächen 2 Frei', tracking=True) + maps_werbeflaechen_b = fields.Char('Werbeflächenbeschreibung 2',tracking=True) + maps_werbemedien = fields.Char('Werbeflächen-Dateien',tracking=True) + maps_freespaces_b_show = fields.Boolean('Freie Flächen zeigen ?', tracking=True) + maps_freespaces_b = fields.Char('Freie Werbeflächen',tracking=True) vertragsschreiber = fields.Many2one('res.partner',domain="['&',('dsspartner','=',True),('dsspartner_vertrieb','=',True)]",tracking=True) standortpartner = fields.Many2one('res.partner',domain="['&',('dsspartner','=',True),('dsspartner_standort','=',True)]",tracking=True) vertriebspartner = fields.Many2many('res.partner',domain="['&',('dsspartner','=',True),('dsspartner_vertrieb','=',True)]",tracking=True) @@ -84,6 +97,25 @@ class dssprojects(models.Model): cloudlink = fields.Char('Cloud Verzeichnis',help='Verzeichnis für das Project innerhalb des Cloud Struktur') maintains = fields.Many2many('dss.maintaintask',string="Einsätze am Projekt") + @api.model + def _read_group_system_ids(self, stages, domain, order): + project_system_ids = self.env['dss.systemtypen'].search([('open_close_standard_state','=',False)], order='order') + return project_system_ids + + def jumpcloud(self): + urlbase=str(self.env['dss.settings'].search([], limit=1).def_cloud_url_base) + _logger.info("Cloud Open Link Urlbase DB " + str(urlbase)) + if not urlbase: + urlbase = 'https://cloud.logumedia.de/index.php/apps/files/?dir='; + _logger.info("Cloud Open Link Urlbase Used " + str(urlbase)) + url=str(urlbase)+str(dss_settings.dssSettings._get_path_converted(self,self.cloudlink,self)) + _logger.info("Cloud Open Link " + str(url)) + return { + 'type': 'ir.actions.act_url', + 'url': str(url), + 'target': 'new', + } + @api.model def _compute_calendar_start(self): self.date_start_compute=date.today() @@ -164,3 +196,7 @@ class dssprojects(models.Model): else: partners_not_geo_localized |= partner return True + + def pyaction_dss_project_set_def_cloud(self): + self.cloudlink = str(self.env['dss.settings'].search([], limit=1).def_project_cloudpath) + return True diff --git a/models/dss_settings.py b/models/dss_settings.py index 57a1a98..eceeba7 100755 --- a/models/dss_settings.py +++ b/models/dss_settings.py @@ -32,10 +32,13 @@ class dssSettings(models.Model): _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_cloud_url_base = fields.Char('Cloud URL Basis',help='https://xyxxxxxx.de/cccccccc/ bis zum vorkommen des des Grundsystem URL Teils',tracking=True) 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_contract_cloudpath_V2 = fields.Char('Standard Kunden Pfad V2',tracking=True) + def_contract_cloudpath_sample_V2 = fields.Char('Projekt Beispiel V2 :',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) @@ -50,6 +53,7 @@ class dssSettings(models.Model): 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) freigabe_auto_time = fields.Integer('Auto Freigabetage',help='Automatische Freigabe nach x Tagen',tracking=True) + def _get_settingvalue(self,valuename): settings = (self.env['dss.settings'].search([],limit=1)) wert = settings._origin.read([valuename])[0][valuename] @@ -63,12 +67,12 @@ class dssSettings(models.Model): if parts[0] == '$': fels = parts[1:] parts = record._origin.read([fels]) - _logger.info("Default Cloudpath Setzen - MusterProjekt gefunden " + str(parts)) + _logger.info("Get Path - Anfrage-Teil gefunden : " + str(parts)) if parts: value = str(parts[0][fels]) else: value = '' - _logger.info("Default Cloudpath Setzen - MusterProjekt gefunden " + str(value)) + _logger.info("Get Path - Anfrage-Teil gefunden - setze : " + str(value)) alls = alls + value else: alls = alls + str(parts) @@ -110,3 +114,36 @@ class dssSettings(models.Model): def _default_uuid(self): return str(uuid.uuid4()) + @api.model + def saveConfig(self,savemodel,activefields): + _logger.info("Config speichern "+str(savemodel)+" / "+str(activefields)) + for field in activefields: + feldwerte = activefields.get(field) + for wert in feldwerte: + _logger.info("Config speichern : "+str(field)+" / "+str(wert)+" -> "+str(feldwerte.get(wert))) + return 0 + + + +class dssSettingsSave(models.Model): + + _name = "dss.viewsettings" + _description = "DigitalSignage Ansicht Einstellungen" + _inherit = [] + uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID') + model = fields.Many2one('ir.model',string='Ansichtsmodel') + viewtype = fields.Char('Ansichtstyp') + user = fields.Char('User') + column = fields.Char('Spalte') + state_visible = fields.Char('Status sichtbar') + state_collapse = fields.Char('Status zusammengeklappt') + + + @api.model + def _default_uuid(self): + return str(uuid.uuid4()) + + def _default_create_user(self): + return str(self.env.user.name) + + diff --git a/models/dss_systems.py b/models/dss_systems.py index aafbfc2..301195c 100755 --- a/models/dss_systems.py +++ b/models/dss_systems.py @@ -70,6 +70,8 @@ class dsssystems(models.Model): led_hoehe = fields.Integer('LED Hoehe mm') led_pixel_breite = fields.Integer('LED Breite px') led_pixel_hoehe = fields.Integer('LED Hoehe px') + led_cab_in_breite = fields.Integer('LED Cabinets Breite Stck') + led_cab_in_hoehe = fields.Integer('LED Cabinets Hoehe Stck') 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')]") @@ -78,7 +80,9 @@ class dsssystems(models.Model): 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') + led_cabinets_sonstige = fields.Many2many('dss.geraetetypen','led_cabinet_typen','uuid',domain="['&',('grundsystem_kennung','=','LED'),('geraetetyp','=','ANZ')]",string="Cabinets im Verbund") + + zusatz_integrationen = fields.Many2many('dss.geraetetypen','zusatz_typen','uuid') @api.model def _default_uuid(self): diff --git a/models/dss_systemtypen.py b/models/dss_systemtypen.py index 637cf3b..ec4d8bd 100755 --- a/models/dss_systemtypen.py +++ b/models/dss_systemtypen.py @@ -46,6 +46,11 @@ class dsssystemtypen(models.Model): email_template_zuarbeit = fields.Many2one('mail.template',string='Mailvorlage für Zuarbeiterrinnerung', tracking=True) email_template_abzug = fields.Many2one('mail.template',string='Mailvorlage für Korrekturabzug', tracking=True) email_template_start = fields.Many2one('mail.template',string='Mailvorlage für Auslieferung', tracking=True) + open_close_standard_state = fields.Boolean('Wenn Leer geschlossen ? ', tracking=True) + open_close_user_state = fields.Boolean('Leer-Verhalten user',compute='_get_user_openstate',tracking=True) + order = fields.Integer('Reihenfolge') + + @api.model def _default_uuid(self): @@ -67,3 +72,20 @@ class dsssystemtypen(models.Model): rec.icon_5050 = rec.icon return + def _get_user_openstate(self): + state=self.open_close_standard_state + self.open_close_user_state=state + return state + + + +class dssstatesave(models.Model): + + + _name = "dss.statesave" + _description = "DigitalSignage Systemtypen StatusPerUser" + uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID') + stategroup = fields.Selection([('SYSTYP','Systemtypen'),('CONTYP','Vertragsstatus')],'Status Gruppe', required=True) + state = fields.Char('Status', required=True) + user = fields.Char('Benutzer', required=True) + state_open = fields.Boolean('Verhalten ', tracking=True) diff --git a/models/dss_trigger.py b/models/dss_trigger.py index e05a996..e37d13c 100644 --- a/models/dss_trigger.py +++ b/models/dss_trigger.py @@ -67,6 +67,12 @@ class dsstriggertypes(models.Model): def _default_create_user(self): return str(self.env.user.name) + def getfield(self,model,field_name): + value = model + for part in field_name.split('.'): + value = getattr(value,part) + return value + def _check_trigger(self): for record in self: _logger.info('Trigger Check TR_' + str(record)+' Begin') @@ -79,11 +85,12 @@ class dsstriggertypes(models.Model): elif record.trigger_field.ttype in ['one2many']: val = self.env[record.trigger_table.model]._origin.read([record.trigger_field.name]).ids elif record.trigger_field.ttype in ['many2one']: - val = self.env[record.trigger_table.model]._origin.read([record.trigger_field.name]) +# val = self.getfield(self.env[record.trigger_table.model],record.trigger_field.name+'.uuid') + val = self.env[record.trigger_table.model]._fields[record.trigger_field.name].string else: val = False record.trigger_old_value = str(val) - _logger.info('Trigger Check TR_' + str(record)+' oldValue '+str(val)) + _logger.info('Trigger Check TR_' + str(record)+' oldValue '+str(record.trigger_old_value)+' newValue '+str(val)) _logger.info('Trigger Check TR_' + str(record)+' Ende') return "" diff --git a/models/dss_zahlungen.py b/models/dss_zahlungen.py new file mode 100644 index 0000000..7e817f0 --- /dev/null +++ b/models/dss_zahlungen.py @@ -0,0 +1,90 @@ + +# -*- 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 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 dsspayintervals(models.Model): + _name = "dss.payintervals" + _description = "DigitalSignage Abrechnungsintervalle" + _inherit = ['mail.thread','mail.activity.mixin'] + _rec_name = "payintervalname" +# _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) + payintervalname = fields.Char('Interval Name', required=True) + description = fields.Text('Interval Beschreibung') + monate = fields.Float('Interval in Monaten') + + @api.model + def _default_uuid(self): + return str(uuid.uuid4()) + +class dsspaysystems(models.Model): + _name = "dss.paysystems" + _description = "DigitalSignage Abrechnungsarten" + _inherit = ['mail.thread','mail.activity.mixin'] + _rec_name = "payname" +# _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) + payname = fields.Char('Abrechnungsname', required=True) + payonset = fields.Many2many('dss.paysystem_fields') + description = fields.Text('EventBeschreibung') + send_info = fields.Boolean('Informationsemail senden ?') + send_info_to = fields.Many2one('res.users') + send_info_template = fields.Many2one('mail.template') + amount = fields.Float('Kosten') + icon = fields.Image() + + @api.model + def _default_uuid(self): + return str(uuid.uuid4()) + + + +class dsspaysystemfields(models.Model): + _name = "dss.paysystem_fields" + _description = "DigitalSignage Abrechnungsarten_felder" + _inherit = ['mail.thread','mail.activity.mixin'] + _rec_name = "feldname" +# _inherit = ['mail.thread', 'mail.activity.mixin'] + uuid = fields.Char(default=lambda self: self._default_uuid(), required=True, readonly=True, copy=False, string='UUID') +# uuid = fields.Char('UUID', required=True, translate=True) + feldname = fields.Char('Abrechnungs_Feldname', required=True) + payonfieldset = fields.Selection([('VE','Vertragseingang'),('KA','Korrekturabzug'),('ES','Einspielung'),('CH','Jede Änderung'),('XH','X, Änderung')]) + changecount = fields.Integer('Änderungsnummer') + description = fields.Text('EventBeschreibung') + amount = fields.Float('Kosten') + + @api.model + def _default_uuid(self): + return str(uuid.uuid4()) + + diff --git a/security/ir.model.access.csv b/security/ir.model.access.csv index 3f5b4a6..cf68593 100755 --- a/security/ir.model.access.csv +++ b/security/ir.model.access.csv @@ -28,3 +28,4 @@ digitalsignage_dss_triggergroups_group_user,access.dss.triggergroups,model_dss_t digitalsignage_dss_maintaintask_group_user,access.dss.maintaintask,model_dss_maintaintask,base.group_user,1,1,1,1 digitalsignage_dss_provision_group_user,access.dss.provision,model_dss_provision,base.group_user,1,1,1,1 digitalsignage_dss_provisionstypen_group_user,access.dss.provisionstypen,model_dss_provisionstypen,DigitalSignage.group_prov_user,1,1,1,1 +digitalsignage_dss_payintervals_group_user,access.dss.payintervals,model_dss_payintervals,base.group_user,1,1,1,1 diff --git a/static/src/css/website_google_map.css b/static/src/css/website_google_map.css old mode 100644 new mode 100755 index 3d5ec1d..39b34a9 --- a/static/src/css/website_google_map.css +++ b/static/src/css/website_google_map.css @@ -26,3 +26,104 @@ body { margin-bottom: 0; font-family: sans-serif !important; } + +.marker_content { + font-size: 13px !important; + width:100%; + float:left; +} + +.marker_content tr { + line-height: 7px; +} + + +.data_property{ + width:40%; +} + +.data_value{ + width:60%; +} + +.marker_top { + font-size: 16px !important; + font-weight: bold; +} + +.marker_bottom { + font-size: 12px !important; + text-align: center; +} + +.marker_image { + font-size: 12px !important; + text-align: center; + float:left; +} + +.marker_table { + width:100%; +} + +.slider-wrapper { + margin: 1rem; + position: relative; + overflow: hidden; +} +.slides-container { + #height: calc(100vh - 2rem); + height: 200px; + width: 100%; + display: flex; + list-style: none; + margin: 0; + padding: 0; + overflow: scroll; + scroll-behavior: smooth; +} +.slides-container { + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* Internet Explorer 10+ */ +} +/* WebKit */ +.slides-container::-webkit-scrollbar { + width: 0; + height: 0; +} +.slide { + width: 100%; + height: 100%; + flex: 1 0 100%; +} + +.slide-arrow { + position: absolute; + display: flex; + top: 0; + bottom: 0; + margin: auto; + height: 4rem; + background-color: white; + border: none; + width: 2rem; + font-size: 3rem; + padding: 0; + cursor: pointer; + opacity: 0.5; + transition: opacity 100ms; +} +.slide-arrow:hover, +.slide-arrow:focus { + opacity: 1; +} +#slide-arrow-prev { + left: 0; + padding-left: 0.25rem; + border-radius: 0 2rem 2rem 0; +} +#slide-arrow-next { + right: 0; + padding-left: 0.75rem; + border-radius: 2rem 0 0 2rem; +} diff --git a/static/src/js/dss_google_map.js b/static/src/js/dss_google_map.js index 892bac0..7ef788f 100644 --- a/static/src/js/dss_google_map.js +++ b/static/src/js/dss_google_map.js @@ -21,32 +21,161 @@ function initialize_map() { imagePath: '/DigitalSignage/static/src/img/m' }; - google.maps.event.addListener(map, 'click', function() { + google.maps.event.addListener(map, 'click', function () { infoWindow.close(); }); - // Display the bubble once clicked - var onMarkerClick = function() { + var onMarkerClick = function () { var marker = this; var p = marker.project; + if (p.google_freiflaechen_b_show == true) { + var FFS = '' + + 'Freie Flächen' + + '' + + (p.google_freiflaechen_b ? '
' + p.google_freiflaechen_b + '' : '') + + '' + + ''; + } else { + var FFS = ''; + } + infoWindow.setContent( - '
'+ - (partner_url.length ? ''+p.google_name +'' : ''+p.google_name+'
: ' )+ - (p.google_typ ? '
' + p.google_typ + '

' : '')+ - (p.google_image ? '


' : '')+ - (p.google_text ? '
' + p.google_text + '' : '')+ - '
' - ); + '
' + + '
' + + (partner_url.length ? '' + p.google_name + '' : '' + p.google_name + '
: ') + + '
' + + '
' + + '' + + '' + + '' + + '
' + + '
' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + FFS + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
Anzeigesystem' + + (p.google_typ ? '
' + p.google_typ + '' : '') + + '
Interaktiv' + + (p.google_typ_interactive ? '
' + p.google_typ_interactive + '' : '') + + '
Besucherzahl' + + (p.google_visitors ? '
' + p.google_visitors + '' : '') + + '
Anzeigetyp' + + (p.google_displaytyp ? '
' + p.google_displaytyp + '' : '') + + '
Anzeigegrösse' + + (p.google_displaysize ? '
' + p.google_displaysize + '' : '') + + '
Mögliche Werbeart 1 ' + + (p.google_displayflaechen_a ? '
' + p.google_displayflaechen_a + '' : '') + + '
Werbeart 1 Verfügbar ?' + + (p.google_displayflaechen_a_free ? '
' + p.google_displayflaechen_a_free + '' : '') + + '
Mögliche Werbeart 2' + + (p.google_displayflaechen_b ? '
' + p.google_displayflaechen_b + '' : '') + + '
Werbeart 2 Verfügbar ?' + + (p.google_displayflaechen_b_free ? '
' + p.google_displayflaechen_b_free + '' : '') + + '
Nötige Werbemittel' + + (p.google_displayfiles ? '
' + p.google_displayfiles + '' : '') + + '
Buchungscode' + + (p.google_id ? '
' + p.google_id + '' : '') + + '
' + + '
' + + '
' + + (p.google_text ? '
' + p.google_text + '' : '') + + '
' + + '
' + ); infoWindow.open(map, marker); + const slidesContainer = document.getElementById("slides-container"); + const slide = document.querySelector(".slide"); + const prevButton = document.getElementById("slide-arrow-prev"); + const nextButton = document.getElementById("slide-arrow-next"); + console.log("imScript") + google.maps.event.addListener(infoWindow, 'domready', function () { + $('#slide-arrow-prev').click(function () { + const slideWidth = $(".slide").width(); + $('#slides-container').scrollLeft(0); + console.log("leftClick "+slideWidth) + }); + $('#slide-arrow-next').click(function () { + const slideWidth = $(".slide").width(); + $('#slides-container').scrollLeft(slideWidth); + console.log("RightClick "+slideWidth) + }); + }); +// var yourFunction = new YourFunction() + }; + var YourFunction = function () { + this.init = function () { + + }; + this.init(); + } + // Create a bubble for a partner - var set_marker = function(project) { + 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 (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 partners = new google.maps.MarkerImage('/DigitalSignage/static/src/img/' + project.google_marker, new google.maps.Size(55, 55)); var marker = new google.maps.Marker({ project: project, icon: partners, @@ -60,7 +189,7 @@ function initialize_map() { /* eslint-disable no-undef */ // Create the markers and cluster them on the map - if (odoo_projects_data){ /* odoo_partner_data special variable should have been defined in google_map.xml */ + if (odoo_projects_data) { /* odoo_partner_data special variable should have been defined in google_map.xml */ for (var i = 0; i < odoo_projects_data.counter; i++) { set_marker(odoo_projects_data.projects[i]); } @@ -70,4 +199,4 @@ function initialize_map() { } // Initialize map once the DOM has been loaded -google.maps.event.addDomListener(window, 'load', initialize_map); +google.maps.event.addDomListener(window, 'load', initialize_map); \ No newline at end of file diff --git a/static/src/js/form_button.js b/static/src/js/form_button.js new file mode 100644 index 0000000..f080c18 --- /dev/null +++ b/static/src/js/form_button.js @@ -0,0 +1,28 @@ +/** @odoo-module */ +import { ListController } from "@web/views/list/list_controller"; +import { registry } from '@web/core/registry'; +import { listView } from '@web/views/list/list_view'; +import { useService } from "@web/core/utils/hooks"; + +var rpc = require('web.rpc') + +export class configListController extends ListController { + setup() { + super.setup(); + + } + SaveButtonClicked() { + alert(this.archInfo.activeFields) + rpc.query({ + model: 'dss.settings', + method: 'saveConfig', + args: [this.props.resModel,this.archInfo.activeFields], + }); + } +} + +registry.category("views").add("button_in_tree", { + ...listView, + Controller: configListController, + buttonTemplate: "button_config.ListView.Buttons", +}); \ No newline at end of file diff --git a/static/src/js/kanban_button.js b/static/src/js/kanban_button.js new file mode 100644 index 0000000..13e148f --- /dev/null +++ b/static/src/js/kanban_button.js @@ -0,0 +1,26 @@ +/** @odoo-module */ +import { KanbanController } from "@web/views/kanban/kanban_controller"; +import { registry } from '@web/core/registry'; +import { kanbanView } from '@web/views/kanban/kanban_view'; +import { useService } from "@web/core/utils/hooks"; + +var rpc = require('web.rpc') + +export class configKanbanController extends KanbanController { + setup() { + super.setup(); + } + SaveButtonClicked() { + rpc.query({ + model: 'dss.settings', + method: 'saveConfig', + args: [this.props,""], + }); + } +} + +registry.category("views").add("button_in_kanban", { + ...kanbanView, + Controller: configKanbanController, + buttonTemplate: "button_config.KanbanView.Buttons", +}); \ No newline at end of file diff --git a/static/src/xml/form_button.xml b/static/src/xml/form_button.xml new file mode 100644 index 0000000..e7458c8 --- /dev/null +++ b/static/src/xml/form_button.xml @@ -0,0 +1,15 @@ + + + + +