I looking for a functionality to auto create Batch during Stock entry with Batch ID from Stock Entry item custom field. Is anybody have the same use can and successful in implementing. Appreciate sharing your solution.
What is your scenario/use case? So I can understand it better.
When you material receipt type set in stock entry, then it will create a batch automatically if enabled the “Automatically Create New Batch” in Item master.
The ERPNext set-up is Batch ready and can be enabled any time. Tested Ok to auto generate Batch IDs when enabled. But the client would like to manually key in the number series for their own control in Stock Entry item custom field that will be inherited to become the Batch ID. It is needed for type Material Receipt. My use case is type Repack.
@pmjd Need this for Repack operations. Client would like to control their own Batch ID series which will be inherited from parent Stock Entry Repack item custom field. Appreciate any idea.
Probably a SAP WM wannabe I advise you use Workflow. Otherwise you need to override many methods.
Your case is I guess the customer wants to welcome the auto created batch but also wantsnto split the batch thus, creating new bins.
Your right the client is migrating from SAP WM and they would like to retain their old methods. Can workflow really handle this use case? Have not thought about that. I will try to make a few spins.
I reviewed Workflow documentation and I reckon it more on document Approval. Possibly to create a Workflow State - Create Batch! But then again, I cannot see any functionality that would create Batch from Stock Entry Detail item custom field.
I am thinking that this can be accomplish by a Client Script. Wish me luck, I will share the script here.
I would not recommend to place this code on client side. There will be server functions that will execute and complicate the process.
Here’s what I have to offer:
- Do regular Purchase Receipt. The Item should have Automatic Batch enabled.
- Go to received Stock. Determine Batches and Split them via a Material Transfer of type Split in the receiving warehouse.
- The responsible person will do Material Transfer to incoming quality control warehouse and while doing this, will check QI required check on the Transfer. Here you can put a client script to control source warehouse (incoming) and destination warehouse (quality control) and get this field checked. You can even place a block via client script not to move material to other destinations. That would make better sense.
Here, you would have another problem as to which Template to use for QI.
If you did not find the solution yet, or you might want to refactor, you override the Stock Controller methods implemented in Purchase Receipt. Actually not override but extend it.
There you have full control.
Be careful where the time from creation of Purchase Receipt and submission of that document, clients may tend to do purchase receipts from the same purchase order resulting in an overdelivery error (if you have not enabled it).
The purchase order does not care for the receipts in draft state in terms of delivery balance of their items.
It is working now. I proceeded to create a client script to handle and automate the batch with series taken from item custom field of Purchase Receipt.
would you mind sharing your client code?
Posted below. Modify to fit your need.
// Stock Entry Create Batch Button - Working IPRS 6-digit validation and Batch creation.
frappe.ui.form.on('Stock Entry', {
refresh: function (frm) {
// Check if the Stock Entry is unsaved (docstatus === 0) and type is "Individual Paper Receipt"
if (frm.doc.docstatus === 0 && frm.doc.stock_entry_type === "Individual Paper Receipt") {
// Add the "Create Batch" button to the child table grid
frm.fields_dict.items.grid.add_custom_button(__('Create Batch'), function () {
// Loop through each row in the child table (Stock Entry Detail)
frm.doc.items.forEach((item) => {
// Skip the item if is_finished_item is 0
if (item.is_finished_item === 0) {
return;
}
// Validate iprs_no (must be 6 characters)
if (!item.iprs_no || item.iprs_no.length !== 6) {
frappe.msgprint(__('IPRS No. is not valid for Item No. ') + item.idx);
return;
}
// Generate batch_id as "241212 + iprs_no"
let iprs_no = item.iprs_no;
let batch_id = '241212' + iprs_no;
// Perform batch existence check and creation in sequence
frappe.call({
method: 'frappe.client.get_list',
args: {
doctype: 'Batch',
filters: { batch_id: batch_id },
fields: ['name']
},
callback: function (response) {
if (response.message && response.message.length > 0) {
// Batch exists: link it to the Stock Entry item
frappe.model.set_value(item.doctype, item.name, 'batch_no', batch_id);
frappe.msgprint(__('Batch already exists and linked: ') + batch_id);
} else {
// Batch does not exist: Create a new Batch
frappe.call({
method: 'frappe.client.insert',
args: {
doc: {
doctype: 'Batch',
batch_id: batch_id,
item: item.item_code,
manufacturing_date: frm.doc.posting_date,
is_active: 1,
}
},
callback: function (response) {
if (!response.exc) {
// Update the batch_no field in the Stock Entry Detail row
frappe.model.set_value(item.doctype, item.name, 'batch_no', batch_id);
frappe.msgprint(__('Batch created and linked: ') + batch_id);
} else {
frappe.msgprint(__('Error creating batch: ') + batch_id);
}
}
});
}
}
});
});
}, __('Actions')); // Group button under "Actions"
}
}
});
I would override stock_comtroller or purchase_receipt methods if I were you. Is the client aware of hurdles for reverse transactions when you split at that stage?
It is part of their old system process. What we did is basically provide the client what they need. They received 10 containers of goods (1-Purchase Receipt) then split every containers into individual stock units (2-Stock Entry Repack).