跳到主要内容

物料申请过程做库存预留

物料申请阶段直接实现库存预留

在物料申请阶段直接实现库存预留,并根据不同的业务场景进行分类。我们可以扩展 Material Request 功能,结合生产计划和生产工单的预留逻辑。

下述方法为AI提供, 最终并未实践。

实现步骤-方法1

1. 添加自定义字段

Material RequestMaterial Request Item 添加自定义字段 reserved_qty,用于记录预留数量。

  • 路径: 自定义化 ➔ 自定义字段
  • Material Request Item 添加字段 reserved_qty(类型为 Float)

2. 编写自定义脚本

在提交物料申请时,根据不同的业务场景创建相应的库存预留逻辑。例如,如果物料申请类型是“Material Issue”,将其归类为生产计划,并创建库存预留。

python复制代码# 
客户端脚本(Custom Script)
frappe.ui.form.on('Material Request', {
on_submit: function(frm) {
if (frm.doc.material_request_type === 'Material Issue') {
frm.doc.items.forEach(function(item) {
frappe.call({
method: 'erpnext.stock.doctype.stock_entry.stock_entry.make_stock_entry',
args: {
source_name: frm.doc.name,
target_doc: null,
args: {
item_code: item.item_code,
reserved_qty: item.qty,
purpose: 'Material Issue'
}
},
callback: function(r) {
if(!r.exc) {
frappe.msgprint(__('Stock Entry created for item {0}', [item.item_code]));
}
}
});
});
}
}
});

3. 修改服务器端逻辑

在服务器端处理库存预留逻辑时,根据 Material Request 的类型进行不同的处理。例如,对于“Material Issue”类型,将其处理为生产计划预留。

修改 make_stock_entry 方法:

python复制代码# 在 erpnext/stock/doctype/stock_entry/stock_entry.py 中
@frappe.whitelist()
def make_stock_entry(source_name, target_doc=None, args=None):
if args is None:
args = {}
if isinstance(args, str):
args = json.loads(args)

def update_item(obj, target, source_parent):
qty = flt(args.get('reserved_qty')) / target.conversion_factor
target.qty = qty
target.transfer_qty = qty * obj.conversion_factor
target.conversion_factor = obj.conversion_factor

if args.get('purpose') == 'Material Issue':
target.s_warehouse = obj.warehouse
elif args.get('purpose') == 'Material Transfer':
target.t_warehouse = obj.warehouse

doclist = get_mapped_doc(
"Material Request",
source_name,
{
"Material Request": {
"doctype": "Stock Entry",
"validation": {
"docstatus": ["=", 1],
"material_request_type": ["in", ["Material Transfer", "Material Issue", "Customer Provided"]],
},
},
"Material Request Item": {
"doctype": "Stock Entry Detail",
"field_map": {
"name": "material_request_item",
"parent": "material_request",
"uom": "stock_uom",
},
"postprocess": update_item,
"condition": lambda doc: (
flt(doc.ordered_qty, doc.precision("ordered_qty"))
< flt(doc.stock_qty, doc.precision("ordered_qty"))
),
},
},
target_doc,
set_missing_values,
)

return doclist

实现步骤-方法2

1. 服务端创建库存预留逻辑, 采用钩子中调用

在系统中创建一个处理库存预留的函数,根据 Material Request 的类型进行分类处理。

python复制代码
def reserve_stock_for_material_request(material_request):
for item in material_request.items:
reserve_stock(item.item_code, item.qty, material_request.company, material_request.material_request_type)

def reserve_stock(item_code, qty, company, request_type):
bin = frappe.get_doc('Bin', {'item_code': item_code, 'company': company})
if request_type == 'Material Issue':
bin.reserved_qty_for_production += qty
elif request_type == 'Purchase':
bin.reserved_qty_for_purchase += qty
# 其他类型的预留逻辑
bin.save()

# 在 Material Request 的提交钩子中调用
def on_submit(self):
self.reserve_stock_for_material_request(self)

总结

通过以上步骤,我们可以在物料申请阶段实现库存预留,并根据不同的业务场景(如生产计划、生产工单、采购等)进行分类处理。这样可以确保在物料申请提交时,系统会自动为相应的数量进行预留,从而满足业务需求。