Files
gzth/onlyoffice_odoo_templates/models/onlyoffice_odoo_templates.py
T
2024-09-29 23:18:21 +08:00

197 lines
8.6 KiB
Python

import base64
import copy
import json
import re
import os
from odoo import _, api, fields, models
from odoo.exceptions import UserError
from odoo.addons.onlyoffice_odoo.utils import file_utils
from odoo.addons.onlyoffice_odoo_templates.utils import pdf_utils
from odoo.modules import get_module_path
class OnlyOfficeTemplate(models.Model):
_name = "onlyoffice.odoo.templates"
_description = "ONLYOFFICE Templates"
name = fields.Char(required=True, string="Template Name")
template_model_id = fields.Many2one("ir.model", string="Select Model")
template_model_name = fields.Char("Model Description", related="template_model_id.name")
template_model_model = fields.Char("Model", related="template_model_id.model")
file = fields.Binary(string="Upload an existing template")
attachment_id = fields.Many2one("ir.attachment", readonly=True)
mimetype = fields.Char(default="application/pdf")
@api.onchange("name")
def _onchange_name(self):
if self.attachment_id:
self.attachment_id.name = self.name + ".pdf"
self.attachment_id.display_name = self.name
@api.onchange("file")
def _onchange_file(self):
if self.file and self.create_date: # if file exist
decode_file = base64.b64decode(self.file)
is_pdf_form = pdf_utils.is_pdf_form(decode_file)
if not is_pdf_form:
self.file = False
raise UserError(_("Only PDF Form can be uploaded."))
self.attachment_id.datas = self.file
self.file = False
@api.model
def _create_demo_data(self):
module_path = get_module_path(self._module)
templates_dir = os.path.join(module_path, "data", "templates")
if not os.path.exists(templates_dir):
return
model_folders = [name for name in os.listdir(templates_dir) if os.path.isdir(os.path.join(templates_dir, name))]
installed_models = self.env["ir.model"].search([])
installed_models_list = [(model.model, model.name) for model in installed_models]
for model_name in model_folders:
if any(model_name == model[0] for model in installed_models_list):
templates_path = os.path.join(templates_dir, model_name)
templates_name = [name for name in os.listdir(templates_path) if os.path.isfile(os.path.join(templates_path, name)) and name.lower().endswith(".pdf")]
for template_name in templates_name:
template_path = os.path.join(templates_path, template_name)
template = open(template_path, "rb")
try:
template_data = template.read()
template_data = base64.encodebytes(template_data)
model = self.env["ir.model"].search([("model", "=", model_name)], limit=1)
name = template_name.rstrip(".pdf")
self.create({
"name": name,
"template_model_id": model.id,
"file": template_data,
})
finally:
template.close()
return
@api.model
def create(self, vals):
if vals.get("file"):
decode_file = base64.b64decode(vals.get("file"))
is_pdf_form = pdf_utils.is_pdf_form(decode_file)
if not is_pdf_form:
raise UserError(_("Only PDF Form can be uploaded."))
file = vals.get("file") or base64.encodebytes(file_utils.get_default_file_template(self.env.user.lang, "pdf"))
mimetype = file_utils.get_mime_by_ext("pdf")
vals["file"] = file
vals["mimetype"] = mimetype
datas = vals.pop("file", None)
record = super(OnlyOfficeTemplate, self).create(vals)
if datas:
attachment = self.env["ir.attachment"].create(
{
"name": vals.get("name", record.name) + ".pdf",
"display_name": vals.get("name", record.name),
"mimetype": vals.get("mimetype", ""),
"datas": datas,
"res_model": self._name,
"res_id": record.id,
}
)
record.attachment_id = attachment.id
return record
@api.model
def get_fields_for_model(self, model_name):
processed_models = set()
cached_models = {}
def process_model(model_name):
if model_name in processed_models:
return {}
processed_models.add(model_name)
model = self.env["ir.model"].search([("model", "=", model_name)], limit=1)
if not model:
processed_models.discard(model_name)
return {}
description = model.name
fields = self.env[model_name].fields_get([], attributes=("name", "type", "string", "relation"))
form_fields = self.env[model_name].get_view()['models']
form_fields = form_fields[model_name]
field_list = []
for field_name, field_props in fields.items():
field_type = field_props["type"]
if field_type in ["one2many", "many2many", "many2one"] and field_name not in form_fields:
continue
if field_type in ["html", "json"]:
continue # TODO:
field_dict = {
"name": field_name,
"string": field_props.get("string", ""),
"type": field_props["type"],
}
if field_type in ["one2many", "many2many", "many2one"]:
related_model = field_props["relation"]
if cached_models.get(related_model):
field_dict["related_model"] = {
"name": field_name,
"description": cached_models[related_model]["description"],
"fields": cached_models[related_model]["fields"],
}
else:
if field_type == "many2one":
related_description = self.env["ir.model"].search([("model", "=", related_model)], limit=1)
related_description = related_description.name
related_fields = self.env[related_model].fields_get([], attributes=("name", "type", "string"))
related_form_fields = self.env[related_model].get_view()['models']
related_form_fields = related_form_fields[related_model]
related_field_list = []
for (related_field_name, related_field_props) in related_fields.items():
if related_field_props["type"] in ["html", "json"]:
continue # TODO:
if related_field_name not in related_form_fields:
continue
related_field_dict = {
"name": related_field_name,
"string": related_field_props.get("string", ""),
"type": related_field_props["type"],
}
related_field_list.append(related_field_dict)
related_model_info = {
"name": field_name,
"description": related_description,
"fields": related_field_list,
}
if related_field_list:
field_dict["related_model"] = related_model_info
cached_models[related_model] = related_model_info
else:
processed_model = process_model(related_model)
if processed_model:
field_dict["related_model"] = processed_model
cached_models[related_model] = processed_model
field_list.append(field_dict)
model_info = {
"name": model_name,
"description": description,
"fields": field_list,
}
processed_models.discard(model_name)
return model_info
models_info = process_model(model_name)
data = json.dumps(models_info, ensure_ascii=False)
return data