170 lines
7.2 KiB
Python
170 lines
7.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
import os
|
|
from uuid import uuid4
|
|
|
|
from odoo import api, fields, models, tools, _
|
|
from odoo.tools.translate import html_translate
|
|
|
|
|
|
class Room(models.Model):
|
|
_name = "room.room"
|
|
_inherit = ["mail.thread"]
|
|
_description = "Room"
|
|
_order = "name, id"
|
|
_rec_name = 'name'
|
|
|
|
_sql_constraints = [
|
|
("uniq_access_token", "unique(access_token)", "The access token must be unique"),
|
|
("uniq_short_code", "unique(short_code)", "The short code must be unique."),
|
|
]
|
|
# Configuration
|
|
name = fields.Char(string="会议室", required=True, tracking=2)
|
|
description = fields.Html(string="Amenities", translate=html_translate, sanitize=False)
|
|
office_id = fields.Many2one("room.office", string="Office", tracking=3)
|
|
room_booking_ids = fields.One2many("room.booking", "room_id", string="Bookings")
|
|
short_code = fields.Char("Short Code", default=lambda self: str(uuid4())[:8], copy=False, required=True, tracking=1)
|
|
# Technical/Statistics
|
|
access_token = fields.Char("Access Token", default=lambda self: str(uuid4()), copy=False, readonly=True, required=True)
|
|
bookings_count = fields.Integer("Bookings Count", compute="_compute_bookings_count")
|
|
is_available = fields.Boolean(string="Is Room Currently Available", compute="_compute_is_available")
|
|
next_booking_start = fields.Datetime("Next Booking Start", compute="_compute_next_booking_start")
|
|
room_booking_url = fields.Char("Room Booking URL", compute="_compute_room_booking_url")
|
|
# Frontend design fields
|
|
bookable_background_color = fields.Char("Available Background Color", default="#83c5be")
|
|
booked_background_color = fields.Char("Booked Background Color", default="#dd2d4a")
|
|
room_background_image = fields.Image("Background Image")
|
|
|
|
# 二开字段 签到sign in
|
|
|
|
meet_m2 = fields.Float(string="会议室面积")
|
|
meet_equipment = fields.Char(string="会议室设备")
|
|
|
|
office_address = fields.Char(string="会议室地址", required=True)
|
|
company_id = fields.Many2one("res.company", string="公司", required=True)
|
|
meeting_type_template = fields.Selection([('template1', '默认模板')], string='会议室模板')
|
|
meet_document_id = fields.Many2one('documents.document', string="布局图片")
|
|
meet_capacity = fields.Integer(string="容纳人数", required=True)
|
|
|
|
is_meet_tv = fields.Boolean(string="电视")
|
|
is_meet_phone = fields.Boolean(string="电话")
|
|
is_meet_projector = fields.Boolean(string="投影")
|
|
is_meet_whiteboard = fields.Boolean(string="白板")
|
|
is_meet_video = fields.Boolean(string="视频")
|
|
|
|
|
|
@api.onchange('meeting_type_template')
|
|
def onchange_description(self):
|
|
# 获取当前文件的路径
|
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
# 上一层
|
|
parent_dir = os.path.dirname(current_dir)
|
|
# 拼接相对路径,获取HTML文件的完整路径
|
|
file_path = os.path.join(parent_dir, 'static', 'src', 'html', 'template1.html')
|
|
with open(file_path, 'r', encoding='utf-8') as file:
|
|
html_content = file.read()
|
|
if self.meeting_type_template == 'template1':
|
|
self.description = html_content
|
|
|
|
@api.depends("room_booking_ids")
|
|
def _compute_bookings_count(self):
|
|
bookings_count_by_room = dict(self.env["room.booking"]._read_group(
|
|
[("stop_datetime", ">=", fields.Datetime.now()), ("room_id", "in", self.ids)],
|
|
["room_id"],
|
|
["__count"]
|
|
))
|
|
for room in self:
|
|
room.bookings_count = bookings_count_by_room.get(room, 0)
|
|
|
|
# @api.depends("office_id")
|
|
# def _compute_display_name(self):
|
|
# super()._compute_display_name()
|
|
# for room in self:
|
|
# room.display_name = f"{room.office_id.name} - {room.name}"
|
|
|
|
@api.depends("room_booking_ids")
|
|
def _compute_is_available(self):
|
|
now = fields.Datetime.now()
|
|
booked_rooms = {room.id for room, in self.env["room.booking"]._read_group(
|
|
[("start_datetime", "<=", now), ("stop_datetime", ">=", now), ("room_id", "in", self.ids)],
|
|
["room_id"],
|
|
)}
|
|
for room in self:
|
|
room.is_available = room.id not in booked_rooms
|
|
|
|
@api.depends("is_available", "room_booking_ids")
|
|
def _compute_next_booking_start(self):
|
|
now = fields.Datetime.now()
|
|
next_booking_start_by_room = dict(self.env["room.booking"]._read_group(
|
|
[("start_datetime", ">", now), ("room_id", "in", self.filtered('is_available').ids)],
|
|
["room_id"],
|
|
["start_datetime:min"],
|
|
))
|
|
for room in self:
|
|
room.next_booking_start = next_booking_start_by_room.get(room)
|
|
|
|
@api.depends("short_code")
|
|
def _compute_room_booking_url(self):
|
|
for room in self:
|
|
room.room_booking_url = f"{room.get_base_url()}/room/{room.short_code}/book"
|
|
|
|
# ------------------------------------------------------
|
|
# CRUD / ORM
|
|
# ------------------------------------------------------
|
|
|
|
def write(self, vals):
|
|
result = super(Room, self).write(vals)
|
|
for room in self:
|
|
room._notify_booking_view("reload")
|
|
return result
|
|
|
|
# ------------------------------------------------------
|
|
# ACTIONS
|
|
# ------------------------------------------------------
|
|
|
|
def action_open_booking_view(self):
|
|
self.ensure_one()
|
|
return {
|
|
"type": "ir.actions.act_url",
|
|
"url": self.room_booking_url,
|
|
"target": "new",
|
|
}
|
|
|
|
def action_view_bookings(self):
|
|
return {
|
|
"type": "ir.actions.act_window",
|
|
"res_model": "room.booking",
|
|
"name": _("Bookings"),
|
|
"domain": [("room_id", "in", self.ids)],
|
|
"context": {"default_room_id": self.id if len(self) == 1 else False},
|
|
"view_mode": "calendar,gantt,kanban,tree,form",
|
|
}
|
|
|
|
# ------------------------------------------------------
|
|
# TOOLS
|
|
# ------------------------------------------------------
|
|
|
|
def _notify_booking_view(self, method, bookings=False):
|
|
"""The room booking page is meant to be used on a 'static' device (such
|
|
as a tablet) and is not expected to be reloaded manually. We thus need
|
|
a way to notify the frontend page of any change inside the room
|
|
configuration (in which case we reload the view to apply those changes)
|
|
or any booking update.
|
|
"""
|
|
self.ensure_one()
|
|
if method == "reload":
|
|
self.env["bus.bus"]._sendone(f"room_booking#{self.access_token}", "reload", self.room_booking_url)
|
|
elif method in ["create", "delete", "update"]:
|
|
self.env["bus.bus"]._sendone(
|
|
f"room_booking#{self.access_token}",
|
|
f"booking/{method}",
|
|
[{
|
|
"id": booking.id,
|
|
"name": booking.name,
|
|
"start_datetime": booking.start_datetime,
|
|
"stop_datetime": booking.stop_datetime,
|
|
} for booking in (bookings or [])]
|
|
)
|
|
else:
|
|
raise NotImplementedError(f"Method '{method}' is not implemented for '_notify_booking_view'")
|