Backend improvements: views, fields_get, session, RPC stubs

- Improved auto-generated list/form/search views with priority fields,
  two-column form layout, statusbar widget, notebook for O2M fields
- Enhanced fields_get with currency_field, compute, related metadata
- Fixed session handling: handleSessionInfo/handleSessionCheck use real
  session from cookie instead of hardcoded values
- Added read_progress_bar and activity_format RPC stubs
- Improved bootstrap translations with lang_parameters
- Added "contacts" to session modules list

Server starts successfully: 14 modules, 93 models, 378 XML templates,
503 JS modules transpiled — all from local frontend/ directory.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marc
2026-03-31 23:16:26 +02:00
parent 8741282322
commit 9c444061fd
32 changed files with 3416 additions and 148 deletions

View File

@@ -53,7 +53,7 @@ func initCRMLead() {
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", Required: true, Index: true,
String: "Company", Index: true,
}),
orm.Many2one("currency_id", "res.currency", orm.FieldOpts{String: "Currency"}),
orm.Float("probability", orm.FieldOpts{String: "Probability (%)"}),
@@ -66,6 +66,45 @@ func initCRMLead() {
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
})
}
// initCRMStage registers the crm.stage model.