blob: 36a51056bb45ee6758ce6583de00506ad8376c82 [file] [log] [blame]
Ankush Menatec74a5e2024-03-10 19:45:40 +05301frappe.provide("erpnext.stock");
Rushabh Mehta3d2622c2016-04-25 17:53:42 +05302
Faris Ansari1fe891b2021-04-23 08:04:00 +05303erpnext.stock.ItemDashboard = class ItemDashboard {
4 constructor(opts) {
Rushabh Mehta3d2622c2016-04-25 17:53:42 +05305 $.extend(this, opts);
6 this.make();
Faris Ansari1fe891b2021-04-23 08:04:00 +05307 }
8 make() {
Rushabh Mehta3d2622c2016-04-25 17:53:42 +05309 var me = this;
10 this.start = 0;
Anurag Mishraabf974d2021-03-17 18:40:21 +053011 if (!this.sort_by) {
Ankush Menatec74a5e2024-03-10 19:45:40 +053012 this.sort_by = "projected_qty";
13 this.sort_order = "asc";
Rushabh Mehta3d2622c2016-04-25 17:53:42 +053014 }
15
Ankush Menatec74a5e2024-03-10 19:45:40 +053016 this.content = $(frappe.render_template("item_dashboard")).appendTo(this.parent);
17 this.result = this.content.find(".result");
Rushabh Mehta3d2622c2016-04-25 17:53:42 +053018
Ankush Menatec74a5e2024-03-10 19:45:40 +053019 this.content.on("click", ".btn-move", function () {
Anurag Mishraabf974d2021-03-17 18:40:21 +053020 handle_move_add($(this), "Move");
Shivam Mishra38b930b2019-07-05 10:38:48 +053021 });
22
Ankush Menatec74a5e2024-03-10 19:45:40 +053023 this.content.on("click", ".btn-add", function () {
Anurag Mishraabf974d2021-03-17 18:40:21 +053024 handle_move_add($(this), "Add");
Shivam Mishra5738c932019-07-16 12:52:19 +053025 });
26
Ankush Menatec74a5e2024-03-10 19:45:40 +053027 this.content.on("click", ".btn-edit", function () {
28 let item = unescape($(this).attr("data-item"));
29 let warehouse = unescape($(this).attr("data-warehouse"));
30 let company = unescape($(this).attr("data-company"));
31 frappe.db.get_value(
32 "Putaway Rule",
33 {
34 item_code: item,
35 warehouse: warehouse,
36 company: company,
37 },
38 "name",
39 (r) => {
40 frappe.set_route("Form", "Putaway Rule", r.name);
41 }
42 );
marination1087d972020-11-26 10:45:44 +053043 });
44
Shivam Mishra5738c932019-07-16 12:52:19 +053045 function handle_move_add(element, action) {
Ankush Menatec74a5e2024-03-10 19:45:40 +053046 let item = unescape(element.attr("data-item"));
47 let warehouse = unescape(element.attr("data-warehouse"));
48 let actual_qty = unescape(element.attr("data-actual_qty"));
49 let disable_quick_entry = Number(unescape(element.attr("data-disable_quick_entry")));
s-aga-rdc0ddf82023-02-03 18:08:34 +053050 let entry_type = action === "Move" ? "Material Transfer" : "Material Receipt";
Shivam Mishra444091b2019-07-10 10:22:08 +053051
Shivam Mishrafd6ff622019-07-16 12:32:50 +053052 if (disable_quick_entry) {
Shivam Mishra5738c932019-07-16 12:52:19 +053053 open_stock_entry(item, warehouse, entry_type);
Shivam Mishrafd6ff622019-07-16 12:32:50 +053054 } else {
Shivam Mishra5738c932019-07-16 12:52:19 +053055 if (action === "Add") {
Ankush Menatec74a5e2024-03-10 19:45:40 +053056 let rate = unescape($(this).attr("data-rate"));
Anurag Mishraabf974d2021-03-17 18:40:21 +053057 erpnext.stock.move_item(item, null, warehouse, actual_qty, rate, function () {
58 me.refresh();
59 });
60 } else {
61 erpnext.stock.move_item(item, warehouse, null, actual_qty, null, function () {
62 me.refresh();
63 });
Shivam Mishra5738c932019-07-16 12:52:19 +053064 }
Shivam Mishrafd6ff622019-07-16 12:32:50 +053065 }
Shivam Mishra5738c932019-07-16 12:52:19 +053066 }
Shivam Mishra38b930b2019-07-05 10:38:48 +053067
68 function open_stock_entry(item, warehouse, entry_type) {
Ankush Menatec74a5e2024-03-10 19:45:40 +053069 frappe.model.with_doctype("Stock Entry", function () {
70 var doc = frappe.model.get_new_doc("Stock Entry");
s-aga-rdc0ddf82023-02-03 18:08:34 +053071 if (entry_type) {
72 doc.stock_entry_type = entry_type;
73 }
Shivam Mishra38b930b2019-07-05 10:38:48 +053074
Ankush Menatec74a5e2024-03-10 19:45:40 +053075 var row = frappe.model.add_child(doc, "items");
Shivam Mishra38b930b2019-07-05 10:38:48 +053076 row.item_code = item;
s-aga-rdc0ddf82023-02-03 18:08:34 +053077
78 if (entry_type === "Material Transfer") {
79 row.s_warehouse = warehouse;
Ankush Menatec74a5e2024-03-10 19:45:40 +053080 } else {
s-aga-rdc0ddf82023-02-03 18:08:34 +053081 row.t_warehouse = warehouse;
82 }
Shivam Mishra38b930b2019-07-05 10:38:48 +053083
Ankush Menatec74a5e2024-03-10 19:45:40 +053084 frappe.set_route("Form", doc.doctype, doc.name);
Anurag Mishraabf974d2021-03-17 18:40:21 +053085 });
Shivam Mishra38b930b2019-07-05 10:38:48 +053086 }
87
Rushabh Mehta3d2622c2016-04-25 17:53:42 +053088 // more
Ankush Menatec74a5e2024-03-10 19:45:40 +053089 this.content.find(".btn-more").on("click", function () {
marinationa5d8d322020-12-09 16:27:18 +053090 me.start += me.page_length;
Rushabh Mehta3d2622c2016-04-25 17:53:42 +053091 me.refresh();
92 });
Faris Ansari1fe891b2021-04-23 08:04:00 +053093 }
94 refresh() {
Ankush Menatec74a5e2024-03-10 19:45:40 +053095 if (this.before_refresh) {
Rushabh Mehta3d2622c2016-04-25 17:53:42 +053096 this.before_refresh();
97 }
98
marination1087d972020-11-26 10:45:44 +053099 let args = {
100 item_code: this.item_code,
101 warehouse: this.warehouse,
102 parent_warehouse: this.parent_warehouse,
103 item_group: this.item_group,
104 company: this.company,
105 start: this.start,
106 sort_by: this.sort_by,
Ankush Menatec74a5e2024-03-10 19:45:40 +0530107 sort_order: this.sort_order,
marination0f3cfc52020-12-08 19:11:51 +0530108 };
marination1087d972020-11-26 10:45:44 +0530109
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530110 var me = this;
111 frappe.call({
marination1087d972020-11-26 10:45:44 +0530112 method: this.method,
113 args: args,
Anurag Mishraabf974d2021-03-17 18:40:21 +0530114 callback: function (r) {
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530115 me.render(r.message);
Ankush Menatec74a5e2024-03-10 19:45:40 +0530116 if (me.after_refresh) {
Devin Slauenwhite123920d2022-12-29 00:01:26 -0500117 me.after_refresh();
118 }
Ankush Menatec74a5e2024-03-10 19:45:40 +0530119 },
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530120 });
Faris Ansari1fe891b2021-04-23 08:04:00 +0530121 }
122 render(data) {
Ankush Menatec74a5e2024-03-10 19:45:40 +0530123 if (this.start === 0) {
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530124 this.max_count = 0;
125 this.result.empty();
126 }
127
marination0f3cfc52020-12-08 19:11:51 +0530128 let context = "";
marination1087d972020-11-26 10:45:44 +0530129 if (this.page_name === "warehouse-capacity-summary") {
marination0f3cfc52020-12-08 19:11:51 +0530130 context = this.get_capacity_dashboard_data(data);
marination1087d972020-11-26 10:45:44 +0530131 } else {
marination0f3cfc52020-12-08 19:11:51 +0530132 context = this.get_item_dashboard_data(data, this.max_count, true);
marination1087d972020-11-26 10:45:44 +0530133 }
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530134
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530135 // show more button
Ankush Menatec74a5e2024-03-10 19:45:40 +0530136 if (data && data.length === this.page_length + 1) {
137 this.content.find(".more").removeClass("hidden");
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530138
139 // remove the last element
140 data.splice(-1);
141 } else {
Ankush Menatec74a5e2024-03-10 19:45:40 +0530142 this.content.find(".more").addClass("hidden");
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530143 }
144
Vinayak Jethe2c8ce5a2018-01-24 13:51:26 +0530145 // If not any stock in any warehouses provide a message to end user
Stavros Anastasiadis58b58782017-10-05 16:14:50 +0300146 if (context.data.length > 0) {
Ankush Menatec74a5e2024-03-10 19:45:40 +0530147 this.content.find(".result").css("text-align", "unset");
marination1087d972020-11-26 10:45:44 +0530148 $(frappe.render_template(this.template, context)).appendTo(this.result);
Stavros Anastasiadis58b58782017-10-05 16:14:50 +0300149 } else {
marination1087d972020-11-26 10:45:44 +0530150 var message = __("No Stock Available Currently");
Ankush Menatec74a5e2024-03-10 19:45:40 +0530151 this.content.find(".result").css("text-align", "center");
marination1087d972020-11-26 10:45:44 +0530152
marinationa97eb6a2021-02-07 22:27:40 +0530153 $(`<div class='text-muted' style='margin: 20px 5px;'>
marination1087d972020-11-26 10:45:44 +0530154 ${message} </div>`).appendTo(this.result);
Stavros Anastasiadis58b58782017-10-05 16:14:50 +0300155 }
Faris Ansari1fe891b2021-04-23 08:04:00 +0530156 }
marination1087d972020-11-26 10:45:44 +0530157
Faris Ansari1fe891b2021-04-23 08:04:00 +0530158 get_item_dashboard_data(data, max_count, show_item) {
Ankush Menatec74a5e2024-03-10 19:45:40 +0530159 if (!max_count) max_count = 0;
160 if (!data) data = [];
Vinayak Jethe549c1962018-01-24 19:47:59 +0530161
Anurag Mishraabf974d2021-03-17 18:40:21 +0530162 data.forEach(function (d) {
Ankush Menatec74a5e2024-03-10 19:45:40 +0530163 d.actual_or_pending =
164 d.projected_qty +
165 d.reserved_qty +
166 d.reserved_qty_for_production +
167 d.reserved_qty_for_sub_contract;
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530168 d.pending_qty = 0;
Ankush Menatec74a5e2024-03-10 19:45:40 +0530169 d.total_reserved =
170 d.reserved_qty + d.reserved_qty_for_production + d.reserved_qty_for_sub_contract;
Anurag Mishraabf974d2021-03-17 18:40:21 +0530171 if (d.actual_or_pending > d.actual_qty) {
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530172 d.pending_qty = d.actual_or_pending - d.actual_qty;
173 }
174
Ankush Menatec74a5e2024-03-10 19:45:40 +0530175 max_count = Math.max(d.actual_or_pending, d.actual_qty, d.total_reserved, max_count);
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530176 });
Vinayak Jethe549c1962018-01-24 19:47:59 +0530177
marination1087d972020-11-26 10:45:44 +0530178 let can_write = 0;
marination0f3cfc52020-12-08 19:11:51 +0530179 if (frappe.boot.user.can_write.indexOf("Stock Entry") >= 0) {
Vinayak Jethe549c1962018-01-24 19:47:59 +0530180 can_write = 1;
181 }
182
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530183 return {
184 data: data,
185 max_count: max_count,
Anurag Mishraabf974d2021-03-17 18:40:21 +0530186 can_write: can_write,
Ankush Menatec74a5e2024-03-10 19:45:40 +0530187 show_item: show_item || false,
marinationb8aeb9e2021-01-05 12:16:25 +0530188 };
Faris Ansari1fe891b2021-04-23 08:04:00 +0530189 }
marination1087d972020-11-26 10:45:44 +0530190
Faris Ansari1fe891b2021-04-23 08:04:00 +0530191 get_capacity_dashboard_data(data) {
marination0f3cfc52020-12-08 19:11:51 +0530192 if (!data) data = [];
marination1087d972020-11-26 10:45:44 +0530193
Anurag Mishraabf974d2021-03-17 18:40:21 +0530194 data.forEach(function (d) {
195 d.color = d.percent_occupied >= 80 ? "#f8814f" : "#2490ef";
marination1087d972020-11-26 10:45:44 +0530196 });
197
198 let can_write = 0;
marination0f3cfc52020-12-08 19:11:51 +0530199 if (frappe.boot.user.can_write.indexOf("Putaway Rule") >= 0) {
marination1087d972020-11-26 10:45:44 +0530200 can_write = 1;
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530201 }
marination1087d972020-11-26 10:45:44 +0530202
203 return {
204 data: data,
205 can_write: can_write,
marination0f3cfc52020-12-08 19:11:51 +0530206 };
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530207 }
Faris Ansari1fe891b2021-04-23 08:04:00 +0530208};
Shivam Mishra444091b2019-07-10 10:22:08 +0530209
Anurag Mishraabf974d2021-03-17 18:40:21 +0530210erpnext.stock.move_item = function (item, source, target, actual_qty, rate, callback) {
Shivam Mishra444091b2019-07-10 10:22:08 +0530211 var dialog = new frappe.ui.Dialog({
Ankush Menatec74a5e2024-03-10 19:45:40 +0530212 title: target ? __("Add Item") : __("Move Item"),
213 fields: [
214 {
215 fieldname: "item_code",
216 label: __("Item"),
217 fieldtype: "Link",
218 options: "Item",
219 read_only: 1,
220 },
221 {
222 fieldname: "source",
223 label: __("Source Warehouse"),
224 fieldtype: "Link",
225 options: "Warehouse",
226 read_only: 1,
227 },
228 {
229 fieldname: "target",
230 label: __("Target Warehouse"),
231 fieldtype: "Link",
232 options: "Warehouse",
233 reqd: 1,
234 get_query() {
235 return {
236 filters: {
237 is_group: 0,
238 },
239 };
240 },
241 },
242 {
243 fieldname: "qty",
244 label: __("Quantity"),
245 reqd: 1,
246 fieldtype: "Float",
247 description: __("Available {0}", [actual_qty]),
248 },
249 {
250 fieldname: "rate",
251 label: __("Rate"),
252 fieldtype: "Currency",
253 hidden: 1,
254 },
Shivam Mishra444091b2019-07-10 10:22:08 +0530255 ],
Anurag Mishraabf974d2021-03-17 18:40:21 +0530256 });
Shivam Mishra444091b2019-07-10 10:22:08 +0530257 dialog.show();
Ankush Menatec74a5e2024-03-10 19:45:40 +0530258 dialog.get_field("item_code").set_input(item);
Shivam Mishra444091b2019-07-10 10:22:08 +0530259
Anurag Mishraabf974d2021-03-17 18:40:21 +0530260 if (source) {
Ankush Menatec74a5e2024-03-10 19:45:40 +0530261 dialog.get_field("source").set_input(source);
Shivam Mishra444091b2019-07-10 10:22:08 +0530262 } else {
Ankush Menatec74a5e2024-03-10 19:45:40 +0530263 dialog.get_field("source").df.hidden = 1;
264 dialog.get_field("source").refresh();
Shivam Mishra444091b2019-07-10 10:22:08 +0530265 }
266
Anurag Mishraabf974d2021-03-17 18:40:21 +0530267 if (rate) {
Ankush Menatec74a5e2024-03-10 19:45:40 +0530268 dialog.get_field("rate").set_value(rate);
269 dialog.get_field("rate").df.hidden = 0;
270 dialog.get_field("rate").refresh();
Shivam Mishra444091b2019-07-10 10:22:08 +0530271 }
272
Anurag Mishraabf974d2021-03-17 18:40:21 +0530273 if (target) {
Ankush Menatec74a5e2024-03-10 19:45:40 +0530274 dialog.get_field("target").df.read_only = 1;
275 dialog.get_field("target").value = target;
276 dialog.get_field("target").refresh();
Shivam Mishra444091b2019-07-10 10:22:08 +0530277 }
278
Ankush Menatec74a5e2024-03-10 19:45:40 +0530279 dialog.set_primary_action(__("Create Stock Entry"), function () {
Devin Slauenwhitecdf631b2022-06-29 02:36:47 -0400280 if (source && (dialog.get_value("qty") == 0 || dialog.get_value("qty") > actual_qty)) {
281 frappe.msgprint(__("Quantity must be greater than zero, and less or equal to {0}", [actual_qty]));
282 return;
283 }
284
285 if (dialog.get_value("source") === dialog.get_value("target")) {
286 frappe.msgprint(__("Source and target warehouse must be different"));
287 return;
288 }
289
Ankush Menatec74a5e2024-03-10 19:45:40 +0530290 frappe.model.with_doctype("Stock Entry", function () {
291 let doc = frappe.model.get_new_doc("Stock Entry");
292 doc.from_warehouse = dialog.get_value("source");
293 doc.to_warehouse = dialog.get_value("target");
Ankush Menat0bed5922022-01-26 01:01:33 +0530294 doc.stock_entry_type = doc.from_warehouse ? "Material Transfer" : "Material Receipt";
Ankush Menatec74a5e2024-03-10 19:45:40 +0530295 let row = frappe.model.add_child(doc, "items");
296 row.item_code = dialog.get_value("item_code");
297 row.s_warehouse = dialog.get_value("source");
298 row.t_warehouse = dialog.get_value("target");
299 row.qty = dialog.get_value("qty");
Ankush Menat0bed5922022-01-26 01:01:33 +0530300 row.conversion_factor = 1;
Ankush Menatec74a5e2024-03-10 19:45:40 +0530301 row.transfer_qty = dialog.get_value("qty");
302 row.basic_rate = dialog.get_value("rate");
303 frappe.set_route("Form", doc.doctype, doc.name);
Shivam Mishra444091b2019-07-10 10:22:08 +0530304 });
305 });
Anurag Mishraabf974d2021-03-17 18:40:21 +0530306};