添加功能
This commit is contained in:
@@ -1032,6 +1032,7 @@ class ReportExcel(models.Model):
|
||||
output.seek(0)
|
||||
response.stream.write(output.read())
|
||||
output.close()
|
||||
|
||||
def get_xlsx_overtime_report(self, data, response):
|
||||
"""加班明细报表的自定义 Excel 样式"""
|
||||
output = io.BytesIO()
|
||||
@@ -1155,17 +1156,94 @@ class ReportExcel(models.Model):
|
||||
response.stream.write(output.read())
|
||||
output.close()
|
||||
|
||||
def _export_overtime_active(self, start_date, end_date):
|
||||
"""导出加班归档明细"""
|
||||
active_ids = json.loads(self.active_ids) if self.active_ids else []
|
||||
domain = [
|
||||
('carry_forward_date', '>=', start_date),
|
||||
('carry_forward_date', '<', end_date),
|
||||
('is_void', '=', False),
|
||||
('carryover_type', '=', 'fee')
|
||||
]
|
||||
if active_ids:
|
||||
domain = [('id', 'in', active_ids)] + domain
|
||||
filtered_records = self.env['overtime.carryover'].search(domain)
|
||||
|
||||
if not filtered_records:
|
||||
raise UserError(f'在 {self.year} 年 {self.month} 月没有找到符合条件的加班归档记录')
|
||||
|
||||
export_data = []
|
||||
for record in filtered_records:
|
||||
over_line = record.over_line_id
|
||||
# 提前处理时区转换,避免在Excel函数中重复处理
|
||||
tz = self.env.user.tz or 'Asia/Shanghai'
|
||||
user_tz = timezone(tz)
|
||||
|
||||
# 处理开始时间时区转换
|
||||
start_time = ''
|
||||
if over_line and over_line.start_time:
|
||||
start_time_utc = UTC.localize(
|
||||
over_line.start_time) if over_line.start_time.tzinfo is None else over_line.start_time
|
||||
start_time = start_time_utc.astimezone(user_tz).replace(tzinfo=None)
|
||||
|
||||
# 处理结束时间时区转换
|
||||
end_time = ''
|
||||
if over_line and over_line.end_time:
|
||||
end_time_utc = UTC.localize(
|
||||
over_line.end_time) if over_line.end_time.tzinfo is None else over_line.end_time
|
||||
end_time = end_time_utc.astimezone(user_tz).replace(tzinfo=None)
|
||||
|
||||
row_data = {
|
||||
'employee_id': over_line.employee_id.name if over_line and over_line.employee_id else '',
|
||||
'department_id': over_line.department_id.name if over_line and over_line.department_id else '',
|
||||
'start_time': start_time,
|
||||
'end_time': end_time,
|
||||
'carry_forward_date': record.carry_forward_date,
|
||||
'carry_forward_quantity': record.carry_forward_quantity or 0,
|
||||
'carry_forward_state': dict(record._fields.get('carry_forward_state').selection).get(
|
||||
record.carry_forward_state, '') if hasattr(record, 'carry_forward_state') else ''
|
||||
}
|
||||
export_data.append(row_data)
|
||||
|
||||
fields_name = ['employee_id', 'department_id', 'start_time', 'end_time',
|
||||
'carry_forward_date', 'carry_forward_quantity', 'carry_forward_state']
|
||||
field_label = ['姓名', '部门', '加班开始时间', '加班结束时间', '结转日期',
|
||||
'结转时长', '结转结果']
|
||||
|
||||
data = {
|
||||
'report_name': '加班归档明细报表',
|
||||
'model_name': 'overtime.carryover',
|
||||
'fields_name': fields_name,
|
||||
'field_label': field_label,
|
||||
'export_data': export_data, # 传递预处理好的数据
|
||||
}
|
||||
|
||||
return {
|
||||
'type': 'ir.actions.report',
|
||||
'data': {
|
||||
'model': 'report.excel',
|
||||
'options': json.dumps(data, default=date_utils.json_default),
|
||||
'output_format': 'xlsx',
|
||||
'report_name': '加班归档明细报表',
|
||||
},
|
||||
'report_type': 'xlsx',
|
||||
}
|
||||
|
||||
def get_xlsx_overtime_active_report(self, data, response):
|
||||
"""加班归档明细报表的自定义 Excel 样式"""
|
||||
import io
|
||||
import xlsxwriter
|
||||
from pytz import timezone, UTC
|
||||
from datetime import datetime, date
|
||||
|
||||
output = io.BytesIO()
|
||||
workbook = xlsxwriter.Workbook(output, {'in_memory': True})
|
||||
sheet = workbook.add_worksheet('加班归档明细')
|
||||
|
||||
|
||||
# 获取当前用户的时区
|
||||
tz = self.env.user.tz or 'Asia/Shanghai'
|
||||
from pytz import timezone
|
||||
user_tz = timezone(tz)
|
||||
|
||||
|
||||
# 表头格式
|
||||
header_format = workbook.add_format({
|
||||
'font_size': 11,
|
||||
@@ -1198,8 +1276,8 @@ class ReportExcel(models.Model):
|
||||
'valign': 'vcenter',
|
||||
'num_format': 'yyyy-mm-dd'
|
||||
})
|
||||
|
||||
# 写表头
|
||||
|
||||
# 写表头(保持原有样式)
|
||||
col = 0
|
||||
for label in data['field_label']:
|
||||
sheet.write(0, col, label, header_format)
|
||||
@@ -1213,61 +1291,36 @@ class ReportExcel(models.Model):
|
||||
else:
|
||||
sheet.set_column(col, col, 15)
|
||||
col += 1
|
||||
|
||||
# 取记录
|
||||
records = []
|
||||
active_ids = data.get('active_ids')
|
||||
if active_ids:
|
||||
records = self.env[data['model_name']].browse(active_ids)
|
||||
else:
|
||||
records = self.env[data['model_name']].search([])
|
||||
|
||||
|
||||
# ========== 核心修复:使用预处理的 export_data ==========
|
||||
records_data = data.get('export_data', [])
|
||||
|
||||
# 写数据行
|
||||
row = 1
|
||||
for rec in records:
|
||||
for rec_data in records_data:
|
||||
col = 0
|
||||
for field_name in data['fields_name']:
|
||||
field = rec._fields.get(field_name)
|
||||
value = rec[field_name]
|
||||
|
||||
# 根据字段类型处理值
|
||||
if isinstance(value, datetime.datetime):
|
||||
if value:
|
||||
from pytz import UTC
|
||||
value_utc = UTC.localize(value) if value.tzinfo is None else value
|
||||
value_local = value_utc.astimezone(user_tz)
|
||||
sheet.write_datetime(row, col, value_local.replace(tzinfo=None), datetime_format)
|
||||
else:
|
||||
sheet.write(row, col, '', data_format)
|
||||
elif isinstance(value, datetime.date):
|
||||
value = rec_data.get(field_name, '')
|
||||
|
||||
# 根据值类型应用对应格式
|
||||
if isinstance(value, datetime):
|
||||
sheet.write_datetime(row, col, value, datetime_format)
|
||||
elif isinstance(value, date):
|
||||
sheet.write_datetime(row, col, value, date_format)
|
||||
elif field:
|
||||
if field.type == 'many2one':
|
||||
value = value.display_name if value else ''
|
||||
sheet.write(row, col, value, data_format)
|
||||
elif field.type == 'many2many':
|
||||
value = ', '.join(value.mapped('display_name')) if value else ''
|
||||
sheet.write(row, col, value, data_format)
|
||||
elif field.type == 'selection':
|
||||
selection_dict = dict(field.selection)
|
||||
value = selection_dict.get(value, value or '')
|
||||
sheet.write(row, col, value, data_format)
|
||||
elif field.type == 'float':
|
||||
sheet.write(row, col, value or 0, data_format)
|
||||
else:
|
||||
sheet.write(row, col, value or '', data_format)
|
||||
elif isinstance(value, float):
|
||||
sheet.write(row, col, value, data_format)
|
||||
else:
|
||||
sheet.write(row, col, value or '', data_format)
|
||||
col += 1
|
||||
row += 1
|
||||
|
||||
|
||||
# 给整表加筛选
|
||||
if row > 1:
|
||||
sheet.autofilter(0, 0, row - 1, len(data['field_label']) - 1)
|
||||
|
||||
|
||||
# 冻结首行
|
||||
sheet.freeze_panes(1, 0)
|
||||
|
||||
|
||||
workbook.close()
|
||||
output.seek(0)
|
||||
response.stream.write(output.read())
|
||||
|
||||
@@ -212,31 +212,48 @@ class ExportDateWizard(models.TransientModel):
|
||||
def _export_overtime_active(self, start_date, end_date):
|
||||
"""导出加班归档明细"""
|
||||
active_ids = json.loads(self.active_ids) if self.active_ids else []
|
||||
|
||||
domain = [('carry_forward_date', '>=', start_date), ('carry_forward_date', '<', end_date), ('is_void','=', False), ('carry_forward_quantity', '>', 0)]
|
||||
domain = [
|
||||
('carry_forward_date', '>=', start_date),
|
||||
('carry_forward_date', '<', end_date),
|
||||
('is_void', '=', False),
|
||||
('carryover_type', '=', 'fee')
|
||||
]
|
||||
if active_ids:
|
||||
domain = [('id', 'in', active_ids)] + domain
|
||||
|
||||
filtered_records = self.env['overtime.active.line'].search(domain)
|
||||
|
||||
filtered_records = self.env['overtime.carryover'].search(domain)
|
||||
|
||||
if not filtered_records:
|
||||
raise UserError(f'在 {self.year} 年 {self.month} 月没有找到符合条件的加班归档记录')
|
||||
|
||||
filtered_ids = filtered_records.ids
|
||||
|
||||
fields_name = ['employee_id', 'department_id', 'start_time', 'end_time',
|
||||
export_data = []
|
||||
for record in filtered_records:
|
||||
over_line = record.over_line_id
|
||||
carry_forward_state_value = ''
|
||||
if over_line and over_line.carry_forward_state:
|
||||
selection_dict = dict(over_line._fields.get('carry_forward_state').selection)
|
||||
carry_forward_state_value = selection_dict.get(over_line.carry_forward_state, '')
|
||||
row_data = {
|
||||
'employee_id': over_line.employee_id.name if over_line and over_line.employee_id else '',
|
||||
'department_id': over_line.department_id.name if over_line and over_line.department_id else '',
|
||||
'start_time': over_line.start_time if over_line else '',
|
||||
'end_time': over_line.end_time if over_line else '',
|
||||
'carry_forward_date': record.carry_forward_date,
|
||||
'carry_forward_quantity': record.carry_forward_quantity,
|
||||
'carry_forward_state': carry_forward_state_value
|
||||
}
|
||||
export_data.append(row_data)
|
||||
fields_name = ['employee_id', 'department_id', 'start_time', 'end_time',
|
||||
'carry_forward_date', 'carry_forward_quantity', 'carry_forward_state']
|
||||
field_label = ['姓名', '部门', '加班开始时间', '加班结束时间', '结转日期',
|
||||
field_label = ['姓名', '部门', '加班开始时间', '加班结束时间', '结转日期',
|
||||
'结转时长', '结转结果']
|
||||
|
||||
|
||||
data = {
|
||||
'report_name': '加班归档明细报表',
|
||||
'model_name': 'overtime.active.line',
|
||||
'model_name': 'overtime.carryover',
|
||||
'fields_name': fields_name,
|
||||
'field_label': field_label,
|
||||
'active_ids': filtered_ids,
|
||||
'export_data': export_data,
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
'type': 'ir.actions.report',
|
||||
'data': {
|
||||
|
||||
Reference in New Issue
Block a user