Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
sunjie
2025-12-26 21:02:12 +08:00
76 changed files with 1058 additions and 304 deletions
+5
View File
@@ -11,6 +11,11 @@
<field name="model_id" ref="model_room_room"/>
<field name="domain_force">[('company_id', 'in', company_ids)]</field>
</record>
<record model="ir.rule" id="room_booking_rule">
<field name="name">预定会议多公司</field>
<field name="model_id" ref="model_room_booking"/>
<field name="domain_force">[('company_id', 'in', company_ids)]</field>
</record>
<!-- <record id="room_room_comp_rule" model="ir.rule">-->
<!-- <field name="name">Room Room MC Rule</field>-->
<!-- <field name="model_id" ref="model_room_room"/>-->
+2 -1
View File
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
# 1.双向删除
# 2.
from . import soong_workflow
from . import soong_workflow_node
from . import soong_workflow_link
+31 -11
View File
@@ -332,7 +332,7 @@ class SoongWorkflowMixin(models.AbstractModel):
index = 20 # 防止死循环
break
current_department = self.department_id
if btn_rec.link_id and btn_rec.link_id in current_node.out_link_ids:
if btn_rec.link_id in current_node.out_link_ids and len(current_node.out_link_ids) == 1:
matched_link = btn_rec.link_id
next_node = matched_link.node_to
matched_key = next_node.name
@@ -341,14 +341,27 @@ class SoongWorkflowMixin(models.AbstractModel):
# 筛选与当前节点部门匹配的后续节点
valid_nodes = []
for link in current_node.out_link_ids:
target_node = link.node_to
# 如果目标节点有部门限制,且与当前节点部门匹配
if target_node.department_id and any(
dept in current_department or
current_department in self.get_all_sub_departments(dept)
for dept in target_node.department_id
):
valid_nodes.append((target_node, link))
if self.name_title == '业务审批':
category_names = self.information_categories_ids.mapped('name')
target_name = link.name.split('->')[-1].strip()
if '工会活动' in category_names:
if target_name == '工会主席':
target_node = link.node_to
valid_nodes.append((target_node, link))
else:
if target_name == '复核':
target_node = link.node_to
valid_nodes.append((target_node, link))
else:
target_node = link.node_to
# 如果目标节点有部门限制,且与当前节点部门匹配
if target_node.department_id and any(
dept in current_department or
current_department in self.get_all_sub_departments(dept)
for dept in target_node.department_id
):
valid_nodes.append((target_node, link))
# 尝试父部门匹配
if not valid_nodes and current_department and current_department.parent_id:
@@ -734,8 +747,11 @@ class SoongWorkflowMixin(models.AbstractModel):
btn_exec_action_el.set("class", "oe_highlight")
if button.has_icon:
btn_exec_action_el.set("icon", button.icon)
btn_exec_action_el.set("invisible", "state != '%s'" % node.node_name)
btn_exec_action_el.set("context", "{'btn_key':'%s','active_model':'%s'}" % (button.btn_key, self._name),)
invisible_condition = "state != '%s'" % node.node_name
if model == 'purchase.order':
invisible_condition = invisible_condition.replace("询价", "draft")
btn_exec_action_el.set("invisible", invisible_condition)
btn_exec_action_el.set("context","{'btn_key':'%s','active_model':'%s'}" % (button.btn_key, self._name), )
else:
is_apostille = False
if button.btn_hide:
@@ -811,6 +827,10 @@ class SoongWorkflowMixin(models.AbstractModel):
# if button.name == "结束":
# invisible += " or True"
invisible += " or work_end"
if model == 'purchase.order':
invisible = invisible.replace("询价", "draft")
btn_exec_action_el.set("invisible", invisible)
btn_exec_action_el.set("context", "{'btn_key':'%s','active_model':'%s'}" % (button.btn_key, self._name),)
res["arch"] = etree.tostring(arch, encoding="unicode").replace("\t", "")
@@ -62,6 +62,18 @@ class SoongWorkflowRecord(models.Model):
res.append_date2(res)
return res
def log(self):
log = self.env['soong.workflow.log'].search([("model", "=", self.res_model),
("res_id", "=", self.res_id)])
return {
'type': 'ir.actions.act_window',
'name': '日志',
'view_mode': 'tree',
'res_model': 'soong.workflow.log',
'domain': [('id', 'in', log.ids)],
}
def restore(self):
workflow_ids = self.env["soong.workflow.record"].browse(
self._context.get('active_ids', self._context.get('active_id', [])))
@@ -90,12 +90,15 @@
<field name="is_manager" column_invisible="1"/>
<field name="meal" column_invisible="1"/>
<field name="workflow_happen_date" string="发生日期" column_invisible="1"/>
<button name="delete_record" type="object" string="删除" class="btn-primary" confirm="你确定要删除吗?"
invisible="not (is_manager or approve_state == 'start') "/>
<button name="reminders_record" type="object" string="催办" class="btn-primary"
groups="soong_workflow.group_soong_workflow_manager" invisible="approve_state in ['start', 'end']"/>
<button name="revoke_record" type="object" string="撤销" class="btn-primary"
groups="soong_workflow.group_soong_workflow_manager"/>
<button name="log" type="object" string="日志" class="btn-primary"
groups="soong_workflow.group_soong_workflow_manager"/>
</tree>
</field>
</record>
@@ -206,7 +209,6 @@
<field name="type">ir.actions.act_window</field>
<field name="res_model">soong.workflow.record</field>
<field name="view_mode">tree,kanban,search</field>
<!-- <field name="context">{'check_employee': 1, 'search_default_is_start':1, 'search_default_is_to_do':1}</field>-->
<field name="context">{'header_search_default_approve_state': 1, 'header_search_default_to_do':1, 'check_employee': 1}</field>
<field name="domain">[('users_ids', 'in', uid), ('reclaim_state', '=', False), ('soong_state', '=', 'to_do')]</field>
<field name="search_view_id" ref="soong_workflow_record_search1"/>
@@ -28,6 +28,7 @@ class SoongWorkflowCommentWizard(models.TransientModel):
comment = fields.Char(compute='_compute_comment', store=True)
state_list = fields.Char(string="状态列表")
record_id = fields.Integer()
is_selection = fields.Boolean(string="是否自动选择")
trans_link_id = fields.Many2one('trans.link', string='转交节点')
document_ids = fields.Many2many('ir.attachment', string="附件")
return_link_id = fields.Many2one('trans.link', string='退回节点')
@@ -64,6 +65,17 @@ class SoongWorkflowCommentWizard(models.TransientModel):
store=True
)
@api.onchange('is_selection')
def _onchange_is_selection(self):
domain = [('id', 'in', self.employee_ids1.ids)]
if self.is_selection:
if self.is_this_company:
domain.append(('company_id', '=', self.company_id.id))
all_employees = self.env['hr.employee'].search(domain)
self.employee_ids = all_employees
else:
self.employee_ids = False
@api.onchange('employee_ids1')
def _onchange_employee_ids1(self):
if len(self.employee_ids1) == 1:
@@ -59,6 +59,7 @@
</group>
<group>
<field name="is_this_company"/>
<field name="is_selection"/>
<field name="company_id" invisible="1"/>
<field name="employee_ids1" widget="many2many_tags" string="人员范围" invisible="1"/>
<field name="employee_ids" widget="many2many_tags" string="人员范围" domain = "[('company_id', '=', company_id), ('id', 'in', employee_ids1)] if is_this_company else [('id', 'in', employee_ids1)]" options="{'no_create': True}"/>
@@ -43,7 +43,11 @@ class SoongWorkflowRecordRevokeWizard(models.TransientModel):
])
meal_line.unlink()
record_to_update.write({'log_ids': [(5, 0, 0)]})
record_to_update.state = '申请人'
self.record_id.approve_state = 'start'
self.record_id.write({
'approve_state': 'start',
'soong_state': 'to_do',
'employee_ids': [(6, 0, [self.record_id.create_uid.employee_ids.id])],
'users_ids': [(6, 0, [self.record_id.create_uid.id])]
})
+1 -6
View File
@@ -31,7 +31,7 @@ def compute_badge_count_recursive(web_menus, menu_id):
class IrUiMenu(models.Model):
_inherit = "ir.ui.menu"
show_badge_count = fields.Boolean(string="显示菜单角标",default=True)
show_badge_count = fields.Boolean(string="显示菜单角标", default=True)
is_phone = fields.Boolean(string="手机菜单",default=False)
is_pc = fields.Boolean(string="PC菜单",default=True)
@@ -134,7 +134,6 @@ class IrUiMenu(models.Model):
web_menus = {}
for menu in menus.values():
if not menu['id']:
# special root menu case
web_menus['root'] = {
"id": 'root',
"name": menu['name'],
@@ -151,14 +150,11 @@ class IrUiMenu(models.Model):
}
else:
action = menu['action']
if menu['id'] == menu['app_id']:
# if it's an app take action of first (sub)child having one defined
child = menu
while child and not action:
action = child['action']
child = menus[child['children'][0]] if child['children'] else False
action_model, action_id = action.split(',') if action else (False, False)
action_id = int(action_id) if action_id else False
badge_count = 0
@@ -166,7 +162,6 @@ class IrUiMenu(models.Model):
# 增加 show_badge_count 限制是否显示"角标".
if action_model and action_id and menu['show_badge_count']:
action_record = self.env[action_model].browse(action_id).sudo()
if action_model == 'ir.actions.act_window' and action_record.view_mode != 'form':
# 不仅仅是 form 表单,获取 model
res_model = action_record.res_model
+9 -8
View File
@@ -11,15 +11,16 @@
</record>
<menuitem id="financial_sheet_collection_report_menu"
name="财务数据表报表"
action="yuthon_account_report.financial_data_action"
sequence="10"/>
<!-- <menuitem id="financial_sheet_collection_report_menu"-->
<!-- name="财务数据表报表"-->
<!-- -->
<!-- action="yuthon_account_report.financial_data_action"-->
<!-- sequence="10"/>-->
<menuitem id="information_summary_table_report_menu"
name="信息汇总报表"
action="yuthon_account_report.information_aggregation_action"
sequence="10"/>
<!-- <menuitem id="information_summary_table_report_menu"-->
<!-- name="信息汇总报表"-->
<!-- action="yuthon_account_report.information_aggregation_action"-->
<!-- sequence="10"/>-->
<record id="financial_sheet_line_tree" model="ir.ui.view">
<field name="name">financial.sheet.line.tree</field>
@@ -110,6 +110,8 @@ class HrContract(models.Model):
'view_mode': 'form',
'target': 'current',
'context': {
'default_work_end': False,
'default_self_users_ids':[(6, 0, [self.employee_id.user_id.id])],
'default_contract_id': contract_ids.id,
'default_employee_id': contract_ids.employee_id.id
}}
+1
View File
@@ -44,6 +44,7 @@
<field name="is_back" invisible="1"/>
<field name="name"/>
<field name="users_id" options="{'no_create': True}"/>
<field name="company_id" invisible="1"/>
<field name="department_id" invisible="1"/>
<field name="entrusted_agent_id" domain="[('employee_id.department_id', '=', department_id)]" />
<field name="is_entrusted" invisible="not entrusted_agent_id"/>
@@ -887,18 +887,31 @@ class AppletAttendance(Controller):
first_day_str = first_day.strftime('%Y-%m-%d')
last_day_str = last_day.strftime('%Y-%m-%d')
two_months_ago = datetime.now().date() - relativedelta(months=2)
# 去掉 数据为 0 的数据.
valid_archives = request.env(user=SUPERUSER_ID)['property.meter.archives'].search([
('is_virtual_meter', '!=', True),
'|',
('end_time', '=', False),
('end_time', '<=', two_months_ago)
])
electric_records = request.env(user=SUPERUSER_ID)['meter.archives.line'].search([
('archives_state', '!=', 'stop'),
('archives_id', 'in', valid_archives.ids),
('meter_date', '>=', first_day_str),
('meter_date', '<=', last_day_str)
('meter_date', '<=', last_day_str),
])
valid_water_ids = request.env(user=SUPERUSER_ID)['property.meter.water'].search([
'|',
('end_time', '=', False),
('end_time', '<=', two_months_ago)
]).ids
water_records = request.env(user=SUPERUSER_ID)['meter.water.line'].search([
('water_state', '!=', 'stop'),
('meter_date', '>=', first_day_str),
('meter_date', '<=', last_day_str)
('meter_date', '<=', last_day_str),
('water_id', 'in', valid_water_ids)
])
# 接口调整, 电表,水表数据拆分.
@@ -1058,14 +1071,21 @@ class AppletAttendance(Controller):
# ('meter_date', '>=', first_day_str),
# ('meter_date', '<=', last_day_str)]
# 去掉 state
domain = [('epitope_values_id.name', '=', floor_name),
('meter_date', '>=', first_day_str),
('meter_date', '<=', last_day_str)]
domain = [
('epitope_values_id.name', '=', floor_name),
('meter_date', '>=', first_day_str),
('meter_date', '<=', last_day_str)
]
two_months_ago = datetime.now().date() - relativedelta(months=2)
if type == 'electric':
domain.append(('archives_state', '!=', 'stop'))
model = 'meter.archives.line'
domain.extend([
('archives_id.is_virtual_meter', '!=', True),
'|',
('archives_id.end_time', '=', False),
('archives_id.end_time', '<=', two_months_ago)
])
else:
domain.append(('water_state', '!=', 'stop'))
model = 'meter.water.line'
@@ -19,6 +19,7 @@ class GoApprovals(models.Model):
code = fields.Char(string="编号", default=lambda self: self.env['ir.sequence'].next_by_code('overtime_approval'))
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="部门")
company_id = fields.Many2one(related='users_id.employee_id.company_id', string="公司")
reason_application = fields.Char(string="事由")
is_issues = fields.Boolean(string='是否上会')
issues_result = fields.Html(string="会议结果")
@@ -41,6 +42,8 @@ class GoApprovals(models.Model):
end_day_selection = fields.Selection([('half', '上半天'), ('afternoon', '下半天')], string="天")
start_date = fields.Date(string="开始日期", default=fields.Date.today)
end_date = fields.Date(string="结束日期", default=fields.Date.today)
is_this_department = fields.Boolean(string='是否是本部门', default=True)
department_ids = fields.Many2many('hr.department', string="多部门")
def _get_default_name_title(self):
return self._description if self._description else self._name
@@ -48,6 +51,17 @@ class GoApprovals(models.Model):
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])])
@api.onchange('is_this_department')
def _onchange_is_this_department(self):
self.department_ids = [(5, 0, 0)]
if self.is_this_department and self.users_id:
employee = self.env['hr.employee'].search([('user_id', '=', self.users_id.id)], limit=1)
main_department = employee.department_id
all_departments = main_department.search([
('id', 'child_of', main_department.id)
])
self.department_ids = [(6, 0, all_departments.ids)]
@api.onchange('start_day_selection', 'end_day_selection')
def _onchange_selection_fields(self):
for record in self:
@@ -83,6 +83,11 @@ class HrAttendance(models.Model):
if reminder_id:
reminder_id.state = 'done'
def one_time(self):
for att in self.env["hr.attendance"].browse(self._context.get('active_ids', self._context.get('active_id'))):
if att.current_data:
att.current_data_month = f'{att.current_data.year}-{att.current_data.month}'
def task_remind(self):
all_employees = self.env['hr.employee'].search([('name', 'in', ['Administrator', '叶华锋'])])
for employee in all_employees:
+7 -4
View File
@@ -35,7 +35,7 @@
<field name="is_issues"/>
</group>
<group>
<field name="related_issues_id" invisible="is_issues == False"/>
<field name="is_this_department"/>
</group>
</group>
<div class="col-12 text-center">
@@ -67,8 +67,8 @@
<field name="end_date" invisible="not is_day"/>
</group>
<group>
<field name="start_day_selection" invisible="not is_day" string=" " widget="radio"/>
<field name="end_day_selection" invisible="not is_day" string=" " widget="radio"/>
<field name="start_day_selection" invisible="not is_day" string=" "/>
<field name="end_day_selection" invisible="not is_day" string=" "/>
</group>
<group/>
</group>
@@ -85,8 +85,11 @@
</group>
<group col="2">
<group>
<field name="related_issues_id" invisible="is_issues == False"/>
<field name="reason_application"/>
<field name="employee_ids" widget="many2many_tags" options="{'no_create': True}"/>
<field name="company_id" invisible="1"/>
<field name="department_ids" widget="many2many_tags" invisible="1"/>
<field name="employee_ids" widget="many2many_tags" options="{'no_create': True}" domain="[('department_id', 'in', department_ids)] if department_ids else [('company_id', '=', company_id)]"/>
<field name="is_issues" invisible="is_issues == False"/>
<field name="meal"/>
<field name="documents_ids" widget="preview_many2many"/>
@@ -286,6 +286,28 @@ class YuthonHrEmployee(models.Model):
else:
record.date_end = None
def renew(self):
employee_ids = self.env["hr.employee"].browse(
self._context.get("active_ids", self._context.get("active_id"))
)
for record in employee_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.id,
"default_current_status": self.contract_id.date_end,
"default_department1_id": self.department_id.id,
"default_contract_id": self.contract_id.id,
},
}
def update_social_base(self):
current_year = fields.Date.today().year
group_company = self.env['res.company'].search([('name', '=', '集团本部')], limit=1)
+3 -1
View File
@@ -19,9 +19,11 @@
'data/stage_approval_data.xml',
'data/tage_approval_data.xml',
'data/leaving_retired_data.xml',
'data/yuthon_contract_type_data.xml',
'data/yuthon_formation_method_data.xml',
'views/inherit_hr_applicant_views.xml',
'views/inherit_room_booking_views.xml',
'views/inherit_hr_job_views.xml',
# 'views/inherit_hr_job_views.xml',
'views/inherit_hr_employee_views.xml',
'views/yuthon_message_login_views.xml',
'views/yuthon_onboard_approval_views.xml',
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<!-- 合同类型数据 -->
<record id="contract_type_service_consulting" model="yuthon.contract.type">
<field name="name">服务咨询合同</field>
</record>
<record id="contract_type_investment" model="yuthon.contract.type">
<field name="name">投资合同</field>
</record>
<record id="contract_type_operation" model="yuthon.contract.type">
<field name="name">运营合同</field>
</record>
<record id="contract_type_procurement" model="yuthon.contract.type">
<field name="name">采购合同</field>
</record>
<record id="contract_type_capital" model="yuthon.contract.type">
<field name="name">资金合同</field>
</record>
<record id="contract_type_strategic_cooperation" model="yuthon.contract.type">
<field name="name">战略合作协议</field>
</record>
<record id="contract_type_other" model="yuthon.contract.type">
<field name="name">其他合同</field>
</record>
</data>
</odoo>
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<!-- 形成方式数据 -->
<record id="formation_method_bidding" model="yuthon.contract.type">
<field name="name">投标</field>
</record>
<record id="formation_method_negotiation" model="yuthon.contract.type">
<field name="name">议标</field>
</record>
<record id="formation_method_inquiry" model="yuthon.contract.type">
<field name="name">询价</field>
</record>
<record id="formation_method_strategic_cooperation" model="yuthon.contract.type">
<field name="name">战略合作</field>
</record>
<record id="formation_method_entrustment" model="yuthon.contract.type">
<field name="name">委托形成</field>
</record>
</data>
</odoo>
@@ -27,4 +27,5 @@ from . import yuthon_department_change
from . import yuthon_renewal_approval
from . import contract_review_approval
from . import yuthon_employee_add
from . import yuthon_pre_examination
from . import yuthon_pre_examination
from . import yuthon_employee_setting
@@ -13,7 +13,7 @@ class ContractReviewApproval(models.Model):
is_issues = fields.Boolean(string='是否上会')
issues_result = fields.Html(string="会议结果")
related_issues_id = fields.Many2one('issue.library', string="关联议题")
department_id = fields.Many2one('hr.department', string='部门')
department_id = fields.Many2one('hr.department', string='送审部门')
amount = fields.Float(string='合同金额')
remarks = fields.Text(string='情况说明')
documents_ids = fields.Many2many('ir.attachment', string="附件")
@@ -21,6 +21,11 @@ class ContractReviewApproval(models.Model):
default='normal')
active = fields.Boolean('Active', default=True, tracking=True)
work_end = fields.Boolean(string="结束")
contract_type = fields.Many2one('yuthon.contract.type', string="合同类型")
formation_method = fields.Many2one('yuthon.contract.type', string="形成方式")
submitting_unit = fields.Char(string="送审单位")
sign_date = fields.Date(string="合同签订日期")
performance_term_day = fields.Integer(string='履约期限')
def _get_default_name_title(self):
return self._description if self._description else self._name
@@ -60,8 +60,12 @@ class YuthonEmployeeAdd(models.Model):
@api.depends('contract_id', 'version')
def _compute_name(self):
for rec in self:
version_str = self.contract_id.version.lstrip('V')
main_version = version_str.split('.')[0]
new_main_version = int(main_version) + 1
new_version = f"V{new_main_version}.0"
if rec.contract_id:
rec.name = rec.contract_id.name + ' ' + rec.version
rec.name = rec.contract_id.name + ' ' + new_version
else:
rec.name = None
@@ -0,0 +1,24 @@
from odoo import models, fields, api
from dateutil.relativedelta import relativedelta
class YuthonServiceType(models.Model):
_name = 'yuthon.service.type'
_description = '服务类型'
name = fields.Char(string="名称")
class YuthonServiceContractType(models.Model):
_name = 'yuthon.contract.type'
_description = '合同类型和形成方式'
name = fields.Char(string="名称", required=True)
@@ -10,20 +10,22 @@ class YuthonServiceApproval(models.Model):
name = fields.Char(string='标题')
code = fields.Char(string="编号",
default=lambda self: self.env['ir.sequence'].next_by_code('yuthon_service_approval_code'))
service_type = fields.Selection([('done', '在职证明'), ('leaving', '离职证明'), ('income', '收入证明')], string="服务类型")
users_id = fields.Many2one('res.users', string="申请人", default=lambda self: self.env.user.id)
service_type_id = fields.Many2one('yuthon.service.type', string="服务类型")
users_id = fields.Many2one('res.users', string="申请人", default=lambda self: self.env.user)
documents_ids = fields.Many2many('ir.attachment', string="附件")
department_id = fields.Many2one(related='users_id.employee_id.department_id', string="部门", store=True)
employee_id = fields.Many2one('hr.employee', string="员工姓名")
company_id = fields.Many2one(related="users_id.employee_id.company_id", string="公司", store=True)
department_id = fields.Many2one(related='users_id.employee_ids.department_id', string="部门", store=True)
employee_id = fields.Many2one('hr.employee', string="员工姓名", default=lambda self: self.env.user.employee_id.id)
company_id = fields.Many2one(related="users_id.employee_ids.company_id", string="公司", store=True)
tenant_user_card = fields.Many2one('ir.attachment', string="身份证")
onboarding_time = fields.Date(related='employee_id.open_start_time', string="入职时间")
onboarding_time = fields.Date(related='employee_id.open_start_time', string="入职日期")
job_id = fields.Many2one(related='employee_id.job_id', string="岗位")
is_turnover = fields.Boolean()
reason_issuance = fields.Char(string="开证原因")
is_issues = fields.Boolean(string='是否上会')
issues_result = fields.Html(string="会议结果")
related_issues_id = fields.Many2one('issue.library', string="关联议题")
separation_date = fields.Date(string="离职日期")
urgency_level = fields.Selection([('normal', '普件'), ('urgent', '急件'), ('emergency', '特急件')], string='紧急度',
default='normal')
active = fields.Boolean('Active', default=True, tracking=True)
@@ -50,14 +52,13 @@ class YuthonServiceApproval(models.Model):
'approval_date': fields.Datetime.now(),
})
@api.onchange('service_type')
@api.onchange('service_type_id')
def _onchange_service_type(self):
if self.service_type and self.users_id.name:
# 创建一个映射表,将技术值映射到显示文本
service_type_map = {
'done': '在职证明',
'leaving': '离职证明',
'income': '收入证明'
}
service_display = service_type_map.get(self.service_type, self.service_type)
self.name = f"{self.users_id.name}的{service_display}"
if self.service_type_id and self.users_id.name:
self.name = f"{self.users_id.name}的{self.service_type_id.name}"
if self.service_type_id.name == '离职证明':
self.is_turnover = True
else:
self.is_turnover = False
@@ -56,3 +56,5 @@ access_contract_review_approval,contract_review_approval,model_contract_review_a
access_awards_line, awards_line,model_awards_line,base.group_user,1,1,1,1
access_yuthon_employee_add,yuthon_employee_add,model_yuthon_employee_add,base.group_user,1,1,1,1
access_yuthon_pre_examination,yuthon_pre_examination,model_yuthon_pre_examination,base.group_user,1,1,1,1
access_yuthon_service_type,yuthon_service_type,model_yuthon_service_type,base.group_user,1,1,1,1
access_yuthon_contract_type,yuthon_contract_type,model_yuthon_contract_type,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
56 access_awards_line awards_line model_awards_line base.group_user 1 1 1 1
57 access_yuthon_employee_add yuthon_employee_add model_yuthon_employee_add base.group_user 1 1 1 1
58 access_yuthon_pre_examination yuthon_pre_examination model_yuthon_pre_examination base.group_user 1 1 1 1
59 access_yuthon_service_type yuthon_service_type model_yuthon_service_type base.group_user 1 1 1 1
60 access_yuthon_contract_type yuthon_contract_type model_yuthon_contract_type base.group_user 1 1 1 1
@@ -42,12 +42,23 @@
<field name="name_title" readonly="1"/>
</h1>
</div>
<group string="审批信息">
<field name="name" required="1"/>
<field name="work_end" invisible="1"/>
<field name="user_id"/>
<field name="department_id"/>
<field name="amount"/>
<group string="审批信息" col="2">
<group>
<field name="name" required="1"/>
<field name="work_end" invisible="1"/>
<field name="user_id"/>
<field name="department_id"/>
<field name="contract_type"/>
<field name="formation_method"/>
</group>
<group>
<field name="amount"/>
<field name="submitting_unit"/>
<field name="sign_date"/>
<field name="performance_term_day" string="履约期限(天)"/>
</group>
</group>
<group>
<field name="remarks"/>
<field name="documents_ids" widget="preview_many2many"/>
</group>
@@ -60,5 +71,4 @@
<field name="res_model">contract.review.approval</field>
<field name="view_mode">tree,form</field>
</record>
</odoo>
</odoo>
@@ -10,6 +10,7 @@
<button name="pub_leaving_employee" string="离职" type="object"/>
<button name="pub_regularization_employee" string="转正" type="object"/>
<button name="pub_retired_employee" string="退休" type="object"/>
<button name="renew" string="续签" type="object"/>
</xpath>
</field>
</record>
@@ -5,9 +5,9 @@
<field name="model">yuthon.department.change</field>
<field name="arch" type="xml">
<tree string="部门变更审批">
<!-- <header>-->
<!-- <button name="approval_end" type="object" string="结束" dclass="oe_highlight"/>-->
<!-- </header>-->
<!-- <header>-->
<!-- <button name="approval_end" type="object" string="结束" dclass="oe_highlight"/>-->
<!-- </header>-->
<field name="code"/>
<field name="name"/>
</tree>
@@ -52,11 +52,13 @@
<field name="reason_issuance"/>
<field name="company_id" invisible="1"/>
<field name="issues_result" invisible="is_issues == False"/>
<field name="service_type"/>
<field name="employee_id" widget="ztree_select"/>
<field name="service_type_id"/>
<field name="is_turnover" invisible="1"/>
<field name="employee_id" domain="[('user_state', '=', 'leave')] if is_turnover else [('user_state', '=', 'in')]"/>
<field name="job_id"/>
<field name="department_id" invisible="1"/>
<field name="department_id"/>
<field name="onboarding_time"/>
<field name="separation_date" invisible="not is_turnover"/>
<field name="documents_ids" widget="preview_many2many"/>
</group>
</sheet>
@@ -1,5 +1,6 @@
from odoo import api, fields, models, _
from odoo.exceptions import UserError
from datetime import timedelta
class RoomBooking(models.Model):
@@ -9,6 +10,17 @@ class RoomBooking(models.Model):
issue_meeting_line_ids = fields.One2many('issue.meeting.line', 'meeting_booking_id', string="关联议题明细行")
number_of_meetings = fields.Integer(string='会议次数')
@api.constrains('start_datetime')
def _check_start_datetime(self):
for meet in self.issue_meeting_line_ids:
if meet.issue_library_id:
if meet.issue_library_id.is_party == True:
meet.issue_library_id.party_date = self.start_datetime + timedelta(hours=8)
if meet.issue_library_id.is_class == True:
meet.issue_library_id.class_date = self.start_datetime + timedelta(hours=8)
if meet.issue_library_id.is_boss == True:
meet.issue_library_id.boss_date = self.start_datetime + timedelta(hours=8)
def bottom_meeting_approval(self):
library_data = []
for library in self.issue_meeting_line_ids:
@@ -11,6 +11,8 @@ class IssueApprovalDecision(models.Model):
decision_type_on_id = fields.Many2one('issue.approval.decision.type', string='事项类别上级')
sequence = fields.Char(string='序号', store=True)
specifics = fields.Text(string='具体事项')
by_law = fields.Selection([('yes', '是'), ('no', '否')], string='是否经过法律审核')
is_filing = fields.Selection([('yes', '备'), ('no', '否')], string='是否备案')
council_id = fields.Many2one('issue.library.type', string='党总委员会')
team_meet_id = fields.Many2one('issue.library.type', string='经营班子会')
board_meet_id = fields.Many2one('issue.library.type', string='董事会')
@@ -25,6 +27,7 @@ class IssueApprovalDecision(models.Model):
end_date = fields.Date(string="失效日期")
remarks = fields.Text(string='备注')
issue_approval_id = fields.Many2one('issue.approval', string="关联议题审批")
version = fields.Char(string="版本", default="V3.0")
def _get_default_company(self):
company = self.env['res.company'].search([('name', '=', '集团本部')], limit=1)
+10 -7
View File
@@ -12,18 +12,21 @@ class IssueLibrary(models.Model):
name = fields.Char(string='议题名称')
name_text = fields.Text(string='议题名称', compute='_compute_name', readonly=False)
depart_opinions = fields.Text(string='部门意见')
topic_content = fields.Text(string='议题详细描述')
topic_content = fields.Text(string='事项背景')
will_based = fields.Text(string='上会依据')
deliberation_content = fields.Text(string='审议内容', default='建议同意')
is_invisible_workflow = fields.Boolean(string="流程隐藏的判断")
code = fields.Char(string='编号', required=True, copy=False,
default=lambda self: self.env['ir.sequence'].next_by_code('issue_library_code'))
issue_state = fields.Selection([('draft', '待提交'), ('approval', '审批中'), ('on_approval', '已审批'),
('will', '待上会'), ('on_meet', '已上会'), ('cancel', '已取消')],
default='draft', string="议题状态")
is_party = fields.Boolean(string="党支委会", store=True)
is_general_branch = fields.Boolean(string="党总支", store=True)
is_party = fields.Boolean(string="党总支", store=True)
party_date = fields.Datetime(string=' ')
is_class = fields.Boolean(string="班子会", store=True)
class_date = fields.Datetime(string=' ')
is_boss = fields.Boolean(string="董事会", store=True)
boss_date = fields.Datetime(string=' ')
is_note = fields.Boolean(string="上级单位", compute='_compute_issue_library_line_ids', store=True)
is_district_state = fields.Boolean(string="区国资局", compute='_compute_issue_library_line_ids', store=True)
is_district_government = fields.Boolean(string="区政府", compute='_compute_issue_library_line_ids', store=True)
@@ -278,10 +281,10 @@ class IssueLibrary(models.Model):
def unlink(self):
for i in self:
if i.issue_state == 'on_meet':
raise UserError('议题已上会,不能删除')
return super().unlink()
for i in self:
if i.issue_state == 'on_meet':
raise UserError('议题已上会,不能删除')
return super().unlink()
@api.depends('name')
def _compute_name(self):
+1 -1
View File
@@ -12,7 +12,7 @@
<field name="number_of_meetings"/>
</xpath>
<xpath expr="//page[@name='sign']" position="before">
<page string="关联议题" invisible="not is_meeting">
<page string="关联议题" invisible="not is_issue">
<field name="issue_meeting_line_ids">
<tree editable="bottom">
<field name="meeting_booking_id" column_invisible="1"/>
@@ -10,14 +10,17 @@
<field name="decision_type_id" optional="hide"/>
<field name="decision_type_on_id" column_invisible="1"/>
<field name="management_matters_id" optional="hide"/>
<field name="by_law"/>
<field name="council_id"/>
<field name="team_meet_id"/>
<field name="board_meet_id"/>
<field name="district_state_id"/>
<field name="district_government_id"/>
<field name="district_party_id"/>
<field name="is_filing"/>
<field name="remarks"/>
<field name="scope"/>
<field name="version"/>
<field name="company_id" optional="hide"/>
<field name="start_date" optional="hide"/>
<field name="end_date" optional="hide"/>
@@ -50,7 +53,9 @@
<group>
<field name="board_meet_id"/>
<field name="start_date"/>
<field name="department_id" widget="ztree_select"/>
<field name="department_id"/>
<field name="by_law"/>
<field name="is_filing"/>
</group>
<group>
<field name="district_state_id"/>
@@ -58,6 +63,7 @@
<field name="district_party_id"/>
<field name="scope"/>
<field name="company_id"/>
<field name="version"/>
<field name="end_date"/>
</group>
</group>
+2 -1
View File
@@ -64,7 +64,8 @@
<field name="issue_library_id"/>
<field name="employee_id" widget="ztree_select" options="{'no_create': True}"/>
<field name="approval_decision_sequence"/>
<field name="is_party"/>
<field name="is_party" groups="yuthon_salary.group_jtbb_user" string="党总支"/>
<field name="is_party" groups="yuthon_salary.group_lc_user,yuthon_salary.group_wg_user" string="党支委会"/>
<field name="is_class"/>
<field name="is_boss"/>
<field name="is_note"/>
+20 -14
View File
@@ -13,18 +13,21 @@
</header>
<field name="name" column_invisible="1"/>
<field name="name_text" class="list_width"/>
<field name="is_general_branch" groups="yuthon_salary.group_jtbb_user"/>
<field name="is_party" groups="yuthon_salary.group_lc_user,yuthon_salary.group_wg_user"/>
<field name="is_party" groups="yuthon_salary.group_jtbb_user" string="党总支"/>
<field name="is_party" groups="yuthon_salary.group_lc_user,yuthon_salary.group_wg_user" string="党支委会"/>
<field name="party_date" column_invisibl="not party_date"/>
<field name="is_class"/>
<field name="class_date" column_invisibl="not class_date"/>
<field name="is_boss" groups="yuthon_salary.group_jtbb_user"/>
<field name="boss_date" column_invisibl="not boss_date"/>
<field name="is_district_state"/>
<field name="is_district_government"/>
<field name="is_district_party"/>
<field name="issue_state"/>
<field name="code" optional="hide"/>
<field name="company_id" optional="hide"/>
<field name="creart_datetime"/>
<field name="member_of_department" optional="hide"/>
<field name="code" column_invisible="1"/>
<field name="company_id" column_invisible="1"/>
<field name="creart_datetime" column_invisible="1"/>
<field name="member_of_department" column_invisible="1"/>
<button name="single_issue_pull" string="提交" type="object" class="oe_highlight"/>
<button name="issue_cancel" string="取消" type="object" class="oe_highlight"/>
<button name="unlink" string="删除" type="object" class="oe_highlight"/>
@@ -65,9 +68,10 @@
<group>
<field name="name" required="1" force_save="1" invisible="is_invisible_workflow"/>
<field name="topic_content" invisible="is_invisible_workflow"/>
<field name="will_based"/>
<field name="deliberation_content"/>
<field name="documents_ids" widget="preview_many2many" invisible="is_invisible_workflow"/>
<field name="is_invisible_workflow" invisible="1"/>
<field name="name_text" invisible="1"/>
<field name="work_end" invisible="1"/>
<field name="company_id" invisible="1"/>
@@ -82,10 +86,8 @@
</group>
<group col="5" string="决策程序">
<group>
<field name="is_general_branch" groups="yuthon_salary.group_jtbb_user"/>
</group>
<group>
<field name="is_party" groups="yuthon_salary.group_lc_user,yuthon_salary.group_wg_user"/>
<field name="is_party" groups="yuthon_salary.group_jtbb_user" string="党总支"/>
<field name="is_party" groups="yuthon_salary.group_lc_user,yuthon_salary.group_wg_user" string="党支委会"/>
</group>
<group>
<field name="is_class"/>
@@ -104,7 +106,8 @@
<field name="ordinal"/>
<field name="issue_library_id" column_invisible="1"/>
<field name="issue_approval_decision_id" class="list_ids_width"/>
<field name="council_id" readonly="1"/>
<field name="council_id" readonly="1" groups="yuthon_salary.group_jtbb_user" string="党总委员会"/>
<field name="council_id" readonly="1" groups="yuthon_salary.group_wg_user, yuthon_salary.group_lc_user" string="党支委员会"/>
<field name="team_meet_id" readonly="1"/>
<field name="board_meet_id" readonly="1"/>
<field name="district_state_id" readonly="1"/>
@@ -201,8 +204,9 @@
<field name="name"/>
<field name="code"/>
<field name="creart_datetime"/>
<field name="is_general_branch" groups="yuthon_salary.group_jtbb_user"/>
<field name="is_party" groups="yuthon_salary.group_lc_user,yuthon_salary.group_wg_user"/>
<field name="is_party" groups="yuthon_salary.group_jtbb_user" string="党总支"/>
<field name="is_party" groups="yuthon_salary.group_lc_user,yuthon_salary.group_wg_user" string="党支委会"/>
<field name="party_date" column_invisibl="not party_date"/>
<field name="is_district_state"/>
<field name="is_district_government"/>
<field name="is_district_party"/>
@@ -357,6 +361,7 @@
<field name="code"/>
<field name="creart_datetime"/>
<field name="is_class"/>
<field name="class_date" column_invisibl="not class_date"/>
<field name="is_district_state"/>
<field name="is_district_government"/>
<field name="is_district_party"/>
@@ -499,6 +504,7 @@
<field name="code"/>
<field name="creart_datetime"/>
<field name="is_boss" groups="yuthon_salary.group_jtbb_user"/>
<field name="boss_date" column_invisibl="not boss_date"/>
<field name="is_district_state"/>
<field name="is_district_government"/>
<field name="is_district_party"/>
@@ -16,7 +16,8 @@ class ProcessingOrderApproval(models.Model):
display_name = fields.Char(string='名称', compute='_compute_name',)
code = fields.Char(string="编号",
default=lambda self: self.env['ir.sequence'].next_by_code('processing_order_approval_code'))
applicant_id = fields.Many2one('res.users', string="申请人")
applicant_id = fields.Many2one('res.users', string="报修人")
repair_date = fields.Date(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="部门")
company_id = fields.Many2one(related='users_id.employee_id.company_id', string="公司")
@@ -99,6 +100,28 @@ class ProcessingOrderApproval(models.Model):
else:
record.contract_id = False
def open_record(self):
if self.device_id:
return {
'type': 'ir.actions.act_window',
'name': self.device_id.display_name,
'res_model': 'property.device.repair',
'res_id': self.device_id.id,
'view_mode': 'form',
'view_type': 'form',
'target': 'new'
}
elif self.repair_id:
return {
'type': 'ir.actions.act_window',
'name': self.repair_id.display_name,
'res_model': 'property.report.repair',
'res_id': self.repair_id.id,
'view_mode': 'form',
'view_type': 'form',
'target': 'new'
}
@api.onchange('repair_id')
def onchange_repair_id(self):
if self.repair_id:
@@ -7,8 +7,7 @@ from odoo.exceptions import UserError, ValidationError
class PropertyDeviceRelief(models.Model):
_name = 'property.device.repair'
_description = '报事报修(办公设备)'
_inherit = ['soong.workflow.mixin', 'mail.thread.main.attachment', 'mail.activity.mixin']
_description = '报事报修'
name = fields.Char(string='标题', compute='_compute_name', store=True)
code = fields.Char(string="报修编号",
@@ -18,8 +17,7 @@ class PropertyDeviceRelief(models.Model):
company_id = fields.Many2one(related='users_id.employee_id.company_id', string="公司")
software_processing_id = fields.Many2one('software.issues.processing', string="设备类型")
problem_description = fields.Text(string="问题描述")
remake = fields.Text(string="问题描述")
report_state = fields.Selection([('to', '待处理'), ('done', '已处理')], string='状态', default='to')
report_state = fields.Selection([('to_submitted', '待提交'), ('to', '待处理'), ('done', '已处理')], string='状态', default='to_submitted')
create_time = fields.Date(string="填报日期", default=fields.Datetime.now)
urgency_level = fields.Selection([('normal', '普件'), ('urgent', '急件'), ('emergency', '特急件')], string='紧急度',
default='normal')
@@ -38,15 +36,31 @@ class PropertyDeviceRelief(models.Model):
def _compute_name(self):
for rec in self:
if rec.users_id and rec.software_processing_id:
rec.name = f" {rec.software_processing_id.name}-{rec.users_id.name}"
rec.name = f"{rec.users_id.name}-{rec.software_processing_id.name}-{rec.problem_description}"
def device_delete(self):
self.unlink()
def open_record(self):
return {
"type": "ir.actions.act_window",
"res_model": 'processing.order.approval',
"res_id": self.processing_order_id.id,
"name": '详情',
"view_mode": "form",
}
def get_no_read_count(self):
return self.search_count([('report_state', '=', 'to'), ('users_id', '=', self.env.user.id)])
def pull_order(self):
soong_workflow_line_list = []
self.report_state = 'to'
if self.env['processing.order.approval'].search([('device_id', '=', self.id)]):
raise UserError('该设备已生成处理单')
order_id = self.env['processing.order.approval'].create({
'device_id': self.id,
'repair_date': self.create_time,
'applicant_id': self.users_id.id,
'name': self.problem_description,
'code': self.env['ir.sequence'].next_by_code('property_device_repair_code'),
@@ -8,7 +8,6 @@ from odoo.exceptions import UserError
class PropertyRentRelief(models.Model):
_name = 'property.report.repair'
_description = '报事报修(物业)'
_inherit = ['soong.workflow.mixin', 'mail.thread.main.attachment', 'mail.activity.mixin']
name = fields.Char(string='标题', compute='_compute_name', store=True)
code = fields.Char(string="报修编号",
@@ -29,8 +28,6 @@ class PropertyRentRelief(models.Model):
documents_ids = fields.Many2many('ir.attachment', string="附件")
active = fields.Boolean('Active', default=True, tracking=True)
work_end = fields.Boolean(string="结束")
self_users_ids = fields.Many2many('res.users', string="当前经办人",
default=lambda self: [(6, 0, [self.env.user.id])])
create_time = fields.Date(string="填报日期", default=fields.Datetime.now)
processing_order_id = fields.Many2one('processing.order.approval', string="处理单")
def _get_default_name_title(self):
@@ -70,6 +67,7 @@ class PropertyRentRelief(models.Model):
raise UserError('该设备已生成处理单')
order_id = self.env['processing.order.approval'].create({
'repair_id': self.id,
'repair_date': self.create_time,
'applicant_id': self.users_id.id,
'name': self.problem_description,
'problem_description': self.problem_description,
@@ -43,15 +43,19 @@
<field name="name_title" readonly="1"/>
</h1>
</div>
<group string="审批详情">
<group string="报障详情">
<field name="name"/>
<field name="applicant_id"/>
<field name="repair_date"/>
<field name="users_id"/>
<field name="company_id" invisible="1"/>
<field name="department_id" invisible="1"/>
<field name="self_users_ids" invisible="1"/>
<field name="repair_id" invisible="1"/>
<field name="device_id" invisible="1"/>
<field name="documents_ids" widget="preview_many2many"/>
</group>
<group>
<button name="open_record" string="报修详情" type="object" class="btn btn-primary button_width"/>
</group>
<group string="处理详情" col="2" invisible="not repair_id">
<group>
@@ -68,12 +72,11 @@
<group string="处理详情" invisible="not device_id">
<group>
<field name="fault_reason"/>
<field name="device_name"/>
<field name="device_code"/>
</group>
</group>
<group>
<field name="repair_details"/>
<field name="documents_ids" widget="preview_many2many"/>
<field name="processing_results"/>
<field name="is_fee"/>
</group>
@@ -4,13 +4,15 @@
<field name="name">property.device.repair.tree</field>
<field name="model">property.device.repair</field>
<field name="arch" type="xml">
<tree string="报事报修(办公设备)">
<tree string="报事报修">
<field name="name"/>
<field name="code"/>
<field name="software_processing_id"/>
<field name="report_state"/>
<field name="create_time"/>
<button name="pull_order" string="提交" type="object" class="btn-primary"/>
<button name="pull_order" string="提交" type="object" class="btn-primary" invisible="report_state != 'to_submitted'"/>
<button name="device_delete" string="删除" type="object" class="btn-primary" invisible="report_state != 'to_submitted'"/>
<button name="open_record" string="详情" type="object" class="btn-primary" invisible="report_state == 'to_submitted'"/>
</tree>
</field>
</record>
@@ -18,7 +20,7 @@
<field name="name">property.device.repair.form</field>
<field name="model">property.device.repair</field>
<field name="arch" type="xml">
<form string="报事报修(办公设备)" create="1">
<form string="报事报修" create="1">
<sheet>
<widget name="web_ribbon" title="普件" bg_color="text-bg-success"
invisible="urgency_level != 'normal'"/>
@@ -51,6 +53,7 @@
<field name="processing_order_id" invisible="not processing_order_id"/>
<field name="problem_description"/>
<field name="documents_ids" widget="preview_many2many"/>
<field name="report_state"/>
<field name="create_time"/>
</group>
</sheet>
@@ -58,7 +61,13 @@
</field>
</record>
<record id="property_device_repair_action" model="ir.actions.act_window">
<field name="name">报事报修(办公设备)</field>
<field name="name">报事报修</field>
<field name="res_model">property.device.repair</field>
<field name="domain">[('users_id', '=', uid)]</field>
<field name="view_mode">tree,form</field>
</record>
<record id="property_device_repair_all_action" model="ir.actions.act_window">
<field name="name">报事报修(管理员)</field>
<field name="res_model">property.device.repair</field>
<field name="view_mode">tree,form</field>
</record>
@@ -49,7 +49,6 @@
<field name="types_repairs"/>
<field name="company_id" invisible="1"/>
<field name="department_id" invisible="1"/>
<field name="self_users_ids" invisible="1"/>
<field name="processing_order_id" invisible="not processing_order_id"/>
<field name="remake"/>
<field name="documents_ids" widget="preview_many2many"/>
+7
View File
@@ -2,6 +2,7 @@
from odoo import api, fields, models, tools, _
from odoo.exceptions import ValidationError, UserError
import logging
from datetime import datetime, timedelta, date
_logger = logging.getLogger(__name__)
@@ -58,6 +59,12 @@ class YuthonNotice(models.Model):
default=lambda self: [(6, 0, [self.env.user.id])]
)
# @api.onchange('users_ids')
# def _onchange_users_ids(self):
# today = date.today()
# self.start_date = today
# self.create_date1 = today
@api.model_create_multi
def create(self, vals_list):
for i in vals_list:
+1
View File
@@ -9,6 +9,7 @@
'license': 'LGPL-3',
'data': [
'security/ir.model.access.csv',
'security/bank_company_rule.xml',
'security/yuthon_property_group.xml',
'security/yuthon_accounts_group.xml',
'data/data_yuthon_resource_mgmt_config.xml',
@@ -39,14 +39,24 @@ class PropertyBankStatements(models.Model):
voucher_type = fields.Selection([('electronic_transfer', '电子转账凭证'), ('telegraphic_transfer', '电汇凭证')], string='凭证种类')
remake = fields.Text('备注')
registered = fields.Float('挂账')
is_reconciliation = fields.Boolean('是否对账') # 无效
is_reconciliation = fields.Boolean('是否对账')
company_select = fields.Selection([('jhtz', '天河投资'), ('thwg', '天河物管'), ('thcj', '天河城建')])
property_ids = fields.Many2many('yuthon.property', string='物业地址')
bank_state = fields.Selection([('not_reconciled', '未对账'), ('reconciled', '已对账'), ('registered', '挂账'), ('other', '其他')], string='状态', default='not_reconciled')
is_company = fields.Boolean(compute='_compute_is_company', search='_search_part_of_company', default=True)
company_id1 = fields.Many2one('res.company', string='公司')
change_amount = fields.Float(string='修改金额')
receivable_modify_ids = fields.One2many('receivable.modify.line', 'bank_id', string='修改应收单')
def update_company_id(self):
records = self.env['property.bank.statements'].search([])
for record in records:
if record.your_own_unit in ['天河投资', '天投城建']:
record.company_id1 = self.env['res.company'].search([('name', '=', '集团本部')], limit=1)
elif record.your_own_unit in ['天河物管']:
record.company_id1 = self.env['res.company'].search([('name', '=', '天河物管')], limit=1)
elif record.your_own_unit in ['天河粮储']:
record.company_id1 = self.env['res.company'].search([('name', '=', '天河粮储')], limit=1)
def update_record(self):
selected_records = self.env["property.bank.statements"].browse(
self._context.get('active_ids', self._context.get('active_id'))
@@ -112,43 +122,6 @@ class PropertyBankStatements(models.Model):
bank_id.change_amount = change_amount
bank_id.yes_amount = change_amount
@api.depends_context('uid', 'company')
@api.depends('your_own_account')
def _compute_is_company(self):
user_companies = self.env['res.company'].browse(self.env.companies.ids)
user_company_names = set(user_companies.mapped('name'))
# 预定义账号映射关系
account_mapping = {
'集团本部': ['天河投资', '天投城建'],
'天河物管': ['天河物管'],
'天河粮储': ['天河粮储']
}
for record in self:
# 默认不可见
record.is_company = False
# 检查账号是否符合规则
for company_name, allowed_accounts in account_mapping.items():
if company_name in user_company_names:
if record.your_own_unit in allowed_accounts:
record.is_company = True
break
def _search_part_of_company(self, operator, value):
if operator not in ('=', '!=') or not isinstance(value, bool):
raise UserError(_('操作不支持'))
user_companies = self.env['res.company'].browse(self.env.companies.ids)
company_names = user_companies.mapped('name')
visible_accounts = []
if "集团本部" in company_names:
visible_accounts.extend(['天河投资', '天投城建'])
if "天河物管" in company_names:
visible_accounts.append('天河物管')
if not value:
operator = '!=' if operator == '=' else '='
domain = [('your_own_unit', 'in', visible_accounts)] if operator == '=' and visible_accounts else []
return domain or [('id', '=', 0)]
def other(self):
bank_ids = self.env["property.bank.statements"].browse(
self._context.get('active_ids', self._context.get('active_id')))
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- <record model="ir.rule" id="property_bank_statements_rule">-->
<!-- <field name="name">银行流水多公司</field>-->
<!-- <field name="model_id" ref="model_property_bank_statement"/>-->
<!-- <field name="domain_force">[('company_id1', 'in', company_ids)]</field>-->
<!-- </record>-->
</odoo>
@@ -16,7 +16,6 @@
<field name="name_account" />
<field name="your_own_unit"/>
<field name="property_ids" widget="many2many_tags" column_invisible="1"/>
<field name="is_company" column_invisible="1"/>
<field name="bank_state" />
</tree>
</field>
@@ -45,7 +44,6 @@
<field name="your_own_account"/>
<field name="extract"/>
<field name="remake"/>
<field name="is_company"/>
<field name="bank_state"/>
</tree>
</field>
@@ -107,9 +105,15 @@
<field name="name">银行流水</field>
<field name="res_model">property.bank.statements</field>
<field name="view_mode">tree,form,search</field>
<!-- <field name="domain">[('is_company', '=', True)]</field>-->
<field name="context">{'group_by': 'bank_state'}</field>
<field name="view_ids" eval="[(5, 0, 0),
(0, 0, {'view_mode': 'tree', 'view_id': ref('yuthon_property.view_property_bank_statements_tree1')})]"/>
</record>
<record id="all_update_company_id1" model="ir.actions.server">
<field name="name">更新公司</field>
<field name="model_id" ref="yuthon_property.model_property_bank_statements"/>
<field name="binding_model_id" ref="yuthon_property.model_property_bank_statements"/>
<field name="state">code</field>
<field name="code">action = model.update_company_id()</field>
</record>
</odoo>
@@ -19,7 +19,7 @@ class PropertyLeaseRenewal(models.Model):
company_id = fields.Many2one(related='user_id.company_id', string="公司")
code = fields.Char(string="编号",
default=lambda self: self.env['ir.sequence'].next_by_code('property_lease_renewal_code'))
renewal_type = fields.Selection([('early_checkout', '提前退租'), ('lease', '承租方变更')], string='变更类型')
renewal_type = fields.Selection([('early_checkout', '合同终止'), ('lease', '承租方变更')], string='变更类型')
urgency_level = fields.Selection([('normal', '普件'), ('urgent', '急件'), ('emergency', '特急件')], string='紧急度',
default='normal')
def _get_default_name_title(self):
@@ -129,10 +129,13 @@ class PenaltyLineWizard(models.Model):
# 计算剩余本金
remaining_principal = max(0, pay_line.not_collected - pay_amount)
penalty_start_date = pay_date
if is_penalty:
remake = f'支付违约金¥{pay_line.amount}'
else:
remake = f'支付金额¥{pay_line.amount}'
new_penalty_lines.append((0, 0, {
'date': pay_date,
'remake': f'支付金额¥{pay_line.amount}',
'remake':remake,
'days_overdue': days_overdue,
'remaining_principal': remaining_principal,
'penalty': round(current_penalty, 2),
@@ -186,7 +189,7 @@ class PenaltyLineWizard(models.Model):
if non_realtime_lines:
prev_line = non_realtime_lines[-1]
if round(prev_line.remaining_principal or 0, 2) != 0:
base_date = prev_line.date + relativedelta(months=1)
base_date = (prev_line.date + relativedelta(months=1)).replace(day=1)
days_overdue = (self.calculation_date - base_date).days - 1
days_overdue = max(0, days_overdue)
# 计算违约金
@@ -196,7 +199,7 @@ class PenaltyLineWizard(models.Model):
'date': self.calculation_date,
'days_overdue': days_overdue,
'remaining_principal': prev_line.remaining_principal,
'remake': f'{base_date}至{self.calculation_date}',
'remake': f'违约金:{base_date}至{self.calculation_date}',
'penalty': round(current_penalty, 2),
'is_realtime': True,
}))
@@ -586,9 +586,13 @@ class PropertyReconciliationWizard(models.Model):
'is_write': True if line.amount != 0 else False,
'is_penalty': True,
'reconciliation_date': rec.actual_date if line.amount != 0 else None,
'receivable_id': receivable_id.id,
'receivable_id': receivable_id[0].id,
'amount': line.amount,
})
# 删除多余的违约金数据
if len(receivable_id) > 1:
receivable_id = existing_record[1:]
receivable_id.unlink()
rec.amount_been_reconciled += line.amount
yes_amount += line.amount
@@ -607,7 +611,6 @@ class PropertyReconciliationWizard(models.Model):
if unreconciled_receivables:
remaining_contract_ids.append(contract.id)
class PropertyReconciliationLine(models.Model):
_name = 'property.reconciliation.line'
_description = '对账明细'
+1
View File
@@ -10,6 +10,7 @@
'data': [
'security/ir.model.access.csv',
'security/company_rule.xml',
'data/process_code_data.xml',
'report/purchase_workflow_report.xml',
'report/purchase_workflow_templates.xml',
'views/inherit_product_product_views.xml',
@@ -7,4 +7,9 @@
<field name="padding">3</field>
<field name="company_id" eval="False"/>
</record>
<record model="ir.rule" id="model_purchase_order_rule">
<field name="name">采购多公司</field>
<field name="model_id" ref="model_purchase_order"/>
<field name="domain_force">[('company_id', 'in', company_ids)]</field>
</record>
</odoo>
@@ -9,14 +9,44 @@ class InheritPurchaseOrder(models.Model):
_name = 'purchase.order'
_inherit = ['purchase.order', 'soong.workflow.mixin']
json_display = fields.Char(
string="物品详情",
compute='_compute_json_display',
store=True
)
code = fields.Char(string="流水号", default=lambda self: self.env['ir.sequence'].next_by_code('purchase_workflow_approval_code'))
state = fields.Selection(selection_add=[('部门经理', '部门经理'),
('协办', '协办'),
('分管领导', '分管领导'),
('总经理', '总经理')], default='draft')
work_end = fields.Boolean(string="结束")
user_id = fields.Many2one('res.users', string="申请人", default=lambda self: self.env.user)
company_id = fields.Many2one(related='user_id.employee_ids.company_id', string="公司")
department_id = fields.Many2one(related='user_id.employee_ids.department_id', string="部门")
document_ids = fields.Many2many('ir.attachment', string="附件")
start_date = fields.Date(string="申请日期", default=fields.Date.today())
purchase_type = fields.Selection(
[('fixed', '固定资产'), ('low', '低值易耗'), ('service', '服务'), ('day', '日常消耗品')],
string="采购类型", default='fixed')
pay_way = fields.Selection([('onetime', '一次性'), ('installment', '分期')], string="付款方式", default='onetime')
reason_text = fields.Text(string="申请事由")
pay_line_ids = fields.One2many('purchase.order.pay.line', 'order_id', string="付款详情")
low_line_ids = fields.One2many('purchase.low.line', 'order_id', string="低值易耗明细")
service_line_ids = fields.One2many('purchase.service.line', 'order_id', string="服务明细")
fixed_line_ids = fields.One2many('purchase.fixed.line', 'order_id', string="日常消耗品明细")
def update_state(self):
order_ids = self.env["purchase.order"].browse(
self._context.get('active_ids', self._context.get('active_id')))
for order in order_ids:
order.button_cancel()
def end_approval(self):
self.button_confirm()
self.state = 'purchase'
self.write({'work_end': True})
@api.depends(
'order_line.product_id',
+29 -11
View File
@@ -24,13 +24,14 @@ class PurchaseWorkflow(models.Model):
default='normal', required=True)
pay_way = fields.Selection([('onetime', '一次性'), ('installment', '分期')], string="付款方式", default='onetime',
required=True)
pay_amount = fields.Float(string="付款金额")
total = fields.Float(string="合计金额", readonly=True)
document_ids = fields.Many2many('ir.attachment', string="附件")
active = fields.Boolean('启用', default=True, tracking=True)
work_end = fields.Boolean(string="审批结束", default=False, tracking=True)
purchase_order_id = fields.Many2one('purchase.order', string="采购订单", readonly=True)
purchase_type = fields.Selection([('fixed', '固定资产'), ('low', '低值易耗'), ('service', '服务')],
purchase_type = fields.Selection([('fixed', '固定资产'), ('low', '低值易耗'), ('service', '服务'), ('day', '日常消耗品')],
string="采购类型", required=True, default='fixed')
service_content = fields.Text(string="服务内容")
@@ -45,6 +46,7 @@ class PurchaseWorkflow(models.Model):
service_line_ids = fields.One2many('purchase.service.line', 'service_id', string="服务明细")
pay_line_ids = fields.One2many('purchase.order.pay.line', 'purchase_id', string="付款详情")
@api.onchange('purchase_type')
def _onchange_purchase_type(self):
if self.purchase_type == 'fixed':
@@ -113,6 +115,7 @@ class PurchaseOrderPayLine(models.Model):
_description = "付款详情"
purchase_id = fields.Many2one('purchase.workflow', string="关联采购工作流")
order_id = fields.Many2one('purchase.order', string="关联采购")
payment_stage = fields.Char(string="付款阶段")
amount = fields.Char(string="比例/金额")
payment_date = fields.Date(string="付款日期")
@@ -125,14 +128,15 @@ class PurchaseFixedLine(models.Model):
purchase_id = fields.Many2one('purchase.workflow', string="关联采购工作流")
product_id = fields.Many2one('product.product', string="物品名称")
order_id = fields.Many2one('purchase.order', string="关联采购")
brand = fields.Char(string="品牌")
specs = fields.Char(string="规格")
number = fields.Integer(string="数量",)
number = fields.Integer(string="数量")
name = fields.Text(string="描述")
product_packaging_id = fields.Many2one('product.packaging', string="包装")
taxes_id = fields.Many2one('account.tax', string='税项')
unit_id = fields.Many2one(related='product_id.uom_id', string="单位")
price_unit = fields.Float(related='product_id.standard_price', string="单价", store=True)
unit_id = fields.Many2one('uom.uom', string="单位")
price_unit = fields.Float(string="单价", store=True)
total = fields.Float(string="合计", compute='_compute_total', store=True)
@api.depends('price_unit', 'number')
@@ -144,20 +148,25 @@ class PurchaseFixedLine(models.Model):
def _onchange_product_id(self):
if self.product_id:
self.name = self.product_id.display_name
self.unit_id = self.product_id.uom_id
self.price_unit = self.product_id.standard_price
class PurchaseLowLine(models.Model):
_name = 'purchase.low.line'
_description = '低值易耗采购明细'
purchase_id = fields.Many2one('purchase.workflow', string="关联采购工作流")
product_id = fields.Many2one('product.product', string="物品名称")
brand = fields.Char(related="product_id.brand", string="品牌")
specs = fields.Char(related="product_id.specs", string="规格")
order_id = fields.Many2one('purchase.order', string="关联采购")
brand = fields.Char(string="品牌")
specs = fields.Char(string="规格")
name = fields.Text(string="描述")
product_packaging_id = fields.Many2one('product.packaging', string="包装")
taxes_id = fields.Many2one('account.tax', string='税项')
number = fields.Integer(string="数量")
unit_id = fields.Many2one(related='product_id.uom_id', string="单位")
price = fields.Float(related='product_id.standard_price', string="单价", store=True)
unit_id = fields.Many2one('uom.uom', string="单位")
price = fields.Float(string="单价", store=True)
total = fields.Float(string="合计", compute='_compute_total', store=True)
@api.depends('price', 'number')
@@ -169,20 +178,26 @@ class PurchaseLowLine(models.Model):
def _onchange_product_id(self):
if self.product_id:
self.name = self.product_id.display_name
self.brand = self.product_id.brand
self.specs = self.product_id.specs
self.unit_id = self.product_id.uom_id
self.price = self.product_id.standard_price
# 服务采购明细
class PurchaseServiceLine(models.Model):
_name = 'purchase.service.line'
_description = '服务采购明细'
service_id = fields.Many2one('purchase.workflow', string="关联采购工作流")
product_id = fields.Many2one('product.product', string="服务项目")
order_id = fields.Many2one('purchase.order', string="关联采购")
frequency = fields.Integer(string='频次')
fee = fields.Float(string="费用")
name = fields.Text(string="描述", default=lambda self: self.product_id.display_name if self.product_id else False )
name = fields.Text(string="描述")
product_packaging_id = fields.Many2one('product.packaging', string="包装")
taxes_id = fields.Many2one('account.tax', string='税项')
unit_id = fields.Many2one(related='product_id.uom_id', string="单位")
price = fields.Float(related='product_id.standard_price', string="单价", store=True)
unit_id = fields.Many2one('uom.uom', string="单位")
price = fields.Float(string="单价", store=True)
total = fields.Float(string="合计", compute='_compute_total', store=True)
@api.depends('price', 'frequency')
@@ -194,6 +209,9 @@ class PurchaseServiceLine(models.Model):
def _onchange_product_id(self):
if self.product_id:
self.name = self.product_id.display_name
self.unit_id = self.product_id.uom_id
self.price = self.product_id.standard_price
class PurchaseFixedAssets(models.Model):
_name = 'purchase.fixed.assets'
@@ -8,6 +8,9 @@
<xpath expr="//field[@name='partner_ref']" position="attributes">
<attribute name="column_invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='partner_ref']" position="attributes">
<attribute name="column_invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='activity_ids']" position="attributes">
<attribute name="column_invisible">1</attribute>
</xpath>
@@ -22,12 +25,59 @@
</xpath>
</field>
</record>
<record id="inherit_purchase_order_kpis_tree" model="ir.ui.view">
<field name="name">purchase.order.kpis.tree</field>
<field name="model">purchase.order</field>
<field name="inherit_id" ref="purchase.purchase_order_kpis_tree"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='name']" position="attributes">
<attribute name="string">事项</attribute>
</xpath>
<xpath expr="//field[@name='amount_untaxed']" position="attributes">
<attribute name="column_invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='name']" position="after">
<field name="code"/>
</xpath>
<xpath expr="//field[@name='activity_ids']" position="attributes">
<attribute name="column_invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='origin']" position="attributes">
<attribute name="column_invisible">1</attribute>
</xpath>
</field>
</record>
<record id="inherit_purchase_order_form" model="ir.ui.view">
<field name="name">purchase.order.form</field>
<field name="model">purchase.order</field>
<field name="inherit_id" ref="purchase.purchase_order_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='currency_id']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='partner_ref']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='state']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='date_order']" position="after">
<field name="user_id"/>
<field name="start_date"/>
</xpath>
<xpath expr="//field[@name='date_order']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='date_planned']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='currency_id']" position="after">
<field name="code" invisible="1"/>
<field name="company_id" invisible="1"/>
<field name="department_id" invisible="1"/>
<field name="purchase_type"/>
<field name="pay_way"/>
<field name="reason_text"/>
<field name="document_ids" widget="preview_many2many"/>
<field name="is_back" invisible="1"/>
<field name="work_end" invisible="1"/>
@@ -35,22 +85,82 @@
<xpath expr="//field[@name='partner_id']" position="attributes">
<attribute name="domain">[('is_employee', '=', False)]</attribute>
</xpath>
<!-- <xpath expr="//page[@string='purchase_delivery_invoice']" position="after">-->
<!-- <page string="关联流程">-->
<!-- <field name="issue_library_approval_line_ids" readonly="1">-->
<!-- <tree editable="bottom">-->
<!-- <field name="issue_library_id" column_invisible="1"/>-->
<!-- <field name="res_model" column_invisible="1"/>-->
<!-- <field name="res_id" column_invisible="1"/>-->
<!-- <field name="code"/>-->
<!-- <field name="workflow_name"/>-->
<!-- <field name="approval_type"/>-->
<!-- <field name="approval_date"/>-->
<!-- <button name="open_record" type="object" string="详情" class="btn-primary"/>-->
<!-- </tree>-->
<!-- </field>-->
<!-- </page>-->
<!-- </xpath>-->
<xpath expr="//page[@name='products']" position="attributes">
<attribute name="invisible">purchase_type != 'fixed'</attribute>
<attribute name="string">固定资产明细</attribute>
</xpath>
<xpath expr="//page[@name='products']" position="after">
<page string="日常消耗品明细" invisible="purchase_type != 'day'">
<field name="fixed_line_ids">
<tree editable="bottom">
<field name="purchase_id" column_invisible="1"/>
<field name="product_id" required="1"/>
<field name="brand"/>
<field name="specs"/>
<field name="product_packaging_id"/>
<field name="number"/>
<field name="unit_id"/>
<field name="price_unit"/>
<field name="taxes_id"/>
<field name="total" sum="Total"/>
<field name="name" string="描述" required="1"/>
</tree>
</field>
</page>
<page string="低值易耗明细" invisible="purchase_type != 'low'">
<field name="low_line_ids">
<tree editable="bottom">
<field name="purchase_id" column_invisible="1"/>
<field name="product_id" string="物品名称" required="1"/>
<field name="name"/>
<field name="brand"/>
<field name="specs"/>
<field name="number"/>
<field name="unit_id"/>
<field name="price"/>
<field name="taxes_id"/>
<field name="total" sum="Total"/>
</tree>
</field>
</page>
<page string="服务明细" invisible="purchase_type != 'service'">
<field name="service_line_ids">
<tree editable="bottom">
<field name="service_id" column_invisible="1"/>
<field name="product_id" required="1"/>
<field name="name" string="描述" required="1"/>
<field name="frequency"/>
<field name="fee"/>
<field name="product_packaging_id"/>
<field name="unit_id"/>
<field name="price"/>
<field name="taxes_id"/>
<field name="total" sum="Total"/>
</tree>
</field>
</page>
<page string="付款详情" invisible="pay_way == 'onetime'">
<field name="pay_line_ids">
<tree editable="bottom">
<field name="purchase_id" column_invisible="1"/>
<field name="payment_stage" required="1"/>
<field name="amount"/>
<field name="payment_date"/>
<field name="remake"/>
</tree>
</field>
</page>
</xpath>
<xpath expr="//page[@name='purchase_delivery_invoice']" position="attributes">
<attribute name="invisible">True</attribute>
</xpath>
</field>
</record>
<record id="all_purchase_order_cancel" model="ir.actions.server">
<field name="name">取消</field>
<field name="model_id" ref="purchase.model_purchase_order"/>
<field name="binding_model_id" ref="purchase.model_purchase_order"/>
<field name="state">code</field>
<field name="code">action = model.update_state()</field>
</record>
</odoo>
@@ -47,13 +47,14 @@
<field name="company_id" invisible="1"/>
<field name="start_date"/>
<field name="user_id" string="申请人" required="1"/>
<field name="purchase_type" required="1"/>
<field name="partner_id" domain="[('user_ids', '=', False)]" required="1"/>
<field name="pay_way" required="1"/>
<field name="pay_amount" invisible="pay_way != 'onetime'"/>
</group>
<group>
<field name="date_order" string="订单日期" required="1"/>
<field name="date_planned" string="预计到货日期" invisible="purchase_type != 'fixed'" required="1"/>
<field name="purchase_type" required="1"/>
<field name="partner_id" domain="[('user_ids', '=', False)]" required="1"/>
<field name="pay_way" required="1"/>
<field name="service_start_date" string="服务开始时间" invisible="purchase_type != 'service'"/>
<field name="service_end_date" string="服务结束时间" invisible="purchase_type != 'service'"/>
<field name="service_year" string="服务年限" invisible="purchase_type != 'service'"/>
@@ -92,6 +93,23 @@
</tree>
</field>
</page>
<page string="日常消耗品明细" invisible="purchase_type != 'day'">
<field name="fixed_line_ids">
<tree editable="bottom">
<field name="purchase_id" column_invisible="1"/>
<field name="product_id" required="1"/>
<field name="brand"/>
<field name="specs"/>
<field name="product_packaging_id"/>
<field name="number"/>
<field name="unit_id"/>
<field name="price_unit"/>
<field name="taxes_id"/>
<field name="total" sum="Total"/>
<field name="name" string="描述" required="1"/>
</tree>
</field>
</page>
<page string="低值易耗明细" invisible="purchase_type != 'low'">
<field name="low_line_ids">
<tree editable="bottom">
@@ -8,23 +8,18 @@
<div class="card-body">
<!-- 搜索区域 -->
<div class="row mb-2" t-ref="search_area">
<!-- 应收日期范围 -->
<!-- 应收日期范围 -->
<div class="col-6">
<label>日期范围</label>
<div class="d-flex align-items-center gap-2">
<!-- 上一个月 按钮-->
<button class="btn btn-info" style="margin-bottom: 5px" t-on-click="onClickPreMonth">
<i class="oi oi-chevron-left"></i>
</button>
<DateTimeInput
range="true"
range="true"
value="state.startDate"
type="'date'"
placeholder="fromPlaceholder"
onChange="(date) => this.onChangeStartDate(date)"
/>
<i class="oi oi-arrow-right"></i>
<!-- <i class="oi oi-arrow-right"></i>-->
<DateTimeInput
range="true"
value="state.endDate"
@@ -32,9 +27,12 @@
placeholder="toPlaceholder"
onChange="(date) => this.onChangeEndDate(date)"
/>
<!-- 上一个月 按钮-->
<button class="btn btn-info" style="margin-bottom: 5px" t-on-click="onClickPreMonth">
<i class="oi oi-chevron-left"></i>
</button>
<!-- 下一个月-->
<button class="btn btn-sm btn-outline-secondary" style="margin-bottom: 5px" t-on-click="onClickNextMonth">
<button class="btn btn-info" style="margin-bottom: 5px" t-on-click="onClickNextMonth">
<i class="oi oi-chevron-right"></i>
</button>
</div>
+3
View File
@@ -35,6 +35,7 @@
'wizard/yuthon_salary_wizard_views.xml',
'wizard/salary_party_wizard_views.xml',
'wizard/temporary_payslip_wizard_views.xml',
'wizard/salary_import_wizard_views.xml',
'wizard/yuthon_payroll_wizard_views.xml',
'wizard/basic_pension_wizard_views.xml',
'wizard/payroll_labor_wizard_views.xml',
@@ -61,8 +62,10 @@
'yuthon_salary/static/src/js/salary_retired_button.js',
'yuthon_salary/static/src/js/salary_validation_button.js',
'yuthon_salary/static/src/js/salary_year_button.js',
'yuthon_salary/static/src/js/salary_import_button.js',
'yuthon_salary/static/src/xml/salary_create_button.xml',
'yuthon_salary/static/src/xml/salary_labor_button.xml',
'yuthon_salary/static/src/xml/salary_import_button.xml',
'yuthon_salary/static/src/xml/salary_retired_button.xml',
'yuthon_salary/static/src/xml/salary_payslip_button.xml',
'yuthon_salary/static/src/xml/salary_documents_button.xml',
+17 -17
View File
@@ -385,23 +385,23 @@ class InheritHrPayslip(models.Model):
res = super(InheritHrPayslip, self).create(vals_list)
return res
@api.model
def create(self, vals):
"""
为了解决部分薪资生成未生效,单独处理计算公式
工会会费:round(abs(payslip.base_salary * 0.005) * -1, 2) --union_dues
:param vals:
:return:
"""
record = super().create(vals)
employee_id = self.env['hr.employee'].search([('id', '=', vals['employee_id'])])
payroll = self.env['hr.contract'].search([('employee_id', '=', employee_id.id), ('state', '=', 'open')])[-1].structure_type_id.default_struct_id
if payroll.rule_ids.search([('name', '=', '基本工资'), ('struct_id', '=', payroll.id)]):
base_salary = payroll.rule_ids.search([('name', '=', '基本工资'), ('struct_id', '=', payroll.id)])[-1].amount_fix
# if record.worked_days_line_ids.search([('name', '=', '工会会费')]):
# record.line_ids.search([('name', '=', '工会会费')]).total = round(abs(base_salary * 0.005) * -1, 2)
record.write({'union_dues': round(abs(base_salary * 0.005) * -1, 2)})
return record
# @api.model
# def create(self, vals):
# """
# 为了解决部分薪资生成未生效,单独处理计算公式
# 工会会费:round(abs(payslip.base_salary * 0.005) * -1, 2) --union_dues
# :param vals:
# :return:
# """
# record = super().create(vals)
# employee_id = self.env['hr.employee'].search([('id', '=', vals['employee_id'])])
# payroll = self.env['hr.contract'].search([('employee_id', '=', employee_id.id), ('state', '=', 'open')])[-1].structure_type_id.default_struct_id
# if payroll.rule_ids.search([('name', '=', '基本工资'), ('struct_id', '=', payroll.id)]):
# base_salary = payroll.rule_ids.search([('name', '=', '基本工资'), ('struct_id', '=', payroll.id)])[-1].amount_fix
# # if record.worked_days_line_ids.search([('name', '=', '工会会费')]):
# # record.line_ids.search([('name', '=', '工会会费')]).total = round(abs(base_salary * 0.005) * -1, 2)
# record.write({'union_dues': round(abs(base_salary * 0.005) * -1, 2)})
# return record
@api.ondelete(at_uninstall=False)
def _unlink_if_draft_or_cancel(self):
+2 -1
View File
@@ -36,4 +36,5 @@ access_rank_log_line,access_rank_log_line,model_rank_log_line,base.group_user,1,
access_rank_log_wizard,access_rank_log_wizard,model_rank_log_wizard,base.group_user,1,1,1,1
access_basic_pension_wizard,access_basic_pension_wizard,model_basic_pension_wizard,base.group_user,1,1,1,1
access_yuthon_salary_party,access_yuthon_salary_party,model_yuthon_salary_party,base.group_user,1,1,1,1
access_salary_party_wizard,access_salary_party_wizard,model_salary_party_wizard,base.group_user,1,1,1,1
access_salary_party_wizard,access_salary_party_wizard,model_salary_party_wizard,base.group_user,1,1,1,1
access_salary_import_wizard,access_salary_import_wizard,model_salary_import_wizard,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
36 access_salary_party_wizard access_salary_party_wizard model_salary_party_wizard base.group_user 1 1 1 1
37 access_salary_import_wizard access_salary_import_wizard model_salary_import_wizard base.group_user 1 1 1 1
38
39
40
@@ -0,0 +1,29 @@
/** @odoo-module */
import { ListController } from "@web/views/list/list_controller";
import { registry } from '@web/core/registry';
import { listView } from '@web/views/list/list_view';
export class CustomSalaryImportController extends ListController {
setup() {
super.setup();
}
openSalaryImportWizard() {
this.actionService.doAction({
type: 'ir.actions.act_window',
res_model: 'salary.import.wizard',
name: '薪资导入',
view_mode: 'form',
view_type: 'form',
views: [[false, 'form']],
target: 'new', // 以弹窗形式打开
context: {},
});
}
}
registry.category("views").add("custom_salary_import_button", {
...listView,
Controller: CustomSalaryImportController,
buttonTemplate: "salary_import_module.ListView.Buttons",
});
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<templates>
<t t-name="salary_import_module.ListView.Buttons" t-inherit="web.ListView.Buttons">
<xpath expr="//div[hasclass('o_list_buttons')]" position="after">
<button type="button" class="btn btn-primary" style="margin-left: 10px;" t-on-click="openSalaryImportWizard">
薪资导入
</button>
</xpath>
</t>
</templates>
@@ -242,7 +242,7 @@
<field name="name">hr.payslip.tree.validation.jtbb</field>
<field name="model">hr.payslip</field>
<field name="arch" type="xml">
<tree string="薪资审定">
<tree string="薪资审定" js_class="custom_salary_import_button">
<header>
<button name="action_refresh_from_work_entries" string="重新计算" type="object" class="oe_highlight"/>
<button name="all_put_release" type="object" string="推送" class="oe_highlight"/>
@@ -312,7 +312,7 @@
<field name="name">hr.payslip.tree.validation.wg</field>
<field name="model">hr.payslip</field>
<field name="arch" type="xml">
<tree string="薪资审定">
<tree string="薪资审定" js_class="custom_salary_import_button">
<header>
<button name="action_refresh_from_work_entries" string="重新计算" type="object" class="oe_highlight"/>
<button name="all_put_release" type="object" string="推送" class="oe_highlight"/>
@@ -369,7 +369,7 @@
<field name="name">hr.payslip.tree.validation_lc</field>
<field name="model">hr.payslip</field>
<field name="arch" type="xml">
<tree string="薪资审定">
<tree string="薪资审定" js_class="custom_salary_import_button">
<header>
<button name="action_refresh_from_work_entries" string="重新计算" type="object" class="oe_highlight"/>
<button name="all_put_release" type="object" string="推送" class="oe_highlight"/>
+1
View File
@@ -14,3 +14,4 @@ from . import initialize_payroll_wizard
from . import rank_log_wizard
from . import basic_pension_wizard
from . import salary_party_wizard
from . import salary_import_wizard
@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _, SUPERUSER_ID
from odoo.exceptions import ValidationError, UserError
from pypinyin import pinyin, Style
import xlrd
import base64
import datetime
from datetime import datetime, timedelta
class SalaryImportWizard(models.TransientModel):
_name = 'salary.import.wizard'
_description = '薪资导入弹窗'
file = fields.Binary(string='File', required=True)
excel_file = fields.Binary(string="上传Excel表")
excel_name = fields.Char(string="文件名")
def confirm(self):
if not self.excel_file:
raise ValidationError('请上传文件。')
book = xlrd.open_workbook(file_contents=base64.decodebytes(self.excel_file))
sh = book.sheet_by_index(0)
header_row = sh.row(0)
excel_headers = [str(cell.value).strip() for cell in header_row if cell.value]
invalid_headers = [header for header in excel_headers]
for rx in range(1, sh.nrows):
row = sh.row(rx)
self.salary_party_data(row, excel_headers)
def salary_party_data(self, row, excel_headers):
employee_name = row[0].value
employee = self.env['hr.employee'].search([('name', '=', employee_name)], limit=1)
if employee:
payslip_run_name = f"{2025}年-八月"
payslip_run_id = self.env['hr.payslip.run'].search(
[('name', '=', payslip_run_name), ('company_id', '=', employee.company_id.id)], limit=1)
payslip = self.env['hr.payslip'].search([
('payslip_run_id', '=', payslip_run_id.id),
('employee_id', '=', employee.id),
], limit=1)
if not payslip:
payslip_vals = {
'name': employee.name,
'employee_id': employee.id,
'contract_id': employee.contract_id.id,
'payslip_run_id': payslip_run_id.id,
'date_from': datetime(2025, 8, 1).date() ,
'date_to': datetime(2025, 8, 31).date(),
'is_salary_push': True,
'is_salary_release': False
}
payslip = self.env['hr.payslip'].create(payslip_vals)
payslip.compute_sheet()
else:
payslip.is_salary_push = True
payslip.is_salary_release = False
for line in payslip.line_ids:
line_name = line.name
if line_name not in excel_headers:
continue
header_idx = excel_headers.index(line_name) + 1
amount = row[header_idx].value
if amount == 0.0:
continue
line.write({
'amount': amount,
'total': amount,
})
def _get_chinese_month(self, month):
chinese_months = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月',
'十二月']
return chinese_months[month - 1]
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="salary_import_wizard_downloads_action" model="ir.actions.act_url">
<field name="name">模板下载</field>
<field name="target">self</field>
<field name="url">/yuthon_salary/static/others/salary_party.xlsx</field>
</record>
<record id="salary_import_wizard_form" model="ir.ui.view">
<field name="name">弹窗</field>
<field name="model">salary.import.wizard</field>
<field name="arch" type="xml">
<form>
<sheet>
<header>
<button name="%(salary_import_wizard_downloads_action)d" string="模板下载" type="action"
class="btn btn-primary"/>
</header>
<group>
<group>
<field name="excel_file" filename="excel_name"/>
<field name="excel_name" invisible="1"/>
</group>
<group>
</group>
</group>
</sheet>
<footer>
<button name="confirm" string="确认" type="object" class="oe_highlight"/>
<button string="返回" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
</odoo>
+69 -10
View File
@@ -1,9 +1,8 @@
import base64
import json
from odoo import http, fields
from odoo.http import request
from odoo.tools import float_is_zero,float_round
from urllib.parse import quote
class YuthonWillTask(http.Controller):
@@ -56,19 +55,79 @@ class YuthonWillTask(http.Controller):
'message':'success'
})
@http.route('/will/taks/list', methods=['POST'], type='http', auth='none', csrf=False)
def task_list(self, **kwargs):
employee_id = kwargs.get('id')
data = request.env['yuthon.will.task'].sudo().search([])
@http.route('/will/task/list', methods=['POST'], type='http', auth='public', csrf=False)
def will_task_list(self, **kwargs):
employee_id = kwargs.get('employee_id')
start = kwargs.get('start')
request_hour_selection = request.env['yuthon.will.task'].sudo().fields_get(allfields=['request_hour_from'])['request_hour_from']['selection']
result_list = []
for emp in data:
# for task in request.env['yuthon.will.task'].sudo().search(['|', ('employee_ids', 'in', [employee_id]), ('employee_id.id', '=', employee_id)]):
task_ids = request.env['yuthon.will.task'].sudo().search([], offset=start, limit=7)
for task in task_ids:
weekday_str = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"][task.start_date.weekday()]
result = {
'name': emp.name,
'code': emp.code,
}
'id': task.id,
'name': task.name,
'employee_id': task.employee_id.name,
'employee_ids': ', '.join(task.employee_ids.mapped('name')),
'employee_num': len(task.employee_ids),
'start_date': fields.Date.to_string(task.start_date),
'weekday': weekday_str,
'request_hour_from': '',
'request_hour_to': '',
}
hour_dict = dict(request_hour_selection)
result['request_hour_from'] = hour_dict.get(task.request_hour_from)
result['request_hour_to'] = hour_dict.get(task.request_hour_to)
result_list.append(result)
return json.dumps({
'data': result_list,
'code': 200,
'message': 'success'
})
@http.route('/will/task/record', methods=['POST'], type='http', auth='public', csrf=False)
def will_task_record(self, **kwargs):
task_id = kwargs.get('id')
task = request.env['yuthon.will.task'].sudo().search([('id', '=', task_id)])
request_hour_selection = request.env['yuthon.will.task'].sudo().fields_get(allfields=['request_hour_from'])['request_hour_from'][
'selection']
file_list = []
for attach in task.document_ids:
attach_id = request.env['ir.attachment'].sudo().search([('id', '=', attach.id)])
if attach_id:
file_url = 'http://view.officeapps.live.com/op/view.aspx?src=' + quote(
'https://oa.thtzjt.com' + '/web/content/office_preview/' + str(attach_id.id))
file_list.append({'file_url': file_url, 'file_name': attach_id.display_name})
weekday_str = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"][task.start_date.weekday()]
result = {
'id': task.id,
'name': task.name,
'employee_id': task.employee_id.name,
'employee_ids': ', '.join(task.employee_ids.mapped('name')),
'employee_num': len(task.employee_ids),
'start_date': fields.Date.to_string(task.start_date),
'weekday': weekday_str,
'request_hour_from': '',
'request_hour_to': '',
'remarks': task.remarks,
'address': task.address,
# 'file_list': file_list,
'file_list': [{
'file_url':'https://view.officeapps.live.com/op/view.aspx?src=https%3A//oa.thtzjt.com/web/content/office_preview/13672',
'file_name':'excel',
},
{
'file_url':'https://oa.thtzjt.com/web/content/preview/13673',
'file_name':'pdf',
}
],
}
hour_dict = dict(request_hour_selection)
result['request_hour_from'] = hour_dict.get(task.request_hour_from)
result['request_hour_to'] = hour_dict.get(task.request_hour_to)
return json.dumps({
'data': result,
'code': 200,
'message': 'success'
})
@@ -1,10 +1,28 @@
from odoo import api, fields, models
from datetime import datetime, timedelta, date
import logging
_logger = logging.getLogger(__name__)
class InheritRoomBooking(models.Model):
_inherit = 'room.booking'
def get_no_read_count(self):
# 1. 计算各类时间参数
today = date.today() + timedelta(hours=8)
today_start = datetime.combine(today, datetime.min.time())
today_end = datetime.combine(today, datetime.max.time())
domain = [
('start_datetime', '>=', today_start),
('start_datetime', '<=', today_end),
'|',
('stop_datetime', '=', False),
('stop_datetime', '>', datetime.now())
]
matching_records = self.search(domain)
count = len(matching_records)
return count
@api.model
def create(self, vals):
task_time_ids = self.env['yuthon.task.time'].search([('name', '=', '30分钟')])
+44 -28
View File
@@ -82,7 +82,7 @@ class YuthonWillTask(models.Model):
document_ids = fields.Many2many('ir.attachment', string="附件")
address = fields.Char(string='地点')
start_date = fields.Date(string='开始日期', default=fields.Date.today)
task_time = fields.Char(string='任务时间', compute='_compute_task_time')
task_time = fields.Char(string='任务时间')
is_this_company = fields.Boolean(string='本公司', default=True)
task_state = fields.Selection([('will', '待办'), ('done', '已办'), ('cancel', '取消')], default='will', string='状态', store=True)
@@ -106,42 +106,58 @@ class YuthonWillTask(models.Model):
store=True, default=lambda self: [(6, 0, [self.env.user.id])]
)
@api.depends('start_date', 'request_hour_from', 'request_hour_to')
def _compute_task_time(self):
employee_id = fields.Many2one('hr.employee', string="经办人", default=lambda self: self.env.user.employee_id)
task_week = fields.Char(string="周", readonly=True, compute='_compute_task_week')
@api.depends('start_date')
def _compute_task_week(self):
weekdays = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]
for record in self:
if record.start_date:
record.task_week = weekdays[record.start_date.weekday()]
def one_time(self):
will_ids = self.env["yuthon.will.task"].browse(
self._context.get('active_ids', self._context.get('active_id')))
for record in will_ids:
record._check_task_time()
@api.constrains('start_date', 'request_hour_from', 'request_hour_to')
def _check_task_time(self):
for record in self:
date_str = ""
if record.start_date:
date_str = record.start_date.strftime("%Y/%m/%d")
hour_mapping = {
'0': '0:00', '0.5': '0:30',
'1': '01:00', '1.5': '01:30',
'2': '02:00', '2.5': '02:30',
'3': '03:00', '3.5': '03:30',
'4': '04:00', '4.5': '04:30',
'5': '05:00', '5.5': '05:30',
'6': '06:00', '6.5': '06:30',
'7': '07:00', '7.5': '07:30',
'8': '08:00', '8.5': '08:30',
'9': '09:00', '9.5': '09:30',
'10': '10:00', '10.5': '10:30',
'11': '11:00', '11.5': '11:30',
'12': '12:00', '12.5': '12:30',
'13': '13:00', '13.5': '13:30',
'14': '14:00', '14.5': '14:30',
'15': '15:00', '15.5': '15:30',
'16': '16:00', '16.5': '16:30',
'17': '17:00', '17.5': '17:30',
'18': '18:00', '18.5': '18:30',
'19': '19:00', '19.5': '19:30',
'20': '20:00', '20.5': '20:30',
'21': '21:00', '21.5': '21:30',
'22': '22:00', '22.5': '22:30',
'23': '23:00', '23.5': '23:30'
'0': '0:00', '0.25': '0:15', '0.5': '0:30', '0.75': '0:45',
'1': '01:00', '1.25': '01:15', '1.5': '01:30', '1.75': '01:45',
'2': '02:00', '2.25': '02:15', '2.5': '02:30', '2.75': '02:45',
'3': '03:00', '3.25': '03:15', '3.5': '03:30', '3.75': '03:45',
'4': '04:00', '4.25': '04:15', '4.5': '04:30', '4.75': '04:45',
'5': '05:00', '5.25': '05:15', '5.5': '05:30', '5.75': '05:45',
'6': '06:00', '6.25': '06:15', '6.5': '06:30', '6.75': '06:45',
'7': '07:00', '7.25': '07:15', '7.5': '07:30', '7.75': '07:45',
'8': '08:00', '8.25': '08:15', '8.5': '08:30', '8.75': '08:45',
'9': '09:00', '9.25': '09:15', '9.5': '09:30', '9.75': '09:45',
'10': '10:00', '10.25': '10:15', '10.5': '10:30', '10.75': '10:45',
'11': '11:00', '11.25': '11:15', '11.5': '11:30', '11.75': '11:45',
'12': '12:00', '12.25': '12:15', '12.5': '12:30', '12.75': '12:45',
'13': '13:00', '13.25': '13:15', '13.5': '13:30', '13.75': '13:45',
'14': '14:00', '14.25': '14:15', '14.5': '14:30', '14.75': '14:45',
'15': '15:00', '15.25': '15:15', '15.5': '15:30', '15.75': '15:45',
'16': '16:00', '16.25': '16:15', '16.5': '16:30', '16.75': '16:45',
'17': '17:00', '17.25': '17:15', '17.5': '17:30', '17.75': '17:45',
'18': '18:00', '18.25': '18:15', '18.5': '18:30', '18.75': '18:45',
'19': '19:00', '19.25': '19:15', '19.5': '19:30', '19.75': '19:45',
'20': '20:00', '20.25': '20:15', '20.5': '20:30', '20.75': '20:45',
'21': '21:00', '21.25': '21:15', '21.5': '21:30', '21.75': '21:45',
'22': '22:00', '22.25': '22:15', '22.5': '22:30', '22.75': '22:45',
'23': '23:00', '23.25': '23:15', '23.5': '23:30', '23.75': '23:45'
}
from_time = hour_mapping.get(record.request_hour_from, "")
to_time = hour_mapping.get(record.request_hour_to, "")
if date_str and from_time and to_time:
record.task_time = f"{date_str} {from_time}"
record.task_time = f"{date_str} {record.task_week} {from_time}"
else:
record.task_time = ""
@@ -13,5 +13,13 @@
<field name="category_id" ref="module_yuthon_will_task"/>
<field name="implied_ids" eval="[(4, ref('group_yuthon_will_task_user'))]"/>
</record>
<record id="group_module_room_booking" model="ir.module.category">
<field name="name">会议组</field>
</record>
<record id="group_room_booking_manager" model="res.groups">
<field name="name">会议管理员</field>
<field name="category_id" ref="group_module_room_booking"/>
<field name="users" eval="[(4, ref('base.user_admin'))]"/>
</record>
</data>
</odoo>
@@ -23,6 +23,7 @@
name="预定会议"
action="room.room_booking_action"
parent="menu_yuthon_will_task"
groups="yuthon_will_task.group_room_booking_manager"
sequence="10"/>
<menuitem id="room_booking_menu_will"
name="会议室"
@@ -8,22 +8,22 @@
decoration-muted = "task_state == 'cancel'"
decoration-danger="priority == 'very_urgent'"
decoration-info="priority == 'urgent'"
decoration-success="priority == 'important'">
decoration-success="priority == 'important'" limit="15">
<field name='start_date' column_invisible="1"/>
<field name='task_time' />
<field name='name' required="1"/>
<field name='employee_ids' widget="many2many_tags" required="1" options="{'no_create': True}"/>
<field name="address"/>
<field name='remarks'/>
<field name='document_ids' widget="many2many_tags"/>
<field name='employee_ids2' widget="many2many_tags" domain="[('user_role_ids.name', 'in', ['司机'])]" options="{'no_create': True}"/>
<field name='task_time_ids' widget="many2many_tags" required="1"/>
<!-- <field name='document_ids' widget="many2many_tags"/>-->
<!-- <field name='employee_ids2' widget="many2many_tags" domain="[('user_role_ids.name', 'in', ['司机'])]" options="{'no_create': True}"/>-->
<!-- <field name='task_time_ids' widget="many2many_tags" required="1"/>-->
<field name='priority'/>
<field name='task_state' readonly="1"/>
<field name='users_ids' widget="many2many_tags" column_invisible="1"/>
<field name='user_role_ids' widget="many2many_tags" column_invisible="1"/>
<field name="user_id" optional="hide"/>
<field name='creation_time' optional="hide"/>
<!-- <field name='users_ids' widget="many2many_tags" column_invisible="1"/>-->
<!-- <field name='user_role_ids' widget="many2many_tags" column_invisible="1"/>-->
<!-- <field name="employee_id" optional="hide"/>-->
<!-- <field name='creation_time' optional="hide"/>-->
<button name="button_add_comment" string="提醒" type="object" class="oe_highlight" invisible="task_state == 'cancel'"/>
<button name="button_add_comment_cancel" string="取消" type="object" class="oe_highlight" invisible="task_state == 'cancel'"/>
<button name="schedule_reminders" string="提醒任务" type="object" class="oe_highlight" groups="base.group_system"/>
@@ -73,7 +73,8 @@
<group>
<label for="start_date"/>
<div class="d-inline-flex w-100">
<field name="start_date" string="日期:" class="me-2" style="max-width: 10rem !important;"/>
<field name="start_date" string="日期" class="me-2" style="max-width: 6rem !important;"/>
<field name="task_week" string="" class="me-2" style="max-width: 4rem !important;"/>
<field name="request_hour_from" string=" " class="ms-2" style="max-width: 5rem !important;"/>→
<field name="request_hour_to" string=" " class="ms-2" style="max-width: 5rem !important;"/>
</div>
@@ -83,10 +84,10 @@
</group>
</group>
<group>
<field name="user_id"/>
<field name="employee_id"/>
<field name="task_state" invisible="1"/>
<field name="company_id" invisible="1"/>
<field name="employee_ids" widget="many2many_tags" options="{'no_create': True}" domain = "[('company_id', '=', company_id), ('user_id.name', '!=', 'Administrator')] if is_this_company else []"/>
<field name="employee_ids" widget="many2many_tags" options="{'no_create': True}" domain="[('company_id', '=', company_id)] if is_this_company else []"/>
<field name="user_role_ids" widget="many2many_tags" invisible="1"/>
</group>
<group col="2">
@@ -103,11 +104,6 @@
<field name="creation_time" invisible="1"/>
</group>
</sheet>
<!-- <div class="oe_chatter">-->
<!-- <field name="message_follower_ids" groups="base.group_user" options="{'post_refresh': 'recipients'}"/>-->
<!-- <field name="activity_ids"/>-->
<!-- <field name="message_ids"/>-->
<!-- </div>-->
</form>
</field>
</record>
@@ -119,22 +115,22 @@
decoration-muted = "task_state == 'cancel'"
decoration-danger="priority == 'very_urgent'"
decoration-info="priority == 'urgent'"
decoration-success="priority == 'important'" create="false" edit="false" js_class="custom_task_tree_button">
decoration-success="priority == 'important'" create="false" edit="false" js_class="custom_task_tree_button" limit="15">
<field name='start_date' column_invisible="1"/>
<field name='task_time' />
<field name='name' required="1"/>
<field name='employee_ids' widget="many2many_tags" required="1" options="{'no_create': True}"/>
<field name="address"/>
<field name='remarks'/>
<field name='document_ids' widget="many2many_tags"/>
<field name='employee_ids2' widget="many2many_tags" domain="[('user_role_ids.name', 'in', ['司机'])]" options="{'no_create': True}"/>
<field name='task_time_ids' widget="many2many_tags" required="1"/>
<!-- <field name='document_ids' widget="many2many_tags"/>-->
<!-- <field name='employee_ids2' widget="many2many_tags" domain="[('user_role_ids.name', 'in', ['司机'])]" options="{'no_create': True}"/>-->
<!-- <field name='task_time_ids' widget="many2many_tags" required="1"/>-->
<field name='priority'/>
<field name='task_state' readonly="1"/>
<field name='users_ids' widget="many2many_tags" column_invisible="1"/>
<field name='user_role_ids' widget="many2many_tags" column_invisible="1"/>
<field name="user_id" optional="hide"/>
<field name='creation_time' optional="hide"/>
<!-- <field name='users_ids' widget="many2many_tags" column_invisible="1"/>-->
<!-- <field name='user_role_ids' widget="many2many_tags" column_invisible="1"/>-->
<!-- <field name="employee_id" optional="hide"/>-->
<!-- <field name='creation_time' optional="hide"/>-->
<button name="button_add_comment" string="提醒" type="object" class="oe_highlight" invisible="task_state == 'cancel'"/>
<button name="button_add_comment_cancel" string="取消" type="object" class="oe_highlight" invisible="task_state == 'cancel'"/>
</tree>
@@ -171,10 +167,11 @@
</div>
<group col="2">
<group>
<label for="start_date"/>
<div class="d-inline-flex w-100">
<field name="start_date" string="日期:" class="me-2"
<label for="start_date"/>
<div class="d-inline-flex w-100">
<field name="start_date" string="日期" class="me-2"
style="max-width: 10rem !important;"/>
<field name="task_week" string="" class="me-2" style="max-width: 4rem !important;"/>
<field name="request_hour_from" string=" " class="ms-2"
style="max-width: 5rem !important;"/>→
<field name="request_hour_to" string=" " class="ms-2"
@@ -186,7 +183,7 @@
</group>
</group>
<group>
<field name="user_id" domain="[('company_id', '=', company_id)]"/>
<field name="employee_id" domain="[('company_id', '=', company_id)]"/>
<field name="company_id" invisible="1"/>
<field name="employee_ids" widget="many2many_tags" options="{'no_create': True}"/>
<field name='users_ids' widget="many2many_tags" invisible="1"/>
@@ -258,4 +255,11 @@
<field name='domain'>[('user_role_ids.name', 'in', ['董事长', '分管领导', '总经理', '部门副经理', '副总经理', '司机'])]</field>
<field name="context">{'search_default_next_seven_days': 1}</field>
</record>
<record id="all_yuthon_will_task" model="ir.actions.server">
<field name="name">更新</field>
<field name="model_id" ref="yuthon_will_task.model_yuthon_will_task"/>
<field name="binding_model_id" ref="yuthon_will_task.model_yuthon_will_task"/>
<field name="state">code</field>
<field name="code">action = model.one_time()</field>
</record>
</odoo>
@@ -38,11 +38,6 @@
name="报事报修(物业)"
action="yuthon_maintain.property_report_repair_action"
sequence="20"/>
<menuitem id="property_device_repair_action_brand"
parent="information_root_board"
name="报事报修(办公设备)"
action="yuthon_maintain.property_device_repair_action"
sequence="20"/>
<menuitem id="processing_order_approval_action_menu"
parent="information_root_board"
name="处理单审批"
+12 -2
View File
@@ -702,12 +702,22 @@
parent="holiday_manage_menu_root_board"
action="soong_workflow.soong_workflow_record_done_action"
sequence="4"/>
<menuitem id="property_device_repair_action_brand"
parent="holiday_manage_menu_root_board"
name="报事报修"
action="yuthon_maintain.property_device_repair_action"
sequence="5"/>
<menuitem id="property_device_repair_action_brand_all"
parent="holiday_manage_menu_root_board"
name="报事报修(管理员)"
action="yuthon_maintain.property_device_repair_all_action"
groups="base.group_system"
sequence="5"/>
<menuitem id="yuthon_notice_menu1_board"
parent="holiday_manage_menu_root_board"
name="通知公告"
action="yuthon_notice.approval_notice_action"
sequence="5"/>
sequence="7"/>
<menuitem id='menu_yuthon_will_task_root'
name='我的日程'
parent='holiday_manage_menu_root_board'
+9 -4
View File
@@ -8,11 +8,16 @@
name="订单"
parent="purchase_menus_root_board"
sequence="1"/>
<menuitem id="purchase_fixe_assets_approval_root"
name="采购审批单"
<!-- <menuitem id="purchase_fixe_assets_approval_root"-->
<!-- name="采购审批单"-->
<!-- parent="purchase_menus_order_root"-->
<!-- action="yuthon_purchase.view_purchase_workflow_action"-->
<!-- sequence="1"/>-->
<menuitem id="purchase_fixe_assets_rfq_root"
name="询价"
parent="purchase_menus_order_root"
action="yuthon_purchase.view_purchase_workflow_action"
sequence="1"/>
action="purchase.purchase_rfq"
sequence="3"/>
<menuitem id="purchase_fixe_assets_root"
name="采购单"
parent="purchase_menus_order_root"