pengyuthon
This commit is contained in:
@@ -67,3 +67,8 @@ class preview(http.Controller):
|
||||
# http://view.officeapps.live.com/op/view.aspx?src=https%3A%2F%2Fj2762p6576.vicp.fun%2Fpreview_easy%2Fstatic%2Fdescription%2F123.xlsx
|
||||
# http://view.officeapps.live.com/op/view.aspx?src=https%3A%2F%2Fj2762p6576.vicp.fun%2Fweb%2Fcontent%2Foffice_preview%2F863
|
||||
return werkzeug.wrappers.Response(attach.raw, status=200, headers=headers)
|
||||
|
||||
@http.route('/web/document_module/installed', type='json', method=['POST'], auth='none')
|
||||
def document_module_installed(self):
|
||||
document_module = request.env['ir.module.module'].sudo().search([('name', '=', 'documents')])
|
||||
return {'installed': document_module and document_module.state == 'installed'}
|
||||
|
||||
@@ -36,6 +36,9 @@ export class Many2ManyBinaryField extends Many2ManyTagsField {
|
||||
nameCreateField: { type: String, optional: true },
|
||||
string: { type: String, optional: true },
|
||||
noSearchMore: { type: Boolean, optional: true },
|
||||
showSelectBtn: { type: Boolean, optional: true },
|
||||
previewType: { type: String, optional: true },
|
||||
previewString: { type: String, optional: true },
|
||||
};
|
||||
|
||||
setup() {
|
||||
@@ -106,16 +109,10 @@ export class Many2ManyBinaryField extends Many2ManyTagsField {
|
||||
}
|
||||
|
||||
preview_Obj(id, name) {
|
||||
|
||||
|
||||
var winStr = 'height=600,width=1000,top=' + (screen.height - 600) / 2 + ',left=' + (screen.width - 1000) / 2 + ',toolbar=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=no,location=no';
|
||||
var newWin = window.open('/web/content/preview/'+ id , name, winStr);
|
||||
newWin.focus();
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
var winStr = 'height=600,width=1000,top=' + (screen.height - 600) / 2 + ',left=' + (screen.width - 1000) / 2 + ',toolbar=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=no,location=no';
|
||||
var newWin = window.open('/web/content/preview/'+ id , name, winStr);
|
||||
newWin.focus();
|
||||
}
|
||||
|
||||
getExtension(file) {
|
||||
return file.name.replace(/^.*\./, "");
|
||||
@@ -167,6 +164,21 @@ export class Many2ManyBinaryField extends Many2ManyTagsField {
|
||||
title,
|
||||
});
|
||||
}
|
||||
get documentsInstalled() {
|
||||
try {
|
||||
const result = $.ajax({
|
||||
url: "/web/document_module/installed",
|
||||
type: "POST",
|
||||
async: false, // 设置为 false 表示同步请求
|
||||
contentType: "application/json",
|
||||
data: "{}"
|
||||
});
|
||||
return result?.responseJSON?.result?.installed;
|
||||
} catch (error) {
|
||||
console.error('Error fetching document installed status:', error);
|
||||
return false; // 或者其他默认值
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const many2ManyBinaryField = {
|
||||
@@ -186,6 +198,9 @@ export const many2ManyBinaryField = {
|
||||
],
|
||||
extractProps: ({ attrs, options }) => ({
|
||||
acceptedFileExtensions: options.accepted_file_extensions,
|
||||
showSelectBtn: options.show_select_btn === undefined ? true : options.show_select_btn,
|
||||
previewType: options.preview_type,
|
||||
previewString: options.preview_string,
|
||||
className: attrs.class,
|
||||
}),
|
||||
};
|
||||
|
||||
@@ -6,8 +6,9 @@
|
||||
</t>
|
||||
</xpath>
|
||||
<xpath expr="//div[hasclass('oe_add')]" position="inside">
|
||||
<button class="btn btn-secondary o_attach" t-on-click="onExternalBtnClick" data-tooltip="Attach">
|
||||
选择文档
|
||||
<button t-if="documentsInstalled and props.showSelectBtn" class="btn btn-secondary o_attach" t-on-click="onExternalBtnClick" data-tooltip="Attach">
|
||||
<i class="fa fa-folder-open-o"/>
|
||||
选择文件
|
||||
<!-- <Many2XAutocomplete -->
|
||||
<!-- id="props.id" -->
|
||||
<!-- resModel="relation" -->
|
||||
@@ -28,30 +29,37 @@
|
||||
</t>
|
||||
<t t-name="Many2ManyBinaryField.attachment_preview1" owl="1">
|
||||
<t t-set="editable" t-value="!props.readonly"/>
|
||||
<div t-attf-class="o_attachment o_attachment_many2many #{ editable ? 'o_attachment_editable' : '' } #{upload ? 'o_attachment_uploading' : ''}" t-att-title="file.name">
|
||||
<div class="o_attachment_wrap">
|
||||
<t t-set="ext" t-value="getExtension(file)"/>
|
||||
<t t-set="url" t-value="getUrl(file.id)"/>
|
||||
<div class="o_image_box float-start" t-att-data-tooltip="'Preview ' + file.name">
|
||||
|
||||
<span class="o_image o_hover" t-on-click.stop="() => this.preview_Obj(file.id,file.name)" t-att-data-mimetype="file.mimetype" t-att-data-ext="ext" role="img"/>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="caption">
|
||||
<a class="ml4" t-att-data-tooltip="'Download ' + file.name" t-att-href="getUrl(file.id)"><t t-esc='file.name'/></a>
|
||||
</div>
|
||||
<div class="caption small">
|
||||
<a class="ml4 small text-uppercase" t-att-href="getUrl(file.id)"><b><t t-esc='ext'/></b></a>
|
||||
<div t-if="editable" class="progress o_attachment_progress_bar">
|
||||
<div class="progress-bar progress-bar-striped active" style="width: 100%">Uploading</div>
|
||||
<t t-if="props.previewType and props.previewType === 'button'">
|
||||
<button class="btn btn-secondary o_attach" t-on-click.stop="() => this.preview_Obj(file.id,file.name)" data-tooltip="Attach">
|
||||
<i class="fa fa-eye"/>
|
||||
<span t-if="props.previewString" t-out="props.previewString"/>
|
||||
<span t-else="" t-out="'预览文件'"/>
|
||||
</button>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<div t-attf-class="o_attachment o_attachment_many2many #{ editable ? 'o_attachment_editable' : '' } #{upload ? 'o_attachment_uploading' : ''}" t-att-title="file.name">
|
||||
<div class="o_attachment_wrap">
|
||||
<t t-set="ext" t-value="getExtension(file)"/>
|
||||
<t t-set="url" t-value="getUrl(file.id)"/>
|
||||
<div class="o_image_box float-start" t-att-data-tooltip="'Preview ' + file.name">
|
||||
<span class="o_image o_hover" t-on-click.stop="() => this.preview_Obj(file.id,file.name)" t-att-data-mimetype="file.mimetype" t-att-data-ext="ext" role="img"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="o_attachment_uploaded"><i class="text-success fa fa-check" role="img" aria-label="Uploaded" title="Uploaded"/></div>
|
||||
<div t-if="editable" class="o_attachment_delete" t-on-click.stop="() => this.onFileRemove(file.id)"><span class="text-white" role="img" aria-label="Delete" title="Delete">×</span></div>
|
||||
<div class="caption">
|
||||
<a class="ml4" t-att-data-tooltip="'Download ' + file.name" t-att-href="getUrl(file.id)"><t t-esc='file.name'/></a>
|
||||
</div>
|
||||
<div class="caption small">
|
||||
<a class="ml4 small text-uppercase" t-att-href="getUrl(file.id)"><b><t t-esc='ext'/></b></a>
|
||||
<div t-if="editable" class="progress o_attachment_progress_bar">
|
||||
<div class="progress-bar progress-bar-striped active" style="width: 100%">Uploading</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="o_attachment_uploaded"><i class="text-success fa fa-check" role="img" aria-label="Uploaded" title="Uploaded"/></div>
|
||||
<div t-if="editable" class="o_attachment_delete" t-on-click.stop="() => this.onFileRemove(file.id)"><span class="text-white" role="img" aria-label="Delete" title="Delete">×</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
'views/inherit_hr_type_views.xml',
|
||||
'views/inherit_hr_leave_allocation_views.xml',
|
||||
'views/inherit_hr_leave_accrual_plan_views.xml',
|
||||
'views/hr_leave_accrual_views.xml',
|
||||
'views/hr_leave_batch.xml',
|
||||
'views/hr_leave_accrual_views.xml',
|
||||
],
|
||||
'demo': [],
|
||||
'depends': ['hr_holidays'],
|
||||
|
||||
@@ -1,12 +1,42 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from odoo import models, fields, api, _
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class HrLeave(models.Model):
|
||||
_inherit = 'hr.leave'
|
||||
# class HrLeave(models.Model):
|
||||
# _inherit = 'hr.leave'
|
||||
#
|
||||
# batch_id = fields.Many2one(string='批量', comodel_name='hr.leave.batch', required=True, ondelete='cascade')
|
||||
|
||||
batch_id = fields.Many2one(string='批量', comodel_name='hr.leave.batch', required=True, ondelete='cascade')
|
||||
HOUR_SELECTION = [
|
||||
('0', '00:00'), ('0.5', '00:30'),
|
||||
('1', '01:00'), ('1.5', '01:30'),
|
||||
('2', '01:00'), ('2.5', '01:30'),
|
||||
('3', '03:00'), ('3.5', '01: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')
|
||||
]
|
||||
|
||||
|
||||
class HolidaysRequestBatch(models.Model):
|
||||
@@ -21,12 +51,14 @@ class HolidaysRequestBatch(models.Model):
|
||||
return emp
|
||||
|
||||
name = fields.Char(string='标题')
|
||||
employee_id = fields.Many2one(string='员工', comodel_name='hr.employee', required=True, default=_get_default_emp,
|
||||
index=True)
|
||||
leave_ids = fields.One2many(string='详情', comodel_name='hr.leave', inverse_name='batch_id')
|
||||
state = fields.Selection(string='状态', selection=[('draft', '撤回'), ('confirm', '转交'),
|
||||
('refuse', '拒绝'), ('validate', '审批')
|
||||
], default='draft', tracking=True, copy=False)
|
||||
employee_id = fields.Many2one(string='员工', comodel_name='hr.employee', required=True, default=_get_default_emp, index=True)
|
||||
# leave_ids = fields.One2many(string='详情', comodel_name='hr.leave', inverse_name='batch_id')
|
||||
state = fields.Selection(string='状态', selection=[
|
||||
('draft', '撤回'),
|
||||
('confirm', '转交'),
|
||||
('refuse', '拒绝'),
|
||||
('validate', '审批'),
|
||||
], default='draft', tracking=True, copy=False)
|
||||
leave_id = fields.Many2one('res.users', string="请假人", default=lambda self: self.env.user.id)
|
||||
department_id = fields.Many2one(related='leave_id.employee_id.department_id', string="部门")
|
||||
days = fields.Float(string='天数')
|
||||
@@ -34,6 +66,21 @@ class HolidaysRequestBatch(models.Model):
|
||||
text = fields.Html(string='申请事由')
|
||||
leave_line_ids = fields.One2many('hr.leave.line', 'leave_batch_id', string="关联请假详情明细行")
|
||||
is_issues = fields.Boolean(string='是否上会')
|
||||
leave_by_hour = fields.Boolean(string='按小时请假', default=False)
|
||||
leave_unit = fields.Selection(string='时长单位', selection=[('day', '天'), ('hour', '小时')])
|
||||
|
||||
@api.constrains('leave_line_ids')
|
||||
def _check_leave_line_ids(self):
|
||||
for rec in self:
|
||||
if rec.leave_line_ids.filtered(lambda line: line.leave_duration <= 0):
|
||||
raise ValidationError('请假天数不能小于0')
|
||||
if rec.leave_line_ids.filtered(lambda line: line.residual < 0):
|
||||
raise ValidationError('假期剩余天数不能小于0')
|
||||
|
||||
@api.onchange('leave_by_hour')
|
||||
def _onchange_leave_by_hour(self):
|
||||
self.leave_unit = 'hour' if self.leave_by_hour else 'day'
|
||||
self.leave_line_ids = None
|
||||
|
||||
# 提交
|
||||
def action_submit(self):
|
||||
@@ -70,27 +117,111 @@ class HrLeaveLine(models.Model):
|
||||
_name = 'hr.leave.line'
|
||||
|
||||
leave_batch_id = fields.Many2one('hr.leave.batch', string="关联请假审批")
|
||||
leave_type_id = fields.Many2one('hr.leave.type', string="请假类型")
|
||||
available_days = fields.Integer(string="可用天数")
|
||||
applicants = fields.Selection(related='leave_type_id.request_unit', string="申请单位")
|
||||
employee_id = fields.Many2one(string='员工', comodel_name='hr.employee', related='leave_batch_id.employee_id')
|
||||
leave_type_id = fields.Many2one(
|
||||
string="请假类型",
|
||||
comodel_name='hr.leave.type',
|
||||
domain="""
|
||||
('company_id', 'in', [employee_company_id, False]),
|
||||
'|',
|
||||
('requires_allocation', '=', 'no'),
|
||||
('has_valid_allocation', '=', True),
|
||||
]""")
|
||||
available_days = fields.Float(string="可用天数", digits=(16, 2), compute="_compute_available_days")
|
||||
leave_documents_ids = fields.Many2many(related='leave_type_id.leave_documents_id', string="假期详情说明")
|
||||
start_time = fields.Date(string="开始时间")
|
||||
end_time = fields.Date(string="结束时间")
|
||||
days = fields.Float(string="天数", compute='_compute_days')
|
||||
residual = fields.Float(string="剩余天数",compute='_compute_remaining_days')
|
||||
start_time = fields.Date(string="开始日期", required=True)
|
||||
start_hour_from = fields.Selection(string="开始时间", selection=HOUR_SELECTION)
|
||||
end_time = fields.Date(string="结束日期", required=True)
|
||||
end_hour_from = fields.Selection(string="结束时间", selection=HOUR_SELECTION)
|
||||
leave_duration = fields.Float(string="时长", compute='_compute_leave_duration')
|
||||
leave_unit = fields.Selection(string="单位", related='leave_batch_id.leave_unit')
|
||||
residual = fields.Float(string="剩余时长", compute='_compute_remaining_days')
|
||||
custom_document_ids = fields.Many2many(
|
||||
string='文件',
|
||||
comodel_name='ir.attachment',
|
||||
relation='leave_custom_doc_rel',
|
||||
column1='leave_id',
|
||||
column2='attachment_id'
|
||||
)
|
||||
|
||||
@api.constrains('start_time', 'end_time')
|
||||
def _constraints_leave_date(self):
|
||||
"""
|
||||
按小时请假时不能跨天
|
||||
"""
|
||||
for rec in self:
|
||||
if rec.leave_batch_id.leave_by_hour:
|
||||
if rec.start_time != rec.end_time:
|
||||
raise ValidationError('按小时请假禁止跨天')
|
||||
|
||||
@api.depends('start_time', 'end_time')
|
||||
def _compute_days(self):
|
||||
@api.depends('leave_type_id')
|
||||
def _compute_available_days(self):
|
||||
for rec in self:
|
||||
rec.available_days = rec.leave_type_id.virtual_remaining_leaves
|
||||
|
||||
@api.depends('start_time', 'start_hour_from', 'end_time', 'end_hour_from')
|
||||
def _compute_leave_duration(self):
|
||||
"""
|
||||
根据不同单位计算不同的时长,去除国家法定节假日与双休
|
||||
天: 使用start_time - end_time
|
||||
小时: 使用start_time + start_hour_from - end_time + end_hour_from
|
||||
"""
|
||||
leave_duration = 0
|
||||
for record in self:
|
||||
if record.start_time and record.end_time:
|
||||
delta = record.end_time - record.start_time
|
||||
record.days = delta.days
|
||||
else:
|
||||
record.days = 0
|
||||
# 按小时
|
||||
if record.leave_batch_id.leave_by_hour:
|
||||
if record.start_hour_from and record.end_hour_from:
|
||||
hour_selection = dict(HOUR_SELECTION)
|
||||
start_time_obj = datetime.strptime(hour_selection[record.start_hour_from], "%H:%M").time()
|
||||
end_time_obj = datetime.strptime(hour_selection[record.end_hour_from], "%H:%M").time()
|
||||
start_date = datetime.combine(record.start_time, start_time_obj)
|
||||
end_time = datetime.combine(record.end_time, end_time_obj)
|
||||
leave_duration = (end_time - start_date).total_seconds() / 3600
|
||||
else:
|
||||
start_date = datetime.combine(record.start_time, datetime.min.time())
|
||||
end_time = datetime.combine(record.end_time, datetime.min.time())
|
||||
leave_duration = record._get_leave_duration(start_date, end_time)
|
||||
record.leave_duration = leave_duration
|
||||
|
||||
@api.depends('available_days', 'days')
|
||||
@api.depends('available_days', 'leave_duration')
|
||||
def _compute_remaining_days(self):
|
||||
for record in self:
|
||||
record.residual = record.available_days - record.days
|
||||
# 如果假期类型需要分配
|
||||
if record.leave_type_id.requires_allocation == 'yes':
|
||||
record.residual = record.available_days - record.residual
|
||||
else:
|
||||
record.residual = 0
|
||||
|
||||
@api.onchange('start_time', 'start_hour_from', 'end_time', 'end_hour_from')
|
||||
def _onchange_leave_date(self):
|
||||
if self.leave_batch_id.leave_by_hour and self.start_time and self.end_time and self.start_time != self.end_time:
|
||||
raise ValidationError('按小时请假禁止跨天')
|
||||
|
||||
# 计算开始时间与结束时间之间的时长
|
||||
def _get_leave_duration(self, start_time: datetime, end_time: datetime):
|
||||
"""
|
||||
公共假期计算
|
||||
查询所有公共假期(resource.calendar.leaves)
|
||||
通过开始时间与结束时间,去除公共假期,再去除双休,计算时长,
|
||||
"""
|
||||
self.ensure_one()
|
||||
all_resource_calendar_leaves = self.env['resource.calendar.leaves'].search([('resource_id', '=', False)])
|
||||
# 创建一个集合存储假期的每一天
|
||||
holidays = []
|
||||
for holiday in all_resource_calendar_leaves:
|
||||
# 根据公共假期的开始时间与结束时间计算时间段
|
||||
current = holiday.date_from
|
||||
while current <= holiday.date_to:
|
||||
# 将当天0点的时间戳放入假期集合
|
||||
holidays.append(int(int(current.timestamp()) + 8 * 3600) // 86400 * 86400 - 8 * 3600)
|
||||
current += timedelta(days=1)
|
||||
effective_days = 0
|
||||
current = start_time
|
||||
while current <= end_time:
|
||||
current_timestamp = int(int(current.timestamp()) + 8 * 3600) // 86400 * 86400 - 8 * 3600
|
||||
if current.weekday() < 5 and current_timestamp not in holidays: # 0-4为工作日
|
||||
effective_days += 1
|
||||
current += timedelta(days=1)
|
||||
|
||||
return effective_days
|
||||
|
||||
@@ -31,8 +31,7 @@
|
||||
<header>
|
||||
<field name="state" widget="statusbar" invisible="1"/>
|
||||
<button name="action_submit" type="object" class="oe_highlight" string="Submit" invisible="1"/>
|
||||
<button name="action_validate" type="object" class="oe_highlight" string="Validate"
|
||||
invisible="1"/>
|
||||
<button name="action_validate" type="object" class="oe_highlight" string="Validate" invisible="1"/>
|
||||
<button name="action_refuse" type="object" class="oe_highlight" string="Refuse" invisible="1"/>
|
||||
<button name="action_draft" type="object" class="oe_highlight" string="Retract" invisible="1"/>
|
||||
</header>
|
||||
@@ -53,43 +52,50 @@
|
||||
<field name="text"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="employee_id" invisible="1" force_save="1"/>
|
||||
<field name="department_id"/>
|
||||
<field name="leave_by_hour"/>
|
||||
<field name="leave_unit"/>
|
||||
</group>
|
||||
<group>
|
||||
<!-- <field name="days"/>-->
|
||||
<!-- <field name="hours"/>-->
|
||||
<!-- <field name="days"/> -->
|
||||
<!-- <field name="hours"/> -->
|
||||
<field name="is_issues" invisible="1"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="详情" invisible="1">
|
||||
<field name="leave_ids" mode="tree"
|
||||
context="{'form_view_ref': 'hr_holidays.hr_leave_view_form_dashboard_new_time_off'}">
|
||||
<tree>
|
||||
<field name="state" column_invisible="True"/>
|
||||
<field name="holiday_type"/>
|
||||
<!-- <field name="holiday_status_id" class="fw-bold" readonly="state in ['cancel', 'refuse', 'validate', 'validate1']"/>-->
|
||||
<field name="name"/>
|
||||
<field name="date_from"
|
||||
readonly="state in ['cancel', 'refuse', 'validate', 'validate1']"/>
|
||||
<field name="date_to"
|
||||
readonly="state in ['cancel', 'refuse', 'validate', 'validate1']"/>
|
||||
<field name="duration_display"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
<page string="请假详情">
|
||||
<field name="leave_line_ids">
|
||||
<tree editable="bottom">
|
||||
<field name="leave_batch_id" column_invisible="1"/>
|
||||
<field name="leave_type_id"/>
|
||||
<field name="employee_id" column_invisible="1"/>
|
||||
<field name="leave_type_id"
|
||||
force_save="1"
|
||||
domain="[
|
||||
('request_unit', '=', leave_unit),
|
||||
'|',
|
||||
('requires_allocation', '=', 'no'),
|
||||
'&',
|
||||
('has_valid_allocation', '=', True),
|
||||
'|',
|
||||
('allows_negative', '=', True),
|
||||
'&',
|
||||
('virtual_remaining_leaves', '>', 0),
|
||||
('allows_negative', '=', False),
|
||||
]"
|
||||
context="{'employee_id': employee_id, 'default_date_from': start_time, 'default_date_to': end_time}"
|
||||
options="{'no_create': True, 'no_open': True, 'request_type': 'leave'}"
|
||||
/>
|
||||
<field name="available_days"/>
|
||||
<field name="applicants"/>
|
||||
<field name="start_time"/>
|
||||
<field name="start_hour_from" column_invisible="not parent.leave_by_hour" required="parent.leave_by_hour"/>
|
||||
<field name="end_time"/>
|
||||
<field name="days" sum="Total"/>
|
||||
<field name="end_hour_from" column_invisible="not parent.leave_by_hour" required="parent.leave_by_hour"/>
|
||||
<field name="leave_duration" sum="Total"/>
|
||||
<field name="leave_unit"/>
|
||||
<field name="residual"/>
|
||||
<field name="leave_documents_ids" widget="preview_many2many"/>
|
||||
<field name="leave_documents_ids" widget="preview_many2many" options="{'preview_type': 'button', 'preview_string': '查看详情'}"/>
|
||||
<field name="custom_document_ids" widget="preview_many2many" options="{'show_select_btn': false}"/>
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
|
||||
Reference in New Issue
Block a user