package models import "odoo-go/pkg/orm" // initCRMLead registers the crm.lead model. // Mirrors: odoo/addons/crm/models/crm_lead.py func initCRMLead() { m := orm.NewModel("crm.lead", orm.ModelOpts{ Description: "Lead/Opportunity", Order: "priority desc, id desc", RecName: "name", }) m.AddFields( orm.Char("name", orm.FieldOpts{String: "Opportunity", Required: true, Index: true}), orm.Selection("type", []orm.SelectionItem{ {Value: "lead", Label: "Lead"}, {Value: "opportunity", Label: "Opportunity"}, }, orm.FieldOpts{String: "Type", Required: true, Default: "lead", Index: true}), orm.Many2one("partner_id", "res.partner", orm.FieldOpts{String: "Customer", Index: true}), orm.Char("partner_name", orm.FieldOpts{String: "Company Name"}), orm.Char("email_from", orm.FieldOpts{String: "Email", Index: true}), orm.Char("phone", orm.FieldOpts{String: "Phone"}), orm.Char("website", orm.FieldOpts{String: "Website"}), orm.Char("function", orm.FieldOpts{String: "Job Position"}), orm.Selection("state", []orm.SelectionItem{ {Value: "open", Label: "Open"}, {Value: "won", Label: "Won"}, {Value: "lost", Label: "Lost"}, }, orm.FieldOpts{String: "Status", Default: "open"}), orm.Many2one("stage_id", "crm.stage", orm.FieldOpts{String: "Stage", Index: true}), orm.Many2one("user_id", "res.users", orm.FieldOpts{String: "Salesperson", Index: true}), orm.Many2one("team_id", "crm.team", orm.FieldOpts{String: "Sales Team", Index: true}), orm.Monetary("expected_revenue", orm.FieldOpts{ String: "Expected Revenue", CurrencyField: "currency_id", }), orm.Monetary("recurring_revenue", orm.FieldOpts{ String: "Recurring Revenue", CurrencyField: "currency_id", }), orm.Selection("recurring_plan", []orm.SelectionItem{ {Value: "monthly", Label: "Monthly"}, {Value: "quarterly", Label: "Quarterly"}, {Value: "yearly", Label: "Yearly"}, }, orm.FieldOpts{String: "Recurring Plan"}), orm.Date("date_deadline", orm.FieldOpts{String: "Expected Closing"}), orm.Datetime("date_last_stage_update", orm.FieldOpts{String: "Last Stage Update"}), orm.Selection("priority", []orm.SelectionItem{ {Value: "0", Label: "Normal"}, {Value: "1", Label: "Low"}, {Value: "2", Label: "High"}, {Value: "3", Label: "Very High"}, }, orm.FieldOpts{String: "Priority", Default: "0"}), orm.Integer("color", orm.FieldOpts{String: "Color Index"}), orm.Many2many("tag_ids", "crm.tag", orm.FieldOpts{String: "Tags"}), orm.Many2one("company_id", "res.company", orm.FieldOpts{ String: "Company", Index: true, }), orm.Many2one("currency_id", "res.currency", orm.FieldOpts{String: "Currency"}), orm.Float("probability", orm.FieldOpts{String: "Probability (%)"}), orm.Boolean("active", orm.FieldOpts{String: "Active", Default: true}), orm.Text("description", orm.FieldOpts{String: "Notes"}), orm.Many2one("lost_reason_id", "crm.lost.reason", orm.FieldOpts{String: "Lost Reason"}), // Address fields orm.Char("city", orm.FieldOpts{String: "City"}), orm.Char("street", orm.FieldOpts{String: "Street"}), orm.Char("zip", orm.FieldOpts{String: "Zip"}), orm.Many2one("country_id", "res.country", orm.FieldOpts{String: "Country"}), ) // DefaultGet: set company_id from the session so that DB NOT NULL constraint is satisfied m.DefaultGet = func(env *orm.Environment, fields []string) orm.Values { vals := make(orm.Values) if env.CompanyID() > 0 { vals["company_id"] = env.CompanyID() } return vals } // action_set_won: mark lead as won m.RegisterMethod("action_set_won", func(rs *orm.Recordset, args ...interface{}) (interface{}, error) { env := rs.Env() for _, id := range rs.IDs() { env.Tx().Exec(env.Ctx(), `UPDATE crm_lead SET state = 'won', probability = 100 WHERE id = $1`, id) } return true, nil }) // action_set_lost: mark lead as lost m.RegisterMethod("action_set_lost", func(rs *orm.Recordset, args ...interface{}) (interface{}, error) { env := rs.Env() for _, id := range rs.IDs() { env.Tx().Exec(env.Ctx(), `UPDATE crm_lead SET state = 'lost', probability = 0, active = false WHERE id = $1`, id) } return true, nil }) // convert_to_opportunity: lead → opportunity m.RegisterMethod("convert_to_opportunity", func(rs *orm.Recordset, args ...interface{}) (interface{}, error) { env := rs.Env() for _, id := range rs.IDs() { env.Tx().Exec(env.Ctx(), `UPDATE crm_lead SET type = 'opportunity' WHERE id = $1 AND type = 'lead'`, id) } return true, nil }) // convert_opportunity: alias for convert_to_opportunity m.RegisterMethod("convert_opportunity", func(rs *orm.Recordset, args ...interface{}) (interface{}, error) { env := rs.Env() for _, id := range rs.IDs() { env.Tx().Exec(env.Ctx(), `UPDATE crm_lead SET type = 'opportunity' WHERE id = $1`, id) } return true, nil }) // action_set_won_rainbowman: set won stage + rainbow effect m.RegisterMethod("action_set_won_rainbowman", func(rs *orm.Recordset, args ...interface{}) (interface{}, error) { env := rs.Env() // Find Won stage var wonStageID int64 env.Tx().QueryRow(env.Ctx(), `SELECT id FROM crm_stage WHERE is_won = true LIMIT 1`).Scan(&wonStageID) if wonStageID == 0 { wonStageID = 4 // fallback } for _, id := range rs.IDs() { env.Tx().Exec(env.Ctx(), `UPDATE crm_lead SET stage_id = $1, probability = 100 WHERE id = $2`, wonStageID, id) } return map[string]interface{}{ "effect": map[string]interface{}{ "type": "rainbow_man", "message": "Congrats, you won this opportunity!", }, }, nil }) } // initCRMStage registers the crm.stage model. // Mirrors: odoo/addons/crm/models/crm_stage.py func initCRMStage() { m := orm.NewModel("crm.stage", orm.ModelOpts{ Description: "CRM Stage", Order: "sequence, name, id", }) m.AddFields( orm.Char("name", orm.FieldOpts{String: "Stage Name", Required: true, Translate: true}), orm.Integer("sequence", orm.FieldOpts{String: "Sequence", Default: 1}), orm.Boolean("fold", orm.FieldOpts{String: "Folded in Pipeline"}), orm.Boolean("is_won", orm.FieldOpts{String: "Is Won Stage"}), orm.Many2many("team_ids", "crm.team", orm.FieldOpts{String: "Sales Teams"}), orm.Text("requirements", orm.FieldOpts{String: "Requirements"}), ) } // initCRMTeam registers the crm.team model. // Mirrors: odoo/addons/crm/models/crm_team.py func initCRMTeam() { m := orm.NewModel("crm.team", orm.ModelOpts{ Description: "Sales Team", Order: "sequence, name", }) m.AddFields( orm.Char("name", orm.FieldOpts{String: "Sales Team", Required: true, Translate: true}), orm.Integer("sequence", orm.FieldOpts{String: "Sequence", Default: 10}), orm.Many2one("company_id", "res.company", orm.FieldOpts{ String: "Company", Index: true, }), orm.Many2many("member_ids", "res.users", orm.FieldOpts{String: "Channel Members"}), orm.Integer("color", orm.FieldOpts{String: "Color Index"}), orm.Boolean("active", orm.FieldOpts{String: "Active", Default: true}), ) } // initCRMTag registers the crm.tag model. // Mirrors: odoo/addons/crm/models/crm_lead.py CrmTag func initCRMTag() { orm.NewModel("crm.tag", orm.ModelOpts{ Description: "CRM Tag", Order: "name", }).AddFields( orm.Char("name", orm.FieldOpts{String: "Tag Name", Required: true, Translate: true}), orm.Integer("color", orm.FieldOpts{String: "Color Index"}), ) } // initCRMLostReason registers the crm.lost.reason model. // Mirrors: odoo/addons/crm/models/crm_lost_reason.py func initCRMLostReason() { orm.NewModel("crm.lost.reason", orm.ModelOpts{ Description: "Opp. Lost Reason", Order: "name", }).AddFields( orm.Char("name", orm.FieldOpts{String: "Description", Required: true, Translate: true}), orm.Boolean("active", orm.FieldOpts{String: "Active", Default: true}), ) }