Files
2026-09-24 19:38:13 +08:00

169 lines
9.4 KiB
Python
Raw Permalink 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, Command
from odoo.exceptions import UserError
# 已进入签约流程的业务状态:这些物业不再放入挂牌申报表
SIGN_FLOW_STATES = ('to_sign', 'signing', 'signed')
class PropertyRentalForm(models.Model):
_name = 'property.rental.form'
_description = '挂牌申报表'
_rec_name = 'name'
_inherit = ['mail.thread.main.attachment', 'mail.activity.mixin', 'soong.workflow.mixin']
name = fields.Char(string="名称", required=True)
reason = fields.Text(string="正文")
documents_ids = fields.Many2many('ir.attachment', string="附件")
listing_method = fields.Selection([('enterprise', '企业自挂牌'), ('makeup', '广交所挂牌')], 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="部门")
property_rental_form_line_ids = fields.One2many('property.rental.form.line', 'property_rental_form_id', string="关联挂牌申报表明细行")
is_issues = fields.Boolean(string='是否上会')
issues_result = fields.Html(string="会议结果")
related_issues_id = fields.Many2one('issue.library', string="关联议题")
code = fields.Char(string="编号",
default=lambda self: self.env['ir.sequence'].next_by_code('property_rental_form_code'))
urgency_level = fields.Selection([('normal', '普件'), ('urgent', '急件'), ('emergency', '特急件')], string='紧急度',
default='normal')
active = fields.Boolean('Active', default=True, tracking=True)
work_end = fields.Boolean(string="结束")
def _get_default_name_title(self):
return self._description if self._description else self._name
name_title = fields.Char(default=_get_default_name_title)
self_users_ids = fields.Many2many('res.users', string="当前经办人", default=lambda self: [(6, 0, [self.env.user.id])])
# 「经办人 / 审批状态」取自本单据的工作流记录(口径同 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='property_rental_form_line_ids.property_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.model
def _get_listable_properties(self, properties):
"""剔除已进入签约流程(待签约 / 签约中 / 已签约)的物业 —— 这些不放进挂牌申报表"""
return properties.filtered(lambda prop: prop.business_state not in SIGN_FLOW_STATES)
@api.model
def _check_listing_available(self, properties):
"""挂牌申请的前置校验:
① 物业尚未进入挂牌流程(业务状态为 挂牌中/已挂牌 时不可再提交;待签约/签约中/已签约
已由 `_get_listable_properties()` 在入口处剔除,此处作兜底);
② 同一物业不能重复申请 —— 已存在「未进回收站」的挂牌申报表即视为已申请过。
"""
labels = dict(self.env['yuthon.property']._fields['business_state'].selection)
locked_states = ('listing', 'listed', 'to_sign', 'signing', 'signed')
not_ready = properties.filtered(lambda prop: prop.business_state in locked_states)
if not_ready:
detail = '、'.join(
'%s(%s)' % (prop.name, labels.get(prop.business_state) or '未设置')
for prop in not_ready)
raise UserError('以下物业已进入挂牌/签约流程,不能提交挂牌申请:%s' % detail)
duplicated = self._find_duplicated_properties(properties)
if duplicated:
raise UserError('以下物业已提交过挂牌申请(未进回收站),不能重复申请:%s'
% '、'.join(duplicated.mapped('name')))
@api.model
def _find_duplicated_properties(self, properties):
"""已存在「未进回收站」的挂牌申报表的物业(判断依据:该单据有有效的工作流记录)"""
forms = self.env['property.rental.form'].search([
('property_rental_form_line_ids.property_id', 'in', properties.ids),
])
alive = forms.filtered(lambda form: form._has_active_workflow_record())
return alive.mapped('property_rental_form_line_ids.property_id') & properties
@api.model_create_multi
def create(self, vals_list):
# 已进入签约流程(待签约 / 签约中 / 已签约)的物业**不放进挂牌申报表**:在建表前直接剔除这些明细行
prop_ids = []
for vals in vals_list:
cmds = vals.get('property_rental_form_line_ids') or []
kept = []
for cmd in cmds:
if cmd[0] == Command.CREATE and len(cmd) > 2 and cmd[2].get('property_id'):
prop = self.env['yuthon.property'].browse(cmd[2]['property_id'])
if prop.business_state in SIGN_FLOW_STATES:
continue
prop_ids.append(prop.id)
kept.append(cmd)
if len(kept) != len(cmds):
if not kept:
raise UserError('所选物业均已进入签约流程(待签约/签约中/已签约),不能在挂牌申报表中提交')
vals['property_rental_form_line_ids'] = kept
# 再校验(在建表之前):已进入挂牌/签约流程的物业不能提交
if prop_ids:
self._check_listing_available(self.env['yuthon.property'].browse(prop_ids))
forms = super().create(vals_list)
# 保存时业务状态为「待挂牌」;推进到「挂牌中」是在**转交**时(见 _on_workflow_transfer)
props = forms.mapped('property_rental_form_line_ids.property_id')
waiting = props.filtered(
lambda prop: prop.business_state not in ('listing', 'listed', 'to_sign', 'signing', 'signed'))
if waiting:
waiting.write({'business_state': 'to_list'})
return forms
def _on_workflow_transfer(self):
"""转交(工作流弹窗触发,仅挂牌申报表/成交确认书):关联物业业务状态「待挂牌」→「挂牌中」"""
props = self.mapped('property_rental_form_line_ids.property_id')
waiting = props.filtered(lambda prop: prop.business_state in (False, '', 'to_list'))
if waiting:
waiting.write({'business_state': 'listing'})
def end_approval(self):
"""审批结束:关联物业的业务状态推进为「已挂牌」"""
props = self.mapped('property_rental_form_line_ids.property_id')
waiting = props.filtered(lambda prop: prop.business_state in (False, '', 'listing'))
if waiting:
waiting.write({'business_state': 'listed'})
def action_transaction_confirmed(self):
"""成交确认书:把本单的物业带进「成交确认审批」(property.confirm) 的物业列表"""
self.ensure_one()
properties = self.property_rental_form_line_ids.mapped('property_id')
if not properties:
raise UserError('该挂牌申报表未关联物业,无法生成成交确认书')
form_id = self.env.ref('yuthon_property_approval.view_property_confirm_form').id
return {
'name': '成交确认审批',
'type': 'ir.actions.act_window',
'res_model': 'property.confirm',
'view_mode': 'form',
'views': [(form_id, 'form')],
'target': 'current',
'context': {
'default_lease_ids': [(0, 0, {'address_id': prop.id}) for prop in properties],
},
}
class PropertyRentalFormLine(models.Model):
_name = 'property.rental.form.line'
_description = '挂牌申报表明细行'
property_rental_form_id = fields.Many2one('property.rental.form', string="关联挂牌申报表")
property_id = fields.Many2one('yuthon.property', string='物业名称', required=True)
registered_id = fields.Many2one(related='property_id.registered_id', string='证载用途')
evaluation_area = fields.Float(related='property_id.evaluation_area', string='出租面积(m²)')
current_status = fields.Date(related='property_id.current_status', string='租聘到期日')
now_rent_price = fields.Float(related='property_id.rental_unit_price',string='现租价(元/m² •月)')
evaluate_rent_price = fields.Float(string='评估租(元/m² •月)')
upset_square = fields.Float(string='底价(元/m² •月)')
upset = fields.Float(string='底价(元/月)')
lease_period = fields.Char(string='租凭年限')
increment_rate = fields.Float(string='递增率')
rental_use = fields.Many2one('yuthon.rental.purpose',string='出租用途')
other = fields.Char(string='其他')
remarks = fields.Text(string='备注')