update
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
|
||||
import json
|
||||
from jsonschema import validate
|
||||
|
||||
from odoo import _, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
from .ai import QuickboardAiGenerator
|
||||
from .ai.consts import QUICKBOARD_DATA_UI_JSON_SCHEMA, QUICKBOARD_BG_COLORS, QUICKBOARD_FG_COLORS
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
class QuickboardGenerator(models.TransientModel):
|
||||
_name = "quickboard.generator"
|
||||
_description = "Generate quickbaord items with AI."
|
||||
|
||||
model_ids = fields.Many2many('ir.model', string='Model')
|
||||
layout_by_ai = fields.Boolean("Layout by AI", default=False)
|
||||
|
||||
def action_generate_quickboard(self):
|
||||
if len(self.model_ids.ids) < 1:
|
||||
return {
|
||||
'name': _('Generate Quickboard'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'quickboard.generator',
|
||||
'view_type': 'form',
|
||||
'view_mode': 'form',
|
||||
'res_id': self.id,
|
||||
'target': 'new',
|
||||
}
|
||||
|
||||
screen_width = self.env.context.get("screen_width")
|
||||
screen_height = self.env.context.get("screen_height")
|
||||
cell_width = self.env.context.get("cell_width")
|
||||
cell_height = self.env.context.get("cell_height")
|
||||
|
||||
try:
|
||||
gen = QuickboardAiGenerator(self.env)
|
||||
quickboard = gen.generate_quickboard(
|
||||
self.model_ids,
|
||||
self.layout_by_ai,
|
||||
screen_width,
|
||||
screen_height,
|
||||
cell_width,
|
||||
cell_height
|
||||
)
|
||||
quickboard_json = json.loads(quickboard)
|
||||
validate(quickboard_json, QUICKBOARD_DATA_UI_JSON_SCHEMA)
|
||||
|
||||
quickboard_item = self.env['quickboard.item']
|
||||
items = quickboard_item.search([])
|
||||
for o in items:
|
||||
o.unlink()
|
||||
|
||||
for o in quickboard_json:
|
||||
_logger.info(f"Creating quickboard item: {o}")
|
||||
|
||||
model = self.env["ir.model"].search([("model", "=", o["model"])])
|
||||
value_field = self.env["ir.model.fields"].search([("model_id", "=", model.id), ("name", "=", o["value_field"])])
|
||||
|
||||
if not value_field.id:
|
||||
raise Exception("AI generated invalid field: %s." % {o["value_field"]})
|
||||
|
||||
# Sometime AI choose the wrong aggregate function, we could return the result to AI with json schema validation.
|
||||
# But, it would mean failing the result and making another attempt, the alternative is we just fix it here.
|
||||
if value_field.ttype not in ['float', 'integer', 'monetary'] and o["aggregate_function"] != "count":
|
||||
o["aggregate_function"] = "count"
|
||||
|
||||
vals = {
|
||||
"name": o["name"],
|
||||
"model_id": model.id,
|
||||
"icon": o["icon"],
|
||||
"type": o["type"],
|
||||
"value_field_id": [value_field.id],
|
||||
"aggregate_function": o["aggregate_function"],
|
||||
"x_pos": o["x_pos"],
|
||||
"y_pos": o["y_pos"],
|
||||
"height": o["height"],
|
||||
"width": o["width"]
|
||||
}
|
||||
if o["type"] == "basic":
|
||||
text_color = 0
|
||||
if o["text_color"] and o["text_color"] in QUICKBOARD_FG_COLORS:
|
||||
text_color = QUICKBOARD_FG_COLORS.index(o["text_color"])
|
||||
|
||||
back_color = 0
|
||||
if o["text_color"] and o["text_color"] in QUICKBOARD_BG_COLORS:
|
||||
back_color = QUICKBOARD_BG_COLORS.index(o["text_color"])
|
||||
|
||||
vals.update({
|
||||
"text_color": text_color,
|
||||
"background_color": back_color,
|
||||
})
|
||||
elif o["type"] == "chart":
|
||||
dimension_field = self.env["ir.model.fields"].search([("model_id", "=", model.id), ("name", "=", o["dimension_field"])])
|
||||
if not dimension_field.id:
|
||||
raise Exception("AI generated invalid field: %s." % {o["dimension_field"]})
|
||||
|
||||
vals.update({
|
||||
"dimension_field_id": dimension_field.id,
|
||||
"chart_type": o["chart_type"],
|
||||
})
|
||||
|
||||
if "datetime_granularity" in o:
|
||||
vals.update({
|
||||
"datetime_granularity": o["datetime_granularity"]
|
||||
})
|
||||
elif o["type"] == "list":
|
||||
dimension_field = self.env["ir.model.fields"].search([("model_id", "=", model.id), ("name", "=", o["dimension_field"])])
|
||||
if not dimension_field.id:
|
||||
raise Exception("AI generated invalid field: %s." % {o["dimension_field"]})
|
||||
|
||||
vals.update({
|
||||
"dimension_field_id": dimension_field.id,
|
||||
"list_row_limit": o["list_row_limit"]
|
||||
})
|
||||
|
||||
if "datetime_granularity" in o:
|
||||
vals.update({
|
||||
"datetime_granularity": o["datetime_granularity"]
|
||||
})
|
||||
|
||||
quickboard_item.with_context(ai_generation=True).create(vals)
|
||||
except Exception as e:
|
||||
_logger.error("Error generating quickboard", e)
|
||||
raise ValidationError(_("Unfortunately the AI didn't generate valid quickboard. Please try again."))
|
||||
|
||||
for rec in self:
|
||||
self.env["bus.bus"]._sendone("quickboard", "quickboard_updated", {})
|
||||
|
||||
return True
|
||||
Reference in New Issue
Block a user