frappe.provide("erpnext.pos"); {% include "erpnext/public/js/controllers/taxes_and_totals.js" %} frappe.pages['pos'].on_page_load = function (wrapper) { var page = frappe.ui.make_app_page({ parent: wrapper, title: __('Point of Sale'), single_column: true }); frappe.db.get_value('POS Settings', {name: 'POS Settings'}, 'is_online', (r) => { if (r && r.is_online && !cint(r.is_online)) { // offline wrapper.pos = new erpnext.pos.PointOfSale(wrapper); cur_pos = wrapper.pos; } else { // online frappe.set_route('point-of-sale'); } }); } frappe.pages['pos'].refresh = function (wrapper) { window.onbeforeunload = function () { return wrapper.pos.beforeunload() } } erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ init: function (wrapper) { this.page_len = 20; this.freeze = false; this.page = wrapper.page; this.wrapper = $(wrapper).find('.page-content'); this.set_indicator(); this.onload(); this.make_menu_list(); this.bind_events(); this.bind_items_event(); this.si_docs = this.get_doc_from_localstorage(); }, beforeunload: function (e) { if (this.connection_status == false && frappe.get_route()[0] == "pos") { e = e || window.event; // For IE and Firefox prior to version 4 if (e) { e.returnValue = __("You are in offline mode. You will not be able to reload until you have network."); return } // For Safari return __("You are in offline mode. You will not be able to reload until you have network."); } }, check_internet_connection: function () { var me = this; //Check Internet connection after every 30 seconds setInterval(function () { me.set_indicator(); }, 5000) }, set_indicator: function () { var me = this; // navigator.onLine this.connection_status = false; this.page.set_indicator(__("Offline"), "grey") frappe.call({ method: "frappe.handler.ping", callback: function (r) { if (r.message) { me.connection_status = true; me.page.set_indicator(__("Online"), "green") } } }) }, onload: function () { var me = this; this.get_data_from_server(function () { me.make_control(); me.create_new(); }); }, make_menu_list: function () { var me = this; this.page.clear_menu(); // for mobile this.page.add_menu_item(__("Pay"), function () { me.validate(); me.update_paid_amount_status(true); me.create_invoice(); me.make_payment(); }).addClass('visible-xs'); this.page.add_menu_item(__("New Sales Invoice"), function () { me.save_previous_entry(); me.create_new(); }) this.page.add_menu_item(__("Sync Master Data"), function () { me.get_data_from_server(function () { me.load_data(false); me.make_item_list(); me.set_missing_values(); }) }); this.page.add_menu_item(__("Sync Offline Invoices"), function () { me.sync_sales_invoice() }); this.page.add_menu_item(__("POS Profile"), function () { frappe.set_route('List', 'POS Profile'); }); }, email_prompt: function() { var me = this; var fields = [{label:__("To"), fieldtype:"Data", reqd: 0, fieldname:"recipients",length:524288}, {fieldtype: "Section Break", collapsible: 1, label: "CC & Standard Reply"}, {fieldtype: "Section Break"}, {label:__("Subject"), fieldtype:"Data", reqd: 1, fieldname:"subject",length:524288}, {fieldtype: "Section Break"}, {label:__("Message"), fieldtype:"Text Editor", reqd: 1, fieldname:"content"}, {fieldtype: "Section Break"}, {fieldtype: "Column Break"}]; this.email_dialog = new frappe.ui.Dialog({ title: "Email", fields: fields, primary_action_label: __("Send"), primary_action: function() { me.send_action(); } }); this.email_dialog.show() }, send_action: function() { this.email_queue = this.get_email_queue() this.email_queue[this.frm.doc.offline_pos_name] = JSON.stringify(this.email_dialog.get_values()) this.update_email_queue() this.email_dialog.hide() }, update_email_queue: function () { try { localStorage.setItem('email_queue', JSON.stringify(this.email_queue)); } catch (e) { frappe.throw(__("LocalStorage is full, did not save")) } }, get_email_queue: function () { try { return JSON.parse(localStorage.getItem('email_queue')) || {}; } catch (e) { return {} } }, get_customers_details: function () { try { return JSON.parse(localStorage.getItem('customer_details')) || {}; } catch (e) { return {} } }, dialog_actions: function () { var me = this; $(this.list_body).find('.list-select-all').click(function () { me.removed_items = []; $(me.list_body).find('.list-delete').prop("checked", $(this).is(":checked")) if ($(this).is(":checked")) { $.each(me.si_docs, function (index, data) { for (key in data) { me.removed_items.push(key) } }) } me.toggle_delete_button(); }) $(this.list_body).find('.list-delete').click(function () { me.name = $(this).parent().parent().attr('invoice-name'); if ($(this).is(":checked")) { me.removed_items.push(me.name); } else { me.removed_items.pop(me.name) } me.toggle_delete_button(); }) }, edit_record: function () { var me = this; doc_data = this.get_invoice_doc(this.si_docs); if (doc_data) { this.frm.doc = doc_data[0][this.name]; this.set_missing_values(); this.refresh(false); this.toggle_input_field(); this.list_dialog && this.list_dialog.hide(); } }, delete_records: function () { var me = this; this.validate_list() this.remove_doc_from_localstorage() this.update_localstorage(); // this.dialog_actions(); this.toggle_delete_button(); }, validate_list: function() { var me = this; this.si_docs = this.get_submitted_invoice() $.each(this.removed_items, function(index, name){ $.each(me.si_docs, function(key, data){ if(me.si_docs[key][name] && me.si_docs[key][name].offline_pos_name == name ){ frappe.throw(__("Submitted orders can not be deleted")) } }) }) }, toggle_delete_button: function () { var me = this; if(this.pos_profile_data["allow_delete"]) { if (this.removed_items && this.removed_items.length > 0) { $(this.page.wrapper).find('.btn-danger').show(); } else { $(this.page.wrapper).find('.btn-danger').hide(); } } }, get_doctype_status: function (doc) { if (doc.docstatus == 0) { return { status: "Draft", indicator: "red" } } else if (doc.outstanding_amount == 0) { return { status: "Paid", indicator: "green" } } else { return { status: "Submitted", indicator: "blue" } } }, set_missing_values: function () { var me = this; doc = JSON.parse(localStorage.getItem('doc')) if (this.frm.doc.payments.length == 0) { this.frm.doc.payments = doc.payments; this.calculate_outstanding_amount(); } if (this.frm.doc.customer) { this.party_field.$input.val(this.frm.doc.customer); } if (!this.frm.doc.write_off_account) { this.frm.doc.write_off_account = doc.write_off_account } if (!this.frm.doc.account_for_change_amount) { this.frm.doc.account_for_change_amount = doc.account_for_change_amount } }, get_invoice_doc: function (si_docs) { var me = this; this.si_docs = this.get_doc_from_localstorage(); return $.grep(this.si_docs, function (data) { for (key in data) { return key == me.name } }) }, get_data_from_server: function (callback) { var me = this; frappe.call({ method: "erpnext.accounts.doctype.sales_invoice.pos.get_pos_data", freeze: true, freeze_message: __("Master data syncing, it might take some time"), callback: function (r) { localStorage.setItem('doc', JSON.stringify(r.message.doc)); me.init_master_data(r) me.set_interval_for_si_sync(); me.check_internet_connection(); if (callback) { callback(); } } }) }, init_master_data: function (r) { var me = this; this.doc = JSON.parse(localStorage.getItem('doc')); this.meta = r.message.meta; this.item_data = r.message.items; this.item_groups = r.message.item_groups; this.customers = r.message.customers; this.serial_no_data = r.message.serial_no_data; this.batch_no_data = r.message.batch_no_data; this.tax_data = r.message.tax_data; this.contacts = r.message.contacts; this.address = r.message.address || {}; this.price_list_data = r.message.price_list_data; this.bin_data = r.message.bin_data; this.pricing_rules = r.message.pricing_rules; this.print_template = r.message.print_template; this.pos_profile_data = r.message.pos_profile; this.default_customer = r.message.default_customer || null; this.print_settings = locals[":Print Settings"]["Print Settings"]; this.letter_head = (this.pos_profile_data.length > 0) ? frappe.boot.letter_heads[this.pos_profile_data[letter_head]] : {}; }, save_previous_entry: function () { if (this.frm.doc.docstatus < 1 && this.frm.doc.items.length > 0) { this.create_invoice(); } }, create_new: function () { var me = this; this.frm = {} this.name = null; this.load_data(true); this.setup(); this.set_default_customer() }, load_data: function (load_doc) { var me = this; this.items = this.item_data; this.actual_qty_dict = {}; if (load_doc) { this.frm.doc = JSON.parse(localStorage.getItem('doc')); } $.each(this.meta, function (i, data) { frappe.meta.sync(data) locals["DocType"][data.name] = data; }) this.print_template_data = frappe.render_template("print_template", { content: this.print_template, title: "POS", base_url: frappe.urllib.get_base_url(), print_css: frappe.boot.print_css, print_settings: this.print_settings, header: this.letter_head.header, footer: this.letter_head.footer, landscape: false, columns: [] }) }, setup: function () { this.make(); this.set_primary_action(); this.party_field.$input.attr('disabled', false); if(this.selected_row) { this.selected_row.hide() } }, set_default_customer: function() { if (this.default_customer && !this.frm.doc.customer) { this.party_field.$input.val(this.default_customer); this.frm.doc.customer = this.default_customer; this.numeric_keypad.show(); this.toggle_list_customer(false) this.toggle_item_cart(true) } }, set_transaction_defaults: function (party) { var me = this; this.party = party; this.price_list = (party == "Customer" ? this.frm.doc.selling_price_list : this.frm.doc.buying_price_list); this.price_list_field = (party == "Customer" ? "selling_price_list" : "buying_price_list"); this.sales_or_purchase = (party == "Customer" ? "Sales" : "Purchase"); }, make: function () { this.make_item_list(); this.make_discount_field() }, make_control: function() { this.frm = {} this.frm.doc = this.doc this.set_transaction_defaults("Customer"); this.frm.doc["allow_user_to_edit_rate"] = this.pos_profile_data["allow_user_to_edit_rate"] ? true : false, this.wrapper.html(frappe.render_template("pos", this.frm.doc)); this.make_search(); this.make_customer(); this.make_list_customers(); this.bind_numeric_keypad(); }, make_search: function () { var me = this; this.serach_item = frappe.ui.form.make_control({ df: { "fieldtype": "Data", "label": "Item", "fieldname": "pos_item", "placeholder": __("Search Item") }, parent: this.wrapper.find(".search-item"), only_input: true, }); this.serach_item.make_input(); this.serach_item.$input.on("keypress", function (event) { clearTimeout(me.last_search_timeout); me.last_search_timeout = setTimeout(() => { if((me.serach_item.$input.val() != "") || (event.which == 13)) { me.items = me.get_items(); me.make_item_list(); } }, 400); }); this.search_item_group = this.wrapper.find('.search-item-group'); sorted_item_groups = this.get_sorted_item_groups() var dropdown_html = sorted_item_groups.map(function(item_group) { return "
' + html + '
') .get(0); } }); this.prepare_customer_mapper() this.autocomplete_customers(); this.party_field.$input .on('input', function (e) { me.party_field.awesomeplete.list = me.customers_mapper; }) .on('awesomplete-select', function (e) { var customer = me.party_field.awesomeplete .get_item(e.originalEvent.text.value); if (!customer) return; // create customer link if (customer.action) { customer.action.apply(me); return; } me.toggle_list_customer(false); me.toggle_edit_button(true); me.update_customer_data(customer); me.refresh(); me.set_focus(); me.list_customers_btn.removeClass("view_customer"); }) .on('focus', function (e) { $(e.target).val('').trigger('input'); me.toggle_edit_button(false); if(me.frm.doc.items.length) { me.toggle_list_customer(false) me.toggle_item_cart(true) } else { me.toggle_list_customer(true) me.toggle_item_cart(false) } }) .on("awesomplete-selectcomplete", function (e) { var item = me.party_field.awesomeplete .get_item(e.originalEvent.text.value); // clear text input if item is action if (item.action) { $(this).val(""); } }); }, prepare_customer_mapper: function() { var me = this; this.customers_mapper = this.customers.map(function (c) { contact = me.contacts[c.name]; return { label: c.name, value: c.name, customer_name: c.customer_name, customer_group: c.customer_group, territory: c.territory, phone: contact ? contact["phone"] : '', mobile_no: contact ? contact["mobile_no"] : '', email_id: contact ? contact["email_id"] : '', searchtext: ['customer_name', 'customer_group', 'value', 'label', 'email_id', 'phone', 'mobile_no'] .map(key => c[key]).join(' ') .toLowerCase() } }); this.customers_mapper.push({ label: "" + " " + __("Create a new Customer") + "", value: 'is_action', action: me.add_customer }); }, autocomplete_customers: function() { this.party_field.awesomeplete.list = this.customers_mapper; }, toggle_edit_button: function(flag) { this.page.wrapper.find('.edit-customer-btn').toggle(flag); }, toggle_list_customer: function(flag) { this.list_customers.toggle(flag); }, toggle_item_cart: function(flag) { this.wrapper.find('.pos-bill-wrapper').toggle(flag); }, add_customer: function() { this.frm.doc.customer = ""; this.update_customer(true); this.numeric_keypad.show(); }, update_customer: function (new_customer) { var me = this; this.customer_doc = new frappe.ui.Dialog({ 'title': 'Customer', fields: [ { "label": __("Full Name"), "fieldname": "full_name", "fieldtype": "Data", "reqd": 1 }, { "fieldtype": "Section Break" }, { "label": __("Email Id"), "fieldname": "email_id", "fieldtype": "Data" }, { "fieldtype": "Column Break" }, { "label": __("Contact Number"), "fieldname": "phone", "fieldtype": "Data" }, { "fieldtype": "Section Break" }, { "label": __("Address Name"), "read_only": 1, "fieldname": "name", "fieldtype": "Data" }, { "label": __("Address Line 1"), "fieldname": "address_line1", "fieldtype": "Data" }, { "label": __("Address Line 2"), "fieldname": "address_line2", "fieldtype": "Data" }, { "fieldtype": "Column Break" }, { "label": __("City"), "fieldname": "city", "fieldtype": "Data" }, { "label": __("State"), "fieldname": "state", "fieldtype": "Data" }, { "label": __("ZIP Code"), "fieldname": "pincode", "fieldtype": "Data" }, { "label": __("Customer POS Id"), "fieldname": "customer_pos_id", "fieldtype": "Data", "hidden": 1 } ] }) this.customer_doc.show() this.render_address_data() this.customer_doc.set_primary_action(__("Save"), function () { me.make_offline_customer(new_customer); me.pos_bill.show(); me.list_customers.hide(); }); }, render_address_data: function() { var me = this; this.address_data = this.address[this.frm.doc.customer] || {}; if(!this.address_data.email_id || !this.address_data.phone) { this.address_data = this.contacts[this.frm.doc.customer]; } this.customer_doc.set_values(this.address_data) if(!this.customer_doc.fields_dict.full_name.$input.val()) { this.customer_doc.set_value("full_name", this.frm.doc.customer) } if(!this.customer_doc.fields_dict.customer_pos_id.value) { this.customer_doc.set_value("customer_pos_id", $.now()) } }, get_address_from_localstorage: function() { this.address_details = this.get_customers_details() return this.address_details[this.frm.doc.customer] }, make_offline_customer: function(new_customer) { this.frm.doc.customer = this.frm.doc.customer || this.customer_doc.get_values().full_name; this.frm.doc.customer_pos_id = this.customer_doc.fields_dict.customer_pos_id.value; this.customer_details = this.get_customers_details(); this.customer_details[this.frm.doc.customer] = this.get_prompt_details(); this.party_field.$input.val(this.frm.doc.customer); this.update_address_and_customer_list(new_customer) this.autocomplete_customers(); this.update_customer_in_localstorage() this.update_customer_in_localstorage() this.customer_doc.hide() }, update_address_and_customer_list: function(new_customer) { var me = this; if(new_customer) { this.customers_mapper.push({ label: this.frm.doc.customer, value: this.frm.doc.customer, customer_group: "", territory: "" }); } this.address[this.frm.doc.customer] = JSON.parse(this.get_prompt_details()) }, get_prompt_details: function() { this.prompt_details = this.customer_doc.get_values(); this.prompt_details['country'] = this.pos_profile_data.country; this.prompt_details['territory'] = this.pos_profile_data["territory"]; this.prompt_details['customer_group'] = this.pos_profile_data["customer_group"]; this.prompt_details['customer_pos_id'] = this.customer_doc.fields_dict.customer_pos_id.value; return JSON.stringify(this.prompt_details) }, update_customer_data: function (doc) { var me = this; this.frm.doc.customer = doc.label || doc.name; this.frm.doc.customer_name = doc.customer_name; this.frm.doc.customer_group = doc.customer_group; this.frm.doc.territory = doc.territory; this.pos_bill.show(); this.numeric_keypad.show(); }, make_item_list: function () { var me = this; if (!this.price_list) { frappe.msgprint(__("Price List not found or disabled")); return; } me.item_timeout = null; var $wrap = me.wrapper.find(".item-list"); me.wrapper.find(".item-list").empty(); if (this.items.length > 0) { $.each(this.items, function(index, obj) { if(index < me.page_len) { $(frappe.render_template("pos_item", { item_code: obj.name, item_price: format_currency(me.price_list_data[obj.name], me.frm.doc.currency), item_name: obj.name === obj.item_name ? "" : obj.item_name, item_image: obj.image, item_stock: __('Stock Qty') + ": " + me.get_actual_qty(obj), color: frappe.get_palette(obj.item_name), abbr: frappe.get_abbr(obj.item_name) })).tooltip().appendTo($wrap); } }); $wrap.append(`" +__("Not items found")+"
").appendTo($wrap) } if (this.items.length == 1 && this.serach_item.$input.val()) { this.serach_item.$input.val(""); this.add_to_cart(); } }, get_items: function (item_code) { // To search item as per the key enter var me = this; this.item_serial_no = {}; this.item_batch_no = {}; if (item_code) { return $.grep(this.item_data, function (item) { if (item.item_code == item_code) { return true } }) } this.items_list = this.apply_category(); key = this.serach_item.$input.val().toLowerCase().replace(/[&\/\\#,+()\[\]$~.'":*?<>{}]/g, '\\$&'); var re = new RegExp('%', 'g'); var reg = new RegExp(key.replace(re, '[\\w*\\s*[a-zA-Z0-9]*]*')) search_status = true if (key) { return $.grep(this.items_list, function (item) { if (search_status) { if (in_list(me.batch_no_data[item.item_code], me.serach_item.$input.val())) { search_status = false; return me.item_batch_no[item.item_code] = me.serach_item.$input.val() } else if (me.serial_no_data[item.item_code] && in_list(Object.keys(me.serial_no_data[item.item_code]), me.serach_item.$input.val())) { search_status = false; me.item_serial_no[item.item_code] = [me.serach_item.$input.val(), me.serial_no_data[item.item_code][me.serach_item.$input.val()]] return true } else if (item.barcode == me.serach_item.$input.val()) { search_status = false; return item.barcode == me.serach_item.$input.val(); } else if (reg.test(item.item_code.toLowerCase()) || (item.description && reg.test(item.description.toLowerCase())) || reg.test(item.item_name.toLowerCase()) || reg.test(item.item_group.toLowerCase())) { return true } } }) } else { return this.items_list; } }, apply_category: function() { var me = this; category = this.selected_item_group || "All Item Groups"; if(category == 'All Item Groups') { return this.item_data } else { return this.item_data.filter(function(element, index, array){ return element.item_group == category; }); } }, bind_items_event: function() { var me = this; $(this.wrapper).on('click', '.pos-bill-item', function() { $(me.wrapper).find('.pos-bill-item').removeClass('active'); $(this).addClass('active'); me.numeric_val = ""; me.numeric_id = "" me.item_code = $(this).attr("data-item-code"); me.render_selected_item() me.bind_qty_event() me.update_rate() $(me.wrapper).find(".selected-item").scrollTop(1000); }) }, bind_qty_event: function () { var me = this; $(this.wrapper).on("change", ".pos-item-qty", function () { var item_code = $(this).parents(".pos-selected-item-action").attr("data-item-code"); var qty = $(this).val(); me.update_qty(item_code, qty) me.update_value() }) $(this.wrapper).find("[data-action='increase-qty']").on("click", function () { var item_code = $(this).parents(".pos-bill-item").attr("data-item-code"); var qty = flt($(this).parents(".pos-bill-item").find('.pos-item-qty').val()) + 1; me.update_qty(item_code, qty) }) $(this.wrapper).find("[data-action='decrease-qty']").on("click", function () { var item_code = $(this).parents(".pos-bill-item").attr("data-item-code"); var qty = flt($(this).parents(".pos-bill-item").find('.pos-item-qty').val()) - 1; me.update_qty(item_code, qty) }) $(this.wrapper).on("change", ".pos-item-disc", function () { var item_code = $(this).parents(".pos-selected-item-action").attr("data-item-code"); var discount = $(this).val(); me.update_discount(item_code, discount) me.update_value() }) }, bind_events: function() { var me = this; // if form is local then allow this function // $(me.wrapper).find(".pos-item-wrapper").on("click", function () { $(this.wrapper).on("click", ".pos-item-wrapper", function () { me.item_code = ''; me.customer_validate(); if($(me.pos_bill).is(":hidden")) return; if (me.frm.doc.docstatus == 0) { me.items = me.get_items($(this).attr("data-item-code")) me.add_to_cart(); me.clear_selected_row(); } }); me.bind_delete_event() }, update_qty: function (item_code, qty) { var me = this; this.items = this.get_items(item_code); this.validate_serial_no() this.set_item_details(item_code, "qty", qty); }, update_discount: function(item_code, discount) { var me = this; this.items = this.get_items(item_code); this.set_item_details(item_code, "discount_percentage", discount); }, update_rate: function () { var me = this; $(this.wrapper).on("change", ".pos-item-price", function () { var item_code = $(this).parents(".pos-selected-item-action").attr("data-item-code"); me.set_item_details(item_code, "rate", $(this).val()); me.update_value() }) }, update_value: function() { var me = this; var fields = {qty: ".pos-item-qty", "discount_percentage": ".pos-item-disc", "rate": ".pos-item-price", "amount": ".pos-amount"} this.child_doc = this.get_child_item(this.item_code); if(me.child_doc.length) { $.each(fields, function(key, field) { $(me.selected_row).find(field).val(me.child_doc[0][key]) }) } else { this.clear_selected_row(); } }, clear_selected_row: function() { $(this.wrapper).find('.selected-item').empty(); }, render_selected_item: function() { this.child_doc = this.get_child_item(this.item_code); $(this.wrapper).find('.selected-item').empty(); if(this.child_doc.length) { this.child_doc[0]["allow_user_to_edit_rate"] = this.pos_profile_data["allow_user_to_edit_rate"] ? true : false, this.selected_row = $(frappe.render_template("pos_selected_item", this.child_doc[0])) $(this.wrapper).find('.selected-item').html(this.selected_row) } $(this.selected_row).find('.form-control').click(function(){ $(this).select(); }) }, get_child_item: function(item_code) { var me = this; return $.map(me.frm.doc.items, function(doc){ if(doc.item_code == item_code) { return doc } }) }, set_item_details: function (item_code, field, value) { var me = this; if (value < 0) { frappe.throw(__("Enter value must be positive")); } this.remove_item = [] $.each(this.frm.doc["items"] || [], function (i, d) { if (d.item_code == item_code) { if (d.serial_no && field == 'qty') { me.validate_serial_no_qty(d, item_code, field, value) } d[field] = flt(value); d.amount = flt(d.rate) * flt(d.qty); if (d.qty == 0) { me.remove_item.push(d.idx) } if(field=="discount_percentage" && value == 0) { d.rate = d.price_list_rate; } } }); if (field == 'qty') { this.remove_zero_qty_item(); } this.update_paid_amount_status(false) }, remove_zero_qty_item: function () { var me = this; var idx = 0; this.items = [] $.each(this.frm.doc["items"] || [], function (i, d) { if (!in_list(me.remove_item, d.idx)) { d.idx = idx; me.items.push(d); idx++; } }); this.frm.doc["items"] = this.items; }, make_discount_field: function () { var me = this; this.wrapper.find('input.discount-percentage').on("change", function () { me.frm.doc.additional_discount_percentage = flt($(this).val(), precision("additional_discount_percentage")); var total = me.frm.doc.grand_total if (me.frm.doc.apply_discount_on == 'Net Total') { total = me.frm.doc.net_total } me.frm.doc.discount_amount = flt(total * flt(me.frm.doc.additional_discount_percentage) / 100, precision("discount_amount")); me.wrapper.find('input.discount-amount').val(me.frm.doc.discount_amount) me.refresh(); }); this.wrapper.find('input.discount-amount').on("change", function () { me.frm.doc.discount_amount = flt($(this).val(), precision("discount_amount")); me.frm.doc.additional_discount_percentage = 0.0; me.wrapper.find('input.discount-percentage').val(0); me.refresh(); }); }, customer_validate: function () { var me = this; if (!this.frm.doc.customer || this.party_field.get_value() == "") { frappe.throw(__("Please select customer")) } }, add_to_cart: function () { var me = this; var caught = false; var no_of_items = me.wrapper.find(".pos-bill-item").length; this.customer_validate(); this.mandatory_batch_no(); this.validate_serial_no(); this.validate_warehouse(); if (no_of_items != 0) { $.each(this.frm.doc["items"] || [], function (i, d) { if (d.item_code == me.items[0].item_code) { caught = true; d.qty += 1; d.amount = flt(d.rate) * flt(d.qty); if (me.item_serial_no[d.item_code]) { d.serial_no += '\n' + me.item_serial_no[d.item_code][0] d.warehouse = me.item_serial_no[d.item_code][1] } if (me.item_batch_no.length) { d.batch_no = me.item_batch_no[d.item_code] } } }); } // if item not found then add new item if (!caught) this.add_new_item_to_grid(); this.update_paid_amount_status(false) this.wrapper.find(".item-cart-items").scrollTop(1000); }, add_new_item_to_grid: function () { var me = this; this.child = frappe.model.add_child(this.frm.doc, this.frm.doc.doctype + " Item", "items"); this.child.item_code = this.items[0].item_code; this.child.item_name = this.items[0].item_name; this.child.stock_uom = this.items[0].stock_uom; this.child.brand = this.items[0].brand; this.child.description = this.items[0].description || this.items[0].item_name; this.child.discount_percentage = 0.0; this.child.qty = 1; this.child.item_group = this.items[0].item_group; this.child.cost_center = this.pos_profile_data['cost_center'] || this.items[0].cost_center; this.child.income_account = this.pos_profile_data['income_account'] || this.items[0].income_account; this.child.warehouse = (this.item_serial_no[this.child.item_code] ? this.item_serial_no[this.child.item_code][1] : (this.pos_profile_data['warehouse'] || this.items[0].default_warehouse)); this.child.price_list_rate = flt(this.price_list_data[this.child.item_code], 9) / flt(this.frm.doc.conversion_rate, 9); this.child.rate = flt(this.price_list_data[this.child.item_code], 9) / flt(this.frm.doc.conversion_rate, 9); this.child.actual_qty = me.get_actual_qty(this.items[0]); this.child.amount = flt(this.child.qty) * flt(this.child.rate); this.child.batch_no = this.item_batch_no[this.child.item_code]; this.child.serial_no = (this.item_serial_no[this.child.item_code] ? this.item_serial_no[this.child.item_code][0] : ''); this.child.item_tax_rate = JSON.stringify(this.tax_data[this.child.item_code]); }, update_paid_amount_status: function (update_paid_amount) { if (this.name) { update_paid_amount = update_paid_amount ? false : true; } this.refresh(update_paid_amount); }, refresh: function (update_paid_amount) { var me = this; this.refresh_fields(update_paid_amount); this.set_primary_action(); }, refresh_fields: function (update_paid_amount) { this.apply_pricing_rule(); this.discount_amount_applied = false; this._calculate_taxes_and_totals(); this.calculate_discount_amount(); this.show_items_in_item_cart(); this.set_taxes(); this.calculate_outstanding_amount(update_paid_amount); this.set_totals(); }, get_company_currency: function () { return erpnext.get_currency(this.frm.doc.company); }, show_items_in_item_cart: function () { var me = this; var $items = this.wrapper.find(".items").empty(); var $no_items_message = this.wrapper.find(".no-items-message"); $no_items_message.toggle(this.frm.doc.items.length === 0); var $totals_area = this.wrapper.find('.totals-area'); $totals_area.toggle(this.frm.doc.items.length > 0); $.each(this.frm.doc.items || [], function (i, d) { $(frappe.render_template("pos_bill_item_new", { item_code: d.item_code, item_name: (d.item_name === d.item_code || !d.item_name) ? "" : ("