0

I am working on some website modifications on the appointment module to change some behaviors. What I am trying to do is make it able to choose more than one appointment in (/calendar/<appointment_type>) before sending the user to the confirmation form. The original functionality is works by sending the user to confirm his appointment by clicking on any hour button he choose, First I have tried to inherit and replace the XML snippet (calendar_appointment_slots.xml) which is concerned with giving an href for each hour button by ones that don't have an href. This is the original XML code

<?xml version="1.0" encoding="UTF-8"?>
<template>
    <t t-name="appointment.slots_list">
        <h5 class="text-center" t-out="slotDate"/>
        <div class="o_slots_list row">
            <t t-foreach="slots" t-as="slot">
                <div class="col-md-6 col-12 mt-2 px-1">
                    <a class="btn btn-block btn-outline-primary text-black col-12"
                        t-attf-href="/calendar/#{appointment_type_id}/info?employee_id=#{slot['employee_id']}&amp;date_time=#{slot['datetime']}&amp;duration=#{slot['duration']}#{filter_appointment_type_ids ? '&amp;filter_appointment_type_ids=' + filter_appointment_type_ids : ''}"
                        t-out="slot['hours']"/>
                </div>
            </t>
        </div>
    </t>
</template>

and this is what I want to replace with

<?xml version="1.0" encoding="utf-8"?>
<template>
        <t t-name="my_module.inherit_slots_list" t-inherit="appointment.slots_list" t-inherit-mode="extension">
            <xpath expr="//div[@class='o_slots_list row'][1]/t[1]" position="replace">
                <t t-foreach="slots" t-as="slot">
                <div class="col-md-6 col-12 mt-2 px-1">
                    <a class="btn btn-block btn-outline-primary text-black col-12 o_time"
                        t-out="slot['hours']"/>
                </div>
            </t>
            </xpath>
        </t>
</template>

then I have tried to inherit a JS file (appointment_select_appointment_slot.js) and add a function to append more than one appointment based on a number that user can choose to a list of appointments before sending the result to some backend route. This is the original appointment_select_appointment_slot.js

odoo.define('appointment.select_appointment_slot', function (require) {
'use strict';

var core = require('web.core');
var publicWidget = require('web.public.widget');
var qweb = core.qweb;

publicWidget.registry.appointmentSlotSelect = publicWidget.Widget.extend({
    selector: '.o_appointment',
    xmlDependencies: ['/appointment/static/src/xml/calendar_appointment_slots.xml'],
    events: {
        'change select[name="timezone"]': '_onRefresh',
        'change select[id="selectEmployee"]': '_onRefresh',
        'click .o_js_calendar_navigate': '_onCalendarNavigate',
        'click .o_day': '_onClickDaySlot',
    },

    /**
     * Navigate between the months available in the calendar displayed
     */
    _onCalendarNavigate: function (ev) {
        var parent = this.$('.o_appointment_month:not(.d-none)');
        let monthID = parseInt(parent.attr('id').split('-')[1]);
        monthID += ((this.$(ev.currentTarget).attr('id') === 'nextCal') ? 1 : -1);
        parent.addClass('d-none');
        this.$(`div#month-${monthID}`).removeClass('d-none');
    },

    /**
     * Display the list of slots available for the date selected
     */
    _onClickDaySlot: function (ev) {
        this.$('.o_slot_selected').removeClass('o_slot_selected');
        this.$(ev.currentTarget).addClass('o_slot_selected');

        const appointmentTypeID = this.$("input[name='appointment_type_id']").val();
        const appointmentTypeIDs = this.$("input[name='filter_appointment_type_ids']").val();
        const slotDate = this.$(ev.currentTarget.firstElementChild).attr('id');
        const slots = JSON.parse(this.$(ev.currentTarget).find('div')[0].dataset['availableSlots']);

        let $slotsList = this.$('#slotsList').empty();
        $(qweb.render('appointment.slots_list', {
            slotDate: moment(slotDate).format("dddd D MMMM"),
            slots: slots,
            appointment_type_id: appointmentTypeID,
            filter_appointment_type_ids: appointmentTypeIDs,
        })).appendTo($slotsList);
    },

    /**
     * Refresh the slots info when the user modify the timezone or the employee
     */
    _onRefresh: function (ev) {
        if (this.$("#slots_availabilities")[0]) {
            var self = this;
            const appointmentTypeID = this.$("input[name='appointment_type_id']").val();
            const employeeID = this.$("#slots_form select[name='employee_id']").val();
            const timezone = this.$("select[name='timezone']").val();
            this._rpc({
                route: `/calendar/${appointmentTypeID}/update_available_slots`,
                params: {
                    employee_id: employeeID,
                    timezone: timezone,
                },
            }).then(function (data) {
                if (data) {
                    self.$("#slots_availabilities").replaceWith(data);
                }
            });
        }
    },
});
});

and this is my code

odoo.define('my_module.appointments_num', function (require) {
'use strict';

var select_appointment_slot = require('appointment.select_appointment_slot');
var clicks = 0;
var appointments = []
var numberOfAppointments = 1

select_appointment_slot.include({
    events: _.extend({}, select_appointment_slot.prototype.events, {
        'click .o_time': '_onTimeClick',
        'click .dropdown-item-number': '_onNumberClick'
    }),

    _onTimeClick: function (ev) {
        if (this.$("#slots_availabilities")[0]) {
            clicks++;
            var self = this;
            const appointmentsNumber = this.$("select[name='number_of_appointments']").val();
            const timeSelected = this.$(ev.currentTarget).text();
            const appointmentTypeID = this.$("input[name='appointment_type_id']").val();
            const employeeID = this.$("#slots_form select[name='employee_id']").val();
            const timezone = this.$("select[name='timezone']").val();
            const slots = JSON.parse(this.$('.o_slot_selected').find('div')[0].dataset['availableSlots']);
            $.each(slots , function(index, value) {
                if (value['hours'] === timeSelected){
                    appointments.push(value);
                    return false;
                }
            });
            if (clicks === numberOfAppointments){
                this._rpc({
                    route: `/calendar/${appointmentTypeID}/list_of_appointments`,
                    params: {
                        appointments
                    },
                })
            }
        }
    },

    _onNumberClick: function(ev){
        numberOfAppointments = parseInt(this.$(ev.currentTarget).text());
        alert(numberOfAppointments);
    }

});
});

My problem is neither the JS inheritance works nor the XML. I would really appreciate if someone can help me to make this work. Thanks!

1 Answers1

0

Have you register the js and xml file in manifest.py file of your module?