Files
gzth/yuthon_property/models/yuthon_property.py
T
2026-04-30 14:55:35 +08:00

960 lines
46 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from odoo import models, fields, api
from odoo.exceptions import UserError, ValidationError
from pypinyin import pinyin,lazy_pinyin
from datetime import datetime,date
import calendar
class YuthonProperty(models.Model):
_name = 'yuthon.property'
_description = '物业管理'
_inherit = ['mail.thread.main.attachment', 'mail.activity.mixin']
_rec_name = 'name'
_order = 'first_letter'
name = fields.Text(string="资产名称")
tax = fields.Float(string="税率", default=0.09)
users_id = fields.Many2one('res.users', string="申请人", default=lambda self: self.env.user.id)
code = fields.Char(string="物业编号", default=lambda self: self.env['ir.sequence'].next_by_code('yuthon_property_message_code'))
referred_id = fields.Many2one('yuthon.lot.setting', string="地段")
units = fields.Char(string="单元")
house_type_id = fields.Many2one('yuthon.resource.house.type', string="户型")
district = fields.Char(string="区")
building_area = fields.Float(string="建筑面积", digits=(16, 4))
title_deed = fields.Char(string="产权证号", compute="_compute_title_information_fields", store=True)
effective_date = fields.Date(string="生效日期", compute="compute_information_fields", store=True)
end_date = fields.Date(string="失效日期", compute="compute_information_fields", store=True)
property_source = fields.Selection([('cut', '划入'), ('self', '自建'),
('replace', '置换'), ('buy', '购入'),
('entrust', '委托'), ('Rent', '租入')], string='资产来源')
remark = fields.Char(string="备注")
vr_link = fields.Char(string="VR链接")
current_rent = fields.Float(string="现租金")
is_done_split = fields.Boolean(string="已拆分")
is_done_merge = fields.Boolean(string="已合并")
property_building_id = fields.Many2one('property.floor.setting', string="楼盘")
property_floor_id = fields.Many2one('property.floor.setting', string="楼层")
property_orientation = fields.Selection([('north', '东'), ('south', '南'), ('east', '西'), ('west', '北')],
string="朝向")
street = fields.Char(string="街道")
property_state = fields.Selection([('on_rent', '在租'), ('vacant', '空置')], string='租赁状态', default='on_rent')
property_leasing = fields.Selection([('to', '待评估'), ('ing', '评估中'), ('done', '已评估'), ('net', '挂网'), ('signing', '签约中')], string='评估状态', default='to')
purpose_id = fields.Many2one('yuthon.resource.purpose', string="管理类型", compute="compute_information_fields", store=True)
is_meter = fields.Boolean(string="水表")
live_room = fields.Many2one('yuthon.live.room', string="居住用房")
is_electricity_meter = fields.Boolean(string="电表")
is_confirm_authorization = fields.Boolean(string="确权")
property_card = fields.Html(string="产权证")
asset_type_id = fields.Many2one('yuthon.resource.type', string="出租类型")
is_hvac = fields.Boolean(string="使用中央空调")
is_handle_land = fields.Boolean(string="办理土地有偿使用手续")
property_use_id = fields.Integer(string="物业用途ID")
image_1920 = fields.Image(string="图片")
description = fields.Html(string="描述")
is_message_fee = fields.Boolean(string="管理费")
financial_address = fields.Char(string="财务地址")
message_standard_id = fields.Many2one('property.message.fee', string="管理费标准")
rental_unit_price = fields.Float(string="评估单价")
title_number = fields.Char(string="产权编号")
suite_area = fields.Float(string="套内面积", digits=(16, 4))
admin_id = fields.Many2one('res.users', string="片区管理员", compute="compute_information_fields", store=True)
lessee_id = fields.Many2one('property.tenant.information', string='承租方', compute="_compute_lessee_id")
title_address = fields.Many2one('yuthon.property.message', string="产权地址", compute="_compute_title_information_fields", store=True)
company_id = fields.Many2one('yuthon.property.company', string="公司", compute="compute_information_fields", store=True)
rental_address = fields.Text(string="出租地址")
tenure_type = fields.Selection([('self', '自有'), ('agency', '代管')], string='权属类型', compute="compute_information_fields", store=True)
ame = fields.Char(string='标题')
management_area = fields.Float(string="管理面积", digits=(16, 4), compute="compute_information_fields", store=True)
rent_area = fields.Float(string="可租面积", digits=(16, 4), compute="compute_information_fields", store=True)
equity_area = fields.Float(string="产权面积", group_operator=None, digits=(16, 4), compute="_compute_title_information_fields", store=True)
decoration_type = fields.Selection([('blank', '毛坯'), ('hardcover', '精装'), ('brands', '简装'), ('rsz', '豪装')],
string="装修类型")
feature_ids = fields.Many2many('feature.setting', string="特色")
major_ids = fields.One2many('yuthon.major.event.line', 'yuthon_property_id', string="重大事项明细行")
water_meter_ids = fields.One2many('yuthon.property.water', 'yuthon_property_id', string='水表列表')
energy_meter_ids = fields.One2many('yuthon.property.energy', 'yuthon_property_id', string='电表列表')
title_information_ids = fields.One2many('title.information.line', 'yuthon_property_id', string='关联产权信息明细行')
manage_information_ids = fields.One2many('manage.information.line', 'yuthon_property_id',
string='关联管理信息明细行')
disassembly_information_ids = fields.One2many('disassembly.information.line', 'yuthon_property_id',
string='关联拆分信息明细行')
assessment_ids = fields.One2many('yuthon.property.assessment', 'yuthon_property_id', string='关联评估明细行')
repair_ids = fields.One2many('yuthon.property.repair', 'yuthon_property_id', string='关联维修明细行')
produce_ids = fields.One2many('yuthon.property.production', 'yuthon_property_id', string='关联安全生产明细行')
property_merge_approval_id = fields.Many2one('yuthon.property', string='关联物业信息')
reference_ids = fields.One2many('yuthon.reference.conditions', 'yuthon_property_id', string='关联出租参考条件明细行')
first_letter = fields.Char(string="首字母", compute='_compute_first_letter', store=True)
owner_id = fields.Many2one('yuthon.owner.message', string="权属人", compute='_compute_title_information_fields', store=True)
vacant_duration = fields.Float(string="空置时长", digits=(16, 2))
lease_period = fields.Integer(string='租赁期限(<=)')
rent_period = fields.Integer(string="免租期(<=)")
first_years_begin = fields.Integer(string='第几年开始')
increments_few_years = fields.Integer(string='每几年递增')
annual_increase_percentage = fields.Float(string='递增百分比', igits=(6, 2))
annual_increase_amount = fields.Float(string='递增金额', igits=(6, 2))
rent_unit = fields.Float(string='租金单价', igits=(6, 2))
property_type = fields.Selection([('property', '物业'), ('guanggao', '广告位'), ('guanzi', '管子间'), ('room', '机房'), ('base_station','基站'), ('other', '其他')], string="资产类型", default='property')
is_new = fields.Boolean(string="是否最新物业", compute= 'compute_is_new', default=True, store=True)
kingdee_property_id = fields.Char(string="金蝶云物业资产id")
def update_property_state(self):
today = date.today()
current_year = today.year
current_month = today.month
# rentable_properties = self.env["yuthon.property"].browse(
# self._context.get('active_ids', self._context.get('active_id')))
rentable_properties = self.search([('purpose_id.name', '=', '可租')])
for prop in rentable_properties:
contract_lines = self.env['property.lease.contract.line'].search([
('address_id', '=', prop.id),
('lease_id.is_contract', '=', False),
])
if contract_lines:
sorted_lines = sorted(
contract_lines,
key=lambda line: line.lease_id.actual_end_time or date.max,
reverse=True
)
lease_id = sorted_lines[0]
else:
lease_id = self.env['property.lease.contract.line']
if not lease_id:
prop.write({'property_state': 'vacant'})
continue
actual_end = lease_id.lease_id.actual_end_time
if not actual_end:
prop.write({'property_state': 'on_rent'})
continue
end_day = actual_end.day
# 判断实际结束日期是否在本月
is_current_month = (actual_end.year == current_year) and (actual_end.month == current_month)
# 获取本月最后一天
last_day = calendar.monthrange(current_year, current_month)[1]
if is_current_month:
# 实际结束日期在本月
if end_day == last_day:
# 是本月月底 → 状态为在租
prop.write({'property_state': 'on_rent'})
else:
# 非月底 → 直接空置(无论是否大于今天)
prop.write({'property_state': 'vacant'})
else:
# 实际结束日期不在本月 → 按大于/小于今天判断
if actual_end > today:
prop.write({'property_state': 'on_rent'})
else:
prop.write({'property_state': 'vacant'})
def update_mange(self):
property_ids = self.env['yuthon.property'].search([('name', 'ilike', '天河商贸大厦')])
for property_id in property_ids:
property_id.is_message_fee = True
def update_is_new(self):
# property_ids = self.env["yuthon.property"].browse(
# self._context.get('active_ids', self._context.get('active_id')))
property_ids = self.env['yuthon.property'].search([])
for property_id in property_ids:
property_id.compute_is_new()
def update_message(self):
property_ids = self.env["yuthon.property"].browse(
self._context.get('active_ids', self._context.get('active_id')))
for property_rec in property_ids:
if not property_rec.manage_information_ids:
continue
date_groups = {}
for line in property_rec.manage_information_ids:
date_key = line.start_time or 'no_date'
if date_key not in date_groups:
date_groups[date_key] = []
date_groups[date_key].append(line.id)
ids_to_unlink = []
for date_key, line_ids in date_groups.items():
if len(line_ids) > 1:
ids_to_unlink.extend(line_ids[1:])
if ids_to_unlink:
self.env['manage.information.line'].browse(ids_to_unlink).unlink()
@api.depends('manage_information_ids', 'manage_information_ids.start_time',
'manage_information_ids.end_date', 'is_done_split')
def compute_is_new(self):
current_date = fields.Date.today()
for record in self:
has_valid_line = True
if record.disassembly_information_ids:
record.is_new = False
continue
for line in record.manage_information_ids:
start_valid = line.start_time <= current_date if line.start_time else False
end_valid = (not line.end_date) or (line.end_date >= current_date)
if start_valid and end_valid:
has_valid_line = True
break
record.is_new = has_valid_line
@api.onchange('reference_ids')
def _onchange_reference_ids(self):
for record in self:
if record.reference_ids:
record.lease_period = record.reference_ids[-1].lease_period
record.rent_period = record.reference_ids[-1].rent_period
record.first_years_begin = record.reference_ids[-1].first_years_begin
record.increments_few_years = record.reference_ids[-1].increments_few_years
record.annual_increase_percentage = record.reference_ids[-1].annual_increase_percentage
record.annual_increase_amount = record.reference_ids[-1].annual_increase_amount
record.rent_unit = record.reference_ids[-1].rent_unit
else:
record.lease_period = 0.0
record.rent_period = 0.0
record.first_years_begin = 0.0
record.increments_few_years = 0.0
record.annual_increase_percentage = 0.0
record.annual_increase_amount = 0.0
record.rent_unit = 0.0
@api.depends('name')
def _compute_first_letter(self):
for record in self:
name = record.name
if name:
first_char = name[0]
pinyin_list = lazy_pinyin(first_char)
if pinyin_list:
record.first_letter = pinyin_list[0][0].upper()
else:
record.first_letter = ''
else:
record.first_letter = ''
@api.depends('title_information_ids.start_time', 'title_information_ids.owner_id',
'title_information_ids.title_certificate', 'title_information_ids.registered_id',
'title_information_ids.property_message_id',
'title_information_ids.equity_area')
def _compute_title_information_fields(self):
for rec in self:
if rec.title_information_ids:
latest_title = rec.title_information_ids.sorted('start_time', reverse=True)[0]
rec.update({
'title_address': latest_title.property_message_id,
'owner_id': latest_title.owner_id,
'title_deed': latest_title.title_certificate,
'registered_id': latest_title.registered_id,
'equity_area': latest_title.equity_area,
})
def update_manage(self):
property_ids = self.env['yuthon.property'].search([])
for record in property_ids:
record.compute_information_fields()
@api.depends('manage_information_ids.start_time', 'manage_information_ids.end_date',
'manage_information_ids.precinct_id', 'manage_information_ids.tenure_type',
'manage_information_ids.management_area', 'manage_information_ids.rent_area',
'manage_information_ids.admin_id', 'manage_information_ids.purpose_id',
'manage_information_ids.company_id')
def compute_information_fields(self):
current_date = fields.Date.today() # 获取当前日期
for rec in self:
valid_info = rec.manage_information_ids.filtered(
lambda info: info.start_time <= current_date and
(not info.end_date or info.end_date >= current_date)
)
if valid_info:
current_info = valid_info[0]
rec.update({
'effective_date': current_info.start_time,
'end_date': current_info.end_date,
'purpose_id': current_info.purpose_id,
'precinct_id': current_info.precinct_id,
'tenure_type': current_info.tenure_type,
'management_area': current_info.management_area,
'rent_area': current_info.rent_area,
'admin_id': current_info.admin_id,
'company_id': current_info.company_id,
})
contract_lines = self.env['property.lease.contract.line'].search([
('address_id', '=', rec.id)
])
if contract_lines:
contract_lines.write({'admin_line_id': current_info.admin_id})
else:
rec.update({
'purpose_id': False,
'precinct_id': False,
'tenure_type': False,
'management_area': False,
'rent_area': False,
'admin_id': False,
'company_id': False,
})
# 物业关联电表按钮
def add_archives_meter_button(self):
"""
关联水电表按钮
:return:
"""
return {
'name': '物业关联电表弹窗',
'type': 'ir.actions.act_window',
'res_model': 'utility.meter.wizard',
'view_mode': 'form',
'target': 'new',
'context': {
'default_property_id': self.id,
'default_meter_type': 'archives',
}
}
# 物业关联水表按钮
def add_water_meter_button(self):
return {
'name': '物业关联水表弹窗',
'type': 'ir.actions.act_window',
'res_model': 'utility.meter.wizard',
'view_mode': 'form',
'target': 'new',
'context': {
'default_property_id': self.id,
'default_meter_type': 'water',
}
}
# @api.onchange('energy_meter_ids')
# def _onchange_energy_meter_ids(self):
# if not hasattr(self.id, 'origin') or not self.id.origin:
# return
# target_property_id = self.id.origin
# meter_model = self.env['property.meter.archives']
# related_meters = meter_model.search([
# ('yuthon_property_ids', 'in', [target_property_id])
# ])
# if related_meters:
# related_meters.write({
# 'yuthon_property_ids': [(6, 0, [])]
# })
# for rec in self.energy_meter_ids:
# meter_id = meter_model.browse(rec.property_meter_archives_id.id)
# meter_id.write({
# 'yuthon_property_ids': [(6, 0, [target_property_id])]
# })
@api.onchange('water_meter_ids')
def _onchange_water_meter_idss(self):
if not hasattr(self.id, 'origin') or not self.id.origin:
return
target_property_id = self.id.origin
water_meter_model = self.env['property.meter.water']
related_water_meters = water_meter_model.search([
('yuthon_property_ids', 'in', [target_property_id])
])
if related_water_meters:
related_water_meters.write({
'yuthon_property_ids': [(6, 0, [])]
})
for rec in self.water_meter_ids:
meter_id = water_meter_model.browse(rec.property_meter_water_id.id)
meter_id.write({
'yuthon_property_ids': [(6, 0, [target_property_id])]
})
@api.onchange('building_area')
def _onchange_building_area(self):
for rec in self:
rec.management_area = rec.building_area
rec.rent_area = rec.building_area
# 待评估物业相关信息
unit_price = fields.Float(string='单价')
current_status = fields.Date(string='现状(合同到期日)')
registered_id = fields.Many2one('yuthon.purpose.evidence', string='证载用途', compute="_compute_title_information_fields", store=True)
rental_conditions = fields.Text(string='出租条件')
district_manager = fields.Char(string='片区负责人')
remarks = fields.Text(string='备注')
evaluation_asset = fields.Char(string='评估资产')
evaluation_area = fields.Float(string='评估面积(m²)')
evaluation_category = fields.Char(string='评估类别')
precinct_id = fields.Many2one('yuthon.precinct.message', string="所属片区", compute="compute_information_fields", store=True)
last_hand_rent_price = fields.Float(string='上一手历史租金单价(元/m²•月)')
gov_rent_price = fields.Float(string='政府租金参考价')
evaluation_rent_price = fields.Float(string='评估散租单价(元/m²•月)')
evaluation_rent_total = fields.Float(string='评估总价(元•月,散租)')
evaluation_whole_rent_price = fields.Float(string='评估整租单价(元/m² •月)')
evaluation_whole_rent_total = fields.Float(string='评估总价(元•月,整租)')
def update_precinct(self):
property_ids = self.env["yuthon.property"].browse(
self._context.get('active_ids', self._context.get('active_id')))
for rec in property_ids:
rec.compute_information_fields()
def put_declare_approval(self):
property_ids = self.env["yuthon.property"].browse(
self._context.get('active_ids', self._context.get('active_id')))
form_id = self.env.ref('yuthon_property_approval.view_property_rental_form_form').id
property_list = []
for record in property_ids:
property_list.append([0, 0, {'property_id': record.id}])
return {
'name': '提交出租申报',
'view_mode': 'form',
'res_model': 'property.rental.form',
'type': 'ir.actions.act_window',
'views': [(form_id, 'form')],
"context": {'default_property_rental_form_line_ids': property_list}
}
def open_record(self):
return {
"type": "ir.actions.act_window",
"res_model": 'yuthon.property',
"res_id": self.id,
"name": '物业详情',
"view_mode": "form",
}
def put_offline_approval(self):
form_id = self.env.ref('yuthon_property_approval.view_property_offline_registration_form').id
return {
'name': '提交下线出租',
'view_mode': 'form',
'res_model': 'property.offline.registration',
'type': 'ir.actions.act_window',
'views': [(form_id, 'form')],
"context": {
'default_property_id': self.id
}
}
def put_adjustment_approval(self):
form_id = self.env.ref('yuthon_property_approval.view_property_rental_conditions_form').id
return {
'name': '出租价格调整申请',
'view_mode': 'form',
'res_model': 'property.rental.conditions',
'type': 'ir.actions.act_window',
'views': [(form_id, 'form')],
"context": {
'default_property_id': self.id
}
}
def put_property_handover(self):
property_ids = self.env["yuthon.property"].browse(
self._context.get('active_ids', self._context.get('active_id')))
form_id = self.env.ref('yuthon_property_approval.view_property_handover_form').id
property_list = []
for record in property_ids:
property_list.append([0, 0, {'property_id': record.id}])
return {
'name': '提交物业移交',
'view_mode': 'form',
'res_model': 'property.handover',
'type': 'ir.actions.act_window',
'views': [(form_id, 'form')],
"context": {
'default_property_handover_ids': property_list
}
}
def put_property_management(self):
property_ids = self.env["yuthon.property"].browse(
self._context.get('active_ids', self._context.get('active_id')))
form_id = self.env.ref('yuthon_property_approval.view_property_management_form').id
property_list = []
today = fields.Date.today()
for record in property_ids:
for manage in record.manage_information_ids:
# 判断记录是否有效:start_time ≤ today ≤ end_date(或end_date为空)
if manage.start_time and manage.start_time <= today:
if not manage.end_date or manage.end_date >= today:
manage_id = manage
else:
manage_id = False
else:
manage_id = False
property_list.append([0, 0, {'property_id': record.id,
'precinct_id': record.precinct_id.id,
'purpose_id': manage_id.purpose_id.id if manage_id else None,
'information_line_id': manage_id.id if manage_id else None}])
return {
'name': '提交物业变更',
'view_mode': 'form',
'res_model': 'property.management',
'type': 'ir.actions.act_window',
'views': [(form_id, 'form')],
"context": {
'default_management_line2_ids': property_list
}
}
def put_assessment_approval(self):
for record in self:
self.env['property.evaluation.plan'].create({
'name': record.name,
'property_ids': [(6, 0, [record.id])],
'evaluation_area': record.rent_area,
'owner_id': record.owner_id.id if record.owner_id else None,
'registered_id': record.registered_id.id if record.registered_id else None,
'lease_period': record.lease_period,
'first_years_begin': record.first_years_begin,
'increments_few_years': record.increments_few_years,
'annual_increase_amount': record.annual_increase_amount,
'rent_unit': record.rent_unit,
'annual_increase_percentage': record.reference_ids[-1].annual_increase_percentage if record.reference_ids else None,
'assessment_category': 'rent_money',
'remake': record.remark,
})
record.write({'property_state': 'ing'})
return {
"name": "物业评估方案",
'type': 'ir.actions.act_window',
'res_model': 'property.evaluation.plan',
"view_mode": "tree",
}
def all_assessment_approval(self):
property_ids = self.env["yuthon.property"].browse(
self._context.get('active_ids', self._context.get('active_id')))
for record in property_ids:
if record.property_leasing == 'ing':
raise UserError(f'{record.name}该物业已在评估,请勿重复提交')
self.env['property.evaluation.plan'].create({
'name': record.name,
'property_ids': [(6, 0, [record.id])],
'evaluation_area': record.rent_area,
'owner_id': record.owner_id.id if record.owner_id else None,
'registered_id': record.registered_id.id if record.registered_id else None,
'lease_period': record.lease_period,
'first_years_begin': record.first_years_begin,
'increments_few_years': record.increments_few_years,
'annual_increase_amount': record.annual_increase_amount,
'rent_unit': record.rent_unit,
'annual_increase_percentage': record.reference_ids[-1].annual_increase_percentage if record.reference_ids else None,
'assessment_category': 'rent_money',
'remake': record.remark,
})
record.write({'property_leasing': 'ing'})
return {
"name": "物业评估方案",
'type': 'ir.actions.act_window',
'res_model': 'property.evaluation.plan',
"view_mode": "tree",
}
# 拆分
def put_split_approval(self):
property_ids = self.env["yuthon.property"].browse(
self._context.get('active_ids', self._context.get('active_id')))
for record in property_ids:
form_id = self.env.ref('yuthon_property_approval.view_property_split_approval_form').id
return {
'name': '拆分物业审批',
'view_mode': 'form',
'res_model': 'property.split.approval',
'type': 'ir.actions.act_window',
'views': [(form_id, 'form')],
'context': {
'default_property_id': record.id
}}
# 合并
def put_merge_approval(self):
property_ids = self.env["yuthon.property"].browse(
self._context.get('active_ids', self._context.get('active_id')))
form_id = self.env.ref('yuthon_property_approval.view_property_merge_approval_form').id
property_list = []
for record in property_ids:
property_list.append([0, 0, {
'property_id': record.id
}])
return {
'name': '合并物业审批',
'view_mode': 'form',
'res_model': 'property.merge.approval',
'type': 'ir.actions.act_window',
'views': [(form_id, 'form')],
'context': {
'default_property_merge_approval_line_ids':property_list
}}
def action_yuthon_property_wizard(self):
return {
"type": "ir.actions.act_window",
"name": "批量导入物业",
"res_model": "yuthon.property.wizard",
"view_mode": "form",
"target": "new",
}
def action_relevance_contract(self):
property_ids = self.env["yuthon.property"].browse(
self._context.get('active_ids', self._context.get('active_id')))
property_contract_list = []
for record in property_ids:
contract_ids = self.env["'property.lease.contract.line"].search([('address_id', '=', record.id)])
if contract_ids:
for contract in contract_ids:
record.write({'contract_id': contract.lease_id.id})
def trigger_company_id(self):
property_ids = self.env["yuthon.property"].browse(
self._context.get('active_ids', self._context.get('active_id')))
for record in property_ids:
precinct_id = self.env["yuthon.precinct.message"].search([('employee_id.name', '=', record.owner_id.name)])
owner_id = record.title_information_ids[-1].owner_id.id if record.title_information_ids else ''
company_id = record.manage_information_ids[-1].company_id.id if record.manage_information_ids else ''
lease_period = record.reference_ids[-1].lease_period if record.reference_ids else ''
rent_period = record.reference_ids[-1].rent_period if record.reference_ids else ''
first_years_begin = record.reference_ids[-1].first_years_begin if record.reference_ids else ''
increments_few_years = record.reference_ids[-1].increments_few_years if record.reference_ids else ''
annual_increase_amount = record.reference_ids[-1].annual_increase_amount if record.reference_ids else ''
rent_unit = record.reference_ids[-1].rent_unit if record.reference_ids else ''
title_address = record.title_information_ids[-1].property_message_id if record.title_information_ids else ''
title_deed = record.title_information_ids[-1].title_certificate if record.title_information_ids else ''
registered_id = record.title_information_ids[-1].registered_id.id if record.title_information_ids else ''
record.registered_id = registered_id
record.company_id = company_id
record.title_address = title_address
record.rent_period = rent_period
record.first_years_begin = first_years_begin
record.increments_few_years = increments_few_years
record.annual_increase_amount = annual_increase_amount
record.rent_unit = rent_unit
record.owner_id = owner_id
record.company_id = company_id
record.lease_period = lease_period
record.title_deed = title_deed
record.precinct_id = precinct_id.id if precinct_id else ''
if record.manage_information_ids:
record.manage_information_ids[-1].precinct_id = precinct_id.id if precinct_id else ''
def revert_change(self):
property_ids = self.env["yuthon.property"].browse(
self._context.get('active_ids', self._context.get('active_id')))
for record in property_ids:
lines = record.manage_information_ids
prev_line = lines[-2]
# 删除最后一条记录
lines[-1].unlink()
# 更新当前记录的字段
record.write({
'purpose_id': prev_line.purpose_id.id,
'admin_id': prev_line.admin_id.id,
'precinct_id': prev_line.precinct_id.id,
'company_id': prev_line.company_id.id,
'management_area': prev_line.management_area,
'rent_area': prev_line.rent_area,
'tenure_type': prev_line.tenure_type,
})
# 合同信息还原
contract = self.env['property.lease.contract.line'].search(
[('address_id', '=', record.id)],
limit=1
)
if contract:
lease_id = contract.lease_id
lease_id.write({'admin_id': prev_line.admin_id.id})
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': '操作成功',
'message': '物业变更信息已成功还原',
'sticky': False, # 不显示关闭按钮,自动消失
'type': 'success', # 成功消息样式
}
}
def copy(self, default=None):
new_record = super(YuthonProperty, self).copy(default=default)
for title_line in self.title_information_ids:
title_line.copy({
'yuthon_property_id': new_record.id,
})
for manage_line in self.manage_information_ids:
manage_line.copy({
'yuthon_property_id': new_record.id,
})
return new_record
class YuthonPropertyWater(models.Model):
_name = 'yuthon.property.water'
_description = '水表'
property_meter_water_id = fields.Many2one('property.meter.water', string="水表库")
rate = fields.Integer(related='property_meter_water_id.gauge_magnification', string="倍率", store=True)
standard_id = fields.Many2one(related='property_meter_water_id.standards_id', string="标准", store=True)
installation_date = fields.Date(related='property_meter_water_id.start_time', string="安装日期")
demolition_date = fields.Date(related='property_meter_water_id.end_time', string="拆除日期")
epitope_values_id = fields.Many2one(related='property_meter_water_id.epitope_values_id', string="位置")
yuthon_property_id = fields.Many2one('yuthon.property', string="物业管理")
# 水表跳转
def detail(self):
return {
"type": "ir.actions.act_window",
"name": "水表库",
"res_model": "property.meter.water",
"res_id": self.property_meter_water_id.id,
"view_mode": "form",
"target": "new"
}
def unlink(self):
for record in self:
if record.property_meter_water_id and record.yuthon_property_id:
if record.yuthon_property_id in record.property_meter_water_id.yuthon_property_ids:
record.property_meter_water_id.write({
'yuthon_property_ids': [(3, record.yuthon_property_id.id)]
})
return super().unlink()
class YuthonPropertyEnergy(models.Model):
_name = 'yuthon.property.energy'
_description = '电表'
property_meter_archives_id = fields.Many2one('property.meter.archives', string="电表编号")
unit_number = fields.Char(related='property_meter_archives_id.unit_number', string="单元编号/用途", store=True)
standard_id = fields.Many2one(related='property_meter_archives_id.standards_id', string="标准", store=True)
installation_date = fields.Date(related='property_meter_archives_id.start_time', string="安装日期")
demolition_date = fields.Date(related='property_meter_archives_id.end_time', string="拆除日期")
epitope_values_id = fields.Many2one(related='property_meter_archives_id.epitope_values_id', string="位置")
yuthon_property_id = fields.Many2one('yuthon.property', string="物业管理")
# 电表跳转
def detail(self):
return {
"type": "ir.actions.act_window",
"name": "电表库",
"res_model": "property.meter.archives",
"res_id": self.property_meter_archives_id.id,
"view_mode": "form",
"target": "new"
}
# 补充删除取消关联的逻辑
def unlink(self):
for record in self:
if record.property_meter_archives_id and record.yuthon_property_id:
if record.yuthon_property_id in record.property_meter_archives_id.yuthon_property_ids:
record.property_meter_archives_id.write({
'yuthon_property_ids': [(3, record.yuthon_property_id.id)]
})
return super().unlink()
class TitleInformationLine(models.Model):
_name = 'title.information.line'
_description = '产权信息明细行'
yuthon_property_id = fields.Many2one('yuthon.property', string="关联物业信息")
property_message_id = fields.Many2one('yuthon.property.message', string='产权地址')
owner_id = fields.Many2one(related='property_message_id.owner_id', string="权属人")
equity_area = fields.Float(related='property_message_id.equity_area', string="产权面积", digits=(16, 4))
registered_id = fields.Many2one(related='property_message_id.registered_id', string='证载用途')
property_use_time = fields.Selection(related='property_message_id.property_use_time', string="产权年限")
life_timer = fields.Date(related='property_message_id.life_timer', string="使用时间")
title_certificate = fields.Char(related='property_message_id.title_certificate', string="产权证号")
start_time = fields.Date(string="生效日期", default=fields.Date.today)
end_date = fields.Date(string="失效日期")
def _check_duplicate_date(self, prop_id, date_val, exclude_id=None):
"""Block duplicate effective dates for the same property."""
if not prop_id or not date_val:
return
domain = [
('yuthon_property_id', '=', prop_id),
('start_time', '=', date_val),
]
if exclude_id:
domain.append(('id', '!=', exclude_id))
if self.search_count(domain):
raise UserError('同一物业的产权信息生效日期不能重复。')
@api.model
def create(self, vals):
prop_id = vals.get('yuthon_property_id')
date_val = vals.get('start_time') or fields.Date.context_today(self)
self._check_duplicate_date(prop_id, date_val)
return super().create(vals)
def write(self, vals):
for rec in self:
prop_id = vals.get('yuthon_property_id', rec.yuthon_property_id.id)
date_val = vals.get('start_time', rec.start_time)
rec._check_duplicate_date(prop_id, date_val, exclude_id=rec.id)
return super().write(vals)
def message_record(self):
return {
"type": "ir.actions.act_window",
"res_model": 'yuthon.property.message',
"res_id": self.property_message_id.id,
"name": "详情",
"view_mode": "form",
}
class ManageInformationLine(models.Model):
_name = 'manage.information.line'
_description = '管理信息明细行'
yuthon_property_id = fields.Many2one('yuthon.property', string="关联物业信息")
purpose_id = fields.Many2one('yuthon.resource.purpose', string="管理类型")
precinct_id = fields.Many2one('yuthon.precinct.message', string="所属片区")
tenure_type = fields.Selection([('self', '自有'), ('agency', '代管')], string='权属类型')
management_area = fields.Float(string="管理面积", digits=(16, 4))
rent_area = fields.Float(string="可租面积", digits=(16, 4))
admin_id = fields.Many2one('res.users', string="管理员")
company_id = fields.Many2one('yuthon.property.company', string="公司")
start_time = fields.Date(string="生效日期", default=fields.Date.today)
end_date = fields.Date(string="失效日期")
create_date = fields.Date(string="创建日期", default=fields.Date.today)
def _check_duplicate_date(self, prop_id, date_val, exclude_id=None):
if not prop_id or not date_val:
return
domain = [
('yuthon_property_id', '=', prop_id),
('start_time', '=', date_val),
]
if exclude_id:
domain.append(('id', '!=', exclude_id))
# 临时因报错注释掉
# if self.search_count(domain):
# property_name = self.env['yuthon.property'].search([('id', '=', prop_id)]).name
# raise UserError(f'同一物业的管理信息生效日期不能重复。当前物业:{property_name}id:{prop_id}')
@api.model
def create(self, vals):
prop_id = vals.get('yuthon_property_id')
date_val = vals.get('start_time') or fields.Date.context_today(self)
self._check_duplicate_date(prop_id, date_val)
return super().create(vals)
def write(self, vals):
for rec in self:
prop_id = vals.get('yuthon_property_id', rec.yuthon_property_id.id)
date_val = vals.get('start_time', rec.start_time)
rec._check_duplicate_date(prop_id, date_val, exclude_id=rec.id)
return super().write(vals)
@api.onchange('precinct_id')
def _onchange_precinct_id(self):
for record in self:
if record.precinct_id:
record.admin_id = record.precinct_id.employee_id.user_id
class DisassemblyInformationLine(models.Model):
_name = 'disassembly.information.line'
_description = '拆分信息明细行'
yuthon_property_id = fields.Many2one('yuthon.property', string="关联物业信息")
property_id = fields.Many2one('yuthon.property', string="物业名称")
rent_area = fields.Float(related='property_id.rent_area', string="可租面积")
start_time = fields.Date(related='property_id.effective_date',string="生效日期")
end_date = fields.Date(related='property_id.end_date',string="失效日期")
class YuthonPropertyAssessment(models.Model):
_name = 'yuthon.property.assessment'
_description = '物业评估'
yuthon_property_id = fields.Many2one('yuthon.property', string="关联物业信息")
name = fields.Char(string="评估名称")
class YuthonPropertyRepair(models.Model):
_name = 'yuthon.property.repair'
_description = '维修'
yuthon_property_id = fields.Many2one('yuthon.property', string="关联物业信息")
name = fields.Char(string="维修名称")
class YuthonPropertyProduction(models.Model):
_name = 'yuthon.property.production'
_description = '安全生产'
yuthon_property_id = fields.Many2one('yuthon.property', string="关联物业信息")
produce_id = fields.Many2one('yuthon.property.produce', string="检查项目")
check_context = fields.Text(related='produce_id.check_context', string='检查内容')
check_results = fields.Text(related='produce_id.check_results', string='检查结果')
check_criteria = fields.Text(related='produce_id.check_criteria', string='检查标准')
there_problem = fields.Text(related='produce_id.there_problem', string='存在问题')
problem_suggestion = fields.Text(related='produce_id.problem_suggestion', string='整改措施')
problem_date = fields.Date(related='produce_id.problem_date', string='整改期限')
review_situation = fields.Text(related='produce_id.review_situation', string='复查情况')
check_people = fields.Many2one(related='produce_id.check_people', string="检查人")
check_date = fields.Date(related='produce_id.check_date', string="检查日期")
class YuthonReferenceConditions(models.Model):
_name = 'yuthon.reference.conditions'
_description = '出租参考条件'
yuthon_property_id = fields.Many2one('yuthon.property', string="关联物业信息")
lease_period = fields.Integer(string='租赁期限(<=)')
rent_period = fields.Integer(string="免租期(<=)")
first_years_begin = fields.Integer(string='第几年开始')
increments_few_years = fields.Integer(string='每几年递增')
annual_increase_percentage = fields.Float(string='递增百分比', igits=(6, 2))
annual_increase_amount = fields.Float(string='递增金额', igits=(6, 2))
rent_unit = fields.Float(string='递增单价', igits=(6, 2))
class YuthonMajorEventLine(models.Model):
_name = 'yuthon.major.event.line'
_description = '重大事件'
yuthon_property_id = fields.Many2one('yuthon.property', string="关联物业信息")
major_id = fields.Many2one('major.event.setting', string="重大事件")
inspector_html = fields.Html(related='major_id.inspector_html', string="内容")
documents_ids = fields.Many2many(related='major_id.documents_ids', string="附件")
start_date = fields.Date(related='major_id.start_date', store=True)
def _get_date_from_vals(self, vals):
"""Get start_date considering related major_id."""
if vals.get('start_date'):
return vals['start_date']
major_id = vals.get('major_id')
if major_id:
return self.env['major.event.setting'].browse(major_id).start_date
return None
def _check_duplicate_date(self, prop_id, date_val, exclude_id=None):
if not prop_id or not date_val:
return
domain = [
('yuthon_property_id', '=', prop_id),
('start_date', '=', date_val),
]
if exclude_id:
domain.append(('id', '!=', exclude_id))
if self.search_count(domain):
raise UserError('同一物业的重大事项生效日期不能重复。')
@api.model
def create(self, vals):
prop_id = vals.get('yuthon_property_id')
date_val = self._get_date_from_vals(vals)
self._check_duplicate_date(prop_id, date_val)
return super().create(vals)
def write(self, vals):
for rec in self:
prop_id = vals.get('yuthon_property_id', rec.yuthon_property_id.id)
date_val = self._get_date_from_vals(vals) if 'major_id' in vals or 'start_date' in vals else rec.start_date
rec._check_duplicate_date(prop_id, date_val, exclude_id=rec.id)
return super().write(vals)