chore: fifo queue vs qty after transaction comparison report
This commit is contained in:
parent
e2e0700499
commit
f6d6463a33
@ -0,0 +1,53 @@
|
|||||||
|
// Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
const DIFFERNCE_FIELD_NAMES = [
|
||||||
|
"fifo_qty_diff",
|
||||||
|
"fifo_value_diff",
|
||||||
|
];
|
||||||
|
|
||||||
|
frappe.query_reports["FIFO Queue vs Qty After Transaction Comparison"] = {
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"fieldname": "item_code",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Item",
|
||||||
|
"options": "Item",
|
||||||
|
get_query: function() {
|
||||||
|
return {
|
||||||
|
filters: {is_stock_item: 1, has_serial_no: 0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "item_group",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Item Group",
|
||||||
|
"options": "Item Group",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "warehouse",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Warehouse",
|
||||||
|
"options": "Warehouse",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "from_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"label": "From Posting Date",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "to_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"label": "From Posting Date",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
formatter (value, row, column, data, default_formatter) {
|
||||||
|
value = default_formatter(value, row, column, data);
|
||||||
|
if (DIFFERNCE_FIELD_NAMES.includes(column.fieldname) && Math.abs(data[column.fieldname]) > 0.001) {
|
||||||
|
value = "<span style='color:red'>" + value + "</span>";
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
};
|
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"add_total_row": 0,
|
||||||
|
"columns": [],
|
||||||
|
"creation": "2022-05-11 04:09:13.460652",
|
||||||
|
"disable_prepared_report": 0,
|
||||||
|
"disabled": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Report",
|
||||||
|
"filters": [],
|
||||||
|
"idx": 0,
|
||||||
|
"is_standard": "Yes",
|
||||||
|
"letter_head": "abc",
|
||||||
|
"modified": "2022-05-11 04:09:20.232177",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Stock",
|
||||||
|
"name": "FIFO Queue vs Qty After Transaction Comparison",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"prepared_report": 0,
|
||||||
|
"ref_doctype": "Stock Ledger Entry",
|
||||||
|
"report_name": "FIFO Queue vs Qty After Transaction Comparison",
|
||||||
|
"report_type": "Script Report",
|
||||||
|
"roles": [
|
||||||
|
{
|
||||||
|
"role": "Administrator"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,212 @@
|
|||||||
|
# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
from frappe.utils import flt
|
||||||
|
from frappe.utils.nestedset import get_descendants_of
|
||||||
|
|
||||||
|
SLE_FIELDS = (
|
||||||
|
"name",
|
||||||
|
"item_code",
|
||||||
|
"warehouse",
|
||||||
|
"posting_date",
|
||||||
|
"posting_time",
|
||||||
|
"creation",
|
||||||
|
"voucher_type",
|
||||||
|
"voucher_no",
|
||||||
|
"actual_qty",
|
||||||
|
"qty_after_transaction",
|
||||||
|
"stock_queue",
|
||||||
|
"batch_no",
|
||||||
|
"stock_value",
|
||||||
|
"valuation_rate",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def execute(filters=None):
|
||||||
|
columns = get_columns()
|
||||||
|
data = get_data(filters)
|
||||||
|
return columns, data
|
||||||
|
|
||||||
|
|
||||||
|
def get_data(filters):
|
||||||
|
if not any([filters.warehouse, filters.item_code, filters.item_group]):
|
||||||
|
frappe.throw(_("Any one of following filters required: warehouse, Item Code, Item Group"))
|
||||||
|
sles = get_stock_ledger_entries(filters)
|
||||||
|
return find_first_bad_queue(sles)
|
||||||
|
|
||||||
|
|
||||||
|
def get_stock_ledger_entries(filters):
|
||||||
|
|
||||||
|
sle_filters = {"is_cancelled": 0}
|
||||||
|
|
||||||
|
if filters.warehouse:
|
||||||
|
children = get_descendants_of("Warehouse", filters.warehouse)
|
||||||
|
sle_filters["warehouse"] = ("in", children + [filters.warehouse])
|
||||||
|
|
||||||
|
if filters.item_code:
|
||||||
|
sle_filters["item_code"] = filters.item_code
|
||||||
|
elif filters.get("item_group"):
|
||||||
|
item_group = filters.get("item_group")
|
||||||
|
children = get_descendants_of("Item Group", item_group)
|
||||||
|
item_group_filter = {"item_group": ("in", children + [item_group])}
|
||||||
|
sle_filters["item_code"] = (
|
||||||
|
"in",
|
||||||
|
frappe.get_all("Item", filters=item_group_filter, pluck="name", order_by=None),
|
||||||
|
)
|
||||||
|
|
||||||
|
if filters.from_date:
|
||||||
|
sle_filters["posting_date"] = (">=", filters.from_date)
|
||||||
|
if filters.to_date:
|
||||||
|
sle_filters["posting_date"] = ("<=", filters.to_date)
|
||||||
|
|
||||||
|
return frappe.get_all(
|
||||||
|
"Stock Ledger Entry",
|
||||||
|
fields=SLE_FIELDS,
|
||||||
|
filters=sle_filters,
|
||||||
|
order_by="timestamp(posting_date, posting_time), creation",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def find_first_bad_queue(sles):
|
||||||
|
item_warehouse_sles = {}
|
||||||
|
for sle in sles:
|
||||||
|
item_warehouse_sles.setdefault((sle.item_code, sle.warehouse), []).append(sle)
|
||||||
|
|
||||||
|
data = []
|
||||||
|
|
||||||
|
for _item_wh, sles in item_warehouse_sles.items():
|
||||||
|
for idx, sle in enumerate(sles):
|
||||||
|
queue = json.loads(sle.stock_queue or "[]")
|
||||||
|
|
||||||
|
sle.fifo_queue_qty = 0.0
|
||||||
|
sle.fifo_stock_value = 0.0
|
||||||
|
for qty, rate in queue:
|
||||||
|
sle.fifo_queue_qty += flt(qty)
|
||||||
|
sle.fifo_stock_value += flt(qty) * flt(rate)
|
||||||
|
|
||||||
|
sle.fifo_qty_diff = sle.qty_after_transaction - sle.fifo_queue_qty
|
||||||
|
sle.fifo_value_diff = sle.stock_value - sle.fifo_stock_value
|
||||||
|
|
||||||
|
if sle.batch_no:
|
||||||
|
sle.use_batchwise_valuation = frappe.db.get_value(
|
||||||
|
"Batch", sle.batch_no, "use_batchwise_valuation", cache=True
|
||||||
|
)
|
||||||
|
|
||||||
|
if abs(sle.fifo_qty_diff) > 0.001 or abs(sle.fifo_value_diff) > 0.1:
|
||||||
|
if idx:
|
||||||
|
data.append(sles[idx - 1])
|
||||||
|
data.append(sle)
|
||||||
|
data.append({})
|
||||||
|
break
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def get_columns():
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"fieldname": "name",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": _("Stock Ledger Entry"),
|
||||||
|
"options": "Stock Ledger Entry",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "item_code",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": _("Item Code"),
|
||||||
|
"options": "Item",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "warehouse",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": _("Warehouse"),
|
||||||
|
"options": "Warehouse",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "posting_date",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": _("Posting Date"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "posting_time",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": _("Posting Time"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "creation",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": _("Creation"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "voucher_type",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": _("Voucher Type"),
|
||||||
|
"options": "DocType",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "voucher_no",
|
||||||
|
"fieldtype": "Dynamic Link",
|
||||||
|
"label": _("Voucher No"),
|
||||||
|
"options": "voucher_type",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "batch_no",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": _("Batch"),
|
||||||
|
"options": "Batch",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "use_batchwise_valuation",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": _("Batchwise Valuation"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "actual_qty",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": _("Qty Change"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "qty_after_transaction",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": _("(A) Qty After Transaction"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "stock_queue",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": _("FIFO/LIFO Queue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "fifo_queue_qty",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": _("(C) Total qty in queue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "fifo_qty_diff",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": _("A - C"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "stock_value",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": _("(D) Balance Stock Value"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "fifo_stock_value",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": _("(E) Balance Stock Value in Queue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "fifo_value_diff",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": _("D - E"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "valuation_rate",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": _("(H) Valuation Rate"),
|
||||||
|
},
|
||||||
|
]
|
@ -65,6 +65,8 @@ REPORT_FILTER_TEST_CASES: List[Tuple[ReportName, ReportFilters]] = [
|
|||||||
("Delayed Item Report", {"based_on": "Delivery Note"}),
|
("Delayed Item Report", {"based_on": "Delivery Note"}),
|
||||||
("Stock Ageing", {"range1": 30, "range2": 60, "range3": 90, "_optional": True}),
|
("Stock Ageing", {"range1": 30, "range2": 60, "range3": 90, "_optional": True}),
|
||||||
("Stock Ledger Invariant Check", {"warehouse": "_Test Warehouse - _TC", "item": "_Test Item"}),
|
("Stock Ledger Invariant Check", {"warehouse": "_Test Warehouse - _TC", "item": "_Test Item"}),
|
||||||
|
("FIFO Queue vs Qty After Transaction Comparison", {"warehouse": "_Test Warehouse - _TC"}),
|
||||||
|
("FIFO Queue vs Qty After Transaction Comparison", {"item_group": "All Item Groups"}),
|
||||||
]
|
]
|
||||||
|
|
||||||
OPTIONAL_FILTERS = {
|
OPTIONAL_FILTERS = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user