package server import ( "fmt" "strings" "odoo-go/pkg/orm" ) // handleGetViews implements the get_views method. // Mirrors: odoo/addons/base/models/ir_ui_view.py get_views() func handleGetViews(env *orm.Environment, model string, params CallKWParams) (interface{}, *RPCError) { // Parse views list: [[false, "list"], [false, "form"], [false, "search"]] var viewRequests [][]interface{} if len(params.Args) > 0 { if vr, ok := params.Args[0].([]interface{}); ok { viewRequests = make([][]interface{}, len(vr)) for i, v := range vr { if pair, ok := v.([]interface{}); ok { viewRequests[i] = pair } } } } // Also check kwargs if viewRequests == nil { if vr, ok := params.KW["views"].([]interface{}); ok { viewRequests = make([][]interface{}, len(vr)) for i, v := range vr { if pair, ok := v.([]interface{}); ok { viewRequests[i] = pair } } } } views := make(map[string]interface{}) for _, vr := range viewRequests { if len(vr) < 2 { continue } viewType, _ := vr[1].(string) if viewType == "" { continue } // Try to load from ir_ui_view table arch := loadViewArch(env, model, viewType) if arch == "" { // Generate default view arch = generateDefaultView(model, viewType) } views[viewType] = map[string]interface{}{ "arch": arch, "type": viewType, "model": model, "view_id": 0, "field_parent": false, } } // Build models dict with field metadata models := map[string]interface{}{ model: map[string]interface{}{ "fields": fieldsGetForModel(model), }, } return map[string]interface{}{ "views": views, "models": models, }, nil } // loadViewArch tries to load a view from the ir_ui_view table. func loadViewArch(env *orm.Environment, model, viewType string) string { var arch string err := env.Tx().QueryRow(env.Ctx(), `SELECT arch FROM ir_ui_view WHERE model = $1 AND type = $2 AND active = true ORDER BY priority LIMIT 1`, model, viewType, ).Scan(&arch) if err != nil { return "" } return arch } // generateDefaultView creates a minimal view XML for a model. func generateDefaultView(modelName, viewType string) string { m := orm.Registry.Get(modelName) if m == nil { return fmt.Sprintf("<%s>", viewType, viewType) } switch viewType { case "list", "tree": return generateDefaultListView(m) case "form": return generateDefaultFormView(m) case "search": return generateDefaultSearchView(m) case "kanban": return generateDefaultKanbanView(m) default: return fmt.Sprintf("<%s>", viewType, viewType) } } func generateDefaultListView(m *orm.Model) string { var fields []string count := 0 for _, f := range m.Fields() { if f.Name == "id" || !f.IsStored() || f.Name == "create_uid" || f.Name == "write_uid" || f.Name == "create_date" || f.Name == "write_date" || f.Type == orm.TypeBinary { continue } fields = append(fields, fmt.Sprintf(``, f.Name)) count++ if count >= 8 { break } } return fmt.Sprintf("\n %s\n", strings.Join(fields, "\n ")) } func generateDefaultFormView(m *orm.Model) string { var fields []string for _, f := range m.Fields() { if f.Name == "id" || f.Name == "create_uid" || f.Name == "write_uid" || f.Name == "create_date" || f.Name == "write_date" || f.Type == orm.TypeBinary { continue } if f.Type == orm.TypeOne2many || f.Type == orm.TypeMany2many { continue // Skip relational fields in default form } fields = append(fields, fmt.Sprintf(` `, f.Name)) if len(fields) >= 20 { break } } return fmt.Sprintf("
\n \n \n%s\n \n \n
", strings.Join(fields, "\n")) } func generateDefaultSearchView(m *orm.Model) string { var fields []string // Add name field if it exists if f := m.GetField("name"); f != nil { fields = append(fields, ``) } if f := m.GetField("email"); f != nil { fields = append(fields, ``) } if len(fields) == 0 { fields = append(fields, ``) } return fmt.Sprintf("\n %s\n", strings.Join(fields, "\n ")) } func generateDefaultKanbanView(m *orm.Model) string { nameField := "name" if f := m.GetField("name"); f == nil { nameField = "id" } return fmt.Sprintf(` `, nameField) }