feat: Portal, Email Inbound, Discuss + module improvements
- Portal: /my/* routes, signup, password reset, portal user support - Email Inbound: IMAP polling (go-imap/v2), thread matching - Discuss: mail.channel, long-polling bus, DM, unread count - Cron: ir.cron runner (goroutine scheduler) - Bank Import, CSV/Excel Import - Automation (ir.actions.server) - Fetchmail service - HR Payroll model - Various fixes across account, sale, stock, purchase, crm, hr, project Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
@@ -296,3 +297,73 @@ func applyWriteoffSuggestion(env *orm.Environment, modelID, stLineID int64, amou
|
||||
"suggestions": suggestions,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// initAccountReconcilePreview registers account.reconcile.model.preview (Odoo 18+).
|
||||
// Transient model for previewing reconciliation results before applying.
|
||||
// Mirrors: odoo/addons/account/wizard/account_reconcile_model_preview.py
|
||||
func initAccountReconcilePreview() {
|
||||
m := orm.NewModel("account.reconcile.model.preview", orm.ModelOpts{
|
||||
Description: "Reconcile Model Preview",
|
||||
Type: orm.ModelTransient,
|
||||
})
|
||||
|
||||
m.AddFields(
|
||||
orm.Many2one("model_id", "account.reconcile.model", orm.FieldOpts{
|
||||
String: "Reconcile Model", Required: true,
|
||||
}),
|
||||
orm.Many2one("statement_line_id", "account.bank.statement.line", orm.FieldOpts{
|
||||
String: "Statement Line",
|
||||
}),
|
||||
orm.Text("preview_data", orm.FieldOpts{
|
||||
String: "Preview Data", Compute: "_compute_preview",
|
||||
}),
|
||||
)
|
||||
|
||||
m.RegisterCompute("preview_data", func(rs *orm.Recordset) (orm.Values, error) {
|
||||
env := rs.Env()
|
||||
id := rs.IDs()[0]
|
||||
|
||||
var modelID int64
|
||||
var stLineID *int64
|
||||
env.Tx().QueryRow(env.Ctx(),
|
||||
`SELECT COALESCE(model_id, 0), statement_line_id
|
||||
FROM account_reconcile_model_preview WHERE id = $1`, id,
|
||||
).Scan(&modelID, &stLineID)
|
||||
|
||||
if modelID == 0 {
|
||||
return orm.Values{"preview_data": "[]"}, nil
|
||||
}
|
||||
|
||||
// Read reconcile model lines to preview what would be created
|
||||
rows, err := env.Tx().Query(env.Ctx(),
|
||||
`SELECT rml.label, rml.amount_type, rml.amount,
|
||||
COALESCE(a.code, ''), COALESCE(a.name, '')
|
||||
FROM account_reconcile_model_line rml
|
||||
LEFT JOIN account_account a ON a.id = rml.account_id
|
||||
WHERE rml.model_id = $1
|
||||
ORDER BY rml.sequence`, modelID)
|
||||
if err != nil {
|
||||
return orm.Values{"preview_data": "[]"}, nil
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var preview []map[string]interface{}
|
||||
for rows.Next() {
|
||||
var label, amountType, accCode, accName string
|
||||
var amount float64
|
||||
if err := rows.Scan(&label, &amountType, &amount, &accCode, &accName); err != nil {
|
||||
continue
|
||||
}
|
||||
preview = append(preview, map[string]interface{}{
|
||||
"label": label,
|
||||
"amount_type": amountType,
|
||||
"amount": amount,
|
||||
"account_code": accCode,
|
||||
"account_name": accName,
|
||||
})
|
||||
}
|
||||
|
||||
data, _ := json.Marshal(preview)
|
||||
return orm.Values{"preview_data": string(data)}, nil
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user