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

@@ -315,7 +315,7 @@ func generateInvoiceXML(env *orm.Environment, moveID int64, formatCode string) (
IssueDate: issueDateStr,
DueDate: dueDateStr,
InvoiceTypeCode: typeCode,
DocumentCurrencyCode: "EUR",
DocumentCurrencyCode: getCurrencyCode(env, moveID),
Supplier: UBLParty{
Name: companyName,
Street: ptrStr(companyStreet),
@@ -356,6 +356,19 @@ func generateInvoiceXML(env *orm.Environment, moveID int64, formatCode string) (
return b.String(), nil
}
// getCurrencyCode returns the ISO currency code for an invoice, defaulting to "EUR".
func getCurrencyCode(env *orm.Environment, moveID int64) string {
var code string
env.Tx().QueryRow(env.Ctx(),
`SELECT COALESCE(c.name, 'EUR') FROM account_move m
JOIN res_currency c ON c.id = m.currency_id
WHERE m.id = $1`, moveID).Scan(&code)
if code == "" {
return "EUR"
}
return code
}
// ptrStr safely dereferences a *string, returning "" if nil.
func ptrStr(s *string) string {
if s != nil {