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:
@@ -2,6 +2,7 @@ package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"odoo-go/pkg/orm"
|
||||
)
|
||||
@@ -73,12 +74,14 @@ func initCrmAnalysis() {
|
||||
|
||||
// Win rate
|
||||
var total, won int64
|
||||
_ = env.Tx().QueryRow(env.Ctx(),
|
||||
if err := env.Tx().QueryRow(env.Ctx(),
|
||||
`SELECT COUNT(*), COALESCE(SUM(CASE WHEN s.is_won THEN 1 ELSE 0 END), 0)
|
||||
FROM crm_lead l
|
||||
JOIN crm_stage s ON s.id = l.stage_id
|
||||
WHERE l.type = 'opportunity'`,
|
||||
).Scan(&total, &won)
|
||||
).Scan(&total, &won); err != nil {
|
||||
log.Printf("warning: crm win rate query failed: %v", err)
|
||||
}
|
||||
|
||||
winRate := float64(0)
|
||||
if total > 0 {
|
||||
@@ -99,12 +102,14 @@ func initCrmAnalysis() {
|
||||
env := rs.Env()
|
||||
|
||||
var totalLeads, convertedLeads int64
|
||||
_ = env.Tx().QueryRow(env.Ctx(), `
|
||||
if err := env.Tx().QueryRow(env.Ctx(), `
|
||||
SELECT
|
||||
COUNT(*) FILTER (WHERE type = 'lead'),
|
||||
COUNT(*) FILTER (WHERE type = 'opportunity' AND date_conversion IS NOT NULL)
|
||||
FROM crm_lead WHERE active = true`,
|
||||
).Scan(&totalLeads, &convertedLeads)
|
||||
).Scan(&totalLeads, &convertedLeads); err != nil {
|
||||
log.Printf("warning: crm conversion data query failed: %v", err)
|
||||
}
|
||||
|
||||
conversionRate := float64(0)
|
||||
if totalLeads > 0 {
|
||||
@@ -113,19 +118,23 @@ func initCrmAnalysis() {
|
||||
|
||||
// Average days to convert
|
||||
var avgDaysConvert float64
|
||||
_ = env.Tx().QueryRow(env.Ctx(), `
|
||||
if err := env.Tx().QueryRow(env.Ctx(), `
|
||||
SELECT COALESCE(AVG(EXTRACT(EPOCH FROM (date_conversion - create_date)) / 86400), 0)
|
||||
FROM crm_lead
|
||||
WHERE type = 'opportunity' AND date_conversion IS NOT NULL AND active = true`,
|
||||
).Scan(&avgDaysConvert)
|
||||
).Scan(&avgDaysConvert); err != nil {
|
||||
log.Printf("warning: crm avg days to convert query failed: %v", err)
|
||||
}
|
||||
|
||||
// Average days to close (won)
|
||||
var avgDaysClose float64
|
||||
_ = env.Tx().QueryRow(env.Ctx(), `
|
||||
if err := env.Tx().QueryRow(env.Ctx(), `
|
||||
SELECT COALESCE(AVG(EXTRACT(EPOCH FROM (date_closed - create_date)) / 86400), 0)
|
||||
FROM crm_lead
|
||||
WHERE state = 'won' AND date_closed IS NOT NULL`,
|
||||
).Scan(&avgDaysClose)
|
||||
).Scan(&avgDaysClose); err != nil {
|
||||
log.Printf("warning: crm avg days to close query failed: %v", err)
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"total_leads": totalLeads,
|
||||
|
||||
Reference in New Issue
Block a user