blob: 386ed9ed93eb74a9b1ce07a9588467c129d3b083 [file] [log] [blame]
Rohit Waghchaure6087fe12016-04-09 14:31:09 +05301frappe.provide("erpnext.pos");
2{% include "erpnext/public/js/controllers/taxes_and_totals.js" %}
3
Rushabh Mehta06fa46f2015-01-29 18:09:11 +05304frappe.pages['pos'].on_page_load = function(wrapper) {
Rushabh Mehta4c36d732015-01-01 15:59:34 +05305 var page = frappe.ui.make_app_page({
Rushabh Mehta72e17192014-08-08 15:30:49 +05306 parent: wrapper,
Rohit Waghchaure6087fe12016-04-09 14:31:09 +05307 title: 'Point of Sale',
Rushabh Mehta72e17192014-08-08 15:30:49 +05308 single_column: true
9 });
Rohit Waghchauree0934d12016-05-11 15:04:57 +053010
11 wrapper.pos = new erpnext.pos.PointOfSale(wrapper)
Rushabh Mehta72e17192014-08-08 15:30:49 +053012}
Rohit Waghchaure6087fe12016-04-09 14:31:09 +053013
Rohit Waghchauree0934d12016-05-11 15:04:57 +053014frappe.pages['pos'].refresh = function(wrapper) {
15 wrapper.pos.on_refresh_page()
16}
17
18
Rohit Waghchaure6087fe12016-04-09 14:31:09 +053019erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
Rohit Waghchauree0934d12016-05-11 15:04:57 +053020 init: function(wrapper){
21 this.load = true;
22 this.page = wrapper.page;
23 this.wrapper = $(wrapper).find('.page-content');
Rohit Waghchaure6087fe12016-04-09 14:31:09 +053024 this.set_indicator();
25 this.onload();
26 this.make_menu_list();
27 this.set_interval_for_si_sync();
28 this.si_docs = this.get_doc_from_localstorage();
29 },
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +053030
Rohit Waghchauree0934d12016-05-11 15:04:57 +053031 on_refresh_page: function() {
32 var me = this;
33 if(this.load){
34 this.load = false;
35 }else{
36 this.create_new();
37 }
38 },
Rohit Waghchaure6087fe12016-04-09 14:31:09 +053039
40 check_internet_connection: function(){
41 var me = this;
42 //Check Internet connection after every 30 seconds
43 setInterval(function(){
44 me.set_indicator();
45 }, 30000)
46 },
47
48 set_indicator: function(){
49 var me = this;
50 // navigator.onLine
51 this.page.set_indicator("Offline", "grey")
52 frappe.call({
53 method:"frappe.handler.ping",
54 callback: function(r){
55 if(r.message){
56 me.connection_status = true;
57 me.page.set_indicator("Online", "green")
58 }
59 }
60 })
61 },
62
63 onload: function(){
64 var me = this;
Rohit Waghchaure6087fe12016-04-09 14:31:09 +053065 this.get_data_from_server(function(){
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +053066 me.create_new();
Rohit Waghchaure6087fe12016-04-09 14:31:09 +053067 });
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +053068
Rohit Waghchaure6087fe12016-04-09 14:31:09 +053069 this.check_internet_connection();
70 },
71
72 make_menu_list: function(){
73 var me = this;
74
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +053075 this.page.add_menu_item(__("New Sales Invoice"), function() {
76 me.create_new()
77 })
78
79 this.page.add_menu_item(__("View Offline Records"), function(){
Rohit Waghchaure6087fe12016-04-09 14:31:09 +053080 me.show_unsync_invoice_list()
81 });
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +053082
Rohit Waghchaure6087fe12016-04-09 14:31:09 +053083 this.page.add_menu_item(__("Sync Master Data"), function(){
Rohit Waghchauree0934d12016-05-11 15:04:57 +053084 me.get_data_from_server(function(){
85 me.load_data()
86 me.make_customer()
87 me.make_item_list()
88 })
Rohit Waghchaure6087fe12016-04-09 14:31:09 +053089 });
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +053090
91 this.page.add_menu_item(__("POS Profile"), function() {
92 frappe.set_route('POS Profile');
93 });
Rohit Waghchaure6087fe12016-04-09 14:31:09 +053094 },
95
96 show_unsync_invoice_list: function(){
97 var me = this;
98 this.si_docs = this.get_doc_from_localstorage();
99
100 this.list_dialog = new frappe.ui.Dialog({
101 title: 'Invoice List'
102 });
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530103
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530104 this.list_dialog.show();
105 this.list_body = this.list_dialog.body;
106 $(this.list_body).append('<div class="row list-row list-row-head pos-invoice-list">\
Rohit Waghchauree0934d12016-05-11 15:04:57 +0530107 <div class="col-xs-3">Sr</div>\
108 <div class="col-xs-3">Customer</div>\
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530109 <div class="col-xs-3 text-right">Grand Total</div>\
110 <div class="col-xs-3 text-right">Status</div>\
111 </div>')
112
113 $.each(this.si_docs, function(index, data){
114 for(key in data) {
115 $(frappe.render_template("pos_invoice_list", {
Rohit Waghchauree0934d12016-05-11 15:04:57 +0530116 sr: index + 1,
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530117 name: key,
118 customer: data[key].customer,
Rohit Waghchauree0934d12016-05-11 15:04:57 +0530119 grand_total: format_currency(data[key].grand_total, me.frm.doc.currency),
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530120 status: (data[key].docstatus == 1) ? 'Submitted' : 'Draft'
121 })).appendTo($(me.list_body));
122 }
123 })
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530124
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530125 $(this.list_body).find('.list-row').click(function() {
126 me.name = $(this).attr('invoice-name')
127 doc_data = me.get_invoice_doc(me.si_docs)
128 if(doc_data){
129 me.frm.doc = doc_data[0][me.name];
Rohit Waghchauree0934d12016-05-11 15:04:57 +0530130 me.set_missing_values();
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530131 me.refresh();
132 me.disable_input_field();
133 me.list_dialog.hide();
134 }
135 })
136 },
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530137
Rohit Waghchauree0934d12016-05-11 15:04:57 +0530138 set_missing_values: function(){
139 var me = this;
140 doc = JSON.parse(localStorage.getItem('doc'))
141 if(this.frm.doc.payments.length == 0){
142 this.frm.doc.payments = doc.payments;
143 }
144 },
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530145
146 get_invoice_doc: function(si_docs){
147 var me = this;
148 this.si_docs = this.get_doc_from_localstorage();
149
150 return $.grep(this.si_docs, function(data){
151 for(key in data){
152 return key == me.name
153 }
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530154 })
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530155 },
156
157 get_data_from_server: function(callback){
158 var me = this;
159 frappe.call({
160 method: "erpnext.accounts.doctype.sales_invoice.pos.get_pos_data",
161 freeze: true,
Rohit Waghchauree0934d12016-05-11 15:04:57 +0530162 freeze_message: __("Master data syncing, it might take some time"),
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530163 callback: function(r){
164 window.items = r.message.items;
165 window.customers = r.message.customers;
166 window.pricing_rules = r.message.pricing_rules;
167 window.meta = r.message.meta;
168 window.print_template = r.message.print_template;
169 localStorage.setItem('doc', JSON.stringify(r.message.doc));
170 if(callback){
171 callback();
172 }
173 }
174 })
175 },
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530176
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530177 create_new: function(){
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530178 var me = this;
Rohit Waghchauree0934d12016-05-11 15:04:57 +0530179 this.frm = {}
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530180 this.name = '';
181 this.frm.doc = JSON.parse(localStorage.getItem('doc'))
182 this.load_data();
183 this.setup();
184 },
185
186 load_data: function(){
187 this.items = window.items;
188 this.customers = window.customers;
189 this.pricing_rules = window.pricing_rules;
190
191 $.each(window.meta, function(i, data){
192 frappe.meta.sync(data)
193 })
194
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530195 this.print_template = frappe.render_template("print_template",
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530196 {content: window.print_template, title:"POS"})
197 },
198
199 setup: function(){
200 this.wrapper.html(frappe.render_template("pos", this.frm.doc));
201 this.set_transaction_defaults("Customer");
202 this.make();
203 this.set_primary_action();
204 },
205
206 set_transaction_defaults: function(party) {
207 var me = this;
208 this.party = party;
209 this.price_list = (party == "Customer" ?
210 this.frm.doc.selling_price_list : this.frm.doc.buying_price_list);
211 this.price_list_field = (party == "Customer" ? "selling_price_list" : "buying_price_list");
212 this.sales_or_purchase = (party == "Customer" ? "Sales" : "Purchase");
213 },
214
215 make: function() {
216 this.make_search();
217 this.make_customer();
218 this.make_item_list();
219 this.make_discount_field()
220 },
221
222 make_search: function() {
223 var me = this;
224 this.search = frappe.ui.form.make_control({
225 df: {
226 "fieldtype": "Data",
227 "label": "Item",
228 "fieldname": "pos_item",
229 "placeholder": "Search Item"
230 },
231 parent: this.wrapper.find(".search-area"),
232 only_input: true,
233 });
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530234
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530235 this.search.make_input();
236 this.search.$input.on("keyup", function() {
237 setTimeout(function() {
238 me.items = me.get_items();
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530239 me.make_item_list();
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530240 }, 1000);
241 });
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530242
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530243 this.party_field = frappe.ui.form.make_control({
244 df: {
245 "fieldtype": "Data",
246 "options": this.party,
247 "label": this.party,
248 "fieldname": this.party.toLowerCase(),
249 "placeholder": this.party
250 },
251 parent: this.wrapper.find(".party-area"),
252 only_input: true,
253 });
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530254
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530255 this.party_field.make_input();
256 },
257
258 make_customer: function() {
259 var me = this;
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530260
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530261 if(this.customers.length == 1){
262 this.party_field.$input.val(this.customers[0].name);
263 this.frm.doc.customer = this.customers[0].name;
264 }
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530265
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530266 this.party_field.$input.autocomplete({
267 source: function (request, response) {
268 me.customer_data = me.get_customers(request.term)
269 response($.map(me.customer_data, function(data){
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530270 return {label: data.name, value: data.name,
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530271 customer_group: data.customer_group, territory: data.territory}
272 }))
273 },
274 change: function(event, ui){
275 if(ui.item){
276 me.frm.doc.customer = ui.item.label;
277 me.frm.doc.customer_name = ui.item.customer_name;
278 me.frm.doc.customer_group = ui.item.customer_group;
279 me.frm.doc.territory = ui.item.territory;
280 }else{
281 me.frm.doc.customer = me.party_field.$input.val();
282 }
283 me.refresh();
284 }
285 })
286 },
287
288 get_customers: function(key){
289 var me = this;
290 key = key.toLowerCase()
291 return $.grep(this.customers, function(data) {
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530292 if(data.name.toLowerCase().match(key)
293 || data.customer_name.toLowerCase().match(key)
294 || (data.customer_group && data.customer_group.toLowerCase().match(key))){
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530295 return data
296 }
297 })
298 },
299
300 make_item_list: function() {
301 var me = this;
302 if(!this.price_list) {
303 msgprint(__("Price List not found or disabled"));
304 return;
305 }
306
307 me.item_timeout = null;
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530308
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530309 var $wrap = me.wrapper.find(".item-list");
310 me.wrapper.find(".item-list").empty();
311
312 if (this.items) {
313 $.each(this.items, function(index, obj) {
314 if(index < 16){
315 $(frappe.render_template("pos_item", {
316 item_code: obj.name,
317 item_price: format_currency(obj.price_list_rate, obj.currency),
318 item_name: obj.name===obj.item_name ? "" : obj.item_name,
319 item_image: obj.image ? "url('" + obj.image + "')" : null,
320 color: frappe.get_palette(obj.item_name),
321 abbr: frappe.get_abbr(obj.item_name)
322 })).tooltip().appendTo($wrap);
323 }
324 });
325 }
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530326
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530327 if(this.items.length == 1){
328 this.search.$input.val("");
329 this.add_to_cart();
330 }
331
332 // if form is local then allow this function
333 $(me.wrapper).find("div.pos-item").on("click", function() {
334 me.customer_validate();
335 if(me.frm.doc.docstatus==0) {
336 me.items = me.get_items($(this).attr("data-item-code"))
337 me.add_to_cart();
338 }
339 });
340 },
341
342 get_items: function(item_code){
343 // To search item as per the key enter
344
345 var me = this;
346 this.item_serial_no = {}
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530347
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530348 if(item_code){
349 return $.grep(window.items, function(item){
350 if(item.item_code == item_code ){
351 return true
352 }
353 })
354 }
355
356 key = this.search.$input.val().toLowerCase();
357
358 if(key){
359 return $.grep(window.items, function(item){
360 if( (item.item_code.toLowerCase().match(key)) ||
361 (item.item_name.toLowerCase().match(key)) || (item.item_group.toLowerCase().match(key)) ){
362 return true
363 }else if(item.barcode){
364 return item.barcode == me.search.$input.val()
365 } else if (in_list(item.serial_nos, me.search.$input.val())){
366 me.item_serial_no[item.item_code] = me.search.$input.val()
367 return true
368 }
369 })
370 }else{
371 return window.items;
372 }
373 },
374
375 update_qty: function() {
376 var me = this;
377
378 $(this.wrapper).find(".pos-item-qty").on("change", function(){
379 var item_code = $(this).parents(".pos-bill-item").attr("data-item-code");
380 me.update_qty_against_item_code(item_code, $(this).val());
381 })
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530382
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530383 $(this.wrapper).find("[data-action='increase-qty']").on("click", function(){
384 var item_code = $(this).parents(".pos-bill-item").attr("data-item-code");
385 var qty = flt($(this).parents(".pos-bill-item").find('.pos-item-qty').val()) + 1;
386 me.update_qty_against_item_code(item_code, qty);
387 })
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530388
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530389 $(this.wrapper).find("[data-action='decrease-qty']").on("click", function(){
390 var item_code = $(this).parents(".pos-bill-item").attr("data-item-code");
391 var qty = flt($(this).parents(".pos-bill-item").find('.pos-item-qty').val()) - 1;
392 me.update_qty_against_item_code(item_code, qty);
393 })
394 },
395
396 update_qty_against_item_code: function(item_code, qty){
397 var me = this;
398 if(qty < 0){
399 frappe.throw(__("Quantity must be positive"));
400 }
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530401
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530402 this.remove_item = []
403 $.each(this.frm.doc["items"] || [], function(i, d) {
404 if (d.item_code == item_code) {
405 d.qty = flt(qty);
406 d.amount = flt(d.rate) * flt(d.qty);
407 if(d.qty==0){
408 me.remove_item.push(d.idx)
409 }
410 }
411 });
412 this.remove_zero_qty_item();
413 this.refresh();
414 },
415
416 remove_zero_qty_item: function(){
417 var me = this;
418 idx = 0
419 this.items = []
420 idx = 0
421 $.each(this.frm.doc["items"] || [], function(i, d) {
422 if(!in_list(me.remove_item, d.idx)){
423 d.idx = idx;
424 me.items.push(d);
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530425 idx++;
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530426 }
427 });
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530428
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530429 this.frm.doc["items"] = this.items;
430 },
431
432 make_discount_field: function(){
433 var me = this;
434
435 this.wrapper.find('input.discount-percentage').on("change", function() {
436 me.frm.doc.additional_discount_percentage = flt($(this).val(), precision("additional_discount_percentage"));
437 total = me.frm.doc.grand_total
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530438
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530439 if(me.frm.doc.apply_discount_on == 'Net Total'){
440 total = me.frm.doc.net_total
441 }
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530442
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530443 me.frm.doc.discount_amount = flt(total*flt(me.frm.doc.additional_discount_percentage) / 100, precision("discount_amount"));
444 me.wrapper.find('input.discount-amount').val(me.frm.doc.discount_amount)
445 me.refresh();
446 });
447
448 this.wrapper.find('input.discount-amount').on("change", function() {
449 me.frm.doc.discount_amount = flt($(this).val(), precision("discount_amount"));
450 me.frm.doc.additional_discount_percentage = 0.0;
451 me.wrapper.find('input.discount-percentage').val(0);
452 me.refresh();
453 });
454 },
455
456 customer_validate: function(){
457 var me = this;
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530458
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530459 if(!this.frm.doc.customer){
460 frappe.throw(__("Please select customer"))
461 }
462 },
463
464 add_to_cart: function() {
465 var me = this;
466 var caught = false;
467 var no_of_items = me.wrapper.find(".pos-bill-item").length;
468
469 this.validate_serial_no()
470 this.validate_warehouse();
471
472 if (no_of_items != 0) {
473 $.each(this.frm.doc["items"] || [], function(i, d) {
474 if (d.item_code == me.items[0].item_code) {
475 caught = true;
476 d.qty += 1;
477 d.amount = flt(d.rate) * flt(d.qty)
478 if(me.item_serial_no.length){
479 d.serial_no += '\n' + me.item_serial_no[d.item_code]
480 }
481 }
482 });
483 }
484
485 // if item not found then add new item
486 if (!caught)
487 this.add_new_item_to_grid();
488
489 this.refresh();
490 },
491
492 add_new_item_to_grid: function() {
493 var me = this;
494 this.child = frappe.model.add_child(this.frm.doc, this.frm.doc.doctype + " Item", "items");
495 this.child.item_code = this.items[0].item_code;
496 this.child.item_name = this.items[0].item_name;
497 this.child.stock_uom = this.items[0].stock_uom;
498 this.child.description = this.items[0].description;
499 this.child.qty = 1;
500 this.child.item_group = this.items[0].item_group;
501 this.child.cost_center = this.items[0].cost_center;
502 this.child.income_account = this.items[0].income_account;
503 this.child.warehouse = this.items[0].default_warehouse;
504 this.child.price_list_rate = flt(this.items[0].price_list_rate, 9) / flt(this.frm.doc.conversion_rate, 9);
505 this.child.rate = flt(this.items[0].price_list_rate, 9) / flt(this.frm.doc.conversion_rate, 9);
506 this.child.actual_qty = this.items[0].actual_qty;
507 this.child.amount = flt(this.child.qty) * flt(this.child.rate);
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530508 this.child.serial_no = this.item_serial_no[this.child.item_code];
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530509 },
510
511 refresh: function() {
512 var me = this;
513 this.refresh_fields();
514 this.update_qty();
515 this.set_primary_action();
516 },
517 refresh_fields: function() {
518 this.apply_pricing_rule();
519 this.discount_amount_applied = false;
520 this._calculate_taxes_and_totals();
521 this.calculate_discount_amount();
522 this.show_items_in_item_cart();
523 this.set_taxes();
524 this.calculate_outstanding_amount();
525 this.set_totals();
526 },
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530527
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530528 get_company_currency: function() {
529 return erpnext.get_currency(this.frm.doc.company);
530 },
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530531
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530532 show_item_wise_taxes: function(){
533 return null;
534 },
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530535
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530536 show_items_in_item_cart: function() {
537 var me = this;
538 var $items = this.wrapper.find(".items").empty();
539 me.frm.doc.net_total = 0.0
540 $.each(this.frm.doc.items|| [], function(i, d) {
541 $(frappe.render_template("pos_bill_item", {
542 item_code: d.item_code,
543 item_name: (d.item_name===d.item_code || !d.item_name) ? "" : ("<br>" + d.item_name),
544 qty: d.qty,
545 actual_qty: d.actual_qty,
546 projected_qty: d.projected_qty,
547 rate: format_currency(d.rate, me.frm.doc.currency),
548 amount: format_currency(d.amount, me.frm.doc.currency)
549 })).appendTo($items);
550 });
551
552 this.wrapper.find("input.pos-item-qty").on("focus", function() {
553 $(this).select();
554 });
555 },
556
557 set_taxes: function(){
558 var me = this;
559 me.frm.doc.total_taxes_and_charges = 0.0
560
561 var taxes = this.frm.doc.taxes || [];
562 $(this.wrapper)
563 .find(".tax-area").toggleClass("hide", (taxes && taxes.length) ? false : true)
564 .find(".tax-table").empty();
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530565
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530566 $.each(taxes, function(i, d) {
567 if (d.tax_amount && cint(d.included_in_print_rate) == 0) {
568 $(frappe.render_template("pos_tax_row", {
569 description: d.description,
570 tax_amount: format_currency(flt(d.tax_amount_after_discount_amount),
571 me.frm.doc.currency)
572 })).appendTo(me.wrapper.find(".tax-table"));
573 }
574 });
575 },
576
577 set_totals: function() {
578 var me = this;
579 this.wrapper.find(".net-total").text(format_currency(me.frm.doc.total, me.frm.doc.currency));
580 this.wrapper.find(".grand-total").text(format_currency(me.frm.doc.grand_total, me.frm.doc.currency));
581 },
582
583 set_primary_action: function() {
584 var me = this;
585
586 if (this.frm.doc.docstatus==0 && this.frm.doc.outstanding_amount > 0) {
587 this.page.set_primary_action(__("Pay"), function() {
588 me.validate()
589 me.create_invoice();
590 me.make_payment();
591 });
Rohit Waghchauree0934d12016-05-11 15:04:57 +0530592 }else if(this.frm.doc.docstatus == 0 && this.name){
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530593 this.page.set_primary_action(__("Submit"), function() {
Rohit Waghchauree0934d12016-05-11 15:04:57 +0530594 me.write_off_amount()
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530595 })
596 }else if(this.frm.doc.docstatus == 1){
597 this.page.set_primary_action(__("Print"), function() {
598 html = frappe.render(me.print_template, me.frm.doc)
599 frappe.require("/assets/js/print_format_v3.min.js", function() {
600 w = _p.preview(html);
601 setTimeout(function(){
602 w.print();
603 }, 1000)
604 });
605 })
Rohit Waghchauree0934d12016-05-11 15:04:57 +0530606 }else {
607 this.page.clear_primary_action()
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530608 }
609 },
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530610
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530611 write_off_amount: function(){
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530612 var me = this;
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530613 var value = 0.0;
614
615 if(this.frm.doc.outstanding_amount > 0){
616 dialog = new frappe.ui.Dialog({
617 title: 'Write Off Amount',
618 fields: [
Rohit Waghchauree0934d12016-05-11 15:04:57 +0530619 {fieldtype: "Check", fieldname: "write_off_amount", label: __("Write of Outstanding Amount")},
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530620 ]
Rohit Waghchauree0934d12016-05-11 15:04:57 +0530621 });
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530622
Rohit Waghchauree0934d12016-05-11 15:04:57 +0530623 dialog.show();
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530624
Rohit Waghchauree0934d12016-05-11 15:04:57 +0530625 dialog.fields_dict.write_off_amount.$input.change(function(){
626 write_off_amount = dialog.get_values().write_off_amount
627 me.frm.doc.write_off_outstanding_amount_automatically = write_off_amount;
628 me.frm.doc.base_write_off_amount = (write_off_amount==1) ? flt(me.frm.doc.grand_total - me.frm.doc.paid_amount, precision("outstanding_amount")) : 0;
629 me.frm.doc.write_off_amount = flt(me.frm.doc.base_write_off_amount * me.frm.doc.conversion_rate, precision("write_off_amount"))
630 me.calculate_outstanding_amount();
631 })
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530632
Rohit Waghchauree0934d12016-05-11 15:04:57 +0530633 dialog.set_primary_action(__("Submit"), function(){
634 dialog.hide()
635 me.submit_invoice()
636 })
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530637 }else{
Rohit Waghchauree0934d12016-05-11 15:04:57 +0530638 this.submit_invoice()
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530639 }
640 },
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530641
Rohit Waghchauree0934d12016-05-11 15:04:57 +0530642 submit_invoice: function(){
643 var me = this;
644 frappe.confirm(__("Do you really want to submit the invoice?"), function () {
645 me.change_status();
646 })
647 },
648
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530649 change_status: function(){
650 if(this.frm.doc.docstatus == 0){
651 this.frm.doc.docstatus = 1;
652 this.update_invoice();
653 this.disable_input_field();
654 }
655 },
656
657 disable_input_field: function(){
658 var pointer_events = 'inherit'
659 $(this.wrapper).find('input').attr("disabled", false);
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530660
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530661 if(this.frm.doc.docstatus == 1){
662 pointer_events = 'none'
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530663 $(this.wrapper).find('input').attr("disabled", true);
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530664 }
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530665
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530666 $(this.wrapper).find('.pos-bill-wrapper').css('pointer-events', pointer_events);
667 $(this.wrapper).find('.pos-items-section').css('pointer-events', pointer_events);
668 this.set_primary_action();
669 },
670
671 create_invoice: function(){
672 var me = this;
673 var invoice_data = {}
674 this.si_docs = this.get_doc_from_localstorage();
675 if(this.name){
676 this.update_invoice()
677 }else{
678 this.name = $.now();
679 invoice_data[this.name] = this.frm.doc
680 this.si_docs.push(invoice_data)
681 this.update_localstorage();
682 this.set_primary_action();
683 }
684 },
685
686 update_invoice: function(){
687 var me = this;
688 this.si_docs = this.get_doc_from_localstorage();
689 $.each(this.si_docs, function(index, data){
690 for(key in data){
691 if(key == me.name){
692 me.si_docs[index][key] = me.frm.doc
693 me.update_localstorage();
694 }
695 }
696 })
697 },
698
699 update_localstorage: function(){
700 try{
701 localStorage.setItem('sales_invoice_doc', JSON.stringify(this.si_docs));
702 }catch(e){
703 frappe.throw(__("LocalStorage is full , did not save"))
704 }
705 },
706
707 get_doc_from_localstorage: function(){
Rohit Waghchauree0934d12016-05-11 15:04:57 +0530708 try{
709 return JSON.parse(localStorage.getItem('sales_invoice_doc')) || [];
710 }catch(e){
711 return []
712 }
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530713 },
714
715 set_interval_for_si_sync: function(){
716 var me = this;
717 setInterval(function(){
718 me.sync_sales_invoice()
Rohit Waghchauree0934d12016-05-11 15:04:57 +0530719 }, 60000)
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530720 },
721
722 sync_sales_invoice: function(){
723 var me = this;
724 this.si_docs = this.get_submitted_invoice()
725
726 if(this.connection_status && this.si_docs.length){
727 frappe.call({
728 method: "erpnext.accounts.doctype.sales_invoice.pos.make_invoice",
729 args: {
730 doc_list: me.si_docs
731 },
732 callback: function(r){
733 if(r.message){
734 me.removed_items = r.message;
735 me.remove_doc_from_localstorage();
736 }
737 }
738 })
739 }
740 },
741
742 get_submitted_invoice: function(){
743 invoices = []
744 docs = this.get_doc_from_localstorage()
745 if(docs){
746 invoices = $.map(docs, function(data){
747 for(key in data){
748 if(data[key].docstatus == 1){
749 return data
750 }
751 }
752 });
753 }
754
755 return invoices
756 },
757
758 remove_doc_from_localstorage: function(){
759 var me = this;
760 this.si_docs = this.get_doc_from_localstorage();
Rohit Waghchauree0934d12016-05-11 15:04:57 +0530761 this.new_si_docs = []
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530762 if(this.removed_items){
763 $.each(this.si_docs, function(index, data){
764 for(key in data){
Rohit Waghchauree0934d12016-05-11 15:04:57 +0530765 if(!in_list(me.removed_items, key)){
766 me.new_si_docs.push(data)
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530767 }
768 }
769 })
Rohit Waghchauree0934d12016-05-11 15:04:57 +0530770 this.si_docs = this.new_si_docs;
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530771 this.update_localstorage();
772 }
773 },
774
775 validate: function(){
776 var me = this;
777 this.customer_validate();
778 this.item_validate();
779 },
780
781 item_validate: function(){
782 if(this.frm.doc.items.length == 0){
783 frappe.throw(__("Select items to save the invoice"))
784 }
785 },
786
787 validate_serial_no: function(){
788 var me = this;
789 var item_code = serial_no = '';
790 for (key in this.item_serial_no){
791 item_code = key;
792 serial_no = me.item_serial_no[key]
793 }
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530794
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530795 if(item_code && serial_no){
796 $.each(this.frm.doc.items, function(index, data){
797 if(data.item_code == item_code){
798 if(in_list(data.serial_no.split('\n'), serial_no)){
799 frappe.throw(__(repl("Serial no %(serial_no)s is already taken", {
800 'serial_no': serial_no
801 })))
802 }
803 }
804 })
805 }
806 },
807
808 apply_pricing_rule: function(){
809 var me = this;
810 $.each(this.frm.doc["items"], function(n, item) {
811 pricing_rule = me.get_pricing_rule(item)
812 me.validate_pricing_rule(pricing_rule)
813 if(pricing_rule.length){
814 item.margin_type = pricing_rule[0].margin_type;
815 item.price_list_rate = pricing_rule[0].price || item.price_list_rate;
816 item.margin_rate_or_amount = pricing_rule[0].margin_rate_or_amount;
817 item.discount_percentage = pricing_rule[0].discount_percentage || 0.0;
818 me.apply_pricing_rule_on_item(item)
819 }
820 })
821 },
822
823 get_pricing_rule: function(item){
824 var me = this;
825 return $.grep(this.pricing_rules, function(data){
826 if(data.item_code == item.item_code || in_list(['All Item Groups', item.item_group], data.item_group)) {
827 if(in_list(['Customer', 'Customer Group', 'Territory'], data.applicable_for)){
828 return me.validate_condition(data)
829 }else{
830 return true
831 }
832 }
833 })
834 },
835
836 validate_condition: function(data){
837 //This method check condition based on applicable for
838 condition = this.get_mapper_for_pricing_rule(data)[data.applicable_for]
839 if(in_list(condition[1], condition[0])){
840 return true
841 }
842 },
843
844 get_mapper_for_pricing_rule: function(data){
845 return {
846 'Customer': [data.customer, [this.doc.customer]],
847 'Customer Group': [data.customer_group, [this.doc.customer_group, 'All Customer Groups']],
848 'Territory': [data.territory, [this.doc.territory, 'All Territories']],
849 }
850 },
851
852 validate_pricing_rule: function(pricing_rule){
853 //This method validate duplicate pricing rule
854 var pricing_rule_name = '';
855 var priority = 0;
856 var pricing_rule_list = [];
857 var priority_list = []
858
859 if(pricing_rule.length > 1){
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530860
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530861 $.each(pricing_rule, function(index, data){
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530862 pricing_rule_name += data.name + ','
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530863 priority_list.push(data.priority)
864 if(priority <= data.priority){
865 priority = data.priority
866 pricing_rule_list.push(data)
867 }
868 })
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530869
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530870 count = 0
871 $.each(priority_list, function(index, value){
872 if(value == priority){
873 count++
874 }
875 })
876
877 if(priority == 0 || count > 1){
878 frappe.throw(__(repl("Multiple Price Rules exists with same criteria, please resolve conflict by assigning priority. Price Rules: %(pricing_rule)s", {
879 'pricing_rule': pricing_rule_name
880 })))
881 }
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530882
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530883 return pricing_rule_list
884 }
885 },
Rushabh Mehtad0cee1b2016-05-20 12:54:44 +0530886
Rohit Waghchaure6087fe12016-04-09 14:31:09 +0530887 validate_warehouse: function(){
888 if(!this.items[0].default_warehouse){
889 frappe.throw(__("Deafault warehouse is required for selected item"))
890 }
891 }
892})