Add _inherit (ExtendModel) + Inverse fields + sale extends partner
ORM: - ExtendModel(name) retrieves existing model for extension (mirrors Python _inherit without _name). Panics on missing model. - RegisterInverse(fieldName, fn) convenience for computed write-back - Inverse field handling in Write(): caches new value, calls inverse method so computed fields can be written back Sale module: - Extends res.partner with sale_order_ids (O2M) and sale_order_count (computed) via ExtendModel — demonstrates real _inherit pattern Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -393,6 +393,31 @@ func (rs *Recordset) Write(vals Values) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Handle inverse fields (write-back for computed fields).
|
||||
// Mirrors: odoo/orm/fields.py Field.inverse
|
||||
//
|
||||
// When a computed field with an Inverse method is written to, the inverse
|
||||
// method is called so it can propagate the value to the underlying fields.
|
||||
// In Python Odoo, the inverse method reads self.field_name from cache (which
|
||||
// has the new value). We replicate this by caching the new value before calling.
|
||||
for fieldName := range vals {
|
||||
f := m.GetField(fieldName)
|
||||
if f == nil || f.Inverse == "" {
|
||||
continue
|
||||
}
|
||||
inverseMethod, ok := m.Methods[f.Inverse]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
// Cache the new value so the inverse method can read it via Get()
|
||||
for _, id := range rs.ids {
|
||||
rs.env.cache.Set(m.Name(), id, fieldName, vals[fieldName])
|
||||
}
|
||||
if _, err := inverseMethod(rs); err != nil {
|
||||
return fmt.Errorf("orm: inverse %s.%s: %w", m.name, f.Inverse, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger recompute for stored computed fields that depend on written fields
|
||||
if err := TriggerRecompute(rs, vals); err != nil {
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user