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

@@ -38,8 +38,11 @@ func initAccountLock() {
)
// _compute_string_to_hash: generates the string representation of the move
// used for hash computation. Includes date, journal, partner, amounts.
// used for hash computation. Includes date, journal, partner, amounts, and company VAT.
// Mirrors: odoo/addons/account/models/account_move.py _compute_string_to_hash()
//
// The company VAT is included to ensure entries from different legal entities
// produce distinct hashes even when all other fields match.
ext.RegisterCompute("string_to_hash", func(rs *orm.Recordset) (orm.Values, error) {
env := rs.Env()
moveID := rs.IDs()[0]
@@ -54,6 +57,17 @@ func initAccountLock() {
FROM account_move WHERE id = $1`, moveID,
).Scan(&name, &moveType, &state, &date, &companyID, &journalID, &partnerID)
// Fetch company VAT for inclusion in the hash
var companyVAT string
if companyID > 0 {
env.Tx().QueryRow(env.Ctx(),
`SELECT COALESCE(p.vat, '')
FROM res_company c
LEFT JOIN res_partner p ON p.id = c.partner_id
WHERE c.id = $1`, companyID,
).Scan(&companyVAT)
}
// Include line amounts
rows, err := env.Tx().Query(env.Ctx(),
`SELECT COALESCE(account_id, 0), COALESCE(debit::float8, 0), COALESCE(credit::float8, 0),
@@ -78,9 +92,9 @@ func initAccountLock() {
pid = *partnerID
}
hashStr := fmt.Sprintf("%s|%s|%v|%d|%d|%d|%s",
hashStr := fmt.Sprintf("%s|%s|%v|%d|%d|%d|%s|%s",
name, moveType, date, companyID, journalID, pid,
strings.Join(lineData, ";"))
strings.Join(lineData, ";"), companyVAT)
return orm.Values{"string_to_hash": hashStr}, nil
})