Implement Odoo Bus service for real-time communication

61 views Asked by At

I am having difficulties in setting up real-time communication for my Odoo app. I am still a newbie to javascript so I'm not sure if my javascript code is correct or not This is my odoo code:

class HospitalAppointment(models.Model):
    _name = 'hospital.appointment'
    _inherit = ['mail.thread', 'mail.activity.mixin']
    _description = 'Hospital Appointment'

    name = fields.Char(string='Order Ref', required=True, copy=False, readonly=True, index=True,
                       default=lambda self: _('New'))
    patient_id = fields.Many2one('hospital.patient', string='Patient', required=True)
    patient_age = fields.Integer(string='Age', related='patient_id.age')
    patient_gender = fields.Selection([
        ('male', 'Male'),
        ('female', 'Female')], string='Gender', compute="_compute_patient_gender", store=False)
    state = fields.Selection([
        ('draft', 'Draft'),
        ('confirm', 'Confirm'),
        ('done', 'Done'),
        ('cancel', 'Cancel')], string='Appointment Status', readonly=True, default='draft', tracking=True)
    note = fields.Text(string='Appointment Note')
    date_appointment = fields.Datetime(string='Date', required=True, tracking=True)
    doctor_id = fields.Many2one('hospital.doctor', string='Doctor', required=True, tracking=True)
    doctor_prescription = fields.Text(string='Prescription')
    doctor_prescription_lines = fields.One2many('appointment.prescription.lines', 'appointment_id', required=True, string='Prescription Lines')
    
    @api.model
    def create(self, vals):
        if vals.get('name', _('New')) == _('New'):
            vals['name'] = self.env['ir.sequence'].next_by_code('hospital.appointment') or _('New')

        doctor_app_count = self.env['hospital.appointment'].search_count(
            [('doctor_id', '=', vals.get('doctor_id'))]) + 1
        patient_app_count = self.env['hospital.appointment'].search_count(
            [('patient_id', '=', vals.get('patient_id'))]) + 1
        channel = (self._cr.dbname, 'appointment_notification', self.id)
        message = {
            'doctor_appointment_count': doctor_app_count,
            'patient_appointment_count': patient_app_count
        }
        self.env['bus.bus'].sendone(channel, message)
        print("Message sent!")
        result = super(HospitalAppointment, self).create(vals)
        return result


class Doctor(models.Model):
    _name = 'hospital.doctor'
    _inherit = ['mail.thread', 'mail.activity.mixin']
    _description = 'Hospital Doctor Information'

    reference = fields.Char(string='Order Reference', required=True, copy=False, readonly=True,
                            default=lambda self: _('New'))
    name = fields.Char(string='Name', required=True, tracking=True)
    age = fields.Integer(string='Age', tracking=True)
    gender = fields.Selection([
        ('male', 'Male'),
        ('female', 'Female'),
        ('other', 'Other')
    ], required=True, default='male', tracking=True)
    note = fields.Text(string='Description', tracking=True)
    image = fields.Binary(string='Patient Image', tracking=True)
    appointments = fields.One2many('hospital.appointment', 'doctor_id', string='Appointments')
    doctor_appointment_count = fields.Integer(string='Appointments count', compute='_compute_appointment_count', store=False)


class HospitalPatient(models.Model):
    _name = "hospital.patient"
    _inherit = ['mail.thread', 'mail.activity.mixin']
    _description = "Hospital Patient"

    name = fields.Char(string='Name', required=True, tracking=True)
    reference = fields.Char(string='Order Reference', required=True, copy=False, readonly=True,
                            default=lambda self: _('New'))
    age = fields.Integer(string='Age', required=True, tracking=True)
    gender = fields.Selection([
        ('male', 'Male'),
        ('female', 'Female')
    ], required=True, default='male', tracking=True)
    note = fields.Text(string='Description', tracking=True)
    state = fields.Selection([('draft', 'Draft'), ('confirmed', 'Confirm'), ('cancelled', 'Cancel')],
                             default='draft', string='Status', tracking=True)
    responsible_id = fields.Many2one('res.users', ondelete='set null', string='Responsible', tracking=True)
    appointments = fields.One2many('hospital.appointment', 'patient_id', string='Appointments')
    patient_appointment_count = fields.Integer(string='Appointments', compute='_compute_appointment_count', store=False)

