diff --git a/yuthon_maintain/models/inherit_maintenance_equipment.py b/yuthon_maintain/models/inherit_maintenance_equipment.py
index f4e58720e..cd72e0355 100644
--- a/yuthon_maintain/models/inherit_maintenance_equipment.py
+++ b/yuthon_maintain/models/inherit_maintenance_equipment.py
@@ -100,19 +100,49 @@ class InheritMaintenanceEquipment(models.Model):
workbook = load_workbook(template_path)
sheet = workbook.active
+ # 统计导出数据中最常见的年月(用于标题)
+ year_month_list = []
+ for record in equipment_records:
+ if record.purchase_date:
+ year_month_list.append((record.purchase_date.year, record.purchase_date.month))
+
+ if year_month_list:
+ # 取出现次数最多的年月
+ from collections import Counter
+ most_common_ym = Counter(year_month_list).most_common(1)[0][0]
+ title_year, title_month = most_common_ym
+ else:
+ # 如果没有购入日期,使用当前年月
+ now = datetime.datetime.now()
+ title_year, title_month = now.year, now.month
+
+ # 修改A1单元格:生成动态标题
+ title_text = f'{title_year}年{title_month}月固定资产盘点表'
+ sheet['A1'] = title_text
+ sheet['A1'].alignment = Alignment(horizontal='left', vertical='center')
+
+ # 修改K1单元格:生成制表人信息(直接替换,不追加)
+ current_date = datetime.datetime.now().strftime('%Y-%m-%d')
+ k1_text = f'制表人:叶华锋 {current_date}'
+ sheet['K1'] = k1_text
+ sheet['K1'].alignment = Alignment(horizontal='left', vertical='center')
+
# 从第3行开始写入数据(第1-2行是表头)
row = 3
- # 设置列宽(A列序号列设置为较窄,C列型号列也设置较窄)
- sheet.column_dimensions['A'].width = 6 # 序号列宽度
- sheet.column_dimensions['C'].width = 12 # 型号列宽度
+ # 设置列宽
+ sheet.column_dimensions['A'].width = 6 # 序号列
+ sheet.column_dimensions['B'].width = 20 # 资产编号列(加宽)
+ sheet.column_dimensions['C'].width = 30 # 设备名称列(加宽)
+ sheet.column_dimensions['D'].width = 12 # 型号列
+ sheet.column_dimensions['K'].width = 25 # 制表人列(确保内容完整显示)
# 获取模板样式行(使用第3行作为参考)
template_row_idx = 3
if sheet.max_row >= template_row_idx:
# 先保存第3行的样式
template_styles = {}
- for col in range(1, 11): # A到J列(10列)
+ for col in range(1, 12): # A到K列(11列)
cell = sheet.cell(row=template_row_idx, column=col)
template_styles[col] = {
'font': copy(cell.font),
@@ -132,54 +162,57 @@ class InheritMaintenanceEquipment(models.Model):
for merged_range_str in merged_cells_to_unmerge:
sheet.unmerge_cells(merged_range_str)
- # 先为所有列应用模板样式
- for col in range(1, 11): # A到J列
+ # 先为所有列应用模板样式并统一居中对齐
+ for col in range(1, 12): # A到K列
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 = Alignment(horizontal='center', vertical='center')
+ # 统一设置居中对齐
+ cell.alignment = Alignment(horizontal='center', vertical='center')
# A列:序号(从1开始)
sheet.cell(row=row, column=1, value=index)
- # B列:设备名称
- sheet.cell(row=row, column=2, value=record.name or '')
+ # B列:资产编号
+ sheet.cell(row=row, column=2, value=record.serial_no or '')
- # C列:型号
- sheet.cell(row=row, column=3, value=record.model or '')
+ # C列:设备名称
+ sheet.cell(row=row, column=3, value=record.name or '')
- # D列:原值
- sheet.cell(row=row, column=4, value=record.cost or 0)
+ # D列:型号
+ sheet.cell(row=row, column=4, value=record.model or '')
- # E列:寿命
+ # E列:原值
+ sheet.cell(row=row, column=5, value=record.cost or 0)
+
+ # F列:寿命
warranty_date = ''
if record.warranty_date:
warranty_date = record.warranty_date.strftime('%Y-%m-%d')
- sheet.cell(row=row, column=5, value=warranty_date)
+ sheet.cell(row=row, column=6, value=warranty_date)
- # F列:设备状态
+ # G列:设备状态
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)
+ sheet.cell(row=row, column=7, 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.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.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.category_id.name if record.category_id else '')
- # J列:公司(company 字段)
+ # K列:公司(company 字段)
company = ''
if record.company:
company = dict(record._fields['company'].selection).get(record.company, '')
- sheet.cell(row=row, column=10, value=company)
+ sheet.cell(row=row, column=11, value=company)
# 设置最小行高,确保内容显示完整
if not sheet.row_dimensions[row].height or sheet.row_dimensions[row].height < 30:
@@ -193,8 +226,8 @@ class InheritMaintenanceEquipment(models.Model):
output.seek(0)
excel_data = base64.b64encode(output.read())
- # 创建附件
- filename = f'固定资产盘点表_{datetime.datetime.now().strftime("%Y%m%d%H%M%S")}.xlsx'
+ # 创建附件(文件名只包含日期,不含时分秒)
+ filename = f'固定资产盘点表_{datetime.datetime.now().strftime("%Y%m%d")}.xlsx'
attachment = self.env['ir.attachment'].create({
'name': filename,
'type': 'binary',
diff --git a/yuthon_property/static/tmpl/gudingzichanpandianbiao.xlsx b/yuthon_property/static/tmpl/gudingzichanpandianbiao.xlsx
index 6a8a70b88..5cf4559ef 100644
Binary files a/yuthon_property/static/tmpl/gudingzichanpandianbiao.xlsx and b/yuthon_property/static/tmpl/gudingzichanpandianbiao.xlsx differ
diff --git a/yuthon_stock/models/inherit_stock_move.py b/yuthon_stock/models/inherit_stock_move.py
index cef654be0..8561887ed 100644
--- a/yuthon_stock/models/inherit_stock_move.py
+++ b/yuthon_stock/models/inherit_stock_move.py
@@ -26,3 +26,5 @@ class ProductProduct(models.Model):
class StockMove(models.Model):
_inherit = 'stock.move'
+
+
diff --git a/yuthon_stock/models/inherit_stock_picking.py b/yuthon_stock/models/inherit_stock_picking.py
index d25969e31..42659ac5a 100644
--- a/yuthon_stock/models/inherit_stock_picking.py
+++ b/yuthon_stock/models/inherit_stock_picking.py
@@ -38,9 +38,20 @@ class StockPicking(models.Model):
)
available_product_ids = fields.Many2many(
'product.product',
+ 'stock_picking_product_available_rel',
+ 'picking_id',
+ 'product_id',
compute='_compute_available_product_ids',
string="可用产品"
)
+ available_location_ids = fields.Many2many(
+ 'stock.location',
+ 'stock_picking_location_available_rel',
+ 'picking_id',
+ 'location_id',
+ compute='_compute_available_location_ids',
+ string="可用仓库"
+ )
can_certify = fields.Boolean(
string="可以证明",
compute='_compute_can_certify',
@@ -81,19 +92,39 @@ class StockPicking(models.Model):
})
return result
- @api.depends('location_id')
+ @api.depends('location_id', 'picking_type_code')
def _compute_available_product_ids(self):
- """根据仓库计算可用产品列表"""
+ """根据仓库和作业类型计算可用产品列表"""
for record in self:
- if record.location_id:
- # 查询该仓库中有库存的产品
+ # 如果是入库单,返回所有产品(不限制)
+ if record.picking_type_code == 'incoming':
+ record.available_product_ids = self.env['product.product'].search([])
+ # 如果是借用/领用等,只返回该仓库中有库存的产品
+ elif record.location_id:
quants = self.env['stock.quant'].search([
- ('location_id', '=', record.location_id.id)
+ ('location_id', '=', record.location_id.id),
+ ('quantity', '>', 0) # 只查询有库存的
])
record.available_product_ids = quants.mapped('product_id')
else:
record.available_product_ids = False
+
+ @api.depends('picking_type_code')
+ def _compute_available_location_ids(self):
+ """根据作业类型计算可用仓库列表"""
+ for record in self:
+ # 如果是入库单,不限制仓库选择
+ if record.picking_type_code == 'incoming':
+ record.available_location_ids = self.env['stock.location'].search([])
+ # 如果是借用/领用等,只显示有库存的仓库
+ else:
+ quants = self.env['stock.quant'].search([
+ ('quantity', '>', 0)
+ ])
+ record.available_location_ids = quants.mapped('location_id')
+
+
@api.onchange('user_id')
def _onchange_user_id(self):
if self.user_id:
@@ -173,9 +204,73 @@ class StockPicking(models.Model):
record._compute_json_display()
return True
+ def action_update_name_by_products(self):
+ """批量更新入库单名称(根据产品生成)"""
+ updated_count = 0
+ for picking in self:
+ # 只处理入库单
+ if picking.picking_type_code == 'incoming' and picking.move_ids_without_package:
+ product_names = picking.move_ids_without_package.mapped('product_id.name')
+ if product_names:
+ products_str = '/'.join(product_names)
+ # 添加入库单ID确保唯一性
+ new_name = f"{products_str}的入库单-{picking.id}"
+ picking.write({'name': new_name})
+ updated_count += 1
+
+ # 返回提示消息
+ return {
+ 'type': 'ir.actions.client',
+ 'tag': 'display_notification',
+ 'params': {
+ 'title': '更新完成',
+ 'message': f'已成功更新 {updated_count} 条入库单的名称',
+ 'type': 'success',
+ 'sticky': False,
+ }
+ }
+
def action_acceptance(self):
"""验收按钮"""
self.ensure_one()
self.acceptance_date = fields.Datetime.now()
self.receipt_status = 'certification' # 状态变为证明
- return True
\ No newline at end of file
+ return True
+
+ @api.model_create_multi
+ def create(self, vals_list):
+ """重写create方法,根据产品生成入库单名称"""
+ pickings = super(StockPicking, self).create(vals_list)
+
+ for picking in pickings:
+ # 只处理入库单(picking_type_code为incoming)
+ if picking.picking_type_code == 'incoming' and picking.move_ids_without_package:
+ # 获取所有产品名称
+ product_names = picking.move_ids_without_package.mapped('product_id.name')
+ if product_names:
+ # 用/连接产品名称
+ products_str = '/'.join(product_names)
+ # 生成新的name格式:产品/产品/产品的入库单-ID(确保唯一性)
+ new_name = f"{products_str}的入库单-{picking.id}"
+ # 更新name字段
+ picking.write({'name': new_name})
+
+ return pickings
+
+ def write(self, vals):
+ """重写write方法,当产品变化时更新入库单名称"""
+ result = super(StockPicking, self).write(vals)
+
+ # 如果修改了move_ids相关字段,更新name
+ if 'move_ids_without_package' in vals or 'move_ids' in vals:
+ for picking in self:
+ if picking.picking_type_code == 'incoming' and picking.move_ids_without_package:
+ product_names = picking.move_ids_without_package.mapped('product_id.name')
+ if product_names:
+ products_str = '/'.join(product_names)
+ new_name = f"{products_str}的入库单-{picking.id}"
+ # 避免递归调用,使用super().write
+ if picking.name != new_name:
+ super(StockPicking, picking).write({'name': new_name})
+
+ return result
\ No newline at end of file
diff --git a/yuthon_stock/views/inherit_stock_picking.xml b/yuthon_stock/views/inherit_stock_picking.xml
index da76036bf..b29f956a6 100644
--- a/yuthon_stock/views/inherit_stock_picking.xml
+++ b/yuthon_stock/views/inherit_stock_picking.xml
@@ -8,8 +8,11 @@
+
+ [('id', 'in', available_location_ids)]
+
- receipt_status in ['acceptance', 'certification']
+ state != 'draft' and receipt_status in ['acceptance', 'certification']
1
@@ -18,6 +21,7 @@
+
@@ -31,14 +35,14 @@
-
-
-
+
+
+
-
-
-
+
+
+
@@ -66,10 +70,10 @@
供应商
- receipt_status in ['acceptance', 'certification']
+ state != 'draft' and receipt_status in ['acceptance', 'certification']
- receipt_status in ['acceptance', 'certification']
+ state != 'draft' and receipt_status in ['acceptance', 'certification']
@@ -84,6 +88,11 @@
stock.picking
+
+
+
编号