def _duration_validation(self):
     for option in self:
         if functions.float_to_time(
                 option.duration) < '00:05' or functions.float_to_time(
                     option.duration) > '08:00':
             raise ValidationError(
                 _('The duration value must be between 0:05 and 8:00!'))
Пример #2
0
    def check_slot_is_possible(self, option_id, appointment_date, appointee_id, slot_id):

        if not appointment_date:
            return False

        if not appointee_id:
            return False

        if not option_id:
            return False

        if not slot_id:
            return False

        option = request.env['s2u.appointment.option'].sudo().search([('id', '=', option_id)])
        if not option:
            return False
        slot = request.env['s2u.appointment.slot'].sudo().search([('id', '=', slot_id)])
        if not slot:
            return False

        date_start = datetime.datetime.strptime(appointment_date, '%d/%m/%Y').strftime('%Y-%m-%d')

        # if today, then skip slots in te past (< current time)
        if date_start == datetime.datetime.now().strftime('%Y-%m-%d') and self.ld_to_utc(date_start + ' ' + functions.float_to_time(slot.slot), appointee_id) < datetime.datetime.now(pytz.utc):
            return False

        event_start = self.ld_to_utc(date_start + ' ' + functions.float_to_time(slot.slot), appointee_id).strftime("%Y-%m-%d %H:%M:%S")
        event_stop = self.ld_to_utc(date_start + ' ' + functions.float_to_time(slot.slot), appointee_id,
                                    duration=option.duration).strftime("%Y-%m-%d %H:%M:%S")

        query = """
                SELECT e.id FROM calendar_event e, calendar_event_res_partner_rel ep  
                    WHERE ep.res_partner_id = %s AND
                          e.active = true AND
                          (e.recurrency = false or e.recurrency is null) AND
                          e.id = ep.calendar_event_id AND 
                        ((e.start >= %s AND e.start <= %s) OR
                             (e.start <= %s AND e.stop >= %s) OR
                             (e.stop >= %s) AND e.stop <= %s)                                       
        """
        request.env.cr.execute(query, (self.appointee_id_to_partner_id(appointee_id),
                                       event_start, event_stop,
                                       event_start, event_stop,
                                       event_start, event_stop))
        res = request.env.cr.fetchall()
        if not res:
            if not self.recurrent_events_overlapping(appointee_id, event_start, event_stop):
                return True

        return False
