添加功能

This commit is contained in:
李鹏宇
2026-03-16 10:40:31 +08:00
parent 84b7348707
commit 2fd86cf0cc
2 changed files with 130 additions and 60 deletions
+99 -46
View File
@@ -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': {