1
0
forked from Mapan/odoo17e
odoo17e-kedaikipas58/addons/appointment/populate/appointment_slot.py
2024-12-10 09:04:09 +07:00

124 lines
5.8 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import datetime
import pytz
from odoo import models
from odoo.addons.appointment.populate import data
from odoo.tools import populate
class AppointmentSlot(models.Model):
_inherit = "appointment.slot"
_populate_dependencies = [
'res.company',
'appointment.type',
]
_populate_sizes = {'small': 120, 'medium': 320, 'large': 4000}
def _populate_factories(self):
def compute_hours_and_duration(iterator, *args):
random = populate.Random('hoursduration')
appointment_type_duration_max_half_day = max(
data.appointment_type["appointment_duration_half_day"].keys())
for values in iterator:
app_type = self.env["appointment.type"].browse(values["appointment_type_id"])
app_type_long_duration = app_type.appointment_duration > appointment_type_duration_max_half_day
# 1/5 or always if appointment type duration > max duration for a half-day: give a
# single slot starting from start of AM until end of PM (some of these slots will
# be tagged 'allday')
if random.random() < .2 or app_type_long_duration:
yield {
**values,
'start_hour': random.choices(
*zip(*data.appointment_slot.get("start_time_am").items()))[0],
'end_hour': random.choices(
*zip(*data.appointment_slot.get("end_time_pm").items()))[0],
'allday': random.random() < 0.5 if app_type_long_duration else False,
}
else: # Yield a morning and an afternoon slot
for start_hours, end_hours in zip(["start_time_am", "start_time_pm"],
["end_time_am", "end_time_pm"]):
yield {
**values,
'start_hour': random.choices(
*zip(*data.appointment_slot.get(start_hours).items()))[0],
'end_hour': random.choices(
*zip(*data.appointment_slot.get(end_hours).items()))[0],
'allday': False,
}
def _compute_slot_type_and_datetimes(iterator, *kwargs):
# Yield one or two slots with specified start and end datetime attributes for
# `category="custom"` appointment types with the required "unique" slot_type, or a
# single "recurring" slot_type slot
random = populate.Random('slottypes')
for values in iterator:
app_type = self.env["appointment.type"].browse(values["appointment_type_id"])
if app_type.category != 'custom':
yield {**values, "slot_type": "recurring"}
else: # Create randomly placed unique slot(s)
start_datetime = (
datetime.datetime.now()
.replace(hour=8 + random.randint(0, 3),
minute=5 * random.choice([0, 2, 3, 4, 6, 9, 10]),
second=0)
+ datetime.timedelta(days=int(values["weekday"]))
- datetime.datetime.now(pytz.timezone(app_type["appointment_tz"]))
.utcoffset())
new_values = {
"slot_type": "unique",
"start_datetime": start_datetime,
"end_datetime": start_datetime + datetime.timedelta(
hours=app_type["appointment_duration"]),
"allday": False
}
yield {**values, **new_values}
# Sometimes two per day, with a "taken" slot in-between
if random.random() < 0.5:
new_values["start_datetime"] += datetime.timedelta(
hours=2 * app_type["appointment_duration"])
new_values["end_datetime"] += datetime.timedelta(
hours=2 * app_type["appointment_duration"])
yield {**values, **new_values}
appointment_type_ids = self.env['appointment.type'].browse(
self.env.registry.populated_models['appointment.type']).filtered_domain([
('category', 'in', ['punctual', 'recurring', 'custom'])]).ids
# We need values for 5-6 days for each appointment_type_id.
# We populate 7 days then later randomly drop one or more
slots = [
populate.chain_factories([
('appointment_type_id', populate.iterate(appointment_type_ids)),
('weekday', populate.iterate([weekday])),
('_hours_duration', compute_hours_and_duration)
], self._name)
for weekday in range(1, 8)
]
def _compute_slot_times(iterator, *args):
random = populate.Random('slottimes')
for slot in slots:
for new_values in slot:
if new_values["__complete"]:
break
new_values["weekday"] = str(
(new_values["weekday"] + new_values["appointment_type_id"]) % 8)
# Min 1 day without
if new_values["weekday"] == '0' or random.random() < 0.15:
continue
this_data = {**new_values, **next(iterator)}
yield this_data
return [
('_this_data', _compute_slot_times),
('_slot_type_and_datetimes', _compute_slot_type_and_datetimes),
]