Пример #3
0
    def online_appointment_confirm(self, **post):
        error = {}
        error_message = []

        if request.env.user._is_public():
            param = request.env['ir.config_parameter'].sudo().search(
                [('key', '=', 's2u_online_appointment')], limit=1)
            if not param or param.value.lower() != 'public':
                return request.render(
                    's2u_online_appointment.only_registered_users')
            if not post.get('name', False):
                error['name'] = True
                error_message.append(_('Please enter your name.'))
            if not post.get('email', False):
                error['email'] = True
                error_message.append(_('Please enter your email address.'))
            elif not functions.valid_email(post.get('email', '')):
                error['email'] = True
                error_message.append(_('Please enter a valid email address.'))
            if not post.get('phone', False):
                error['phone'] = True
                error_message.append(_('Please enter your phone number.'))

        try:
            appointee_id = int(post.get('appointee_id', 0))
        except:
            appointee_id = 0
        if not appointee_id:
            error['appointee_id'] = True
            error_message.append(_('Please select a valid appointee.'))

        option = request.env['s2u.appointment.option'].sudo().search([
            ('id', '=', int(post.get('appointment_option_id', 0)))
        ])
        if not option:
            error['appointment_option_id'] = True
            error_message.append(_('Please select a valid subject.'))

        slot = request.env['s2u.appointment.slot'].sudo().search([
            ('id', '=', int(post.get('timeslot_id', 0)))
        ])
        if not slot:
            error['timeslot_id'] = True
            error_message.append(_('Please select a valid timeslot.'))

        try:
            date_start = datetime.datetime.strptime(
                post['appointment_date'], '%d/%m/%Y').strftime('%Y-%m-%d')
            day_slot = date_start + ' ' + functions.float_to_time(slot.slot)
            start_datetime = self.ld_to_utc(day_slot, appointee_id)
        except:
            error['appointment_date'] = True
            error_message.append(_('Please select a valid date.'))

        values = self.prepare_values(form_data=post)
        if error_message:
            values['error'] = error
            values['error_message'] = error_message
            return request.render('s2u_online_appointment.make_appointment',
                                  values)

        if not self.check_slot_is_possible(option.id, post['appointment_date'],
                                           appointee_id, slot.id):
            values['error'] = {'timeslot_id': True}
            values['error_message'] = [
                _('Slot is already occupied, please choose another slot.')
            ]
            return request.render('s2u_online_appointment.make_appointment',
                                  values)

        appointee_partner_id = self.appointee_id_to_partner_id(appointee_id)
        partner = request.env.user.partner_id
        if request.env.user._is_public():
            partner = request.env['res.partner'].sudo().search([
                '|', ('phone', 'ilike', values['phone']),
                ('email', 'ilike', values['email'])
            ])
            if not partner:
                partner = request.env['res.partner'].sudo().create({
                    'name':
                    values['name'],
                    'phone':
                    values['phone'],
                    'email':
                    values['email']
                })
        partner_ids = [appointee_partner_id, partner[0].id]

        appointment = {
            'name':
            option.name,
            'description':
            post.get('remarks', ''),
            'start':
            start_datetime.strftime("%Y-%m-%d %H:%M:%S"),
            'stop': (start_datetime +
                     datetime.timedelta(minutes=round(option.duration * 60))
                     ).strftime("%Y-%m-%d %H:%M:%S"),
            'duration':
            option.duration,
            'categ_ids':
            [(6, 0,
              request.env.ref(
                  's2u_online_appointment_estarbien.calendar_event_type_s2u_online_appointment'
              ).ids)],
            'partner_ids': [(6, 0, partner_ids)]
        }
        # set detaching = True, we do not want to send a mail to the attendees
        appointment = request.env['calendar.event'].sudo().with_context(
            detaching=True).create(appointment)
        # set all attendees on 'accepted'
        appointment.attendee_ids.write({'state': 'accepted'})

        ##inherited automated action for telemedicine
        #venta = [('partner_id','in',partner_ids), ('state','in',['sale']), ('order_line.product_id.website_published','=',True)]
        #venta = request.env['sale.order'].sudo().search(venta, limit=1, order='create_date desc')
        #if venta and not request.env['sinerkia_jitsi_meet.jitsi_meet'].sudo().search([('order_id','=',venta.id)]) :
        #    local_start_datetime = start_datetime.astimezone(timezone(request.env.user.tz or DEFAULT_TIMEZONE))
        #    #partners = request.env['res.partner'].sudo().search([('id', 'in', partner_ids)])
        #    jitsi = {'name': 'Reunión del paciente ' + partner[0].name + ' el ' + local_start_datetime.strftime('%d/%m/%Y') + ' a las ' + local_start_datetime.strftime('%H:%M:%S'),
        #             'date': start_datetime.strftime("%Y-%m-%d %H:%M:%S"),
        #             'date_delay': option.duration,
        #             'external_participants': [(0,0,{'name': partner[0].email})],
        #             'event_id': appointment.id,
        #             'order_id': venta.id}
        #    jitsi = request.env['sinerkia_jitsi_meet.jitsi_meet'].sudo().create(jitsi)
        #    patient = request.env['medical.patient'].sudo().search([('id','=',partner[0].id)])
        #    if not patient :
        #        patient = request.env['medical.patient'].sudo().create({'patient_id': partner[0].id})
        #    doctor = request.env['medical.physician'].sudo().search([('partner_id','=',appointee_partner_id)],limit=1)
        #    if not doctor :
        #        doctor = request.env['medical.physician'].sudo().create({'partner_id': appointee_partner_id})
        #    cita = {'patient_id': patient.id,
        #            'doctor_id': doctor.id,
        #            'appointment_date': start_datetime.strftime("%Y-%m-%d %H:%M:%S"),
        #            'appointment_end': (start_datetime + datetime.timedelta(minutes=round(option.duration * 60))).strftime("%Y-%m-%d %H:%M:%S"),
        #            'duration': option.duration * 60,
        #            'no_invoice': True,
        #            'consultations_id': venta.order_line[0].product_id.id}
        #    cita = request.env['medical.appointment'].create(cita)

        # registered user, we want something to show in his portal
        if not request.env.user._is_public():
            registration = {
                'partner_id': request.env.user.partner_id.id,
                'appointee_id': self.appointee_id_to_partner_id(appointee_id),
                'event_id': appointment.id
            }
            registration = request.env['s2u.appointment.registration'].create(
                registration)

        return request.redirect(
            '/online-appointment/appointment-scheduled?appointment=%d' %
            appointment.id)
