This commit is contained in:
李鹏宇
2026-04-22 19:30:49 +08:00
parent c4903e3ce0
commit e6bd1b7d01
5 changed files with 100 additions and 16 deletions
+2 -1
View File
@@ -1 +1,2 @@
from . import models from . import models
from . import wizard
+2
View File
@@ -9,6 +9,8 @@
'depends': ['base', 'stock', 'purchase_stock', 'documents', 'maintenance', 'funenc_json_widget'], 'depends': ['base', 'stock', 'purchase_stock', 'documents', 'maintenance', 'funenc_json_widget'],
'data': [ 'data': [
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'security/company_rule.xml',
'wizard/stock_picking_transfer_wizard_views.xml',
'views/menu.xml', 'views/menu.xml',
'views/inherit_stock_picking.xml', 'views/inherit_stock_picking.xml',
'views/Inherit_stock_picking_type_views.xml', 'views/Inherit_stock_picking_type_views.xml',
+55 -9
View File
@@ -2,6 +2,7 @@
from odoo import api, fields, models from odoo import api, fields, models
from odoo.exceptions import UserError from odoo.exceptions import UserError
import json import json
from lxml import etree
class StockPicking(models.Model): class StockPicking(models.Model):
@@ -24,7 +25,10 @@ class StockPicking(models.Model):
employee_id = fields.Many2one('hr.employee', string="验收人") employee_id = fields.Many2one('hr.employee', string="验收人")
department_id = fields.Many2one('hr.department', string="部门") department_id = fields.Many2one('hr.department', string="部门")
certifier_id = fields.Many2one('res.users', string="证明人") certifier_id = fields.Many2one('res.users', string="证明人")
user_id = fields.Many2one('res.users', string="采购人员", compute="_compute_origin") acceptance_user_id = fields.Many2one('res.users', string="指定验收人")
certifier_user_id = fields.Many2one('res.users', string="指定证明人")
is_admin = fields.Boolean(string='是否管理员', compute='_compute_is_admin')
user_id = fields.Many2one('res.users', string="采购人员", compute="_compute_origin", store=True)
receipt_status = fields.Selection([ receipt_status = fields.Selection([
('acceptance', '验收'), ('acceptance', '验收'),
('certification', '证明'), ('certification', '证明'),
@@ -65,6 +69,11 @@ class StockPicking(models.Model):
store=False store=False
) )
def _compute_is_admin(self):
is_admin = self.env.user.has_group('base.group_system')
for rec in self:
rec.is_admin = is_admin
@api.depends('user_id', 'employee_id') @api.depends('user_id', 'employee_id')
def _compute_can_certify(self): def _compute_can_certify(self):
"""计算当前用户是否可以证明(不是采购人也不是验收人)""" """计算当前用户是否可以证明(不是采购人也不是验收人)"""
@@ -240,16 +249,19 @@ class StockPicking(models.Model):
record.user_id = False record.user_id = False
def button_validate(self): def button_validate(self):
"""重写确认入库方法,改名为证明按钮""" """重写确认入库方法,改名为证明按鈕"""
for record in self: for record in self:
if record.receipt_status == 'certification': if record.receipt_status == 'certification':
# 使用write方法强制写入只读字段 # 如果已指定证明人,检查当前用户是否是指定证明人
if record.certifier_user_id and record.certifier_user_id.id != self.env.user.id:
raise UserError('只有指定的证明人才能执行证明!')
certifier = record.certifier_user_id or self.env.user
# 自动填充证明人和时间,状态变为入库
record.write({ record.write({
'certifier_id': self.env.user.id, 'certifier_id': certifier.id,
'certification_date': fields.Datetime.now(), 'certification_date': fields.Datetime.now(),
'receipt_status': 'receipt' # 状态变为入库 'receipt_status': 'receipt'
}) })
# 自动为标签含"固定资产"的产品创建 maintenance.equipment 记录
for move in record.move_ids_without_package: for move in record.move_ids_without_package:
product = move.product_id product = move.product_id
if product and '固定资产' in product.product_tag_ids.mapped('name'): if product and '固定资产' in product.product_tag_ids.mapped('name'):
@@ -311,15 +323,49 @@ class StockPicking(models.Model):
return True return True
def action_acceptance(self): def action_acceptance(self):
"""验收按钮:自动填充验收人和验收时间""" """验收按鈕:检查是否指定验收人,自动填充验收人和验收时间"""
self.ensure_one() self.ensure_one()
# 获取当前用户对应的员工记录 # 如果已指定验收人,检查当前用户是否是指定验收人
current_employee = self.env.user.employee_ids[:1] if self.env.user.employee_ids else False if self.acceptance_user_id and self.acceptance_user_id.id != self.env.user.id:
raise UserError('只有指定的验收人才能执行验收!')
# 用指定验收人填充,没有指定则取当前用户
acceptor = self.acceptance_user_id or self.env.user
current_employee = acceptor.employee_ids[:1] if acceptor.employee_ids else False
self.acceptance_date = fields.Datetime.now() self.acceptance_date = fields.Datetime.now()
if current_employee: if current_employee:
self.employee_id = current_employee.id self.employee_id = current_employee.id
self.receipt_status = 'certification' # 状态变为证明 self.receipt_status = 'certification' # 状态变为证明
return True return True
def action_transfer_acceptance(self):
"""转交验收:弹出选人 wizard"""
self.ensure_one()
return {
'type': 'ir.actions.act_window',
'name': '转交验收',
'res_model': 'stock.picking.transfer.wizard',
'view_mode': 'form',
'target': 'new',
'context': {
'default_picking_id': self.id,
'default_transfer_type': 'acceptance',
},
}
def action_transfer_certifier(self):
"""转交证明:弹出选人 wizard"""
self.ensure_one()
return {
'type': 'ir.actions.act_window',
'name': '转交证明',
'res_model': 'stock.picking.transfer.wizard',
'view_mode': 'form',
'target': 'new',
'context': {
'default_picking_id': self.id,
'default_transfer_type': 'certifier',
},
}
def _generate_sh_sequence(self, date=None): def _generate_sh_sequence(self, date=None):
"""生成 SH+年月+三位序号 格式的编号,按月重置""" """生成 SH+年月+三位序号 格式的编号,按月重置"""
@@ -1 +1,2 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_stock_picking_transfer_wizard,stock.picking.transfer.wizard,model_stock_picking_transfer_wizard,,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_stock_picking_transfer_wizard stock.picking.transfer.wizard model_stock_picking_transfer_wizard 1 1 1 1
+40 -6
View File
@@ -25,16 +25,37 @@
<field name="state" invisible="1"/> <field name="state" invisible="1"/>
<field name="can_certify" invisible="1"/> <field name="can_certify" invisible="1"/>
<field name="trigger_auto_fill" invisible="1"/> <field name="trigger_auto_fill" invisible="1"/>
<field name="acceptance_user_id" invisible="1"/>
<field name="certifier_user_id" invisible="1"/>
<field name="is_admin" invisible="1"/>
</xpath> </xpath>
<xpath expr="//page[@name='operations']//field[@name='move_ids_without_package']//field[@name='product_id']" position="attributes"> <xpath expr="//page[@name='operations']//field[@name='move_ids_without_package']//field[@name='product_id']" position="attributes">
<attribute name="options">{'no_create': True}</attribute> <attribute name="options">{'no_create': True}</attribute>
<attribute name="domain">[('id', 'in', parent.available_product_ids)]</attribute> <attribute name="domain">[('id', 'in', parent.available_product_ids)]</attribute>
</xpath> </xpath>
<xpath expr="//header/button[@name='%(stock.act_stock_return_picking)d']" position="after"> <xpath expr="//button[@name='%(stock.act_stock_return_picking)d']" position="attributes">
<button name="action_acceptance" string="验收" type="object" class="btn-primary" invisible="receipt_status != 'acceptance'"/> <attribute name="invisible">1</attribute>
<!-- <button name="action_revoke_receipt" string="撤回入库" type="object" class="btn-secondary"--> </xpath>
<!-- invisible="receipt_status != 'receipt'"--> <xpath expr="//button[@name='action_confirm']" position="attributes">
<!-- groups="base.group_system"/>--> <attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//button[@name='action_cancel']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//header" position="inside">
<!-- 转交验收:管理员且尚未转交时可见 -->
<button name="action_transfer_acceptance" string="转交验收" type="object" class="btn-secondary"
invisible="receipt_status != 'acceptance' or acceptance_user_id != False or not is_admin"/>
<!-- 验收按钮:只有指定验收人可见,且当前用户是指定人 -->
<button name="action_acceptance" string="验收" type="object" class="btn-primary"
invisible="receipt_status != 'acceptance' or acceptance_user_id == False or acceptance_user_id != uid"/>
<!-- 转交证明:验收人才能转交,且尚未转交证明时可见 -->
<button name="action_transfer_certifier" string="转交证明" type="object" class="btn-secondary"
invisible="receipt_status != 'certification' or certifier_user_id != False or acceptance_user_id != uid"/>
<!-- 撤回入库:管理员且入库状态时可见 -->
<button name="action_revoke_receipt" string="撤回入库" type="object" class="btn-secondary"
invisible="receipt_status != 'receipt' or not is_admin"/>
</xpath> </xpath>
<xpath expr="//page[@name='operations']/field[@name='move_ids_without_package']" position="after"> <xpath expr="//page[@name='operations']/field[@name='move_ids_without_package']" position="after">
<group> <group>
@@ -55,7 +76,7 @@
</xpath> </xpath>
<xpath expr="//button[@name='button_validate' and @class='oe_highlight']" position="attributes"> <xpath expr="//button[@name='button_validate' and @class='oe_highlight']" position="attributes">
<attribute name="string">证明</attribute> <attribute name="string">证明</attribute>
<attribute name="invisible">receipt_status != 'certification' or not can_certify</attribute> <attribute name="invisible">receipt_status != 'certification' or certifier_user_id == False or certifier_user_id != uid</attribute>
</xpath> </xpath>
<xpath expr="//field[@name='location_dest_id'][@groups='stock.group_stock_multi_locations']" position="attributes"> <xpath expr="//field[@name='location_dest_id'][@groups='stock.group_stock_multi_locations']" position="attributes">
<attribute name="invisible">1</attribute> <attribute name="invisible">1</attribute>
@@ -268,6 +289,19 @@
<record id="stock.action_picking_tree_incoming" model="ir.actions.act_window"> <record id="stock.action_picking_tree_incoming" model="ir.actions.act_window">
<field name="name">收货</field> <field name="name">收货</field>
<field name="context">{'contact_display': 'partner_address', 'default_company_id': allowed_company_ids[0], 'restricted_picking_type_code': 'incoming', 'search_default_reception': 1, 'search_default_my_pickings': 1}</field>
</record>
<record id="inherit_view_picking_internal_search_my" model="ir.ui.view">
<field name="name">inherit.view.picking.internal.search.my</field>
<field name="model">stock.picking</field>
<field name="inherit_id" ref="stock.view_picking_internal_search"/>
<field name="arch" type="xml">
<xpath expr="//filter[@name='reception']" position="after">
<filter name="my_pickings" string="我的收货"
domain="['|', '|', ('user_id', '=', uid), ('employee_id.user_id', '=', uid), ('certifier_id', '=', uid)]"/>
</xpath>
</field>
</record> </record>
</odoo> </odoo>