blob: dfb9e44283cecefe0a0d56abd874c72e6b84ce9c [file] [log] [blame]
Rushabh Mehta3d2622c2016-04-25 17:53:42 +05301frappe.provide('erpnext.stock');
2
3erpnext.stock.ItemDashboard = Class.extend({
Anurag Mishraabf974d2021-03-17 18:40:21 +05304 init: function (opts) {
Rushabh Mehta3d2622c2016-04-25 17:53:42 +05305 $.extend(this, opts);
6 this.make();
7 },
Anurag Mishraabf974d2021-03-17 18:40:21 +05308 make: function () {
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) {
Rushabh Mehta3d2622c2016-04-25 17:53:42 +053012 this.sort_by = 'projected_qty';
13 this.sort_order = 'asc';
14 }
15
16 this.content = $(frappe.render_template('item_dashboard')).appendTo(this.parent);
17 this.result = this.content.find('.result');
18
Anurag Mishraabf974d2021-03-17 18:40:21 +053019 this.content.on('click', '.btn-move', function () {
20 handle_move_add($(this), "Move");
Shivam Mishra38b930b2019-07-05 10:38:48 +053021 });
22
Anurag Mishraabf974d2021-03-17 18:40:21 +053023 this.content.on('click', '.btn-add', function () {
24 handle_move_add($(this), "Add");
Shivam Mishra5738c932019-07-16 12:52:19 +053025 });
26
Anurag Mishraabf974d2021-03-17 18:40:21 +053027 this.content.on('click', '.btn-edit', function () {
marination1087d972020-11-26 10:45:44 +053028 let item = unescape($(this).attr('data-item'));
29 let warehouse = unescape($(this).attr('data-warehouse'));
30 let company = unescape($(this).attr('data-company'));
Anurag Mishraabf974d2021-03-17 18:40:21 +053031 frappe.db.get_value('Putaway Rule', {
32 'item_code': item,
33 'warehouse': warehouse,
34 'company': company
35 }, 'name', (r) => {
36 frappe.set_route("Form", "Putaway Rule", r.name);
37 });
marination1087d972020-11-26 10:45:44 +053038 });
39
Shivam Mishra5738c932019-07-16 12:52:19 +053040 function handle_move_add(element, action) {
41 let item = unescape(element.attr('data-item'));
42 let warehouse = unescape(element.attr('data-warehouse'));
43 let actual_qty = unescape(element.attr('data-actual_qty'));
44 let disable_quick_entry = Number(unescape(element.attr('data-disable_quick_entry')));
Anurag Mishraabf974d2021-03-17 18:40:21 +053045 let entry_type = action === "Move" ? "Material Transfer" : null;
Shivam Mishra444091b2019-07-10 10:22:08 +053046
Shivam Mishrafd6ff622019-07-16 12:32:50 +053047 if (disable_quick_entry) {
Shivam Mishra5738c932019-07-16 12:52:19 +053048 open_stock_entry(item, warehouse, entry_type);
Shivam Mishrafd6ff622019-07-16 12:32:50 +053049 } else {
Shivam Mishra5738c932019-07-16 12:52:19 +053050 if (action === "Add") {
51 let rate = unescape($(this).attr('data-rate'));
Anurag Mishraabf974d2021-03-17 18:40:21 +053052 erpnext.stock.move_item(item, null, warehouse, actual_qty, rate, function () {
53 me.refresh();
54 });
55 } else {
56 erpnext.stock.move_item(item, warehouse, null, actual_qty, null, function () {
57 me.refresh();
58 });
Shivam Mishra5738c932019-07-16 12:52:19 +053059 }
Shivam Mishrafd6ff622019-07-16 12:32:50 +053060 }
Shivam Mishra5738c932019-07-16 12:52:19 +053061 }
Shivam Mishra38b930b2019-07-05 10:38:48 +053062
63 function open_stock_entry(item, warehouse, entry_type) {
Anurag Mishraabf974d2021-03-17 18:40:21 +053064 frappe.model.with_doctype('Stock Entry', function () {
Shivam Mishra38b930b2019-07-05 10:38:48 +053065 var doc = frappe.model.get_new_doc('Stock Entry');
66 if (entry_type) doc.stock_entry_type = entry_type;
67
68 var row = frappe.model.add_child(doc, 'items');
69 row.item_code = item;
70 row.s_warehouse = warehouse;
71
72 frappe.set_route('Form', doc.doctype, doc.name);
Anurag Mishraabf974d2021-03-17 18:40:21 +053073 });
Shivam Mishra38b930b2019-07-05 10:38:48 +053074 }
75
Rushabh Mehta3d2622c2016-04-25 17:53:42 +053076 // more
Anurag Mishraabf974d2021-03-17 18:40:21 +053077 this.content.find('.btn-more').on('click', function () {
marinationa5d8d322020-12-09 16:27:18 +053078 me.start += me.page_length;
Rushabh Mehta3d2622c2016-04-25 17:53:42 +053079 me.refresh();
80 });
81
82 },
Anurag Mishraabf974d2021-03-17 18:40:21 +053083 refresh: function () {
84 if (this.before_refresh) {
Rushabh Mehta3d2622c2016-04-25 17:53:42 +053085 this.before_refresh();
86 }
87
marination1087d972020-11-26 10:45:44 +053088 let args = {
89 item_code: this.item_code,
90 warehouse: this.warehouse,
91 parent_warehouse: this.parent_warehouse,
92 item_group: this.item_group,
93 company: this.company,
94 start: this.start,
95 sort_by: this.sort_by,
96 sort_order: this.sort_order
marination0f3cfc52020-12-08 19:11:51 +053097 };
marination1087d972020-11-26 10:45:44 +053098
Rushabh Mehta3d2622c2016-04-25 17:53:42 +053099 var me = this;
100 frappe.call({
marination1087d972020-11-26 10:45:44 +0530101 method: this.method,
102 args: args,
Anurag Mishraabf974d2021-03-17 18:40:21 +0530103 callback: function (r) {
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530104 me.render(r.message);
105 }
106 });
107 },
Anurag Mishraabf974d2021-03-17 18:40:21 +0530108 render: function (data) {
109 if (this.start === 0) {
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530110 this.max_count = 0;
111 this.result.empty();
112 }
113
marination0f3cfc52020-12-08 19:11:51 +0530114 let context = "";
marination1087d972020-11-26 10:45:44 +0530115 if (this.page_name === "warehouse-capacity-summary") {
marination0f3cfc52020-12-08 19:11:51 +0530116 context = this.get_capacity_dashboard_data(data);
marination1087d972020-11-26 10:45:44 +0530117 } else {
marination0f3cfc52020-12-08 19:11:51 +0530118 context = this.get_item_dashboard_data(data, this.max_count, true);
marination1087d972020-11-26 10:45:44 +0530119 }
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530120
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530121 this.max_count = this.max_count;
122
123 // show more button
Anurag Mishraabf974d2021-03-17 18:40:21 +0530124 if (data && data.length === (this.page_length + 1)) {
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530125 this.content.find('.more').removeClass('hidden');
126
127 // remove the last element
128 data.splice(-1);
129 } else {
130 this.content.find('.more').addClass('hidden');
131 }
132
Vinayak Jethe2c8ce5a2018-01-24 13:51:26 +0530133 // If not any stock in any warehouses provide a message to end user
Stavros Anastasiadis58b58782017-10-05 16:14:50 +0300134 if (context.data.length > 0) {
marination1087d972020-11-26 10:45:44 +0530135 this.content.find('.result').css('text-align', 'unset');
136 $(frappe.render_template(this.template, context)).appendTo(this.result);
Stavros Anastasiadis58b58782017-10-05 16:14:50 +0300137 } else {
marination1087d972020-11-26 10:45:44 +0530138 var message = __("No Stock Available Currently");
139 this.content.find('.result').css('text-align', 'center');
140
marinationa97eb6a2021-02-07 22:27:40 +0530141 $(`<div class='text-muted' style='margin: 20px 5px;'>
marination1087d972020-11-26 10:45:44 +0530142 ${message} </div>`).appendTo(this.result);
Stavros Anastasiadis58b58782017-10-05 16:14:50 +0300143 }
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530144 },
marination1087d972020-11-26 10:45:44 +0530145
Anurag Mishraabf974d2021-03-17 18:40:21 +0530146 get_item_dashboard_data: function (data, max_count, show_item) {
147 if (!max_count) max_count = 0;
148 if (!data) data = [];
Vinayak Jethe549c1962018-01-24 19:47:59 +0530149
Anurag Mishraabf974d2021-03-17 18:40:21 +0530150 data.forEach(function (d) {
Nabin Haita6746402018-03-28 11:16:00 +0530151 d.actual_or_pending = d.projected_qty + d.reserved_qty + d.reserved_qty_for_production + d.reserved_qty_for_sub_contract;
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530152 d.pending_qty = 0;
Nabin Hait2c7a6e62018-03-12 14:12:12 +0530153 d.total_reserved = d.reserved_qty + d.reserved_qty_for_production + d.reserved_qty_for_sub_contract;
Anurag Mishraabf974d2021-03-17 18:40:21 +0530154 if (d.actual_or_pending > d.actual_qty) {
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530155 d.pending_qty = d.actual_or_pending - d.actual_qty;
156 }
157
158 max_count = Math.max(d.actual_or_pending, d.actual_qty,
159 d.total_reserved, max_count);
160 });
Vinayak Jethe549c1962018-01-24 19:47:59 +0530161
marination1087d972020-11-26 10:45:44 +0530162 let can_write = 0;
marination0f3cfc52020-12-08 19:11:51 +0530163 if (frappe.boot.user.can_write.indexOf("Stock Entry") >= 0) {
Vinayak Jethe549c1962018-01-24 19:47:59 +0530164 can_write = 1;
165 }
166
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530167 return {
168 data: data,
169 max_count: max_count,
Anurag Mishraabf974d2021-03-17 18:40:21 +0530170 can_write: can_write,
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530171 show_item: show_item || false
marinationb8aeb9e2021-01-05 12:16:25 +0530172 };
marination1087d972020-11-26 10:45:44 +0530173 },
174
Anurag Mishraabf974d2021-03-17 18:40:21 +0530175 get_capacity_dashboard_data: function (data) {
marination0f3cfc52020-12-08 19:11:51 +0530176 if (!data) data = [];
marination1087d972020-11-26 10:45:44 +0530177
Anurag Mishraabf974d2021-03-17 18:40:21 +0530178 data.forEach(function (d) {
179 d.color = d.percent_occupied >= 80 ? "#f8814f" : "#2490ef";
marination1087d972020-11-26 10:45:44 +0530180 });
181
182 let can_write = 0;
marination0f3cfc52020-12-08 19:11:51 +0530183 if (frappe.boot.user.can_write.indexOf("Putaway Rule") >= 0) {
marination1087d972020-11-26 10:45:44 +0530184 can_write = 1;
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530185 }
marination1087d972020-11-26 10:45:44 +0530186
187 return {
188 data: data,
189 can_write: can_write,
marination0f3cfc52020-12-08 19:11:51 +0530190 };
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530191 }
marination0f3cfc52020-12-08 19:11:51 +0530192});
Shivam Mishra444091b2019-07-10 10:22:08 +0530193
Anurag Mishraabf974d2021-03-17 18:40:21 +0530194erpnext.stock.move_item = function (item, source, target, actual_qty, rate, callback) {
Shivam Mishra444091b2019-07-10 10:22:08 +0530195 var dialog = new frappe.ui.Dialog({
196 title: target ? __('Add Item') : __('Move Item'),
Anurag Mishraabf974d2021-03-17 18:40:21 +0530197 fields: [{
198 fieldname: 'item_code',
199 label: __('Item'),
200 fieldtype: 'Link',
201 options: 'Item',
202 read_only: 1
203 },
204 {
205 fieldname: 'source',
206 label: __('Source Warehouse'),
207 fieldtype: 'Link',
208 options: 'Warehouse',
209 read_only: 1
210 },
211 {
212 fieldname: 'target',
213 label: __('Target Warehouse'),
214 fieldtype: 'Link',
215 options: 'Warehouse',
216 reqd: 1
217 },
218 {
219 fieldname: 'qty',
220 label: __('Quantity'),
221 reqd: 1,
222 fieldtype: 'Float',
223 description: __('Available {0}', [actual_qty])
224 },
225 {
226 fieldname: 'rate',
227 label: __('Rate'),
228 fieldtype: 'Currency',
229 hidden: 1
230 },
Shivam Mishra444091b2019-07-10 10:22:08 +0530231 ],
Anurag Mishraabf974d2021-03-17 18:40:21 +0530232 });
Devin Slauenwhitebdba0642021-05-18 06:42:53 -0400233 var submitted = false;
Shivam Mishra444091b2019-07-10 10:22:08 +0530234 dialog.show();
235 dialog.get_field('item_code').set_input(item);
236
Anurag Mishraabf974d2021-03-17 18:40:21 +0530237 if (source) {
Shivam Mishra444091b2019-07-10 10:22:08 +0530238 dialog.get_field('source').set_input(source);
239 } else {
240 dialog.get_field('source').df.hidden = 1;
241 dialog.get_field('source').refresh();
242 }
243
Anurag Mishraabf974d2021-03-17 18:40:21 +0530244 if (rate) {
Shivam Mishra444091b2019-07-10 10:22:08 +0530245 dialog.get_field('rate').set_value(rate);
246 dialog.get_field('rate').df.hidden = 0;
247 dialog.get_field('rate').refresh();
248 }
249
Anurag Mishraabf974d2021-03-17 18:40:21 +0530250 if (target) {
Shivam Mishra444091b2019-07-10 10:22:08 +0530251 dialog.get_field('target').df.read_only = 1;
252 dialog.get_field('target').value = target;
253 dialog.get_field('target').refresh();
254 }
255
Anurag Mishraabf974d2021-03-17 18:40:21 +0530256 dialog.set_primary_action(__('Submit'), function () {
Devin Slauenwhitebdba0642021-05-18 06:42:53 -0400257 if(submitted) return;
Shivam Mishra444091b2019-07-10 10:22:08 +0530258 var values = dialog.get_values();
Anurag Mishraabf974d2021-03-17 18:40:21 +0530259 if (!values) {
Shivam Mishra444091b2019-07-10 10:22:08 +0530260 return;
261 }
Anurag Mishraabf974d2021-03-17 18:40:21 +0530262 if (source && values.qty > actual_qty) {
Shivam Mishra444091b2019-07-10 10:22:08 +0530263 frappe.msgprint(__('Quantity must be less than or equal to {0}', [actual_qty]));
264 return;
265 }
Anurag Mishraabf974d2021-03-17 18:40:21 +0530266 if (values.source === values.target) {
Shivam Mishra444091b2019-07-10 10:22:08 +0530267 frappe.msgprint(__('Source and target warehouse must be different'));
268 }
269
Devin Slauenwhitebdba0642021-05-18 06:42:53 -0400270 submitted = true;
Shivam Mishra444091b2019-07-10 10:22:08 +0530271 frappe.call({
272 method: 'erpnext.stock.doctype.stock_entry.stock_entry_utils.make_stock_entry',
273 args: values,
Ankush Menat042b8522021-05-18 16:31:55 +0530274 btn: dialog.get_primary_btn(),
Shivam Mishra444091b2019-07-10 10:22:08 +0530275 freeze: true,
Ankush Menat042b8522021-05-18 16:31:55 +0530276 freeze_message: __('Creating Stock Entry'),
Anurag Mishraabf974d2021-03-17 18:40:21 +0530277 callback: function (r) {
Shivam Mishra444091b2019-07-10 10:22:08 +0530278 frappe.show_alert(__('Stock Entry {0} created',
Anurag Mishraabf974d2021-03-17 18:40:21 +0530279 ['<a href="/app/stock-entry/' + r.message.name + '">' + r.message.name + '</a>']));
Shivam Mishra444091b2019-07-10 10:22:08 +0530280 dialog.hide();
281 callback(r);
282 },
283 });
284 });
285
Anurag Mishraabf974d2021-03-17 18:40:21 +0530286 $('<p style="margin-left: 10px;"><a class="link-open text-muted small">' +
287 __("Add more items or open full form") + '</a></p>')
Shivam Mishra444091b2019-07-10 10:22:08 +0530288 .appendTo(dialog.body)
289 .find('.link-open')
Anurag Mishraabf974d2021-03-17 18:40:21 +0530290 .on('click', function () {
291 frappe.model.with_doctype('Stock Entry', function () {
Shivam Mishra444091b2019-07-10 10:22:08 +0530292 var doc = frappe.model.get_new_doc('Stock Entry');
293 doc.from_warehouse = dialog.get_value('source');
294 doc.to_warehouse = dialog.get_value('target');
295 var row = frappe.model.add_child(doc, 'items');
296 row.item_code = dialog.get_value('item_code');
297 row.f_warehouse = dialog.get_value('target');
298 row.t_warehouse = dialog.get_value('target');
299 row.qty = dialog.get_value('qty');
300 row.conversion_factor = 1;
301 row.transfer_qty = dialog.get_value('qty');
302 row.basic_rate = dialog.get_value('rate');
303 frappe.set_route('Form', doc.doctype, doc.name);
Anurag Mishraabf974d2021-03-17 18:40:21 +0530304 });
Shivam Mishra444091b2019-07-10 10:22:08 +0530305 });
Anurag Mishraabf974d2021-03-17 18:40:21 +0530306};