Пример #4
0
    def get_days_with_free_slots(self, option_id, appointee_id, year, month, criteria):

        if not option_id:
            return {}

        if not appointee_id:
            return {}

        start_datetimes = {}
        start_date = datetime.date(year, month, 1)
        for i in range(31):
            if start_date < datetime.date.today():
                start_date += datetime.timedelta(days=1)
                continue
            if start_date.weekday() not in start_datetimes:
                start_datetimes[start_date.weekday()] = []
            start_datetimes[start_date.weekday()].append(start_date.strftime('%Y-%m-%d'))
            start_date += datetime.timedelta(days=1)
            if start_date.month != month:
                break

        day_slots = []

        option = request.env['s2u.appointment.option'].sudo().search([('id', '=', option_id)])
        if not option:
            return {}

        for weekday, dates in start_datetimes.items():
            slots = request.env['s2u.appointment.slot'].sudo().search([('user_id', '=', appointee_id),
                                                                       ('day', '=', str(weekday))])
            slots = self.filter_slots(slots, criteria)

            for slot in slots:
                for d in dates:
                    # if d == today, then skip slots in te past (< current time)
                    if d == datetime.datetime.now().strftime('%Y-%m-%d') and self.ld_to_utc(d + ' ' + functions.float_to_time(slot.slot), appointee_id) < datetime.datetime.now(pytz.utc):
                        continue

                    day_slots.append({
                        'timeslot': functions.float_to_time(slot.slot),
                        'date': d,
                        'start': self.ld_to_utc(d + ' ' + functions.float_to_time(slot.slot), appointee_id).strftime("%Y-%m-%d %H:%M:%S"),
                        'stop': self.ld_to_utc(d + ' ' + functions.float_to_time(slot.slot), appointee_id, duration=option.duration).strftime("%Y-%m-%d %H:%M:%S")
                    })
        days_with_free_slots = {}
        for d in day_slots:
            if d['date'] in days_with_free_slots:
                # this day is possible, there was a slot possible so skip other slot calculations for this day
                # We only need to inform the visitor he can click on this day (green), after that he needs to
                # select a valid slot.
                continue

            query = """
                    SELECT e.id FROM calendar_event e, calendar_event_res_partner_rel ep  
                        WHERE ep.res_partner_id = %s AND 
                              e.active = true AND
                              (e.recurrency = false or e.recurrency is null) AND
                              e.id = ep.calendar_event_id AND  
                            ((e.start >= %s AND e.start <= %s) OR
                             (e.start <= %s AND e.stop >= %s) OR
                             (e.stop >= %s) AND e.stop <= %s)                                         
            """
            request.env.cr.execute(query, (self.appointee_id_to_partner_id(appointee_id),
                                           d['start'], d['stop'],
                                           d['start'], d['stop'],
                                           d['start'], d['stop']))
            res = request.env.cr.fetchall()
            if not res:
                if not self.recurrent_events_overlapping(appointee_id, d['start'], d['stop']):
                    days_with_free_slots[d['date']] = True
        return days_with_free_slots
Пример #5
0
        def slot_present(slots, slot):

            for s in slots:
                if s['timeslot'] == functions.float_to_time(slot):
                    return True
            return False
Пример #6
0
    def get_free_appointment_slots_for_day(self, option_id, appointment_date, appointee_id, criteria):

        def slot_present(slots, slot):

            for s in slots:
                if s['timeslot'] == functions.float_to_time(slot):
                    return True
            return False

        if not appointment_date:
            return []

        if not appointee_id:
            return []

        option = request.env['s2u.appointment.option'].sudo().search([('id', '=', option_id)])
        if not option:
            return []

        week_day = datetime.datetime.strptime(appointment_date, '%d/%m/%Y').weekday()
        slots = request.env['s2u.appointment.slot'].sudo().search([('user_id', '=', appointee_id),
                                                                   ('day', '=', str(week_day))])
        slots = self.filter_slots(slots, criteria)

        date_start = datetime.datetime.strptime(appointment_date, '%d/%m/%Y').strftime('%Y-%m-%d')
        free_slots = []
        for slot in slots:
            # skip double slots
            if slot_present(free_slots, slot.slot):
                continue

            # if today, then skip slots in te past (< current time)
            if date_start == datetime.datetime.now().strftime('%Y-%m-%d') and self.ld_to_utc(date_start + ' ' + functions.float_to_time(slot.slot), appointee_id) < datetime.datetime.now(pytz.utc):
                continue

            event_start = self.ld_to_utc(date_start + ' ' + functions.float_to_time(slot.slot), appointee_id).strftime("%Y-%m-%d %H:%M:%S")
            event_stop = self.ld_to_utc(date_start + ' ' + functions.float_to_time(slot.slot), appointee_id,
                                        duration=option.duration).strftime("%Y-%m-%d %H:%M:%S")

            # check normal calendar events
            query = """
                    SELECT e.id FROM calendar_event e, calendar_event_res_partner_rel ep  
                        WHERE ep.res_partner_id = %s AND
                              e.active = true AND
                              (e.recurrency = false or e.recurrency is null) AND 
                              e.id = ep.calendar_event_id AND 
                            ((e.start >= %s AND e.start <= %s) OR
                             (e.start <= %s AND e.stop >= %s) OR
                             (e.stop >= %s) AND e.stop <= %s)                                         
            """
            request.env.cr.execute(query, (self.appointee_id_to_partner_id(appointee_id),
                                           event_start, event_stop,
                                           event_start, event_stop,
                                           event_start, event_stop))
            res = request.env.cr.fetchall()
            if not res:
                if not self.recurrent_events_overlapping(appointee_id, event_start, event_stop):
                    free_slots.append({
                        'id': slot.id,
                        'timeslot': functions.float_to_time(slot.slot)
                    })

        return free_slots
