blob: 2748436fd845921f20e0c5513abb2ca006c3038e [file] [log] [blame]
Rushabh Mehta3d2622c2016-04-25 17:53:42 +05301frappe.provide('erpnext.stock');
2
3erpnext.stock.ItemDashboard = Class.extend({
4 init: function(opts) {
5 $.extend(this, opts);
6 this.make();
7 },
8 make: function() {
9 var me = this;
10 this.start = 0;
11 if(!this.sort_by) {
12 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
19 // move
20 this.content.on('click', '.btn-move', function() {
21 erpnext.stock.move_item($(this).attr('data-item'), $(this).attr('data-warehouse'),
22 null, $(this).attr('data-actual_qty'), null, function() { me.refresh(); });
23 });
24
25 this.content.on('click', '.btn-add', function() {
26 erpnext.stock.move_item($(this).attr('data-item'), null, $(this).attr('data-warehouse'),
27 $(this).attr('data-actual_qty'), $(this).attr('data-rate'),
28 function() { me.refresh(); });
29 });
30
31 // more
32 this.content.find('.btn-more').on('click', function() {
33 me.start += 20;
34 me.refresh();
35 });
36
37 },
38 refresh: function() {
39 if(this.before_refresh) {
40 this.before_refresh();
41 }
42
43 var me = this;
44 frappe.call({
45 method: 'erpnext.stock.dashboard.item_dashboard.get_data',
46 args: {
47 item_code: this.item_code,
48 warehouse: this.warehouse,
Rushabh Mehta057db062016-11-08 12:40:04 +053049 item_group: this.item_group,
Rushabh Mehta3d2622c2016-04-25 17:53:42 +053050 start: this.start,
51 sort_by: this.sort_by,
52 sort_order: this.sort_order,
53 },
54 callback: function(r) {
55 me.render(r.message);
56 }
57 });
58 },
59 render: function(data) {
60 if(this.start===0) {
61 this.max_count = 0;
62 this.result.empty();
63 }
64
65 var context = this.get_item_dashboard_data(data, this.max_count, true);
66 this.max_count = this.max_count;
67
68 // show more button
Rushabh Mehtaaed79e92016-06-02 17:49:16 +053069 if(data && data.length===21) {
Rushabh Mehta3d2622c2016-04-25 17:53:42 +053070 this.content.find('.more').removeClass('hidden');
71
72 // remove the last element
73 data.splice(-1);
74 } else {
75 this.content.find('.more').addClass('hidden');
76 }
77
Vinayak Jethe2c8ce5a2018-01-24 13:51:26 +053078 // If not any stock in any warehouses provide a message to end user
Stavros Anastasiadis58b58782017-10-05 16:14:50 +030079 if (context.data.length > 0) {
80 $(frappe.render_template('item_dashboard_list', context)).appendTo(this.result);
81 } else {
82 var message = __(" Currently no stock available in any warehouse")
Rushabh Mehtad5c64162017-11-14 15:27:28 +053083 $("<span class='text-muted small'>"+message+"</span>").appendTo(this.result);
Stavros Anastasiadis58b58782017-10-05 16:14:50 +030084 }
Rushabh Mehta3d2622c2016-04-25 17:53:42 +053085 },
86 get_item_dashboard_data: function(data, max_count, show_item) {
87 if(!max_count) max_count = 0;
Rushabh Mehta0dcb8612016-05-31 07:22:37 +053088 if(!data) data = [];
Vinayak Jethe549c1962018-01-24 19:47:59 +053089
Rushabh Mehta3d2622c2016-04-25 17:53:42 +053090 data.forEach(function(d) {
91 d.actual_or_pending = d.projected_qty + d.reserved_qty + d.reserved_qty_for_production;
92 d.pending_qty = 0;
Nabin Hait2c7a6e62018-03-12 14:12:12 +053093 d.total_reserved = d.reserved_qty + d.reserved_qty_for_production + d.reserved_qty_for_sub_contract;
Rushabh Mehta3d2622c2016-04-25 17:53:42 +053094 if(d.actual_or_pending > d.actual_qty) {
95 d.pending_qty = d.actual_or_pending - d.actual_qty;
96 }
97
98 max_count = Math.max(d.actual_or_pending, d.actual_qty,
99 d.total_reserved, max_count);
100 });
Vinayak Jethe549c1962018-01-24 19:47:59 +0530101
102 var can_write = 0;
103 if(frappe.boot.user.can_write.indexOf("Stock Entry")>=0){
104 can_write = 1;
105 }
106
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530107 return {
108 data: data,
109 max_count: max_count,
Vinayak Jethe549c1962018-01-24 19:47:59 +0530110 can_write:can_write,
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530111 show_item: show_item || false
112 }
113 }
114})
115
116erpnext.stock.move_item = function(item, source, target, actual_qty, rate, callback) {
117 var dialog = new frappe.ui.Dialog({
118 title: target ? __('Add Item') : __('Move Item'),
119 fields: [
120 {fieldname: 'item_code', label: __('Item'),
121 fieldtype: 'Link', options: 'Item', read_only: 1},
122 {fieldname: 'source', label: __('Source Warehouse'),
123 fieldtype: 'Link', options: 'Warehouse', read_only: 1},
124 {fieldname: 'target', label: __('Target Warehouse'),
125 fieldtype: 'Link', options: 'Warehouse', reqd: 1},
126 {fieldname: 'qty', label: __('Quantity'), reqd: 1,
127 fieldtype: 'Float', description: __('Available {0}', [actual_qty]) },
128 {fieldname: 'rate', label: __('Rate'), fieldtype: 'Currency', hidden: 1 },
129 ],
130 })
131 dialog.show();
132 dialog.get_field('item_code').set_input(item);
133
134 if(source) {
135 dialog.get_field('source').set_input(source);
136 } else {
137 dialog.get_field('source').df.hidden = 1;
138 dialog.get_field('source').refresh();
139 }
140
141 if(rate) {
Rushabh Mehta5dfe20c2016-04-26 12:59:08 +0530142 dialog.get_field('rate').set_value(rate);
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530143 dialog.get_field('rate').df.hidden = 0;
144 dialog.get_field('rate').refresh();
145 }
146
147 if(target) {
148 dialog.get_field('target').df.read_only = 1;
149 dialog.get_field('target').value = target;
150 dialog.get_field('target').refresh();
151 }
152
153 dialog.set_primary_action(__('Submit'), function() {
Rushabh Mehta5dfe20c2016-04-26 12:59:08 +0530154 var values = dialog.get_values();
Rushabh Mehta3d2622c2016-04-25 17:53:42 +0530155 if(!values) {
156 return;
157 }
158 if(source && values.qty > actual_qty) {
159 frappe.msgprint(__('Quantity must be less than or equal to {0}', [actual_qty]));
160 return;
161 }
162 if(values.source === values.target) {
163 frappe.msgprint(__('Source and target warehouse must be different'));
164 }
165
166 frappe.call({
167 method: 'erpnext.stock.doctype.stock_entry.stock_entry_utils.make_stock_entry',
168 args: values,
169 callback: function(r) {
170 frappe.show_alert(__('Stock Entry {0} created',
171 ['<a href="#Form/Stock Entry/'+r.message.name+'">' + r.message.name+ '</a>']));
172 dialog.hide();
173 callback(r);
174 },
175 });
176 });
Rushabh Mehta5dfe20c2016-04-26 12:59:08 +0530177
Rushabh Mehta1aa1c8a2016-04-29 12:19:59 +0530178 $('<p style="margin-left: 10px;"><a class="link-open text-muted small">'
179 + __("Add more items or open full form") + '</a></p>')
Rushabh Mehta5dfe20c2016-04-26 12:59:08 +0530180 .appendTo(dialog.body)
181 .find('.link-open')
182 .on('click', function() {
Rushabh Mehta1aa1c8a2016-04-29 12:19:59 +0530183 frappe.model.with_doctype('Stock Entry', function() {
184 var doc = frappe.model.get_new_doc('Stock Entry');
185 doc.from_warehouse = dialog.get_value('source');
186 doc.to_warehouse = dialog.get_value('target');
Faris Ansariab74ca72017-05-30 12:54:42 +0530187 var row = frappe.model.add_child(doc, 'items');
Rushabh Mehta1aa1c8a2016-04-29 12:19:59 +0530188 row.item_code = dialog.get_value('item_code');
189 row.f_warehouse = dialog.get_value('target');
190 row.t_warehouse = dialog.get_value('target');
191 row.qty = dialog.get_value('qty');
Nabin Haite68f32c2017-03-03 15:00:41 +0530192 row.conversion_factor = 1;
193 row.transfer_qty = dialog.get_value('qty');
Rushabh Mehta1aa1c8a2016-04-29 12:19:59 +0530194 row.basic_rate = dialog.get_value('rate');
195 frappe.set_route('Form', doc.doctype, doc.name);
196 })
Rushabh Mehta5dfe20c2016-04-26 12:59:08 +0530197 });
Vinayak Jethe549c1962018-01-24 19:47:59 +0530198}