mirror of
https://github.com/frappe/erpnext.git
synced 2026-02-13 09:43:49 +00:00
feat(report): add batch qty update functionality in report
(cherry picked from commit f40c492a05)
This commit is contained in:
committed by
Mergify
parent
40481508f1
commit
57c356a1cd
@@ -0,0 +1,71 @@
|
||||
// Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.query_reports["Stock Qty vs Batch Qty"] = {
|
||||
filters: [
|
||||
{
|
||||
fieldname: "item",
|
||||
label: __("Item"),
|
||||
fieldtype: "Link",
|
||||
options: "Item",
|
||||
get_query: function () {
|
||||
return {
|
||||
filters: { has_batch_no: true },
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldname: "batch",
|
||||
label: __("Batch"),
|
||||
fieldtype: "Link",
|
||||
options: "Batch",
|
||||
get_query: function () {
|
||||
const item_code = frappe.query_report.get_filter_value("item");
|
||||
return {
|
||||
filters: { item: item_code },
|
||||
};
|
||||
},
|
||||
},
|
||||
],
|
||||
onload: function (report) {
|
||||
report.page.add_inner_button(__("Update Batch Qty"), function () {
|
||||
let indexes = frappe.query_report.datatable.rowmanager.getCheckedRows();
|
||||
let selected_rows = indexes
|
||||
.map((i) => frappe.query_report.data[i])
|
||||
.filter((row) => row.difference != 0);
|
||||
|
||||
if (selected_rows.length) {
|
||||
frappe.call({
|
||||
method: "erpnext.stock.report.stock_qty_vs_batch_qty.stock_qty_vs_batch_qty.update_batch_qty",
|
||||
args: {
|
||||
batches: selected_rows,
|
||||
},
|
||||
callback: function (r) {
|
||||
if (!r.exc) {
|
||||
report.refresh();
|
||||
}
|
||||
},
|
||||
});
|
||||
} else {
|
||||
frappe.msgprint(__("Please select at least one row with difference value"));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
formatter: function (value, row, column, data, default_formatter) {
|
||||
value = default_formatter(value, row, column, data);
|
||||
if (column.fieldname == "difference" && data) {
|
||||
if (data.difference > 0) {
|
||||
value = "<span style='color:red'>" + value + "</span>";
|
||||
} else if (data.difference < 0) {
|
||||
value = "<span style='color:red'>" + value + "</span>";
|
||||
}
|
||||
}
|
||||
return value;
|
||||
},
|
||||
get_datatable_options(options) {
|
||||
return Object.assign(options, {
|
||||
checkboxColumn: true,
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"add_total_row": 0,
|
||||
"add_translate_data": 0,
|
||||
"columns": [],
|
||||
"creation": "2025-10-07 20:03:45.952352",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"filters": [],
|
||||
"idx": 0,
|
||||
"is_standard": "Yes",
|
||||
"letterhead": null,
|
||||
"modified": "2025-10-07 20:03:45.952352",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Stock Qty vs Batch Qty",
|
||||
"owner": "Administrator",
|
||||
"prepared_report": 0,
|
||||
"ref_doctype": "Item",
|
||||
"report_name": "Stock Qty vs Batch Qty",
|
||||
"report_type": "Script Report",
|
||||
"roles": [
|
||||
{
|
||||
"role": "Stock Manager"
|
||||
},
|
||||
{
|
||||
"role": "Stock User"
|
||||
}
|
||||
],
|
||||
"timeout": 0
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
# Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
import json
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.query_builder import DocType
|
||||
|
||||
from erpnext.stock.doctype.batch.batch import get_batch_qty
|
||||
|
||||
|
||||
def execute(filters=None):
|
||||
if not filters:
|
||||
filters = {}
|
||||
|
||||
columns = get_columns()
|
||||
data = get_data(filters)
|
||||
|
||||
return columns, data
|
||||
|
||||
|
||||
def get_columns() -> list[dict]:
|
||||
columns = [
|
||||
{
|
||||
"label": _("Item Code"),
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"options": "Item",
|
||||
"width": 200,
|
||||
},
|
||||
{"label": _("Item Name"), "fieldname": "item_name", "fieldtype": "Data", "width": 200},
|
||||
{"label": _("Batch"), "fieldname": "batch", "fieldtype": "Link", "options": "Batch", "width": 200},
|
||||
{"label": _("Batch Qty"), "fieldname": "batch_qty", "fieldtype": "Float", "width": 150},
|
||||
{"label": _("Stock Qty"), "fieldname": "stock_qty", "fieldtype": "Float", "width": 150},
|
||||
{"label": _("Difference"), "fieldname": "difference", "fieldtype": "Float", "width": 150},
|
||||
]
|
||||
|
||||
return columns
|
||||
|
||||
|
||||
def get_data(filters):
|
||||
item_filter = filters.get("item")
|
||||
batch_filter = filters.get("batch")
|
||||
|
||||
Batch = DocType("Batch")
|
||||
|
||||
query = (
|
||||
frappe.qb.from_(Batch)
|
||||
.select(Batch.item.as_("item_code"), Batch.item_name, Batch.batch_qty, Batch.name.as_("batch_no"))
|
||||
.where(Batch.disabled == 0)
|
||||
)
|
||||
|
||||
if item_filter:
|
||||
query = query.where(Batch.item == item_filter)
|
||||
|
||||
if batch_filter:
|
||||
query = query.where(Batch.name == batch_filter)
|
||||
|
||||
batch_list = query.run(as_dict=True)
|
||||
data = []
|
||||
for batch in batch_list:
|
||||
batches = get_batch_qty(batch_no=batch.batch_no)
|
||||
|
||||
if not batches:
|
||||
continue
|
||||
|
||||
batch_qty = batch.get("batch_qty", 0)
|
||||
actual_qty = sum(b.get("qty", 0) for b in batches)
|
||||
|
||||
difference = batch_qty - actual_qty
|
||||
|
||||
row = {
|
||||
"item_code": batch.item_code,
|
||||
"item_name": batch.item_name,
|
||||
"batch": batch.batch_no,
|
||||
"batch_qty": batch_qty,
|
||||
"stock_qty": actual_qty,
|
||||
"difference": difference,
|
||||
}
|
||||
|
||||
data.append(row)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def update_batch_qty(batches=None):
|
||||
if not batches:
|
||||
return
|
||||
|
||||
batches = json.loads(batches)
|
||||
for batch in batches:
|
||||
batch_name = batch.get("batch")
|
||||
stock_qty = batch.get("stock_qty")
|
||||
|
||||
frappe.db.set_value("Batch", batch_name, "batch_qty", stock_qty)
|
||||
|
||||
frappe.msgprint(_("Batch Qty updated successfully"), alert=True)
|
||||
Reference in New Issue
Block a user