Files
gzth/yuthon_official/models/yuthon_official.py
T
2026-07-02 15:02:40 +08:00

584 lines
26 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.
# -*- coding: utf-8 -*-
from email.policy import default
from odoo import api, fields, models, tools
from odoo.exceptions import ValidationError, UserError
class YuthonOfficial(models.Model):
_name = 'yuthon.official'
_description = '行政发文'
_inherit = ['soong.workflow.mixin', 'mail.thread.main.attachment', 'mail.activity.mixin']
_rec_name = 'name'
name = fields.Char(string="标题")
text = fields.Text(string="标题", compute='_compute_text', store=True)
code = fields.Char(string="编号", default=lambda self: self.env['ir.sequence'].next_by_code('official_code'))
official_type_id = fields.Many2one('official.type', string="文件类型")
is_cold = fields.Boolean(string="发文编号")
reference_cold = fields.Char(string="发文字号")
major_event_category = fields.Integer(string="重大事项所属类别")
official_partner_id = fields.Many2one('official.partner', string="来文单位")
remarks = fields.Char(string="备注事项")
main_text = fields.Text(string='文件内容')
come_file_id = fields.Char(string="来文编号")
incoming_file_id = fields.Char(string="收文编号")
main_flats_ids = fields.Many2many(
'main.flats',
'yuthon_official_main_flats_rel',
'official_id',
'main_flats_id',
string="主送单位"
)
copy_flats_ids = fields.Many2many(
'main.flats',
'yuthon_official_copy_flats_rel',
'official_id',
'copy_flat_id',
string="抄送单位"
)
main_unit_type = fields.Selection([
('gov', '行政事业单位'),
('other', '其他单位')
], string='主送单位类型')
copy_unit_type = fields.Selection([
('gov', '行政事业单位'),
('other', '其他单位')
], string='抄送单位类型')
department_ids = fields.Many2many('hr.department', string='部门范围')
employee_ids = fields.Many2many('hr.employee', string='人员范围')
users_role_ids = fields.Many2many('soong.user.role', string='角色范围')
servings_number = fields.Integer(string="份数")
urgency_level = fields.Selection([('normal', '一般'), ('urgent', '紧急'), ('extra_urgent', '特急')], string="紧急程度", default='normal')
secret_level = fields.Selection([('normal', '一般'), ('urgent', '秘密'), ('secret', '机密'), ('so_secret', '绝密')], string="密级")
date = fields.Datetime(string="拟稿日期", default=fields.Datetime.now)
official_statu = fields.Selection([('done', '办结'), ('approval', '审核')], string="公文环节")
users_id = fields.Many2one('res.users', string="拟稿人", default=lambda self: self.env.user)
department_id = fields.Many2one('hr.department', string="拟稿部门")
allowed_department_ids = fields.Many2many('hr.department', compute='_compute_allowed_departments', store=False)
company_id = fields.Many2one(related='users_id.company_id', string="公司")
company_id1 = fields.Many2one('res.company', string="公司前缀", default=lambda self: self.env.company)
is_meet = fields.Boolean(string="是否上会")
issues_result = fields.Html(string="会议结果")
related_issues_id = fields.Many2one('issue.library', string="关联议题")
is_official_incoming = fields.Boolean(string="是否收文")
active = fields.Boolean('Active', default=True, tracking=True)
is_chapter = fields.Selection([('yes', '是'), ('no', '否')], string="是否用章")
type_stamp_ids = fields.Many2many('seals.type.setting', string='用章类型', domain="['&', ('start_date', '<=', context_today()), '|', ('end_date', '=', False), ('end_date', '>=', context_today())]")
scope_chapter_ids = fields.Many2many('seals.scope.setting', string='用章范围')
red_suit = fields.Char(string="套红")
official_documents_ids = fields.Many2many('ir.attachment', string="附件")
is_supervising = fields.Boolean(string="是否督办")
deadline = fields.Datetime(string="办理期限")
done_date = fields.Date(string="完成时间")
workflow_inspector_ids = fields.One2many('soong.workflow.inspector', 'yuthon_official_id', string="督办事项")
approve_state = fields.Selection([("start", "草稿"), ("pending", "审批中"), ("end", "结束")], string="审批状态",
compute='_compute_workflow', index=True)
room_booking_ids = fields.One2many('room.booking', 'yuthon_official_id', string="会议关联")
issue_library_ids = fields.One2many('issue.library', 'yuthon_official_id', string="议题关联")
work_end = fields.Boolean(string="结束")
official_state = fields.Selection([('to_do', '待转'), ('done', '已转')], string="状态")
sub_id = fields.Many2one('yuthon.sub.enterprises', 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])])
is_company = fields.Boolean(string="本公司", default=True, compute='_compute_is_company',
search='_search_part_of_company')
@api.onchange('users_id')
def _onchange_users_id(self):
employee = self.users_id.employee_id
if employee:
self.department_id = employee.department_id
else:
self.department_id = False
@api.depends('users_id')
def _compute_allowed_departments(self):
for record in self:
employee = record.users_id.employee_id
if employee:
dept_ids = [employee.department_id.id] + employee.department_ids.ids
record.allowed_department_ids = [(6, 0, dept_ids)]
else:
record.allowed_department_ids = [(6, 0, [])]
@api.depends('code')
def _compute_workflow(self):
for record in self:
record.approve_state = False
workflow = self.env['soong.workflow.record'].sudo().search(
[('code', '=', record.code)],
limit=1
)
if workflow:
record.approve_state = workflow.approve_state
@api.depends_context('uid', 'company')
@api.depends('company_id')
def _compute_is_company(self):
active_company_ids = self.env.companies
for employee in self:
employee.is_company = employee.company_id in active_company_ids
def _search_part_of_company(self, operator, value):
company_ids = self.env.companies.ids
if not value:
operator = '!=' if operator == '=' else '='
if operator == '=':
return [('company_id', 'in', company_ids)]
else:
return [('company_id', 'not in', company_ids)]
@api.depends('name')
def _compute_text(self):
for record in self:
record.text = record.name or ''
def end_approval(self):
self.write({'work_end': True})
if any(flat.name == '广州市天河投资集团有限公司' for flat in self.main_flats_ids):
all_document_ids = list(self.official_documents_ids.ids)
for log in self.log_ids:
log_doc_ids = log.document_ids.ids if log.document_ids else []
for doc_id in log_doc_ids:
if doc_id not in all_document_ids:
all_document_ids.append(doc_id)
if self.company_id.name == '集团本部':
official_partner_id = self.env['official.partner'].search([('name', '=', '广州市天河投资集团有限公司')])
elif self.company_id.name == '天河物管':
official_partner_id = self.env['official.partner'].search([('name', '=', '广州市天河物业管理有限公司')])
else:
official_partner_id = self.env['official.partner'].search([('name', '=', '广州天河粮食储备管理有限公司')])
sub_id = self.env['yuthon.sub.enterprises'].create({
'name': self.name,
'users_id': self.users_id.id,
'state': '申请人',
'code': self.env['ir.sequence'].next_by_code('sub_enterprises_code'),
'official_partner_id': official_partner_id.id,
'reason_application': self.main_text,
'document_ids': [(6, 0, all_document_ids)] if all_document_ids else False
})
workflow_id = self.env['soong.workflow.record'].search([('code', '=', self.code)], limit=1).id
if workflow_id:
self.env['soong.workflow.line'].create({
'model': 'yuthon.sub.enterprises',
'res_id': sub_id.id,
'workflow_record_id': workflow_id
})
self.write({'sub_id': sub_id.id})
@api.onchange('is_cold')
def onchange_is_cold(self):
if self.is_cold:
self.onchange_company_id()
else:
self.reference_cold = False
def receipt_processing(self):
if self.official_state == 'done':
raise UserError('该收文已转,请勿重复操作')
return {
'name': '收文处理',
'type': 'ir.actions.act_window',
'res_model': 'yuthon.file.processing',
'view_mode': 'form',
'target': 'new',
'context': {
'default_name': self.name,
'default_official_documents_ids': [(6, 0, [self.official_documents_ids.ids])],
}
}
@api.onchange('is_cold')
def onchange_is_cold(self):
if self.is_cold:
self.onchange_company_id1()
else:
self.reference_cold = False
@api.onchange('main_flats_ids')
def _onchange_main_flats_ids(self):
if self.main_flats_ids:
self.main_unit_type = self.main_flats_ids[0].unit_type
else:
self.main_unit_type = False
@api.onchange('copy_flats_ids')
def _onchange_copy_flats_ids(self):
if self.copy_flats_ids:
self.copy_unit_type = self.copy_flats_ids[0].unit_type
else:
self.copy_unit_type = False
@api.onchange('company_id1')
def onchange_company_id1(self):
current_year = fields.Date.today().year
self.reference_cold = False
if self.company_id1 and self.company_id1.name:
company_name = self.company_id1.name
prefix_map = {
'集团本部': '穗天投',
'天河粮储': '天粮储司',
'天河物管': '穗天物'
}
prefix = prefix_map.get(company_name)
if not prefix:
return
year_str = f"〔{current_year}〕"
domain = [
('company_id1', '=', self.company_id1.id),
('reference_cold', 'like', f"{prefix}{year_str}%")
]
last_record = self.search(domain, order='reference_cold desc', limit=1)
base_num = 27 if (current_year == 2026 and company_name == "集团本部") else 1
max_seq = 0
if last_record and last_record.reference_cold:
try:
seq_str = last_record.reference_cold.split(year_str)[1].rsplit('号', 1)[0]
max_seq = int(seq_str)
except:
max_seq = 0
next_seq = max(max_seq + 1, base_num)
self.reference_cold = f"{prefix}{year_str}{next_seq}号"
def supervising_button(self):
return {
"name": "督查督办",
"type": "ir.actions.act_window",
"view_mode": "form",
"res_model": "soong.workflow.inspector",
"views": [[self.env.ref('soong_workflow.soong_workflow_inspector_form').id, "form"]],
"context": {'default_name': self.name,
'default_start_data': fields.Date.today(),
'default_end_data': self.done_date,
'default_relevancy_type': 'yuthon_official',
'default_yuthon_official_id': self.id,
},
}
def button_meet(self):
return {
"name": "会议",
"type": "ir.actions.act_window",
"view_mode": "form",
"res_model": "room.booking",
"views": [[self.env.ref('room.room_booking_view_form').id, "form"]],
"context": {
'default_name': self.name,
'default_relevancy_type': 'yuthon_official',
'default_yuthon_official_id': self.id,
},
}
def done_publish(self):
users_role_list = department_users_list = []
for depart in self.department_ids:
department_users_data = self.env['hr.employee'].search([('department_id', '=', depart.id)])
department_users_list = [de.id for de in department_users_data]
employee_users_list = [em.user_id.id for em in self.employee_ids]
for user_id in self.users_role_ids:
department_users_data = self.env['soong.user.role'].search([('user_role_id', '=', user_id.id)])
users_role_list = [ro.id for ro in department_users_data]
publish_user_list = list(set(department_users_list + employee_users_list + users_role_list))
partner_ids = self.sudo().env['res.users'].search([('id', 'in', publish_user_list)]).mapped('partner_id').ids
self.sudo().with_context(lang=self.env.lang)._message_auto_subscribe_notify(partner_ids, 'yuthon_official.message_yuthon_official_confirm_users_data')
self.write({"statu": 'done'})
@api.onchange('is_meet')
def _onchange_is_meet(self):
if self.is_meet:
issue_id = self.env['issue.library'].create({'name': self.name, 'is_invisible_workflow': True})
self.related_issues_id = issue_id.id
self.env['issue.library.approval.line'].create({
'issue_library_id': issue_id.id,
'workflow_name': self.name,
'approval_type': self.workflow_id.name,
'res_model': self._name,
'res_id': self.id,
'code': self.code,
'approval_date': fields.Datetime.now(),
})
def action_print_official(self):
"""表单按钮触发打印行政发文审批单"""
self.ensure_one()
report = self.env.ref('yuthon_official.action_official_print_report')
return report.report_action(self)
def button_transfer(self):
"""转交按钮"""
pass
def button_withdraw(self):
"""收回按钮"""
pass
class YuthonPropertyOfficial(models.Model):
_name = 'yuthon.property.official'
_description = '物业发文'
_inherit = ['soong.workflow.mixin', 'mail.thread.main.attachment', 'mail.activity.mixin']
_rec_name = 'name'
name = fields.Char(string="标题")
text = fields.Text(string="标题", compute='_compute_text', store=True)
code = fields.Char(string="编号", default=lambda self: self.env['ir.sequence'].next_by_code('official_code'))
official_type_id = fields.Many2one('official.type', string="文件类型")
is_cold = fields.Boolean(string="发文编号")
reference_cold = fields.Char(string="发文字号")
major_event_category = fields.Integer(string="重大事项所属类别")
official_partner_id = fields.Many2one('official.partner', string="来文单位")
remarks = fields.Char(string="备注事项")
main_text = fields.Text(string='文件内容')
come_file_id = fields.Char(string="来文编号")
incoming_file_id = fields.Char(string="收文编号")
main_flats_ids = fields.Many2many(
'main.flats',
'yuthon_property_official_main_flats_rel',
'official_id',
'main_flats_id',
string="主送单位"
)
copy_flats_ids = fields.Many2many(
'main.flats',
'yuthon_property_official_copy_flats_rel',
'official_id',
'copy_flat_id',
string="抄送单位"
)
main_unit_type = fields.Selection([
('gov', '行政事业单位'),
('other', '其他单位')
], string='主送单位类型')
copy_unit_type = fields.Selection([
('gov', '行政事业单位'),
('other', '其他单位')
], string='抄送单位类型')
department_ids = fields.Many2many('hr.department', string='部门范围')
employee_ids = fields.Many2many('hr.employee', string='人员范围')
users_role_ids = fields.Many2many('soong.user.role', string='角色范围')
servings_number = fields.Integer(string="份数")
urgency_level = fields.Selection([('normal', '一般'), ('urgent', '紧急'), ('extra_urgent', '特急')], string="紧急程度", default='normal')
secret_level = fields.Selection([('normal', '一般'), ('urgent', '秘密'), ('secret', '机密'), ('so_secret', '绝密')], string="密级")
date = fields.Datetime(string="拟稿日期", default=fields.Datetime.now)
official_statu = fields.Selection([('done', '办结'), ('approval', '审核')], string="公文环节")
users_id = fields.Many2one('res.users', string="拟稿人", default=lambda self: self.env.user)
department_id = fields.Many2one(related='users_id.employee_ids.department_id', string="拟稿部门")
company_id = fields.Many2one(related='users_id.company_id', string="公司")
company_id1 = fields.Many2one('res.company', string="公司前缀", default=lambda self: self.env.company)
is_meet = fields.Boolean(string="是否上会")
issues_result = fields.Html(string="会议结果")
related_issues_id = fields.Many2one('issue.library', string="关联议题")
is_official_incoming = fields.Boolean(string="是否收文")
active = fields.Boolean('Active', default=True, tracking=True)
is_chapter = fields.Selection([('yes', '是'), ('no', '否')], string="是否用章")
type_stamp_ids = fields.Many2many('seals.type.setting', string='用章类型', domain="['&', ('start_date', '<=', context_today()), '|', ('end_date', '=', False), ('end_date', '>=', context_today())]")
scope_chapter_ids = fields.Many2many('seals.scope.setting', string='用章范围')
red_suit = fields.Char(string="套红")
official_documents_ids = fields.Many2many('ir.attachment', string="附件")
is_supervising = fields.Boolean(string="是否督办")
deadline = fields.Datetime(string="办理期限")
done_date = fields.Date(string="完成时间")
workflow_inspector_ids = fields.One2many('soong.workflow.inspector', 'yuthon_official_id', string="督办事项")
approve_state = fields.Selection([("start", "草稿"), ("pending", "审批中"), ("end", "结束")], string="审批状态",
compute='_compute_workflow', index=True)
room_booking_ids = fields.One2many('room.booking', 'yuthon_official_id', string="会议关联")
issue_library_ids = fields.One2many('issue.library', 'yuthon_official_id', string="议题关联")
work_end = fields.Boolean(string="结束")
official_state = fields.Selection([('to_do', '待转'), ('done', '已转')], string="状态")
sub_id = fields.Many2one('yuthon.sub.enterprises', 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])])
is_company = fields.Boolean(string="本公司", default=True, compute='_compute_is_company',
search='_search_part_of_company')
@api.depends('code')
def _compute_workflow(self):
for record in self:
record.approve_state = False
workflow = self.env['soong.workflow.record'].sudo().search(
[('code', '=', record.code)],
limit=1
)
if workflow:
record.approve_state = workflow.approve_state
@api.depends_context('uid', 'company')
@api.depends('company_id')
def _compute_is_company(self):
active_company_ids = self.env.companies
for employee in self:
employee.is_company = employee.company_id in active_company_ids
def _search_part_of_company(self, operator, value):
company_ids = self.env.companies.ids
if not value:
operator = '!=' if operator == '=' else '='
if operator == '=':
return [('company_id', 'in', company_ids)]
else:
return [('company_id', 'not in', company_ids)]
@api.depends('name')
def _compute_text(self):
for record in self:
record.text = record.name or ''
def receipt_processing(self):
if self.official_state == 'done':
raise UserError('该收文已转,请勿重复操作')
return {
'name': '收文处理',
'type': 'ir.actions.act_window',
'res_model': 'yuthon.file.processing',
'view_mode': 'form',
'target': 'new',
'context': {
'default_name': self.name,
'default_official_documents_ids': [(6, 0, [self.official_documents_ids.ids])],
}
}
@api.onchange('is_cold')
def onchange_is_cold(self):
if self.is_cold:
self.onchange_company_id1()
else:
self.reference_cold = False
@api.onchange('main_flats_ids')
def _onchange_main_flats_ids(self):
if self.main_flats_ids:
self.main_unit_type = self.main_flats_ids[0].unit_type
else:
self.main_unit_type = False
@api.onchange('copy_flats_ids')
def _onchange_copy_flats_ids(self):
if self.copy_flats_ids:
self.copy_unit_type = self.copy_flats_ids[0].unit_type
else:
self.copy_unit_type = False
@api.onchange('company_id1')
def onchange_company_id1(self):
current_year = fields.Date.today().year
self.reference_cold = False
if self.company_id1 and self.company_id1.name:
company_name = self.company_id1.name
prefix_map = {
'集团本部': '穗天投',
'天河粮储': '天粮储司',
'天河物管': '穗天物'
}
prefix = prefix_map.get(company_name)
if not prefix:
return
year_str = f"〔{current_year}〕"
domain = [
('company_id1', '=', self.company_id1.id),
('reference_cold', 'like', f"{prefix}{year_str}%")
]
last_record = self.search(domain, order='reference_cold desc', limit=1)
base_num = 27 if (current_year == 2026 and company_name == "集团本部") else 1
max_seq = 0
if last_record and last_record.reference_cold:
try:
seq_str = last_record.reference_cold.split(year_str)[1].rsplit('号', 1)[0]
max_seq = int(seq_str)
except:
max_seq = 0
next_seq = max(max_seq + 1, base_num)
self.reference_cold = f"{prefix}{year_str}{next_seq}号"
def supervising_button(self):
return {
"name": "督查督办",
"type": "ir.actions.act_window",
"view_mode": "form",
"res_model": "soong.workflow.inspector",
"views": [[self.env.ref('soong_workflow.soong_workflow_inspector_form').id, "form"]],
"context": {'default_name': self.name,
'default_start_data': fields.Date.today(),
'default_end_data': self.done_date,
'default_relevancy_type': 'yuthon_official',
'default_yuthon_official_id': self.id,
},
}
def button_meet(self):
return {
"name": "会议",
"type": "ir.actions.act_window",
"view_mode": "form",
"res_model": "room.booking",
"views": [[self.env.ref('room.room_booking_view_form').id, "form"]],
"context": {
'default_name': self.name,
'default_relevancy_type': 'yuthon_official',
'default_yuthon_official_id': self.id,
},
}
def done_publish(self):
users_role_list = department_users_list = []
for depart in self.department_ids:
department_users_data = self.env['hr.employee'].search([('department_id', '=', depart.id)])
department_users_list = [de.id for de in department_users_data]
employee_users_list = [em.user_id.id for em in self.employee_ids]
for user_id in self.users_role_ids:
department_users_data = self.env['soong.user.role'].search([('user_role_id', '=', user_id.id)])
users_role_list = [ro.id for ro in department_users_data]
publish_user_list = list(set(department_users_list + employee_users_list + users_role_list))
partner_ids = self.sudo().env['res.users'].search([('id', 'in', publish_user_list)]).mapped('partner_id').ids
self.sudo().with_context(lang=self.env.lang)._message_auto_subscribe_notify(partner_ids, 'yuthon_official.message_yuthon_official_confirm_users_data')
self.write({"statu": 'done'})
@api.onchange('is_meet')
def _onchange_is_meet(self):
if self.is_meet:
issue_id = self.env['issue.library'].create({'name': self.name, 'is_invisible_workflow': True})
self.related_issues_id = issue_id.id
self.env['issue.library.approval.line'].create({
'issue_library_id': issue_id.id,
'workflow_name': self.name,
'approval_type': self.workflow_id.name,
'res_model': self._name,
'res_id': self.id,
'code': self.code,
'approval_date': fields.Datetime.now(),
})
def action_print_official(self):
"""表单按钮触发打印物业发文审批单"""
self.ensure_one()
report = self.env.ref('yuthon_official.action_property_official_print_report')
return report.report_action(self)
def button_transfer(self):
"""转交按钮"""
pass
def button_withdraw(self):
"""收回按钮"""
pass