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:
Marc
2026-04-12 18:41:57 +02:00
parent 2c7c1e6c88
commit 66383adf06
87 changed files with 14696 additions and 654 deletions

View File

@@ -1,6 +1,10 @@
package models
import "odoo-go/pkg/orm"
import (
"fmt"
"odoo-go/pkg/orm"
)
// initPurchaseAgreement registers purchase.requisition and purchase.requisition.line.
// Mirrors: odoo/addons/purchase_requisition/models/purchase_requisition.py
@@ -35,28 +39,32 @@ func initPurchaseAgreement() {
m.RegisterMethod("action_confirm", func(rs *orm.Recordset, args ...interface{}) (interface{}, error) {
env := rs.Env()
for _, id := range rs.IDs() {
env.Tx().Exec(env.Ctx(),
`UPDATE purchase_requisition SET state = 'ongoing' WHERE id = $1 AND state = 'draft'`, id)
if _, err := env.Tx().Exec(env.Ctx(),
`UPDATE purchase_requisition SET state = 'ongoing' WHERE id = $1 AND state = 'draft'`, id); err != nil {
return nil, fmt.Errorf("purchase.requisition: confirm %d: %w", id, err)
}
}
return true, nil
})
// action_done: close the agreement
m.RegisterMethod("action_done", func(rs *orm.Recordset, args ...interface{}) (interface{}, error) {
env := rs.Env()
for _, id := range rs.IDs() {
env.Tx().Exec(env.Ctx(),
`UPDATE purchase_requisition SET state = 'done' WHERE id = $1`, id)
if _, err := env.Tx().Exec(env.Ctx(),
`UPDATE purchase_requisition SET state = 'done' WHERE id = $1`, id); err != nil {
return nil, fmt.Errorf("purchase.requisition: done %d: %w", id, err)
}
}
return true, nil
})
// action_cancel
m.RegisterMethod("action_cancel", func(rs *orm.Recordset, args ...interface{}) (interface{}, error) {
env := rs.Env()
for _, id := range rs.IDs() {
env.Tx().Exec(env.Ctx(),
`UPDATE purchase_requisition SET state = 'cancel' WHERE id = $1`, id)
if _, err := env.Tx().Exec(env.Ctx(),
`UPDATE purchase_requisition SET state = 'cancel' WHERE id = $1`, id); err != nil {
return nil, fmt.Errorf("purchase.requisition: cancel %d: %w", id, err)
}
}
return true, nil
})