blob: 37f637953692cb762c888c2901abe78c223d66e5 [file] [log] [blame]
Anand Doshi885e0742015-03-03 14:55:30 +05301// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
Rushabh Mehtae67d1fb2013-08-05 14:59:54 +05302// License: GNU General Public License v3. See license.txt
Anand Doshi4279dec2012-12-25 18:35:12 +05303
Faris Ansari1fe891b2021-04-23 08:04:00 +05304erpnext.StockAnalytics = class StockAnalytics extends erpnext.StockGridReport {
5 constructor(wrapper, opts) {
Saurabhb35906e2016-07-02 17:12:22 +05306 var args = {
7 title: __("Stock Analytics"),
Ankush Menatec74a5e2024-03-10 19:45:40 +05308 parent: $(wrapper).find(".layout-main"),
Saurabhb35906e2016-07-02 17:12:22 +05309 page: wrapper.page,
Ankush Menatec74a5e2024-03-10 19:45:40 +053010 doctypes: [
11 "Item",
12 "Item Group",
13 "Warehouse",
14 "Stock Ledger Entry",
15 "Brand",
16 "Fiscal Year",
17 "Serial No",
18 ],
Saurabhb35906e2016-07-02 17:12:22 +053019 tree_grid: {
20 show: true,
21 parent_field: "parent_item_group",
Ankush Menatec74a5e2024-03-10 19:45:40 +053022 formatter: function (item) {
23 if (!item.is_group) {
24 return repl(
25 "<a \
Saurabhb35906e2016-07-02 17:12:22 +053026 onclick='frappe.cur_grid_report.show_stock_ledger(\"%(value)s\")'>\
Ankush Menatec74a5e2024-03-10 19:45:40 +053027 %(value)s</a>",
28 {
Saurabhb35906e2016-07-02 17:12:22 +053029 value: item.name,
Ankush Menatec74a5e2024-03-10 19:45:40 +053030 }
31 );
Rushabh Mehtabe2ee182016-04-29 17:22:42 +053032 } else {
Saurabhb35906e2016-07-02 17:12:22 +053033 return item.name;
Rushabh Mehtabe2ee182016-04-29 17:22:42 +053034 }
Ankush Menatec74a5e2024-03-10 19:45:40 +053035 },
Saurabhb35906e2016-07-02 17:12:22 +053036 },
Ankush Menatec74a5e2024-03-10 19:45:40 +053037 };
Saurabhb35906e2016-07-02 17:12:22 +053038
Ankush Menatec74a5e2024-03-10 19:45:40 +053039 if (opts) $.extend(args, opts);
Saurabhb35906e2016-07-02 17:12:22 +053040
Faris Ansari1fe891b2021-04-23 08:04:00 +053041 super(args);
Faris Ansarif97cc032021-05-07 15:32:06 +053042
43 this.filters = [
Ankush Menatec74a5e2024-03-10 19:45:40 +053044 {
45 fieldtype: "Select",
46 label: __("Value or Qty"),
47 fieldname: "value_or_qty",
48 options: [
49 { label: __("Value"), value: "Value" },
50 { label: __("Quantity"), value: "Quantity" },
51 ],
52 filter: function (val, item, opts, me) {
Faris Ansarif97cc032021-05-07 15:32:06 +053053 return me.apply_zero_filter(val, item, opts, me);
Ankush Menatec74a5e2024-03-10 19:45:40 +053054 },
55 },
56 {
57 fieldtype: "Select",
58 label: __("Brand"),
59 link: "Brand",
60 fieldname: "brand",
61 default_value: __("Select Brand..."),
62 filter: function (val, item, opts) {
Faris Ansarif97cc032021-05-07 15:32:06 +053063 return val == opts.default_value || item.brand == val || item._show;
Ankush Menatec74a5e2024-03-10 19:45:40 +053064 },
65 link_formatter: { filter_input: "brand" },
66 },
67 {
68 fieldtype: "Select",
69 label: __("Warehouse"),
70 link: "Warehouse",
71 fieldname: "warehouse",
72 default_value: __("Select Warehouse..."),
73 },
74 { fieldtype: "Date", label: __("From Date"), fieldname: "from_date" },
75 { fieldtype: "Date", label: __("To Date"), fieldname: "to_date" },
76 {
77 fieldtype: "Select",
78 label: __("Range"),
79 fieldname: "range",
80 options: [
81 { label: __("Daily"), value: "Daily" },
82 { label: __("Weekly"), value: "Weekly" },
83 { label: __("Monthly"), value: "Monthly" },
84 { label: __("Quarterly"), value: "Quarterly" },
85 { label: __("Yearly"), value: "Yearly" },
86 ],
87 },
Faris Ansarif97cc032021-05-07 15:32:06 +053088 ];
Faris Ansari1fe891b2021-04-23 08:04:00 +053089 }
90 setup_columns() {
Saurabhb35906e2016-07-02 17:12:22 +053091 var std_columns = [
Ankush Menatec74a5e2024-03-10 19:45:40 +053092 { id: "name", name: __("Item"), field: "name", width: 300 },
93 { id: "brand", name: __("Brand"), field: "brand", width: 100 },
94 { id: "stock_uom", name: __("UOM"), field: "stock_uom", width: 100 },
95 {
96 id: "opening",
97 name: __("Opening"),
98 field: "opening",
99 hidden: true,
100 formatter: this.currency_formatter,
101 },
Saurabhb35906e2016-07-02 17:12:22 +0530102 ];
103
104 this.make_date_range_columns();
105 this.columns = std_columns.concat(this.columns);
Faris Ansari1fe891b2021-04-23 08:04:00 +0530106 }
107
Faris Ansari1fe891b2021-04-23 08:04:00 +0530108 setup_filters() {
Saurabhb35906e2016-07-02 17:12:22 +0530109 var me = this;
Faris Ansari1fe891b2021-04-23 08:04:00 +0530110 super.setup_filters();
Saurabhb35906e2016-07-02 17:12:22 +0530111
112 this.trigger_refresh_on_change(["value_or_qty", "brand", "warehouse", "range"]);
113
114 this.show_zero_check();
Faris Ansari1fe891b2021-04-23 08:04:00 +0530115 }
116 init_filter_values() {
117 super.init_filter_values();
Ankush Menatec74a5e2024-03-10 19:45:40 +0530118 this.filter_inputs.range && this.filter_inputs.range.val("Monthly");
Faris Ansari1fe891b2021-04-23 08:04:00 +0530119 }
120 prepare_data() {
Saurabhb35906e2016-07-02 17:12:22 +0530121 var me = this;
122
Ankush Menatec74a5e2024-03-10 19:45:40 +0530123 if (!this.data) {
Saurabhb35906e2016-07-02 17:12:22 +0530124 var items = this.prepare_tree("Item", "Item Group");
125
126 me.parent_map = {};
127 me.item_by_name = {};
128 me.data = [];
129
Ankush Menatec74a5e2024-03-10 19:45:40 +0530130 $.each(items, function (i, v) {
Saurabhb35906e2016-07-02 17:12:22 +0530131 var d = copy_dict(v);
132
133 me.data.push(d);
134 me.item_by_name[d.name] = d;
Ankush Menatec74a5e2024-03-10 19:45:40 +0530135 if (d.parent_item_group) {
Saurabhb35906e2016-07-02 17:12:22 +0530136 me.parent_map[d.name] = d.parent_item_group;
137 }
138 me.reset_item_values(d);
139 });
140 this.set_indent();
141 this.data[0].checked = true;
142 } else {
143 // otherwise, only reset values
Ankush Menatec74a5e2024-03-10 19:45:40 +0530144 $.each(this.data, function (i, d) {
Saurabhb35906e2016-07-02 17:12:22 +0530145 me.reset_item_values(d);
146 d["closing_qty_value"] = 0;
147 });
148 }
149
150 this.prepare_balances();
151 this.update_groups();
Faris Ansari1fe891b2021-04-23 08:04:00 +0530152 }
153 prepare_balances() {
Saurabhb35906e2016-07-02 17:12:22 +0530154 var me = this;
Faris Ansariab74ca72017-05-30 12:54:42 +0530155 var from_date = frappe.datetime.str_to_obj(this.from_date);
156 var to_date = frappe.datetime.str_to_obj(this.to_date);
Saurabhb35906e2016-07-02 17:12:22 +0530157 var data = frappe.report_dump.data["Stock Ledger Entry"];
158
159 this.item_warehouse = {};
160 this.serialized_buying_rates = this.get_serialized_buying_rates();
161
Ankush Menatec74a5e2024-03-10 19:45:40 +0530162 for (var i = 0, j = data.length; i < j; i++) {
Deepesh Garg3fa2a8c2023-07-15 18:03:16 +0530163 let diff = 0;
Saurabhb35906e2016-07-02 17:12:22 +0530164 var sl = data[i];
165 sl.posting_datetime = sl.posting_date + " " + sl.posting_time;
Faris Ansariab74ca72017-05-30 12:54:42 +0530166 var posting_datetime = frappe.datetime.str_to_obj(sl.posting_datetime);
Saurabhb35906e2016-07-02 17:12:22 +0530167
Ankush Menatec74a5e2024-03-10 19:45:40 +0530168 if (me.is_default("warehouse") ? true : me.warehouse == sl.warehouse) {
Saurabhb35906e2016-07-02 17:12:22 +0530169 var item = me.item_by_name[sl.item_code];
Ankush Menatec74a5e2024-03-10 19:45:40 +0530170 if (item.closing_qty_value == undefined) item.closing_qty_value = 0;
Saurabhb35906e2016-07-02 17:12:22 +0530171
Ankush Menatec74a5e2024-03-10 19:45:40 +0530172 if (me.value_or_qty != "Quantity") {
Saurabhb35906e2016-07-02 17:12:22 +0530173 var wh = me.get_item_warehouse(sl.warehouse, sl.item_code);
Ankush Menatec74a5e2024-03-10 19:45:40 +0530174 var valuation_method = item.valuation_method
175 ? item.valuation_method
176 : frappe.sys_defaults.valuation_method;
Saurabhb35906e2016-07-02 17:12:22 +0530177 var is_fifo = valuation_method == "FIFO";
178
Ankush Menatec74a5e2024-03-10 19:45:40 +0530179 if (sl.voucher_type == "Stock Reconciliation") {
180 diff = sl.qty_after_transaction * sl.valuation_rate - item.closing_qty_value;
Saurabhb35906e2016-07-02 17:12:22 +0530181 wh.fifo_stack = [[sl.qty_after_transaction, sl.valuation_rate, sl.posting_date]];
182 wh.balance_qty = sl.qty_after_transaction;
183 wh.balance_value = sl.valuation_rate * sl.qty_after_transaction;
184 } else {
Deepesh Garg3fa2a8c2023-07-15 18:03:16 +0530185 diff = me.get_value_diff(wh, sl, is_fifo);
Saurabhb35906e2016-07-02 17:12:22 +0530186 }
187 } else {
Ankush Menatec74a5e2024-03-10 19:45:40 +0530188 if (sl.voucher_type == "Stock Reconciliation") {
Deepesh Garg3fa2a8c2023-07-15 18:03:16 +0530189 diff = sl.qty_after_transaction - item.closing_qty_value;
Saurabhb35906e2016-07-02 17:12:22 +0530190 } else {
Deepesh Garg3fa2a8c2023-07-15 18:03:16 +0530191 diff = sl.qty;
Saurabhb35906e2016-07-02 17:12:22 +0530192 }
193 }
194
Ankush Menatec74a5e2024-03-10 19:45:40 +0530195 if (posting_datetime < from_date) {
Saurabhb35906e2016-07-02 17:12:22 +0530196 item.opening += diff;
Ankush Menatec74a5e2024-03-10 19:45:40 +0530197 } else if (posting_datetime <= to_date) {
Saurabhb35906e2016-07-02 17:12:22 +0530198 item[me.column_map[sl.posting_date].field] += diff;
199 } else {
200 break;
201 }
202
203 item.closing_qty_value += diff;
Rushabh Mehtabe2ee182016-04-29 17:22:42 +0530204 }
Saurabhb35906e2016-07-02 17:12:22 +0530205 }
Faris Ansari1fe891b2021-04-23 08:04:00 +0530206 }
207 update_groups() {
Saurabhb35906e2016-07-02 17:12:22 +0530208 var me = this;
Ankush Menatec74a5e2024-03-10 19:45:40 +0530209 $.each(this.data, function (i, item) {
Saurabhb35906e2016-07-02 17:12:22 +0530210 // update groups
Ankush Menatec74a5e2024-03-10 19:45:40 +0530211 if (!item.is_group && me.apply_filter(item, "brand")) {
Saurabhb35906e2016-07-02 17:12:22 +0530212 var balance = item.opening;
Ankush Menatec74a5e2024-03-10 19:45:40 +0530213 $.each(me.columns, function (i, col) {
214 if (col.formatter == me.currency_formatter && !col.hidden) {
Saurabhb35906e2016-07-02 17:12:22 +0530215 item[col.field] = balance + item[col.field];
216 balance = item[col.field];
217 }
218 });
219
220 var parent = me.parent_map[item.name];
Ankush Menatec74a5e2024-03-10 19:45:40 +0530221 while (parent) {
Faris Ansariab74ca72017-05-30 12:54:42 +0530222 var parent_group = me.item_by_name[parent];
Ankush Menatec74a5e2024-03-10 19:45:40 +0530223 $.each(me.columns, function (c, col) {
Saurabhb35906e2016-07-02 17:12:22 +0530224 if (col.formatter == me.currency_formatter) {
Ankush Menatec74a5e2024-03-10 19:45:40 +0530225 parent_group[col.field] = flt(parent_group[col.field]) + flt(item[col.field]);
Anand Doshi4279dec2012-12-25 18:35:12 +0530226 }
227 });
Saurabhb35906e2016-07-02 17:12:22 +0530228 parent = me.parent_map[parent];
Anand Doshi4279dec2012-12-25 18:35:12 +0530229 }
Saurabhb35906e2016-07-02 17:12:22 +0530230 }
231 });
Faris Ansari1fe891b2021-04-23 08:04:00 +0530232 }
233 show_stock_ledger(item_code) {
Saurabhb35906e2016-07-02 17:12:22 +0530234 frappe.route_options = {
235 item_code: item_code,
236 from_date: this.from_date,
Ankush Menatec74a5e2024-03-10 19:45:40 +0530237 to_date: this.to_date,
Saurabhb35906e2016-07-02 17:12:22 +0530238 };
239 frappe.set_route("query-report", "Stock Ledger");
240 }
Faris Ansari1fe891b2021-04-23 08:04:00 +0530241};