XML:

    <record id="view_hospital_appointment_tree" model="ir.ui.view">
        <field name="name">hospital.appointment.view_tree</field>
        <field name="model">hospital.appointment</field>
        <field name="arch" type="xml">
            <tree string="view_hospital_appointment_tree" multi_edit="1">
                <field name="name"/>
                <field name="patient_id"/>
                <field name="patient_age"/>
                <field name="patient_gender"/>
                <field name="state"/>
                <field name="date_appointment"/>
                <field name="doctor_id"/>
            </tree>
        </field>
    </record>

    <record id="view_hospital_appointment_form" model="ir.ui.view">
        <field name="name">hospital.appointment.view_form</field>
        <field name="model">hospital.appointment</field>
        <field name="arch" type="xml">
            <form string="view_hospital_appointment_form">
                <header>
                    <button id="button_confirm" name="action_confirm" string="Confirm" states="draft"
                            confirm="Are you sure with your selection?" type="object" class="oe_highlight"/>
                    <button id="button_done" name="action_done" string="Mark as done" states="confirm"
                            confirm="Are you sure with your selection?" type="object" class="oe_highlight"/>
                    <button id="button_draft" name="action_draft" string="Set to Draft" states="cancel"
                            confirm="Are you sure with your selection?" type="object" class="oe_highlight"/>
                    <button id="button_cancel" name="action_cancel" string="Cancel" states="draft,confirm,done"
                            confirm="Are you sure with your selection?" type="object" />
                    <button name="action_url" string="Open URL" type="object" class="oe_highlight"/>
                    <field name="state" widget="statusbar"/>
                </header>
                <sheet>
                    <div class="oe_title">
                        <h1>
                            <field name="name" readonly="1"/>
                        </h1>
                    </div>
                    <group>
                        <group>
                            <field name="patient_id" options="{'no_create_edit': True}"/>
                            <field name="patient_age"/>
                            <field name="patient_gender"/>
                        </group>
                        <group>
                            <field name="date_appointment"/>
                            <field name="doctor_id" options="{'no_create': True}"/>
                            <field name="note"/>
                        </group>
                    </group>
                    <notebook>
                        <page string="Doctor's prescription">
                            <field name="doctor_prescription"/>
                        </page>
                        <page string="Medicines">
                            <field name="doctor_prescription_lines">
                                <tree editable="bottom">
                                    <field name="name"/>
                                    <field name="quantity"/>
                                </tree>
                                <form>
                                    <group>
                                        <field name="name"/>
                                    </group>
                                </form>
                            </field>
                        </page>
                    </notebook>
                </sheet>
                <div class="oe_chatter">
                    <field name="message_follower_ids" widget="mail_followers"/>
                    <field name="message_ids" widget="mail_thread"/>
                    <field name="activity_ids" widget="mail_activity"/>
                </div>
            </form>
        </field>
    </record>
    <record id="action_hospital_appointment" model="ir.actions.act_window">
        <field name="name">Appointments</field>
        <field name="type">ir.actions.act_window</field>
        <field name="res_model">hospital.appointment</field>
        <field name="view_mode">tree,form</field>
        <field name="context">{'default_note': 'New appointment created'}</field>
        <field name="help" type="html">
            <p class="o_view_nocontent_smiling_face">
                Click to Create New Appointment
            </p>
        </field>
    </record>

    <record id="action_hospital_patient" model="ir.actions.act_window">
        <field name="name">Patients</field>
        <field name="type">ir.actions.act_window</field>
        <field name="res_model">hospital.patient</field>
        <field name="view_mode">tree,form,kanban</field>
        <field name="context">{'default_note': 'New patient created'}</field>
        <field name="help" type="html">
            <p class="o_view_nocontent_smiling_face">
                Click to Create New Patient
            </p>
        </field>
    </record>

    <record id="view_hospital_patient_tree" model="ir.ui.view">
        <field name="name">hospital.patient.tree</field>
        <field name="model">hospital.patient</field>
        <field name="arch" type="xml">
            <tree string="Hospital Patient">
                <field name="name"/>
                <field name="age"/>
                <field name="gender"/>
                <field name="note"/>
                <field name="state"/>
                <field name="patient_appointment_count"/>
                <field name="responsible_id"/>
            </tree>
        </field>
    </record>
    <record id="action_hospital_doctors" model="ir.actions.act_window">
        <field name="name">Doctors</field>
        <field name="type">ir.actions.act_window</field>
        <field name="res_model">hospital.doctor</field>
        <field name="view_mode">tree,form,kanban</field>
        <field name="context">{'default_note': 'New doctor created'}</field>
        <field name="domain">[('age','&gt;',0)]</field>
        <field name="help" type="html">
            <p class="o_view_nocontent_smiling_face">
                Click to Create New Doctors
            </p>
        </field>
    </record>

    <record id="view_hospital_doctors_tree" model="ir.ui.view">
        <field name="name">hospital.doctor.tree</field>
        <field name="model">hospital.doctor</field>
        <field name="arch" type="xml">
            <tree sample="1">
                <field name="reference"/>
                <field name="name"/>
                <field name="age"/>
                <field name="gender"/>
                <field name="note"/>
                <field name="doctor_appointment_count"/>
            </tree>
        </field>
    </record>

