Fix P0-P2 bugs: sale.order M2M, display_name, DefaultGet
P0: Fix sale.order creation (was completely broken) - Corrected M2M junction table name from sale_order_line_account_tax_rel to account_tax_sale_order_line_rel (ORM sorts alphabetically) - Added fallback in BeforeCreate if sequence generation fails P1: Add display_name as magic field on ALL models - Added to addMagicFields() in pkg/orm/model.go (like Python BaseModel) - Computed on-the-fly in Read() from recName field, no DB column - Removed explicit display_name from res.partner (now auto-inherited) P2: Add DefaultGet hooks for sale.order and purchase.order - Sets company_id, currency_id, date_order/date_planned from environment - Follows same pattern as account.move's DefaultGet Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -129,6 +129,13 @@ func (m *Model) addMagicFields() {
|
||||
Readonly: true,
|
||||
}))
|
||||
|
||||
// display_name: computed on-the-fly from rec_name, not stored in DB.
|
||||
// Mirrors: odoo/orm/models.py BaseModel.display_name (computed field on ALL models)
|
||||
m.AddField(Char("display_name", FieldOpts{
|
||||
String: "Display Name",
|
||||
Compute: "_compute_display_name",
|
||||
}))
|
||||
|
||||
if m.logAccess {
|
||||
m.AddField(Many2one("create_uid", "res.users", FieldOpts{
|
||||
String: "Created by",
|
||||
|
||||
@@ -349,12 +349,17 @@ func (rs *Recordset) Read(fields []string) ([]Values, error) {
|
||||
var storedFields []string // Fields that come from the DB query
|
||||
var m2mFields []string // Many2many fields (from junction table)
|
||||
var relatedFields []string // Related fields (from joined table)
|
||||
wantDisplayName := false // Whether display_name was requested
|
||||
|
||||
for _, name := range fields {
|
||||
f := m.GetField(name)
|
||||
if f == nil {
|
||||
return nil, fmt.Errorf("orm: field %q not found on %s", name, m.name)
|
||||
}
|
||||
if name == "display_name" && f.Compute != "" && !f.Store {
|
||||
wantDisplayName = true
|
||||
continue
|
||||
}
|
||||
if f.Type == TypeMany2many {
|
||||
m2mFields = append(m2mFields, name)
|
||||
} else if f.Related != "" && !f.Store {
|
||||
@@ -365,6 +370,25 @@ func (rs *Recordset) Read(fields []string) ([]Values, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// If display_name is requested, ensure the rec_name field is fetched from DB
|
||||
recName := m.recName
|
||||
if wantDisplayName {
|
||||
recNameAlreadyFetched := false
|
||||
for _, sf := range storedFields {
|
||||
if sf == recName {
|
||||
recNameAlreadyFetched = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !recNameAlreadyFetched {
|
||||
recF := m.GetField(recName)
|
||||
if recF != nil && recF.IsStored() {
|
||||
columns = append(columns, fmt.Sprintf("%q", recF.Column()))
|
||||
storedFields = append(storedFields, recName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build query
|
||||
var args []interface{}
|
||||
idPlaceholders := make([]string, len(rs.ids))
|
||||
@@ -426,6 +450,25 @@ func (rs *Recordset) Read(fields []string) ([]Values, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Post-fetch: compute display_name from the rec_name field value.
|
||||
// Mirrors: odoo/orm/models.py BaseModel._compute_display_name()
|
||||
if wantDisplayName {
|
||||
for _, rec := range results {
|
||||
if nameVal, ok := rec[recName]; ok {
|
||||
switch v := nameVal.(type) {
|
||||
case string:
|
||||
rec["display_name"] = v
|
||||
case nil:
|
||||
rec["display_name"] = ""
|
||||
default:
|
||||
rec["display_name"] = fmt.Sprintf("%v", v)
|
||||
}
|
||||
} else {
|
||||
rec["display_name"] = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Post-fetch: M2M fields (from junction tables)
|
||||
if len(m2mFields) > 0 && len(rs.ids) > 0 {
|
||||
for _, fname := range m2mFields {
|
||||
|
||||
Reference in New Issue
Block a user