327 lines
17 KiB
Python
Executable File
327 lines
17 KiB
Python
Executable File
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
|
|
import requests
|
|
import hashlib
|
|
from PIL import Image,ImageDraw,ImageFont
|
|
|
|
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
|
|
from webdav4.client import Client
|
|
from webdav4.fsspec import WebdavFileSystem
|
|
import sys
|
|
|
|
TUYA_LOGGER.setLevel(logging.DEBUG)
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class dsscsvs(models.Model):
|
|
|
|
@api.model
|
|
def create(self,vals):
|
|
result = super().create(vals)
|
|
return result
|
|
|
|
_name = "dss.csvs"
|
|
_description = "DigitalSignage CSV Dateien"
|
|
# _inherit = ['mail.thread','mail.activity.mixin']
|
|
_rec_name = "csv_id"
|
|
# _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')
|
|
csv_id = fields.Char(string="CSV ID", required=True, help = "Das ist eine eindeutige ID für diese Dateityp. Sie wird automatisch generiert und sollte nicht manuell geändert werden.", default=lambda self: self._default_csv_id())
|
|
csv_name = fields.Char(string="CSV Name", required=True, help = "Der Name des Dateityp, die Sie hochladen möchten. Dieser Name wird in der Benutzeroberfläche angezeigt.")
|
|
csv_binary = fields.Binary(string="CSV Datei", help = "Die eigentliche Datei, die Sie hochladen möchten. Diese Datei wird in der Datenbank und Cloud gespeichert")
|
|
csv_filename = fields.Char(string="CSV Dateiname", help = "Der Name der hochgeladenen Datei. Dies wird automatisch aus dem Dateinamen der hochgeladenen Datei abgerufen.",compute="_compute_csv_filename", store=True)
|
|
csv_cloud_link = fields.Char(string="Cloud Link", help = "Der Link zur Datei in der Cloud, wenn die Datei in der Cloud gespeichert ist.")
|
|
csv_description = fields.Text(string="CSV Beschreibung", help = "Eine Beschreibung der hochgeladenen Datei. Dies kann Informationen über den Inhalt der Datei, den Verwendungszweck oder andere relevante Details enthalten.")
|
|
csv_attachment_id = fields.Many2one('ir.attachment', string="CSV Anhang", help = "Der Anhang, der mit dieser CSV-Datei verbunden ist. Dieser Anhang enthält die tatsächliche Datei, die in der Datenbank gespeichert ist.")
|
|
csv_mailtext = fields.Text(string="CSV Mailtext", help = "Der Text, der in der E-Mail verwendet wird, wenn diese CSV-Datei per E-Mail versendet wird.")
|
|
|
|
|
|
|
|
@api.depends('binary_binary')
|
|
@api.onchange('binary_binary')
|
|
def _compute_binary_filename(self):
|
|
"""Compute the binary filename based on the uploaded file."""
|
|
_logger.info("Binary getting Filename - B_"+str(self.id))
|
|
if len(self)>0:
|
|
for record in self:
|
|
if record.binary_binary:
|
|
# Extract the filename from the binary content
|
|
extension = 'jpg' # Default extension
|
|
if isinstance(self.binary_binary, str):
|
|
filedata = base64.b64decode(self.binary_binary.split("base64,")[-1])
|
|
else:
|
|
filedata = base64.b64decode(self.binary_binary)
|
|
filedataStr = str(filedata)
|
|
_logger.info("Binary getting Filename - B_"+str(self.id)+" - ["+str(filedataStr[0:23])+"]")
|
|
if filedataStr[0:12] == "b'\\x89PNG\\":
|
|
extension = 'png'
|
|
elif filedataStr[0:17] == "b'\\xff\\xd8\\xff":
|
|
extension = 'jpg'
|
|
elif filedataStr[0:8] == "b'GIF89a":
|
|
extension = 'gif'
|
|
elif filedataStr[0:22] == "b'\\x49\\x49\\x2a\\x00":
|
|
extension = 'tif'
|
|
elif filedataStr[0:27] == "b'\\x25\\x50\\x44\\x46\\x2d":
|
|
extension = 'pdf'
|
|
elif filedataStr[0:23] == "b'\\x00\\x00\\x00 ftypisom":
|
|
extension = 'mp4'
|
|
elif filedataStr[0:22] == "b'\\x00\\x00\\x00\\x18ftyp":
|
|
extension = 'mp4'
|
|
elif filedataStr[0:12] == "b'\\x42\\x4d":
|
|
extension = 'bmp'
|
|
record.binary_filename = f"{record.binary_mediatype.filepartname}{record.binary_contract.contract_auto_id}.{extension}"
|
|
|
|
@api.model
|
|
def _default_uuid(self):
|
|
return str(uuid.uuid4())
|
|
|
|
@api.model
|
|
def _default_create_date(self):
|
|
return datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
|
|
|
@api.model
|
|
def _default_create_user(self):
|
|
return self.env.user.name if self.env.user else 'System'
|
|
|
|
@api.model
|
|
def _default_binary_id(self):
|
|
# Generate a unique binary ID based on the current timestamp and a random UUID
|
|
return f"Datei_{str(uuid.uuid4())[:8]}"
|
|
|
|
@api.onchange('binary_binary')
|
|
def _onchange_binary_binary(self):
|
|
"""Update binary size and type when binary content is changed."""
|
|
_logger.info("New Binary B_"+str(self.id))
|
|
existing_binary = False
|
|
if not self._origin.binary_binary:
|
|
existing_binary = False
|
|
else:
|
|
existing_binary = True
|
|
|
|
if not self.binary_contract.cloudlink:
|
|
raise ValidationError(_("Der Vertrag hat keinen Cloudlink. Bitte überprüfen Sie den Vertrag."))
|
|
cloudpath = str(self.binary_contract.cloudlink)
|
|
_logger.info("New Binary checking Cloudlink B_"+str(self.id)+" - "+str(cloudpath))
|
|
cloudpath = cloudpath + '/' + str(self.binary_mediatype.cloudlink)
|
|
client = Client("https://cloud.logumedia.de/remote.php/dav/files/OdooDav/", auth=("odooClient@logumedia.de", "lm2020#OdooDav"))
|
|
_logger.info("New Binary checking Cloudlink for cont : "+str(cloudpath))
|
|
cloudexists = False
|
|
if client.exists(cloudpath):
|
|
# Convert self.binary_binary to bytes-like object
|
|
if isinstance(self.binary_binary, str):
|
|
filedata = base64.b64decode(self.binary_binary.split("base64,")[-1])
|
|
else:
|
|
filedata = base64.b64decode(self.binary_binary)
|
|
filedataStr = str(filedata)
|
|
_logger.info("New Binary Cloudlink exists - Saving File - B_"+str(self.id)+" - "+str(cloudpath)+" - " + str(filedata)+' - ' + filedataStr[0:8])
|
|
try:
|
|
decoded_data = filedata
|
|
except base64.binascii.Error as e:
|
|
if 'Incorrect padding' in str(e):
|
|
filedataStr += b'=' * (4 - len(filedataStr) % 4)
|
|
decoded_data = base64.b64decode(filedataStr)
|
|
if filedataStr[0:10] == "b'\x89PNG":
|
|
extension = 'png'
|
|
else:
|
|
extension = 'jpg'
|
|
_logger.info("New Binary Cloudlink exists - Saving File - B_"+str(self.id)+" - "+str(cloudpath)+" - " + str(base64.b64encode(decoded_data)))
|
|
##infile = open('/tmp/'+filename, "w+b")
|
|
#infile = tempfile.NamedTemporaryFile(delete=False)
|
|
##infile.write(filedata)
|
|
##client.upload_fileobj(infile, f"{cloudpath}/{filename}")
|
|
##infile.close()
|
|
##infile.delete() # Delete the temporary file after upload
|
|
cloudexists = True
|
|
else:
|
|
_logger.info("New Binary Cloudlink does not exists B_"+str(self.id)+" - "+str(cloudpath))
|
|
raise ValidationError(_("Der Cloudlink im Vertrag ist nicht vorhanden. Bitte überprüfen Sie den Link ggf. anlegen."))
|
|
|
|
if cloudexists:
|
|
if self.binary_binary:
|
|
# Calculate the size of the binary content
|
|
self.binary_size = len(filedata)
|
|
# Determine the file type based on the binary content
|
|
self.binary_cloud_link = f"{cloudpath}/{self.binary_filename}"
|
|
self.binary_issaved = True
|
|
else:
|
|
self.binary_size = 0
|
|
self.binary_type = ''
|
|
self.binary_cloud_link = ''
|
|
self.binary_issaved = False
|
|
|
|
|
|
def dload(self):
|
|
"""Download the binary file."""
|
|
if not self.binary_binary:
|
|
raise ValidationError(_("No binary file to download."))
|
|
|
|
# Create a temporary file to store the downloaded content
|
|
temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=self.binary_filename)
|
|
temp_file.write(base64.b64decode(self.binary_binary))
|
|
temp_file.close()
|
|
|
|
# Return the file for download
|
|
return {
|
|
'type': 'ir.actions.act_url',
|
|
'url': f'/web/content/{self.id}/{self.binary_filename}?download=true&filename={self.binary_filename}',
|
|
'target': 'self',
|
|
}
|
|
|
|
def dedit(self):
|
|
"""Edit the binary file."""
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'res_model': 'dss.binaries',
|
|
'view_mode': 'form',
|
|
'res_id': self.id,
|
|
'target': 'new',
|
|
}
|
|
|
|
def resend(self):
|
|
"""Resend the binary file to the contract's partner email."""
|
|
if not self.binary_contract:
|
|
raise ValidationError(_("No contract associated with this binary file."))
|
|
if not self.binary_contract.project.standortpartner:
|
|
raise ValidationError(_("No partner associated with the contract."))
|
|
if not self.binary_contract.project.standortpartner.email:
|
|
raise ValidationError(_("The partner does not have an email address."))
|
|
# Send email with the binary file as attachment
|
|
|
|
def genstamp(self):
|
|
_logger.info('Create Stamps for Binary: B_'+str(self.id)+' '+str(id))
|
|
# Bildparameter definieren
|
|
Medium = self.binary_mediatype
|
|
if Medium and Medium.can_gen_stamp and self.binary_contract:
|
|
_logger.info('Create Stamps for Contract : B_'+str(self.id)+' - Contract: C_'+str(self.binary_contract.id)+'- Medium : M_'+str(Medium.id)+' - '+str(Medium.medianame))
|
|
# Bildgröße und Hintergrundfarbe festlegen
|
|
background_color = (255, 255, 255) # Weißer Hintergrund (RGB)
|
|
# Neues Bild erstellen
|
|
maxh = Medium.maxsize_h
|
|
maxw = Medium.maxsize_w
|
|
image = Image.new("RGB", (maxw, maxh), background_color)
|
|
d = ImageDraw.Draw(image)
|
|
Zeilen = Medium.maxsize_h // 6
|
|
zposy = 2
|
|
if self.binary_contract.client:
|
|
text = self.binary_contract.contact_company_name
|
|
_logger.info('Create Stamps for Contract : B_'+str(self.id)+' - Contract: C_'+str(self.binary_contract.id)+'- Medium : M_'+str(Medium.id)+' - Text1: '+str(text))
|
|
if len(text) > 35:
|
|
# Trenne den Text an einem Leerzeichen nahe bei Position 40
|
|
idx = text.rfind(' ', 0, 35)
|
|
if idx == -1:
|
|
idx = 35
|
|
text2 = text[:idx]
|
|
bcount = len(text2) if text2 else 1
|
|
fonts = maxw // (bcount ) *1.8
|
|
if fonts > maxh:
|
|
fonts = maxh - 10
|
|
if fonts <=0 :
|
|
fonts = 10
|
|
# font = ImageFont.truetype("addons/web/static/fonts/sign/Zeyada-Regular.ttf", fonts)
|
|
font = ImageFont.truetype("addons/web/static/fonts/google/Open_Sans/Open_Sans-SemiBold.ttf", fonts)
|
|
d.text((maxw // 2, 1*Zeilen), text2, fill="black",align="center", anchor="ms", font=font) # Beispiel: Ein Rechteck
|
|
text = text[idx:]
|
|
zposy = 2
|
|
if len(text) > 35:
|
|
# Trenne den Text an einem Leerzeichen nahe bei Position 40
|
|
idx = text.rfind(' ', 0, 35)
|
|
if idx == -1:
|
|
idx = 35
|
|
text2 = text[:idx]
|
|
# font = ImageFont.truetype("addons/web/static/fonts/sign/Zeyada-Regular.ttf", fonts)
|
|
font = ImageFont.truetype("addons/web/static/fonts/google/Open_Sans/Open_Sans-SemiBold.ttf", fonts)
|
|
d.text((maxw // 2, zposy*Zeilen), text2, fill="black",align="center", anchor="ms", font=font) # Beispiel: Ein Rechteck
|
|
text = text[idx:]
|
|
zposy = 3
|
|
else:
|
|
bcount = len(text) if text else 1
|
|
fonts = maxw // (bcount ) *1.8
|
|
if fonts > maxh:
|
|
fonts = maxh - 10
|
|
if fonts <=0 :
|
|
fonts = 10
|
|
# font = ImageFont.truetype("addons/web/static/fonts/sign/Zeyada-Regular.ttf", fonts)
|
|
font = ImageFont.truetype("addons/web/static/fonts/google/Open_Sans/Open_Sans-SemiBold.ttf", fonts)
|
|
d.text((maxw // 2, zposy*Zeilen), text, fill="black",align="center", anchor="ms", font=font) # Beispiel: Ein Rechteck
|
|
text = self.binary_contract.contact_street
|
|
bcount = len(text) if text else 1
|
|
Zeilen = maxh // 6
|
|
fonts = maxw // (bcount ) *1.2
|
|
if fonts > maxh:
|
|
fonts = maxh - 10
|
|
if fonts <=0 :
|
|
fonts = 10
|
|
# font = ImageFont.truetype("addons/web/static/fonts/sign/Zeyada-Regular.ttf", fonts)
|
|
font = ImageFont.truetype("addons/web/static/fonts/google/Open_Sans/Open_Sans-Regular.ttf", fonts)
|
|
d.text((maxw // 2, 4*Zeilen), text, fill="black",align="center", anchor="ms", font=font) # Beispiel: Ein Rechteck
|
|
text = self.binary_contract.contact_zip+' '+self.binary_contract.contact_city
|
|
bcount = len(text) if text else 1
|
|
Zeilen = maxh // 6
|
|
fonts = maxw // (bcount ) *1.2
|
|
if fonts > maxh:
|
|
fonts = maxh - 10
|
|
if fonts <=0 :
|
|
fonts = 10
|
|
# font = ImageFont.truetype("addons/web/static/fonts/sign/Zeyada-Regular.ttf", fonts)
|
|
font = ImageFont.truetype("addons/web/static/fonts/google/Open_Sans/Open_Sans-Regular.ttf", fonts)
|
|
d.text((maxw // 2, 5*Zeilen), text, fill="black",align="center", anchor="ms", font=font) # Beispiel: Ein Rechteck
|
|
# Bild speichern
|
|
filename = Medium.filepartname+self.binary_contract.contract_auto_id+".png"
|
|
_logger.info('Create Stamps for Contract : B_'+str(self.id)+' - Contract: C_'+str(self.binary_contract.id)+'- Feld : F_'+str(Medium.id)+' - Filename: '+str(filename))
|
|
image.save(filename)
|
|
_logger.info("Stamp file created "+str(filename))
|
|
_logger.info("Copy file to Binaries B_"+str(self))
|
|
try:
|
|
self.binary_binary = base64.b64encode(open(filename, "rb").read())
|
|
self.binary_filename = filename
|
|
self.binary_type = 'image/png'
|
|
self.binary_size = os.path.getsize(filename)
|
|
self.binary_issaved = False
|
|
self.binary_secured_ro = False
|
|
self.binary_used_ro = False
|
|
finally:
|
|
_logger.info("Binary inserted "+str(self))
|
|
cloudpath = self.binary_contract.cloudlink
|
|
if not cloudpath:
|
|
raise ValidationError(_("Der Vertrag hat keinen Cloudlink. Bitte überprüfen Sie den Vertrag."))
|
|
if not Medium.cloudlink:
|
|
raise ValidationError(_("Der Mediatyp hat keinen Cloudlink. Bitte überprüfen Sie den Mediatyp."))
|
|
cloudpath = cloudpath + '/' + str(Medium.cloudlink)
|
|
_logger.info("Copy file to Cloud Path : "+str(cloudpath))
|
|
try:
|
|
client = Client("https://cloud.logumedia.de/remote.php/dav/files/OdooDav/", auth=("odooClient@logumedia.de", "lm2020#OdooDav"))
|
|
try:
|
|
#client.mkdir(new_folder)
|
|
#_logger.info("Make Cloud Path : "+str(new_folder))
|
|
client.upload_file(filename, f"{cloudpath}/{filename}")
|
|
except Exception as e:
|
|
_logger.info("Make Cloud Path error : "+str(e))
|
|
finally:
|
|
self.binary_issaved = True
|
|
_logger.info("File copied to Cloud Path : "+str(cloudpath))
|
|
return True
|
|
|