Пример #7
0
    def online_appointment_confirm(self, **post):
        error = {}
        error_message = []

        if request.env.user._is_public():
            param = request.env['ir.config_parameter'].sudo().search([('key', '=', 's2u_online_appointment')], limit=1)
            if not param or param.value.lower() != 'public':
                return request.render('s2u_online_appointment.only_registered_users')

            if not post.get('name', False):
                error['name'] = True
                error_message.append(_('Please enter your name.'))
            if not post.get('email', False):
                error['email'] = True
                error_message.append(_('Please enter your email address.'))
            elif not functions.valid_email(post.get('email', '')):
                error['email'] = True
                error_message.append(_('Please enter a valid email address.'))
            if not post.get('phone', False):
                error['phone'] = True
                error_message.append(_('Please enter your phonenumber.'))

        try:
            appointee_id = int(post.get('appointee_id', 0))
        except:
            appointee_id = 0
        if not appointee_id:
            error['appointee_id'] = True
            error_message.append(_('Please select a valid appointee.'))

        option = request.env['s2u.appointment.option'].sudo().search([('id', '=', int(post.get('appointment_option_id', 0)))])
        if not option:
            error['appointment_option_id'] = True
            error_message.append(_('Please select a valid subject.'))

        slot = request.env['s2u.appointment.slot'].sudo().search([('id', '=', int(post.get('timeslot_id', 0)))])
        if not slot:
            error['timeslot_id'] = True
            error_message.append(_('Please select a valid timeslot.'))

        try:
            date_start = datetime.datetime.strptime(post['appointment_date'], '%d/%m/%Y').strftime('%Y-%m-%d')
            day_slot = date_start + ' ' + functions.float_to_time(slot.slot)
            start_datetime = self.ld_to_utc(day_slot, appointee_id)
        except:
            error['appointment_date'] = True
            error_message.append(_('Please select a valid date.'))

        values = self.prepare_values(form_data=post)
        if error_message:
            values['error'] = error
            values['error_message'] = error_message
            return request.render('s2u_online_appointment.make_appointment', values)

        if not self.check_slot_is_possible(option.id, post['appointment_date'], appointee_id, slot.id):
            values['error'] = {'timeslot_id': True}
            values['error_message'] = [_('Slot is already occupied, please choose another slot.')]
            return request.render('s2u_online_appointment.make_appointment', values)

        if request.env.user._is_public():
            partner = request.env['res.partner'].sudo().search(['|', ('phone', 'ilike', values['phone']),
                                                                     ('email', 'ilike', values['email'])])
            if partner:
                partner_ids = [self.appointee_id_to_partner_id(appointee_id),
                               partner[0].id]
            else:
                partner = request.env['res.partner'].sudo().create({
                    'name': values['name'],
                    'phone': values['phone'],
                    'email': values['email']
                })
                partner_ids = [self.appointee_id_to_partner_id(appointee_id),
                               partner[0].id]
        else:
            partner_ids = [self.appointee_id_to_partner_id(appointee_id),
                           request.env.user.partner_id.id]

        # set detaching = True, we do not want to send a mail to the attendees
        appointment = request.env['calendar.event'].sudo().with_context(detaching=True).create({
            'name': option.name,
            'description': post.get('remarks', ''),
            'start': start_datetime.strftime("%Y-%m-%d %H:%M:%S"),
            'stop': (start_datetime + datetime.timedelta(minutes=round(option.duration * 60))).strftime("%Y-%m-%d %H:%M:%S"),
            'duration': option.duration,
            'partner_ids': [(6, 0, partner_ids)]
        })
        # set all attendees on 'accepted'
        appointment.attendee_ids.write({
            'state': 'accepted'
        })

        # registered user, we want something to show in his portal
        if not request.env.user._is_public():
            vals = {
                'partner_id': request.env.user.partner_id.id,
                'appointee_id': self.appointee_id_to_partner_id(appointee_id),
                'event_id': appointment.id
            }
            registration = request.env['s2u.appointment.registration'].create(vals)

        return request.redirect('/online-appointment/appointment-scheduled?appointment=%d' % appointment.id)