diff --git a/yuthon_maintain/models/inherit_maintenance_equipment.py b/yuthon_maintain/models/inherit_maintenance_equipment.py
index 8333d9f5d..b2aeab175 100644
--- a/yuthon_maintain/models/inherit_maintenance_equipment.py
+++ b/yuthon_maintain/models/inherit_maintenance_equipment.py
@@ -5,6 +5,10 @@ import datetime
import qrcode
from io import BytesIO
import base64
+from openpyxl import load_workbook
+from openpyxl.styles import Alignment
+from copy import copy
+from odoo.modules import get_module_resource
def generate_qr(data):
qr = qrcode.QRCode(
@@ -74,6 +78,131 @@ class InheritMaintenanceEquipment(models.Model):
'is_fixed_assets': True,
})
+ def export_inventory_report(self):
+ """导出固定资产盘点表"""
+ equipment_ids = self._context.get('active_ids', [])
+ if not equipment_ids:
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'display_notification',
+ 'params': {
+ 'title': '警告',
+ 'message': '请至少选择一条设备记录',
+ 'type': 'warning',
+ 'sticky': False,
+ }
+ }
+
+ equipment_records = self.env['maintenance.equipment'].browse(equipment_ids)
+
+ # 加载模板文件(模板在 yuthon_property 模块的 static/tmpl 目录下)
+ template_path = get_module_resource('yuthon_property', 'static', 'tmpl', 'gudingzichanpandianbiao.xlsx')
+ workbook = load_workbook(template_path)
+ sheet = workbook.active
+
+ # 从第3行开始写入数据(第1-2行是表头)
+ row = 3
+
+ # 获取模板样式行(使用第3行作为参考)
+ template_row_idx = 3
+ if sheet.max_row >= template_row_idx:
+ # 先保存第3行的样式
+ template_styles = {}
+ for col in range(1, 11): # A到J列(10列)
+ cell = sheet.cell(row=template_row_idx, column=col)
+ template_styles[col] = {
+ 'font': copy(cell.font),
+ 'fill': copy(cell.fill),
+ 'border': copy(cell.border),
+ 'alignment': copy(cell.alignment),
+ }
+ else:
+ template_styles = {}
+
+ for index, record in enumerate(equipment_records, start=1):
+ # 先解除当前行的合并单元格(如果有)
+ merged_cells_to_unmerge = []
+ for merged_range in sheet.merged_cells.ranges:
+ if merged_range.min_row <= row <= merged_range.max_row:
+ merged_cells_to_unmerge.append(str(merged_range))
+ for merged_range_str in merged_cells_to_unmerge:
+ sheet.unmerge_cells(merged_range_str)
+
+ # 先为所有列应用模板样式
+ for col in range(1, 11): # A到J列
+ cell = sheet.cell(row=row, column=col)
+ if col in template_styles:
+ cell.font = copy(template_styles[col]['font'])
+ cell.fill = copy(template_styles[col]['fill'])
+ cell.border = copy(template_styles[col]['border'])
+ cell.alignment = copy(template_styles[col]['alignment'])
+
+ # A列:序号(从1开始)
+ sheet.cell(row=row, column=1, value=index)
+
+ # B列:设备名称
+ sheet.cell(row=row, column=2, value=record.name or '')
+
+ # C列:型号
+ sheet.cell(row=row, column=3, value=record.model or '')
+
+ # D列:原值
+ sheet.cell(row=row, column=4, value=record.cost or 0)
+
+ # E列:寿命
+ warranty_date = ''
+ if record.warranty_date:
+ warranty_date = record.warranty_date.strftime('%Y-%m-%d')
+ sheet.cell(row=row, column=5, value=warranty_date)
+
+ # F列:设备状态
+ mainten_state = ''
+ if record.mainten_state:
+ mainten_state = dict(record._fields['mainten_state'].selection).get(record.mainten_state, '')
+ sheet.cell(row=row, column=6, value=mainten_state)
+
+ # G列:员工
+ sheet.cell(row=row, column=7, value=record.employee_id.name if record.employee_id else '')
+
+ # H列:部门
+ sheet.cell(row=row, column=8, value=record.department_id1.name if record.department_id1 else '')
+
+ # I列:设备类别
+ sheet.cell(row=row, column=9, value=record.category_id.name if record.category_id else '')
+
+ # J列:公司
+ sheet.cell(row=row, column=10, value=record.company_id.name if record.company_id else '')
+
+ # 设置最小行高,确保内容显示完整
+ if not sheet.row_dimensions[row].height or sheet.row_dimensions[row].height < 30:
+ sheet.row_dimensions[row].height = 30
+
+ row += 1
+
+ # 保存到内存
+ output = BytesIO()
+ workbook.save(output)
+ output.seek(0)
+ excel_data = base64.b64encode(output.read())
+
+ # 创建附件
+ filename = f'固定资产盘点表_{datetime.datetime.now().strftime("%Y%m%d%H%M%S")}.xlsx'
+ attachment = self.env['ir.attachment'].create({
+ 'name': filename,
+ 'type': 'binary',
+ 'datas': excel_data,
+ 'res_model': 'maintenance.equipment',
+ 'res_id': equipment_records[0].id,
+ 'mimetype': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+ })
+
+ # 返回下载链接
+ return {
+ 'type': 'ir.actions.act_url',
+ 'url': f'/web/content/{attachment.id}?download=true',
+ 'target': 'self',
+ }
+
class MaintenanceEquipmentLine(models.Model):
_name = 'maintenance.equipment.line'
diff --git a/yuthon_maintain/views/maintenance_equipment_views.xml b/yuthon_maintain/views/maintenance_equipment_views.xml
index b223d5e21..84c373bba 100644
--- a/yuthon_maintain/views/maintenance_equipment_views.xml
+++ b/yuthon_maintain/views/maintenance_equipment_views.xml
@@ -186,4 +186,13 @@
code
action = model.add_office_supplies()
+
+
+ 导出盘点表
+
+
+ list
+ code
+ action = model.export_inventory_report()
+
\ No newline at end of file
diff --git a/yuthon_property/static/tmpl/gudingzichanpandianbiao.xlsx b/yuthon_property/static/tmpl/gudingzichanpandianbiao.xlsx
new file mode 100644
index 000000000..6a8a70b88
Binary files /dev/null and b/yuthon_property/static/tmpl/gudingzichanpandianbiao.xlsx differ
diff --git a/yuthon_stock/models/inherit_stock_picking.py b/yuthon_stock/models/inherit_stock_picking.py
index a6b95e3ec..d25969e31 100644
--- a/yuthon_stock/models/inherit_stock_picking.py
+++ b/yuthon_stock/models/inherit_stock_picking.py
@@ -64,7 +64,7 @@ class StockPicking(models.Model):
record.can_certify = True
def read(self, fields=None, load='_classic_read'):
- """重写read方法,打开验收状态的入库单时自动更新验收时间"""
+ """重写read方法,打开验收/证明状态的入库单时自动更新时间"""
result = super(StockPicking, self).read(fields, load)
# 导入Fields模块
from odoo import fields as odoo_fields
@@ -74,6 +74,11 @@ class StockPicking(models.Model):
record.write({
'acceptance_date': odoo_fields.Datetime.now()
})
+ elif record.receipt_status == 'certification':
+ # 使用write方法更新证明时间
+ record.write({
+ 'certification_date': odoo_fields.Datetime.now()
+ })
return result
@api.depends('location_id')