diff --git a/estate/__manifest__.py b/estate/__manifest__.py
index 4ce24f19e..1c481da80 100644
--- a/estate/__manifest__.py
+++ b/estate/__manifest__.py
@@ -20,7 +20,7 @@
"estate/static/src/scss/estate.scss",
]
},
- "depends": ["base", "mail"], # 依赖的模块列表
+ "depends": ["base", "mail",'hr'], # 依赖的模块列表
"license": "LGPL-3", # 许可证类型
"installable": True, # 是否可安装
"application": True, # 是否为应用程序
diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml
index c2ed2b67b..9ef0ca9fb 100644
--- a/estate/views/estate_property_views.xml
+++ b/estate/views/estate_property_views.xml
@@ -12,7 +12,7 @@
-
+
diff --git a/header_search_panel/static/src/search/header_search/components/quick_filter/quick_filter.js b/header_search_panel/static/src/search/header_search/components/quick_filter/quick_filter.js
index 669ace439..d41858434 100644
--- a/header_search_panel/static/src/search/header_search/components/quick_filter/quick_filter.js
+++ b/header_search_panel/static/src/search/header_search/components/quick_filter/quick_filter.js
@@ -121,5 +121,4 @@ QuickFilter.props = {
groupId: { type: Number, required: true },
// 显示label
showLabel: { type: Boolean, required: false, default: true },
- resModel: { type: String }
}
diff --git a/yuthon_contract/models/inherit_hr_contract.py b/yuthon_contract/models/inherit_hr_contract.py
index 9f771d1af..3f25434dc 100644
--- a/yuthon_contract/models/inherit_hr_contract.py
+++ b/yuthon_contract/models/inherit_hr_contract.py
@@ -10,49 +10,86 @@ class HrContract(models.Model):
_inherit = "hr.contract"
_description = "员工合同拓展"
- code = fields.Char(string="编号", default=lambda self: self.env['ir.sequence'].next_by_code('contract_code'))
- name = fields.Char(string="合同名称", compute='_compute_name', readonly=False)
+ code = fields.Char(
+ string="编号",
+ default=lambda self: self.env["ir.sequence"].next_by_code("contract_code"),
+ )
+ name = fields.Char(string="合同名称", compute="_compute_name", readonly=False)
is_annual_salary = fields.Boolean(string="是否年薪")
- resource_calendar_id = fields.Many2one('resource.calendar', string='考勤时间表')
- state = fields.Selection([
- ('draft', '草稿'),
- ('open', '运行中'),
- ('close', '完成'),
- ('cancel', '已中止'),
- ], string='状态', default='draft', readonly=True, copy=False)
- date_of_entry = fields.Date(related='employee_id.entry_date', string="入职时间")
- salary_group_id = fields.Many2one('yuthon.salary.group', string="工资单分组", store=True, index=True)
- is_internship = fields.Boolean(string="实习期", compute='_compute_name', store=True)
+ resource_calendar_id = fields.Many2one("resource.calendar", string="考勤时间表")
+ state = fields.Selection(
+ [
+ ("draft", "草稿"),
+ ("open", "运行中"),
+ ("close", "完成"),
+ ("cancel", "已中止"),
+ ],
+ string="状态",
+ default="draft",
+ readonly=True,
+ copy=False,
+ )
+ date_of_entry = fields.Date(related="employee_id.entry_date", string="入职时间")
+ salary_group_id = fields.Many2one(
+ "yuthon.salary.group", string="工资单分组", store=True, index=True
+ )
+ is_internship = fields.Boolean(string="实习期", compute="_compute_name", store=True)
date_end = fields.Date(string="合同结束时间")
termination_date = fields.Date(string="中止时间")
- reason_suspension = fields.Selection([
- ('turnover', '离职'),
- ('died', '意外离世'),
- ], string='中止原因')
- work_entry_source = fields.Selection([
- ('calendar', '考勤安排'),
- ('attendance', 'Attendances'),
- ('planning', '特殊排版')])
+ reason_suspension = fields.Selection(
+ [
+ ("turnover", "离职"),
+ ("died", "意外离世"),
+ ],
+ string="中止原因",
+ )
+ work_entry_source = fields.Selection(
+ [
+ ("calendar", "考勤安排"),
+ ("attendance", "Attendances"),
+ ("planning", "特殊排版"),
+ ]
+ )
is_probation = fields.Boolean(string="试用期")
- start_date = fields.Date(string="试用开始日期", required=True, default=fields.Date.today)
- end_date = fields.Date(string="试用结束日期", required=True,
- default=lambda self: fields.Date.today() + relativedelta(months=+2) - relativedelta(days=1))
+ start_date = fields.Date(
+ string="试用开始日期", required=True, default=fields.Date.today
+ )
+ end_date = fields.Date(
+ string="试用结束日期",
+ required=True,
+ default=lambda self: fields.Date.today()
+ + relativedelta(months=+2)
+ - relativedelta(days=1),
+ )
salary_day = fields.Float(string="日薪")
- party_id = fields.Many2one('yuthon.party.setting', string='甲方(用人单位)')
- representatives = fields.Char(related='party_id.representatives', string='法定代表人或委托代理人')
- contract_type_id = fields.Many2one('hr.contract.type', default=lambda self: self.env['hr.contract.type'].search(
- [('name', '=', '正式合同(一签)')],
- limit=1
- ).id or False, string='合同类型')
- economy_type = fields.Char(related='party_id.economy_type', string='经济类型')
- address = fields.Text(related='party_id.address', string='通讯地址')
- contact = fields.Char(related='party_id.contact', string='联系人')
- phone = fields.Char(related='party_id.phone', string='电话')
- documents_ids = fields.Many2many('ir.attachment', string="合同附件")
- current_contract = fields.Boolean(string="当前合同", default=True, compute='_compute_current_contract', store=True)
- is_company = fields.Boolean(string="本公司", default=True, compute='_compute_is_company', search='_search_part_of_company')
+ party_id = fields.Many2one("yuthon.party.setting", string="甲方(用人单位)")
+ representatives = fields.Char(
+ related="party_id.representatives", string="法定代表人或委托代理人"
+ )
+ contract_type_id = fields.Many2one(
+ "hr.contract.type",
+ default=lambda self: self.env["hr.contract.type"]
+ .search([("name", "=", "正式合同(一签)")], limit=1)
+ .id
+ or False,
+ string="合同类型",
+ )
+ economy_type = fields.Char(related="party_id.economy_type", string="经济类型")
+ address = fields.Text(related="party_id.address", string="通讯地址")
+ contact = fields.Char(related="party_id.contact", string="联系人")
+ phone = fields.Char(related="party_id.phone", string="电话")
+ documents_ids = fields.Many2many("ir.attachment", string="合同附件")
+ current_contract = fields.Boolean(
+ string="当前合同", default=True, compute="_compute_current_contract", store=True
+ )
+ is_company = fields.Boolean(
+ string="本公司",
+ default=True,
+ compute="_compute_is_company",
+ search="_search_part_of_company",
+ )
- @api.depends('date_start', 'date_end')
+ @api.depends("date_start", "date_end")
def _compute_current_contract(self):
today = date.today()
for contract in self:
@@ -60,188 +97,197 @@ class HrContract(models.Model):
end_valid = not contract.date_end or contract.date_end >= today
contract.current_contract = start_valid and end_valid
-
- @api.onchange('date_start')
+ @api.onchange("date_start")
def _onchange_date_end(self):
for record in self:
if record.date_start:
record.employee_id.entry_date = record.date_start
- record.date_end = record.date_start + relativedelta(years=1) - relativedelta(days=1)
+ record.date_end = (
+ record.date_start + relativedelta(years=1) - relativedelta(days=1)
+ )
- @api.onchange('contract_type_id')
+ @api.onchange("contract_type_id")
def _onchange_contract_type_id(self):
for record in self:
if record.contract_type_id:
- if record.contract_type_id.name == '正式合同(一签)':
- record.date_end = record.date_start + relativedelta(years=1) - relativedelta(days=1)
- elif record.contract_type_id.name == '正式合同(二签)':
- record.date_end = record.date_start + relativedelta(years=3) - relativedelta(days=1)
+ if record.contract_type_id.name == "正式合同(一签)":
+ record.date_end = (
+ record.date_start
+ + relativedelta(years=1)
+ - relativedelta(days=1)
+ )
+ elif record.contract_type_id.name == "正式合同(二签)":
+ record.date_end = (
+ record.date_start
+ + relativedelta(years=3)
+ - relativedelta(days=1)
+ )
- @api.onchange('date_start')
+ @api.onchange("date_start")
def _onchange_date_start(self):
for record in self:
- if record.date_start and record.state == 'open' and record.employee_id:
+ if record.date_start and record.state == "open" and record.employee_id:
record.employee_id.entry_date = record.date_start
def renew(self):
contract_ids = self.env["hr.contract"].browse(
- self._context.get('active_ids', self._context.get('active_id')))
+ self._context.get("active_ids", self._context.get("active_id"))
+ )
for record in contract_ids:
if len(record) > 1:
raise UserError("只能选择一个合同续签")
return {
- 'name': '续签',
- 'type': 'ir.actions.act_window',
- 'res_model': 'yuthon.renewal.approval',
- 'view_mode': 'form',
- 'context': {
- 'default_employee_id': self.employee_id.id,
- 'default_current_status': self.date_end,
- 'default_contract_id': self.id,
+ "name": "续签",
+ "type": "ir.actions.act_window",
+ "res_model": "yuthon.renewal.approval",
+ "view_mode": "form",
+ "context": {
+ "default_employee_id": self.employee_id.id,
+ "default_current_status": self.date_end,
+ "default_contract_id": self.id,
+ },
}
- }
def pub_leaving_employee(self):
- record_id = self.env["hr.contract"].browse(self._context.get('active_ids', self._context.get('active_id')))
+ record_id = self.env["hr.contract"].browse(
+ self._context.get("active_ids", self._context.get("active_id"))
+ )
if len(record_id) != 1:
raise UserError("请选择一个合同")
- form_id = self.env.ref('yuthon_hr_employee_approval.view_yuthon_leaving_approval_form').id
+ form_id = self.env.ref(
+ "yuthon_hr_employee_approval.view_yuthon_leaving_approval_form"
+ ).id
return {
"type": "ir.actions.act_window",
"name": "离职申请",
"res_model": "yuthon.leaving.approval",
"views": [[form_id, "form"]],
"context": {
- 'default_employee_id': self.employee_id.id,
- }
+ "default_employee_id": self.employee_id.id,
+ },
}
def write(self, vals):
"""在写入时自动更新合同状态"""
today = fields.Date.today()
update_state = False
- if 'date_start' in vals:
+ if "date_start" in vals:
update_state = True
- if 'date_end' in vals:
+ if "date_end" in vals:
update_state = True
- if 'termination_date' in vals:
+ if "termination_date" in vals:
update_state = True
if update_state:
for contract in self:
# 获取最新的开始日期
- start_date = fields.Date.to_date(vals.get('date_start', contract.date_start))
+ start_date = fields.Date.to_date(
+ vals.get("date_start", contract.date_start)
+ )
# 获取最新的结束日期(空值视为无限大)
- end_date = vals.get('date_end', contract.date_end)
+ end_date = vals.get("date_end", contract.date_end)
end_date = fields.Date.to_date(end_date) if end_date else None
# 获取最新的中止时间(空值视为未中止)
- termination_date = vals.get('termination_date', contract.termination_date)
- termination_date = fields.Date.to_date(termination_date) if termination_date else None
+ termination_date = vals.get(
+ "termination_date", contract.termination_date
+ )
+ termination_date = (
+ fields.Date.to_date(termination_date) if termination_date else None
+ )
# 判断合同状态
- if termination_date and termination_date < today: # 新增:优先判断是否已中止
- new_state = 'cancel'
+ if (
+ termination_date and termination_date < today
+ ): # 新增:优先判断是否已中止
+ new_state = "cancel"
elif start_date > today:
- new_state = 'draft'
+ new_state = "draft"
elif end_date and end_date < today:
- new_state = 'close'
+ new_state = "close"
else:
- new_state = 'open'
+ new_state = "open"
# 更新当前合同的状态
- if 'state' not in vals:
- vals['state'] = new_state
+ if "state" not in vals:
+ vals["state"] = new_state
return super(HrContract, self).write(vals)
- @api.model_create_multi
- def create(self, vals): # todo 不触发??
- """在创建时自动更新合同状态"""
- today = fields.Date.today()
-
- start_date = fields.Date.to_date(vals.get('date_start'))
- end_date = vals.get('date_end')
- end_date = fields.Date.to_date(end_date) if end_date else None
- termination_date = vals.get('termination_date')
- termination_date = fields.Date.to_date(termination_date) if termination_date else None
-
- # 根据日期判断状态
- if termination_date and termination_date < today:
- vals['state'] = 'cancel'
- elif start_date > today:
- vals['state'] = 'draft'
- elif end_date and end_date < today:
- vals['state'] = 'close'
- else:
- vals['state'] = 'open'
-
- return super(HrContract, self).create(vals)
-
def update_contract_states(self):
today = date.today()
- active_contracts = self.search([
- ('state', 'not in', ['cancel']),
- ])
+ active_contracts = self.search(
+ [
+ ("state", "not in", ["cancel"]),
+ ]
+ )
for contract in active_contracts:
- new_state = 'open' if not contract.date_end or contract.date_end >= today else 'close'
- if new_state == 'open':
- conflicting_contracts = self.search([
- ('id', '!=', contract.id),
- ('employee_id', '=', contract.employee_id.id),
- ('state', '=', 'open'),
- ])
+ new_state = (
+ "open"
+ if not contract.date_end or contract.date_end >= today
+ else "close"
+ )
+ if new_state == "open":
+ conflicting_contracts = self.search(
+ [
+ ("id", "!=", contract.id),
+ ("employee_id", "=", contract.employee_id.id),
+ ("state", "=", "open"),
+ ]
+ )
if conflicting_contracts:
continue
contract.state = new_state
- @api.depends_context('uid', 'company')
- @api.depends('company_id')
+ @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):
- if operator not in ('=', '!=') or not isinstance(value, bool):
- raise UserError(('Operation not supported'))
+ if operator not in ("=", "!=") or not isinstance(value, bool):
+ raise UserError(("Operation not supported"))
company_ids = self.env.companies.ids # 获取公司ID列表
# 处理反向操作符
if not value:
- operator = '!=' if operator == '=' else '='
+ operator = "!=" if operator == "=" else "="
# 使用company_id in company_ids的结构
- if operator == '=':
- return [('company_id', 'in', company_ids)]
+ if operator == "=":
+ return [("company_id", "in", company_ids)]
else: # operator == '!='
- return [('company_id', 'not in', company_ids)]
+ return [("company_id", "not in", company_ids)]
# @api.onchange('resource_calendar_id')
# def _onchange_resource_calendar_id(self):
- # if self.resource_calendar_id:
- # self.employee_id.sudo().write({'resource_calendar_id': self.resource_calendar_id.id})
+ # if self.resource_calendar_id:
+ # self.employee_id.sudo().write({'resource_calendar_id': self.resource_calendar_id.id})
- @api.depends('contract_type_id')
+ @api.depends("contract_type_id")
def _compute_simplified_name(self):
for record in self:
if record.contract_type_id and record.employee_id:
- record.name = record.contract_type_id.name + '合同'
+ record.name = record.contract_type_id.name + "合同"
else:
- record.name = ' '
+ record.name = " "
if record.contract_type_id:
- if record.contract_type_id.name == '实习协议':
+ if record.contract_type_id.name == "实习协议":
record.is_internship = True
else:
record.is_internship = False
- @api.depends('contract_type_id')
+ @api.depends("contract_type_id")
def _compute_name(self):
for record in self:
if record.contract_type_id and record.employee_id:
- record.name = record.employee_id.name + record.contract_type_id.name + '合同'
+ record.name = (
+ record.employee_id.name + record.contract_type_id.name + "合同"
+ )
else:
- record.name = ' '
+ record.name = " "
if record.contract_type_id:
- if record.contract_type_id.name == '实习协议':
+ if record.contract_type_id.name == "实习协议":
record.is_internship = True
else:
record.is_internship = False
@@ -257,35 +303,74 @@ class HrContract(models.Model):
def update_contract(self):
contract_ids = self.env["hr.contract"].browse(
- self._context.get('active_ids', self._context.get('active_id')))
+ self._context.get("active_ids", self._context.get("active_id"))
+ )
for contract in contract_ids:
company_id = contract.employee_id.company_id
- resource_calendar_id = self.env['resource.calendar'].search([('company_id', '=', company_id.id)], limit=1)
+ resource_calendar_id = self.env["resource.calendar"].search(
+ [("company_id", "=", company_id.id)], limit=1
+ )
contract.resource_calendar_id = resource_calendar_id.id
- @api.onchange('salary_group_id')
+ @api.onchange("salary_group_id")
def _compute_salary_group_id(self):
for contract_id in self:
- employee = self.env['hr.employee'].search([('id', '=', contract_id.employee_id.id)], limit=1)
+ employee = self.env["hr.employee"].search(
+ [("id", "=", contract_id.employee_id.id)], limit=1
+ )
if employee:
employee.salary_group_id = contract_id.salary_group_id.id
else:
employee.salary_group_id = False
- @api.onchange('is_annual_salary')
+ @api.onchange("is_annual_salary")
def _compute_is_annual_salary(self):
for contract_id in self:
- employee = self.env['hr.employee'].search([('id', '=', contract_id.employee_id.id)], limit=1)
+ employee = self.env["hr.employee"].search(
+ [("id", "=", contract_id.employee_id.id)], limit=1
+ )
if employee:
employee.is_annual_salary = contract_id.is_annual_salary
else:
employee.is_annual_salary = False
- @api.model
- def create(self, vals):
- contract = super(HrContract, self).create(vals)
- if contract.employee_id:
- contract.employee_id.write({
- 'contract_id': contract.id,
- })
- return contract
+ @api.model_create_multi
+ def create(self, vals_list):
+ today = fields.Date.today()
+
+ # 先处理状态
+ for vals in vals_list:
+ start_date = (
+ fields.Date.to_date(vals.get("date_start"))
+ if vals.get("date_start")
+ else None
+ )
+ end_date = (
+ fields.Date.to_date(vals.get("date_end"))
+ if vals.get("date_end")
+ else None
+ )
+ termination_date = (
+ fields.Date.to_date(vals.get("termination_date"))
+ if vals.get("termination_date")
+ else None
+ )
+
+ if termination_date and termination_date < today:
+ vals["state"] = "cancel"
+ elif start_date and start_date > today:
+ vals["state"] = "draft"
+ elif end_date and end_date < today:
+ vals["state"] = "close"
+ else:
+ vals["state"] = "open"
+
+ # 创建合同
+ contracts = super().create(vals_list)
+
+ # 更新员工合同字段
+ for contract in contracts:
+ if contract.employee_id:
+ contract.employee_id.write({"contract_id": contract.id})
+
+ return contracts
diff --git a/yuthon_property/views/property_accounts_receivable_views.xml b/yuthon_property/views/property_accounts_receivable_views.xml
index 9da15f90a..01fca119c 100644
--- a/yuthon_property/views/property_accounts_receivable_views.xml
+++ b/yuthon_property/views/property_accounts_receivable_views.xml
@@ -1,107 +1,105 @@
- property.accounts.receivable.tree
- property.accounts.receivable
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 导入应收初始化数据
-
-
- code
- action = model.initialize_wizard()
-
-
- 发票基本信息模板下载
- self
- /yuthon_property/static/tmpl/fapiaojibenxinxi.xlsx
-
-
- 发票基本信息
-
-
- code
-
- property.accounts.receivable.tree
+ property.accounts.receivable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 导入应收初始化数据
+
+
+ code
+ action = model.initialize_wizard()
+
+
+ 发票基本信息模板下载
+ self
+ /yuthon_property/static/tmpl/fapiaojibenxinxi.xlsx
+
+
+ 发票基本信息
+
+
+ code
+
+
-
-
+
+
- 发票明细信息模板下载
- self
- /yuthon_property/static/tmpl/fapiaomingxixinxi.xlsx
-
-
- 发票明细信息
-
-
- code
-
- 发票明细信息模板下载
+ self
+ /yuthon_property/static/tmpl/fapiaomingxixinxi.xlsx
+
+
+ 发票明细信息
+
+
+ code
+
+
-
-
-
- 附加要素
- self
- /yuthon_property/static/tmpl/fujiayaosu.xlsx
-
-
- 附加要素
-
-
- code
-
-
+
+
+ 附加要素
+ self
+ /yuthon_property/static/tmpl/fujiayaosu.xlsx
+
+
+ 附加要素
+
+
+ code
+
+
-
-
-
- 特定业务信息
- self
- /yuthon_property/static/tmpl/tedingyewuxinxi.xlsx
-
-
- 特定业务信息
-
-
- code
-
-
+
+
+ 特定业务信息
+ self
+ /yuthon_property/static/tmpl/tedingyewuxinxi.xlsx
+
+
+ 特定业务信息
+
+
+ code
+
+
-
-
-
+
+
+
\ No newline at end of file
diff --git a/yuthon_property_approval/views/inherit_yuthon_property_views.xml b/yuthon_property_approval/views/inherit_yuthon_property_views.xml
index 13ca4e6fe..e8f426599 100644
--- a/yuthon_property_approval/views/inherit_yuthon_property_views.xml
+++ b/yuthon_property_approval/views/inherit_yuthon_property_views.xml
@@ -294,7 +294,7 @@
-
+