Files
gzth/estate/models/estate_property.py
T
2025-10-21 21:11:15 +08:00

194 lines
7.0 KiB
Python

from odoo import models, fields, api
from datetime import timedelta
from odoo.exceptions import UserError, ValidationError
# 导入异常类
class EstateProperty(models.Model):
_name = "estate.property"
_description = "房地产属性"
# 继承邮件线程和活动混合类
_inherit = ["mail.thread", "mail.activity.mixin"]
# 默认按ID降序排列
_order = "id desc"
name = fields.Char(string="名称", required=True)
description = fields.Text(string="描述")
postcode = fields.Char(string="邮政编码")
# 默认日期为三个月后
date_availability = fields.Date(
string="可用日期",
copy=False,
default=lambda self: fields.Date.today() + timedelta(days=90),
)
expected_price = fields.Float(string="预期价格", required=True)
selling_price = fields.Float(string="销售价格", copy=False)
bedrooms = fields.Integer(string="卧室数量", default=2)
living_area = fields.Integer(string="居住面积")
facades = fields.Integer(string="立面")
garage = fields.Boolean(string="是否有车库")
garden = fields.Boolean(string="是否有花园")
garden_area = fields.Integer(string="花园面积")
garden_orientation = fields.Selection(
[("north", "北"), ("south", "南"), ("east", "东"), ("west", "西")],
string="花园朝向",
)
# 默认货币为公司货币
currency_id = fields.Many2one(
"res.currency",
string="货币",
required=True,
default=lambda self: self.env.ref("base.CNY").id,
)
active = fields.Boolean(string="是否归档", default=True)
# 房屋类型
state = fields.Selection(
[
("new", "新"),
("offer_received", "已收到报价"),
("offer_accepted", "已接受报价"),
("sold", "已售出"),
("canceled", "已取消"),
],
string="状态",
default="new",
required=True,
copy=False,
)
versionflog = fields.Integer(string="换版", default=1)
# 关联房屋类型模型
property_type_id = fields.Many2one(
"estate.property.type", string="房屋类型", required=True
)
# 买家
buyer_id = fields.Many2one("res.partner", string="买家", copy=False)
# 关联联系人模型卖家
seller_id = fields.Many2one(
"res.users", string="卖家", required=True, default=lambda self: self.env.user
)
# 房屋标签
tag_ids = fields.Many2many("estate.property.tag", string="房屋标签")
# 房屋报价
offer_ids = fields.One2many(
"estate.property.offer", "property_id", string="房屋报价"
)
# 房屋总面积
total_area = fields.Float(
string="总面积", compute="_compute_total_area", store=True
)
# 最佳报价
best_price = fields.Float(
string="最佳报价", compute="_compute_best_price", store=True
)
create_date_month = fields.Char(string="创建月份", index=True, copy=False)
# 房产预期价格必须严格为正数
_sql_constraints = [
("check_expected_price", "CHECK(expected_price > 0)", "预期价格必须为正数"),
("check_selling_price", "CHECK(selling_price > 0)", "销售价格必须为正数"),
("check_bedrooms", "CHECK(bedrooms > 0)", "卧室数量必须为正数"),
("check_living_area", "CHECK(living_area > 0)", "居住面积必须为正数"),
("check_facades", "CHECK(facades > 0)", "立面数量必须为正数"),
]
# 无法接受低于预期价格 90% 的报价
@api.constrains("selling_price", "expected_price") # 添加约束
def _check_selling_price(self):
for record in self:
if record.selling_price < record.expected_price * 0.9:
raise ValidationError("销售价格不能低于预期价格的90%")
@api.depends("living_area", "garden_area") # 计算字段
def _compute_total_area(self):
"""计算房屋总面积"""
for record in self:
record.total_area = record.living_area + record.garden_area
@api.depends("offer_ids.price") # 计算字段
def _compute_best_price(self):
"""计算最佳报价"""
for record in self:
best_price = 0.0
if record.offer_ids:
best_price = max(record.offer_ids.mapped("price"))
record.best_price = best_price
def action_sold(self):
"""标记为已售(需先接受报价)"""
if self.state != "offer_accepted":
raise UserError("必须接受报价后才能标记已售")
return self.write({"state": "sold"})
def action_cancel(self):
"""取消交易"""
if self.state == "sold":
raise UserError("已售房产不可取消")
return self.write({"state": "canceled"})
# 如果有花园,设置默认花园面积为50,朝向为南,若没有花园,则设置花园面积为0,朝向为无
@api.onchange("garden")
def _onchange_garden(self):
if self.garden:
self.garden_area = 50
self.garden_orientation = "south"
else:
self.garden_area = 0
self.garden_orientation = False
# 若取消选择车库则弹出警告
@api.onchange("garage")
def _onchange_garage(self):
if not self.garage == False:
return {"warning": {"title": "警告", "message": "确定取消车库吗?"}}
# •如果房产的状态不是‘新建’或‘已取消’,则阻止删除房产
@api.ondelete(at_uninstall=True)
def _unlink_except_new_canceled(self):
"""删除房产"""
for record in self:
if record.state not in ["new", "canceled"]:
raise UserError("只能删除新建或已取消的房产")
# 设置版本日志
def setversionflog(self):
# 空函数,不做任何操作
pass
def write(self, vals):
vals["create_uid"] = self.create_uid
return super(EstateProperty, self).write(vals)
# 定义按钮
def action_set_offer_received(self):
"""设置为已收到报价"""
return self.write({"state": "offer_received"})
def action_set_offer_accepted(self):
"""设置为已接受报价"""
return self.write({"state": "offer_accepted"})
def action_set_sold(self):
"""设置为已售出"""
# 将状态设置为已售出
return self.write({"state": "sold"})
def do_reject_new(self):
"""拒绝新建报价"""
# 将状态设置为"new"
return self.write({"state": "new"})
def do_reject_offer(self):
"""拒绝报价"""
return self.write({"state": "offer_received"})
@api.model_create_multi
def create(self, vals_list):
records = super().create(vals_list)
for rec in records:
if rec.create_date:
rec.create_date_month = rec.create_date.strftime("%Y-%m")
else:
rec.create_date_month = fields.Date.today().strftime("%Y-%m")
return records