183 lines
9.3 KiB
Python
183 lines
9.3 KiB
Python
# -*- coding: utf-8 -*-
|
||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||
|
||
from odoo import models, fields, api, exceptions, _, Command
|
||
from odoo.exceptions import UserError
|
||
|
||
|
||
class PropertyConfirm(models.Model):
|
||
_name = 'property.confirm'
|
||
_description = '物业成交确认审批'
|
||
_inherit = ['soong.workflow.mixin', 'mail.thread.main.attachment', 'mail.activity.mixin']
|
||
_rec_name = 'name'
|
||
|
||
name = fields.Char(string='标题')
|
||
code = fields.Char(string="编号", default=lambda self: self.env['ir.sequence'].next_by_code('property_confirm_code'))
|
||
property_documents_ids = fields.Many2many('documents.document', string="物业成交确认文件")
|
||
lessee = fields.Char(string="承租方")
|
||
users_id = fields.Many2one('res.users', string="申请人", default=lambda self: self.env.user.id)
|
||
department_id = fields.Many2one(related='users_id.employee_id.department_id', string="部门")
|
||
active = fields.Boolean('Active', default=True, tracking=True)
|
||
work_end = fields.Boolean(string="结束")
|
||
urgency_level = fields.Selection([('normal', '普件'), ('urgent', '急件'), ('emergency', '特急件')], string='紧急度', default='normal')
|
||
is_chapter = fields.Selection([('yes', '是'), ('no', '否')], string='是否用章', default='no')
|
||
property_name = fields.Char(string='物业信息')
|
||
handling_opinions = fields.Text(string="经办意见")
|
||
type_stamp_ids = fields.Many2many('seals.type.setting', string='用章类型', domain="['&', ('start_date', '<=', context_today()), '|', ('end_date', '=', False), ('end_date', '>=', context_today())]")
|
||
documents_ids = fields.Many2many('ir.attachment', string="附件")
|
||
lease_ids = fields.One2many('property.lease.contract.line', 'confirm_id', string="物业列表")
|
||
# 面积:下方物业明细行「可租面积(property_area)」的合计
|
||
property_area = fields.Float(string="面积", compute="_compute_property_area", digits=(16, 4))
|
||
# 租期年限(整型)
|
||
lease_term_years = fields.Integer(string="租期年限")
|
||
# 免租天数(整型)
|
||
rent_free_days = fields.Integer(string="免租天数")
|
||
# 每几年递增(整型,与递增百分比组合成「每 __ 年递增 __ %」)
|
||
increments_few_years = fields.Integer(string="每几年递增")
|
||
# 递增百分比
|
||
annual_increase_percentage = fields.Float(string="递增百分比", digits=(6, 2))
|
||
|
||
# 「经办人 / 审批状态」取自本单据的工作流记录(口径同 property.lease.contract)
|
||
employee_ids = fields.Many2many('hr.employee', string="当前经办人", compute='_compute_workflow')
|
||
approve_state = fields.Selection([("start", "草稿"), ("pending", "审批中"), ("end", "结束")],
|
||
string="审批状态", compute='_compute_workflow')
|
||
# 业务状态:取物业明细「第一个」行的物业业务状态(只读展示)
|
||
business_state = fields.Selection(
|
||
related='lease_ids.address_id.business_state', string='业务状态')
|
||
|
||
@api.depends('code')
|
||
def _compute_workflow(self):
|
||
for record in self:
|
||
workflow = record._get_active_workflow_record()
|
||
record.employee_ids = workflow.employee_ids if workflow else False
|
||
record.approve_state = workflow.approve_state if workflow else False
|
||
|
||
@api.depends('lease_ids', 'lease_ids.property_area')
|
||
def _compute_property_area(self):
|
||
# 汇总每条成交确认单下所有物业明细行的可租面积
|
||
for rec in self:
|
||
rec.property_area = sum(rec.lease_ids.mapped('property_area'))
|
||
|
||
@staticmethod
|
||
def _x2m_lease_property_ids(commands):
|
||
"""从「物业列表」的一对多命令里取出物业 id(address_id)"""
|
||
ids = set()
|
||
for cmd in commands or []:
|
||
if cmd[0] == Command.CREATE and len(cmd) > 2 and cmd[2].get('address_id'):
|
||
ids.add(cmd[2]['address_id'])
|
||
return list(ids)
|
||
|
||
@api.model
|
||
def _check_no_duplicate_application(self, properties):
|
||
"""前置校验:同一物业不能重复生成成交确认书
|
||
(已存在「未进回收站」的成交确认书即视为已申请过)"""
|
||
records = self.env['property.confirm'].search([('lease_ids.address_id', 'in', properties.ids)])
|
||
alive = records.filtered(lambda rec: rec._has_active_workflow_record())
|
||
duplicated = alive.mapped('lease_ids.address_id') & properties
|
||
if duplicated:
|
||
raise UserError('以下物业已生成过成交确认书(未进回收站),不能重复申请:%s'
|
||
% '、'.join(duplicated.mapped('name')))
|
||
|
||
@api.model_create_multi
|
||
def create(self, vals_list):
|
||
# 先校验(在建表之前):同一物业不能重复生成成交确认书
|
||
prop_ids = []
|
||
for vals in vals_list:
|
||
prop_ids += self._x2m_lease_property_ids(vals.get('lease_ids'))
|
||
if prop_ids:
|
||
self._check_no_duplicate_application(self.env['yuthon.property'].browse(set(prop_ids)))
|
||
|
||
records = super().create(vals_list)
|
||
# 保存时业务状态为「待签约」;推进到「签约中」是在**转交**时(见 _on_workflow_transfer)
|
||
# 只向前推进:已处于「待签约/签约中/已签约」的不再改动,避免把流程回退
|
||
props = records.mapped('lease_ids.address_id').filtered(
|
||
lambda prop: prop.business_state not in ('to_sign', 'signing', 'signed'))
|
||
if props:
|
||
props.write({'business_state': 'to_sign'})
|
||
return records
|
||
|
||
def _on_workflow_transfer(self):
|
||
"""转交(工作流弹窗触发,仅挂牌申报表/成交确认书):关联物业业务状态「待签约」→「签约中」"""
|
||
props = self.mapped('lease_ids.address_id').filtered(
|
||
lambda prop: prop.business_state in (False, '', 'to_sign'))
|
||
if props:
|
||
props.write({'business_state': 'signing'})
|
||
|
||
def action_create_contract(self):
|
||
"""创建合同:把成交确认书的物业与条件带进租赁合同
|
||
|
||
字段对应关系:
|
||
- 物业 → 合同「物业信息明细行」(`lease_ids.address_id`)
|
||
- 面积 → 合同「总面积」(`total_area`)
|
||
- 租期年限 → 合同「租期(年)」(`lease_term_year`)
|
||
- 免租天数 → 合同「免租期 月/日」;**31 天算 1 个月**(如 32 天 → 1 月 1 日)
|
||
- 每 X 年递增 Y% → 合同「每几年递增」+ 递增方式=百分比 + 递增值
|
||
(对应合同递增组合字段的后半部分,不涉及「自第 X 年开始」)
|
||
"""
|
||
self.ensure_one()
|
||
# 只有审批状态为「结束」的成交确认书才能创建合同(列表按钮同样按此显隐)
|
||
if self.approve_state != 'end':
|
||
raise UserError('只有审批状态为「结束」的成交确认书才能创建合同')
|
||
properties = self.lease_ids.mapped('address_id')
|
||
if not properties:
|
||
raise UserError('该成交确认书未关联物业,无法创建合同')
|
||
form_id = self.env.ref('yuthon_property_approval.view_property_lease_contract_form').id
|
||
# 免租天数换算成「月/日」:31 天 = 1 个月;余数为 0 时借一个月,避免出现「X月0日」
|
||
# 例:31 天 → 0月31日;32 天 → 1月1日;62 天 → 1月31日
|
||
free_months, free_days = divmod(self.rent_free_days or 0, 31)
|
||
if free_months and not free_days:
|
||
free_months -= 1
|
||
free_days = 31
|
||
return {
|
||
'name': '合同审批',
|
||
'type': 'ir.actions.act_window',
|
||
'res_model': 'property.lease.contract',
|
||
'view_mode': 'form',
|
||
'views': [(form_id, 'form')],
|
||
'target': 'current',
|
||
'context': {
|
||
'default_lease_ids': [(0, 0, {'address_id': prop.id}) for prop in properties],
|
||
'default_total_area': self.property_area,
|
||
'default_lease_term_year': self.lease_term_years,
|
||
'default_rent_free_period_month': free_months,
|
||
'default_rent_free_period_days': free_days,
|
||
'default_increments_every_few_years': self.increments_few_years,
|
||
'default_increment_method': 'percentage',
|
||
'default_increment_value': self.annual_increase_percentage,
|
||
},
|
||
}
|
||
|
||
def _get_default_name_title(self):
|
||
return '成交确认书'
|
||
|
||
name_title = fields.Char(default=_get_default_name_title)
|
||
|
||
@api.onchange('property_name')
|
||
def _onchange_property_name(self):
|
||
if self.property_name:
|
||
self.name = '成交确认书-' + self.property_name
|
||
else:
|
||
self.name = '成交确认书'
|
||
|
||
def choose_property_button(self):
|
||
return {
|
||
"type": "ir.actions.act_window",
|
||
"name": "批量选择物业信息",
|
||
"res_model": "choose.confirm.property.wizard",
|
||
"view_mode": "form",
|
||
"target": "new",
|
||
"context": {
|
||
'default_confirm_id': self.id,
|
||
}
|
||
}
|
||
|
||
|
||
class PropertyConfirm(models.Model):
|
||
_inherit = 'property.confirm'
|
||
|
||
def action_print_property_confirm(self):
|
||
"""打印成交确认书"""
|
||
self.ensure_one()
|
||
report = self.env.ref('yuthon_property_approval.action_property_confirm_report')
|
||
return report.report_action(self)
|