package models import "odoo-go/pkg/orm" // initIrModel registers ir.model and ir.model.fields — Odoo's model metadata. // Mirrors: odoo/addons/base/models/ir_model.py // // These meta-models describe all other models at runtime. // They are the foundation for dynamic field access, view generation, and access control. func initIrModel() { // ir.model — Model metadata m := orm.NewModel("ir.model", orm.ModelOpts{ Description: "Models", Order: "model", RecName: "name", }) m.AddFields( orm.Char("name", orm.FieldOpts{String: "Model Description", Required: true, Translate: true}), orm.Char("model", orm.FieldOpts{String: "Model", Required: true, Index: true}), orm.Char("info", orm.FieldOpts{String: "Information"}), orm.One2many("field_id", "ir.model.fields", "model_id", orm.FieldOpts{String: "Fields"}), orm.One2many("access_ids", "ir.model.access", "model_id", orm.FieldOpts{String: "Access"}), orm.One2many("rule_ids", "ir.rule", "model_id", orm.FieldOpts{String: "Record Rules"}), orm.Char("state", orm.FieldOpts{String: "Type", Default: "base"}), orm.Boolean("transient", orm.FieldOpts{String: "Transient Model"}), orm.Many2many("group_ids", "res.groups", orm.FieldOpts{String: "Groups"}), ) // ir.model.fields — Field metadata f := orm.NewModel("ir.model.fields", orm.ModelOpts{ Description: "Fields", Order: "model_id, name", RecName: "name", }) f.AddFields( orm.Char("name", orm.FieldOpts{String: "Field Name", Required: true, Index: true}), orm.Char("field_description", orm.FieldOpts{String: "Field Label", Translate: true}), orm.Many2one("model_id", "ir.model", orm.FieldOpts{ String: "Model", Required: true, OnDelete: orm.OnDeleteCascade, Index: true, }), orm.Char("model", orm.FieldOpts{String: "Model Name", Related: "model_id.model"}), orm.Selection("ttype", []orm.SelectionItem{ {Value: "char", Label: "Char"}, {Value: "text", Label: "Text"}, {Value: "html", Label: "Html"}, {Value: "integer", Label: "Integer"}, {Value: "float", Label: "Float"}, {Value: "monetary", Label: "Monetary"}, {Value: "boolean", Label: "Boolean"}, {Value: "date", Label: "Date"}, {Value: "datetime", Label: "Datetime"}, {Value: "binary", Label: "Binary"}, {Value: "selection", Label: "Selection"}, {Value: "many2one", Label: "Many2one"}, {Value: "one2many", Label: "One2many"}, {Value: "many2many", Label: "Many2many"}, {Value: "reference", Label: "Reference"}, }, orm.FieldOpts{String: "Field Type", Required: true}), orm.Char("relation", orm.FieldOpts{String: "Related Model"}), orm.Char("relation_field", orm.FieldOpts{String: "Relation Field"}), orm.Boolean("required", orm.FieldOpts{String: "Required"}), orm.Boolean("readonly", orm.FieldOpts{String: "Readonly"}), orm.Boolean("index", orm.FieldOpts{String: "Indexed"}), orm.Boolean("store", orm.FieldOpts{String: "Stored", Default: true}), orm.Char("compute", orm.FieldOpts{String: "Compute"}), orm.Char("depends", orm.FieldOpts{String: "Dependencies"}), orm.Text("help", orm.FieldOpts{String: "Field Help"}), orm.Char("state", orm.FieldOpts{String: "Type", Default: "base"}), orm.Integer("size", orm.FieldOpts{String: "Size"}), orm.Char("on_delete", orm.FieldOpts{String: "On Delete", Default: "set null"}), orm.Boolean("translate", orm.FieldOpts{String: "Translatable"}), orm.Text("selection_ids", orm.FieldOpts{String: "Selection Options"}), orm.Char("copied", orm.FieldOpts{String: "Copied", Default: "1"}), orm.Many2many("group_ids", "res.groups", orm.FieldOpts{String: "Groups"}), ) // ir.module.category — Module categories for group organization orm.NewModel("ir.module.category", orm.ModelOpts{ Description: "Application", Order: "name", }).AddFields( orm.Char("name", orm.FieldOpts{String: "Name", Required: true, Translate: true}), orm.Many2one("parent_id", "ir.module.category", orm.FieldOpts{String: "Parent Application"}), orm.One2many("child_ids", "ir.module.category", "parent_id", orm.FieldOpts{String: "Child Applications"}), orm.Integer("sequence", orm.FieldOpts{String: "Sequence"}), orm.Boolean("visible", orm.FieldOpts{String: "Visible", Default: true}), ) } // initIrModelAccess registers ir.model.access — Object-level ACLs. // Mirrors: odoo/addons/base/models/ir_model.py class IrModelAccess // // Access is defined as CSV in each module: // // id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink // access_res_partner,res.partner,model_res_partner,base.group_user,1,1,1,0 func initIrModelAccess() { m := orm.NewModel("ir.model.access", orm.ModelOpts{ Description: "Access Controls", Order: "model_id, group_id", }) m.AddFields( orm.Char("name", orm.FieldOpts{String: "Name", Required: true, Index: true}), orm.Many2one("model_id", "ir.model", orm.FieldOpts{ String: "Model", Required: true, OnDelete: orm.OnDeleteCascade, Index: true, }), orm.Many2one("group_id", "res.groups", orm.FieldOpts{ String: "Group", OnDelete: orm.OnDeleteRestrict, Index: true, }), orm.Boolean("perm_read", orm.FieldOpts{String: "Read Access"}), orm.Boolean("perm_write", orm.FieldOpts{String: "Write Access"}), orm.Boolean("perm_create", orm.FieldOpts{String: "Create Access"}), orm.Boolean("perm_unlink", orm.FieldOpts{String: "Delete Access"}), orm.Boolean("active", orm.FieldOpts{String: "Active", Default: true}), ) } // initIrRule registers ir.rule — Record-level access rules. // Mirrors: odoo/addons/base/models/ir_rule.py class IrRule // // Record rules add WHERE clause filters per user/group: // // Rule: domain = [('company_id', 'in', company_ids)] // → User can only see records of their companies func initIrRule() { m := orm.NewModel("ir.rule", orm.ModelOpts{ Description: "Record Rule", Order: "model_id, name", }) m.AddFields( orm.Char("name", orm.FieldOpts{String: "Name"}), orm.Boolean("active", orm.FieldOpts{String: "Active", Default: true}), orm.Many2one("model_id", "ir.model", orm.FieldOpts{ String: "Model", Required: true, OnDelete: orm.OnDeleteCascade, Index: true, }), orm.Many2many("groups", "res.groups", orm.FieldOpts{String: "Groups"}), orm.Text("domain_force", orm.FieldOpts{String: "Domain"}), orm.Boolean("perm_read", orm.FieldOpts{String: "Apply for Read", Default: true}), orm.Boolean("perm_write", orm.FieldOpts{String: "Apply for Write", Default: true}), orm.Boolean("perm_create", orm.FieldOpts{String: "Apply for Create", Default: true}), orm.Boolean("perm_unlink", orm.FieldOpts{String: "Apply for Delete", Default: true}), orm.Boolean("global", orm.FieldOpts{ String: "Global", Compute: "_compute_global", Store: true, Help: "If no group is specified, the rule is global and applied to everyone", }), ) } // initIrModelData registers ir.model.data — External identifiers (XML IDs). // Mirrors: odoo/addons/base/models/ir_model.py class IrModelData // // Maps module.xml_id → (model, res_id) for referencing records across modules. // Example: 'base.main_company' → res.company(1) func initIrModelData() { m := orm.NewModel("ir.model.data", orm.ModelOpts{ Description: "External Identifiers", Order: "module, name", RecName: "complete_name", }) m.AddFields( orm.Char("name", orm.FieldOpts{String: "External Identifier", Required: true, Index: true}), orm.Char("complete_name", orm.FieldOpts{String: "Complete ID", Compute: "_compute_complete_name"}), orm.Char("module", orm.FieldOpts{String: "Module", Required: true, Index: true, Default: ""}), orm.Char("model", orm.FieldOpts{String: "Model Name", Required: true}), orm.Integer("res_id", orm.FieldOpts{String: "Record ID", Index: true}), orm.Boolean("noupdate", orm.FieldOpts{String: "Non Updatable", Default: false}), ) }