views/assets_backend_inclusion.xml:

<odoo>
    <template id="assets_backend" name="hospital assets" inherit_id="web.assets_backend">
        <xpath expr="." position="inside">
            <script type="text/javascript" src="/om_hospital/static/src/js/AppointmentCountChange.js"></script>
        </xpath>
    </template>
</odoo>

This is my javascript code for the client:

odoo.define('om_hospital.AppointmentCountChange', function (require) {
    "use strict";

    var webClient = require('web.WebClient');
    var bus = require('bus.bus');

    webClient.include({
        start: function () {
            this._super.apply(this, arguments);
            bus.bus.on('appointment_notification', this, this._onNotification);
            bus.start_polling();
        },

        _onNotification: function (notifications) {
            var self = this;
            _.each(notifications, function (notification) {
                var channel = notification[0];
                var message = notification[1];
                if (channel[1] === 'appointment_notification') {
                    self.updateAppointmentCount(message.doctor_appointment_count, message.patient_appointment_count);
                }
            });
        },

        updateAppointmentCount: function (doctor_appointment_count, patient_appointment_count) {
            var doctorAppointmentCountElement = document.querySelector('.doctor_appointment_count .o_field_widget');
            var patientAppointmentCountElement = document.querySelector('.patient_appointment_count .o_field_widget');

            if (doctorAppointmentCountElement && patientAppointmentCountElement) {
                doctorAppointmentCountElement.textContent = doctor_appointment_count;
                doctorAppointmentCountElement.innerHTML = doctor_appointment_count;
                patientAppointmentCountElement.textContent = patient_appointment_count;
                patientAppointmentCountElement.innerHTML = patient_appointment_count;
                console.log(doctor_appointment_count);
                console.log(patient_appointment_count);
            }
        }
    });
});

This is my manifest.py:

{
    'name' : 'Hospital Management',
    'version' : '1.0',
    'summary': 'Hospital management',
    'sequence': 10,
    'description': """Hospital Management Software""",
    'category': 'Productivity',
    'depends' : ['sale', 'mail', 'bus'],
    'data': [
        'security/ir.model.access.csv',
        'data/data.xml',
        'wizard/create_appointment_view.xml',
        'views/appointments_view.xml',
        'views/patients_view.xml',
        'views/kids_view.xml',
        'views/doctors_view.xml',
        'views/sale.xml',
        'views/assets_backend_inclusion.xml',
    ],
    'demo': [],
    'qweb': [],
    'installable': True,
    'application': True,
    'auto_install': False,
    'license': 'LGPL-3',
}

I opened a tab to view and create a new appointment and a tab to view the doctor tree view. When creating a new appointment, the doctor_appointment_count didn't update in real time, I had to reload the doctor_appointment tree view.

Although i added the bus module in the list of depends in manifest file, the console log still printed out a message: "Missing dependencies: "bus.bus""

I hope that I can get some support.

0

There are 0 answers