Initial commit

This commit is contained in:
gsinghpal
2026-02-22 01:22:18 -05:00
commit 5200d5baf0
2394 changed files with 386834 additions and 0 deletions

View File

@@ -0,0 +1,201 @@
# -*- coding: utf-8 -*-
# Copyright 2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)
from datetime import datetime, timedelta
from odoo import api, fields, models
class RcCallDashboard(models.TransientModel):
_name = 'rc.call.dashboard'
_description = 'RingCentral Call Dashboard'
_rec_name = 'name'
name = fields.Char(default='Call Dashboard', readonly=True)
total_count = fields.Integer(compute='_compute_stats')
inbound_count = fields.Integer(compute='_compute_stats')
outbound_count = fields.Integer(compute='_compute_stats')
answered_count = fields.Integer(compute='_compute_stats')
missed_count = fields.Integer(compute='_compute_stats')
avg_duration = fields.Float(compute='_compute_stats', string='Avg Duration (min)')
success_rate = fields.Float(compute='_compute_stats', string='Success Rate (%)')
today_count = fields.Integer(compute='_compute_time_stats', string='Today')
week_count = fields.Integer(compute='_compute_time_stats', string='This Week')
month_count = fields.Integer(compute='_compute_time_stats', string='This Month')
voicemail_count = fields.Integer(compute='_compute_voicemail_stats')
unread_voicemail_count = fields.Integer(compute='_compute_voicemail_stats')
recent_call_ids = fields.Many2many(
'rc.call.history',
compute='_compute_recent_calls',
)
recent_voicemail_ids = fields.Many2many(
'rc.voicemail', 'rc_dashboard_recent_vm_rel',
compute='_compute_voicemail_lists',
)
older_voicemail_ids = fields.Many2many(
'rc.voicemail', 'rc_dashboard_older_vm_rel',
compute='_compute_voicemail_lists',
)
@api.depends_context('uid')
def _compute_stats(self):
Call = self.env['rc.call.history']
for rec in self:
all_calls = Call.search([])
rec.total_count = len(all_calls)
rec.inbound_count = Call.search_count([('direction', '=', 'inbound')])
rec.outbound_count = Call.search_count([('direction', '=', 'outbound')])
rec.answered_count = Call.search_count([('status', '=', 'answered')])
rec.missed_count = Call.search_count([('status', 'in', ('missed', 'no_answer'))])
durations = all_calls.mapped('duration')
rec.avg_duration = round(sum(durations) / len(durations) / 60, 1) if durations else 0.0
rec.success_rate = round(
(rec.answered_count / rec.total_count * 100) if rec.total_count else 0.0, 1
)
@api.depends_context('uid')
def _compute_time_stats(self):
Call = self.env['rc.call.history']
now = datetime.utcnow()
today_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
week_start = today_start - timedelta(days=today_start.weekday())
month_start = today_start.replace(day=1)
for rec in self:
rec.today_count = Call.search_count([('start_time', '>=', today_start)])
rec.week_count = Call.search_count([('start_time', '>=', week_start)])
rec.month_count = Call.search_count([('start_time', '>=', month_start)])
@api.depends_context('uid')
def _compute_recent_calls(self):
for rec in self:
rec.recent_call_ids = self.env['rc.call.history'].search([], limit=20)
@api.depends_context('uid')
def _compute_voicemail_lists(self):
VM = self.env['rc.voicemail']
one_week_ago = datetime.utcnow() - timedelta(days=7)
for rec in self:
rec.recent_voicemail_ids = VM.search([
('received_date', '>=', one_week_ago),
], limit=50)
rec.older_voicemail_ids = VM.search([
('received_date', '<', one_week_ago),
], limit=100)
@api.depends_context('uid')
def _compute_voicemail_stats(self):
VM = self.env['rc.voicemail']
for rec in self:
rec.voicemail_count = VM.search_count([])
rec.unread_voicemail_count = VM.search_count(
[('read_status', '=', 'Unread')],
)
# ──────────────────────────────────────────────────────────
# Navigation actions
# ──────────────────────────────────────────────────────────
def action_open_all(self):
return {
'type': 'ir.actions.act_window',
'name': 'Call History',
'res_model': 'rc.call.history',
'view_mode': 'list,form',
}
def action_open_inbound(self):
return {
'type': 'ir.actions.act_window',
'name': 'Inbound Calls',
'res_model': 'rc.call.history',
'view_mode': 'list,form',
'domain': [('direction', '=', 'inbound')],
}
def action_open_outbound(self):
return {
'type': 'ir.actions.act_window',
'name': 'Outbound Calls',
'res_model': 'rc.call.history',
'view_mode': 'list,form',
'domain': [('direction', '=', 'outbound')],
}
def action_open_missed(self):
return {
'type': 'ir.actions.act_window',
'name': 'Missed Calls',
'res_model': 'rc.call.history',
'view_mode': 'list,form',
'domain': [('status', 'in', ('missed', 'no_answer'))],
}
def action_open_graph(self):
return {
'type': 'ir.actions.act_window',
'name': 'Call Analytics',
'res_model': 'rc.call.history',
'view_mode': 'graph,pivot,list',
}
def action_open_voicemails(self):
return {
'type': 'ir.actions.act_window',
'name': 'Voicemails',
'res_model': 'rc.voicemail',
'view_mode': 'list,form',
}
def action_open_unread_voicemails(self):
return {
'type': 'ir.actions.act_window',
'name': 'Voicemails',
'res_model': 'rc.call.dashboard',
'view_mode': 'form',
'view_id': self.env.ref(
'fusion_ringcentral.view_rc_voicemail_dashboard_form',
).id,
'target': 'current',
}
# ──────────────────────────────────────────────────────────
# Quick action buttons (Call / Message / Fax)
# ──────────────────────────────────────────────────────────
def action_quick_call(self):
"""Open the RingCentral dialer via the Embeddable widget."""
return {
'type': 'ir.actions.act_window_close',
'infos': {
'rc_action': 'call',
'rc_phone_number': '',
},
}
def action_quick_sms(self):
"""Open the RingCentral SMS compose via the Embeddable widget."""
return {
'type': 'ir.actions.act_window_close',
'infos': {
'rc_action': 'sms',
'rc_phone_number': '',
},
}
def action_quick_fax(self):
"""Open the Send Fax wizard."""
return {
'type': 'ir.actions.act_window',
'name': 'Send Fax',
'res_model': 'fusion_faxes.send.fax.wizard',
'view_mode': 'form',
'target': 'new',
}