diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py index 476ce45a1a1..d24df3abac0 100644 --- a/erpnext/accounts/doctype/sales_invoice/pos.py +++ b/erpnext/accounts/doctype/sales_invoice/pos.py @@ -26,13 +26,15 @@ def get_pos_data(): update_multi_mode_option(doc, pos_profile) default_print_format = pos_profile.get('print_format') or "Point of Sale" print_template = frappe.db.get_value('Print Format', default_print_format, 'html') + customers = get_customers_list(pos_profile) return { 'doc': doc, 'default_customer': pos_profile.get('customer'), 'items': get_items_list(pos_profile), 'item_groups': get_item_group(pos_profile), - 'customers': get_customers_list(pos_profile), + 'customers': customers, + 'address': get_customers_address(customers), 'serial_no_data': get_serial_no_data(pos_profile, doc.company), 'batch_no_data': get_batch_no_data(), 'tax_data': get_item_tax_data(), @@ -164,6 +166,19 @@ def get_customers_list(pos_profile): territory from tabCustomer where disabled = 0 and {cond}""".format(cond=cond), tuple(customer_groups), as_dict=1) or {} +def get_customers_address(customers): + customer_address = {} + for data in customers: + address = frappe.db.sql(""" select name, address_line1, address_line2, city, state, + email_id, phone, fax, pincode from `tabAddress` where is_primary_address =1 and name in + (select parent from `tabDynamic Link` where link_doctype = 'Customer' and link_name = %s + and parenttype = 'Address')""", data.name, as_dict=1) + if address: + address_data = address[0] + address_data.update({'full_name': data.customer_name}) + customer_address[data.name] = address_data + return customer_address + def get_child_nodes(group_type, root): lft, rgt = frappe.db.get_value(group_type, root, ["lft", "rgt"]) return frappe.db.sql_list(""" Select name from `tab{tab}` where @@ -258,13 +273,17 @@ def get_pricing_rule_data(doc): return pricing_rules @frappe.whitelist() -def make_invoice(doc_list, email_queue_list): +def make_invoice(doc_list, email_queue_list, customers_list): if isinstance(doc_list, basestring): doc_list = json.loads(doc_list) if isinstance(email_queue_list, basestring): email_queue = json.loads(email_queue_list) + if isinstance(customers_list, basestring): + customers = json.loads(customers_list) + + customers = make_customer_and_address(customers) name_list = [] for docs in doc_list: for name, doc in docs.items(): @@ -281,13 +300,49 @@ def make_invoice(doc_list, email_queue_list): email_queue = make_email_queue(email_queue) return { 'invoice': name_list, - 'email_queue': email_queue + 'email_queue': email_queue, + 'customers': customers } def validate_records(doc): - validate_customer(doc) validate_item(doc) +def make_customer_and_address(customers): + customer_list = [] + for name, data in customers.items(): + if not frappe.db.exists('Customer', name): + name = add_customer(name) + data = json.loads(data) + make_address(data, name) + customer_list.append(name) + return customer_list + +def add_customer(name): + customer_doc = frappe.new_doc('Customer') + customer_doc.customer_name = name + customer_doc.customer_type = 'Company' + customer_doc.customer_group = frappe.db.get_single_value('Selling Settings', 'customer_group') + customer_doc.territory = frappe.db.get_single_value('Selling Settings', 'territory') + customer_doc.flags.ignore_mandatory = True + customer_doc.save(ignore_permissions = True) + frappe.db.commit() + +def make_address(args, customer): + if args.get('name'): + address = frappe.get_doc('Address', args.get('name')) + address.is_primary_address = 1 + address.is_shipping_address = 1 + else: + address = frappe.new_doc('Address') + address.country = frappe.db.get_value('Company', args.get('company'), 'country') + address.append('links',{ + 'link_doctype': 'Customer', + 'link_name': customer + }) + + address.update(args) + address.save(ignore_permissions = True) + def make_email_queue(email_queue): name_list = [] for key, data in email_queue.items(): @@ -304,39 +359,6 @@ def make_email_queue(email_queue): return name_list -def validate_customer(doc): - if not frappe.db.exists('Customer', doc.get('customer')): - customer_doc = frappe.new_doc('Customer') - customer_doc.customer_name = doc.get('customer') - customer_doc.customer_type = 'Company' - customer_doc.customer_group = frappe.db.get_single_value('Selling Settings', 'customer_group') - customer_doc.territory = frappe.db.get_single_value('Selling Settings', 'territory') - customer_doc.flags.ignore_mandatory = True - customer_doc.save(ignore_permissions = True) - frappe.db.commit() - doc['customer'] = customer_doc.name - if doc.get('contact_details'): - args = json.loads(doc.get("contact_details")) - make_address(doc, args, customer_doc.name) - -def make_address(doc, args, customer): - if args.get("address_line1"): - address = frappe.new_doc('Address') - address.address_line1 = args.get('address_line1') - address.address_line2 = args.get('address_line2') - address.city = args.get('city') - address.state = args.get('state') - address.zip_code = args.get('zip_code') - address.email_id = args.get('email_id') - address.flags.ignore_mandatory = True - address.country = frappe.db.get_value('Company', doc.get('company'), 'country') - address.append('links',{ - 'link_doctype': 'Customer', - 'link_name': customer - }) - address.save(ignore_permissions = True) - frappe.db.commit() - def validate_item(doc): for item in doc.get('items'): if not frappe.db.exists('Item', item.get('item_code')): diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js index bd1372b5018..8cc393d4c70 100644 --- a/erpnext/accounts/page/pos/pos.js +++ b/erpnext/accounts/page/pos/pos.js @@ -154,6 +154,14 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ } }, + get_customers_details: function () { + try { + return JSON.parse(localStorage.getItem('customer_details')) || {}; + } catch (e) { + return {} + } + }, + dialog_actions: function () { var me = this; @@ -289,6 +297,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ 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.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; @@ -406,6 +415,10 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ me.items = me.get_items(); me.make_item_list(); }) + + this.wrapper.find(".edit-customer-btn").on("click", function() { + me.update_customer() + }) }, make_list_customers: function () { @@ -609,7 +622,11 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ }, item: function (item, input) { var d = item; - var html = "" + __(d.label || d.value) + ""; + var html = "" + __(d.label || d.value) + "\ + \ + \ + \ + "; return $('
  • ') .data('item.autocomplete', d) .html('

    ' + html + '

    ') @@ -631,7 +648,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ + __("Create a new Customer") + "", value: 'is_action', - action: me.new_customer + action: me.add_customer }); this.party_field.awesomeplete.list = customers; @@ -652,11 +669,6 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ me.refresh(); me.set_focus(); }) - .on('change', function (e) { - if (!e.originalEvent.text) { - me.frm.doc.customer = $(this).val(); - } - }) .on('focus', function (e) { $(e.target).val('').trigger('input'); }) @@ -670,7 +682,12 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ }); }, - new_customer: function () { + add_customer: function() { + this.frm.doc.customer = ""; + this.update_customer() + }, + + update_customer: function () { var me = this; if (!this.connection_status) return; @@ -696,7 +713,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ }, { "label": __("Contact Number"), - "fieldname": "contact_no", + "fieldname": "phone", "fieldtype": "Data" }, { @@ -712,6 +729,11 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ "fieldname": "address_line2", "fieldtype": "Data" }, + { + "label": __("Fax"), + "fieldname": "fax", + "fieldtype": "Data" + }, { "fieldtype": "Column Break" }, @@ -727,13 +749,20 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ }, { "label": __("ZIP Code"), - "fieldname": "zip_code", + "fieldname": "pincode", + "fieldtype": "Data" + }, + { + "label": __("ZIP Code"), + "hidden": 1, + "fieldname": "name", "fieldtype": "Data" } ] }) this.customer_doc.show() + this.render_address_data() this.customer_doc.set_primary_action(__("Save"), function () { me.make_offline_customer(); @@ -741,18 +770,45 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ }); }, + render_address_data: function() { + var me = this; + this.address_data = this.address[this.frm.doc.customer] || this.get_address_from_localstorage(); + prompt_obj = me.customer_doc.fields_dict; + $.each(this.address_data, function(key, value){ + if(prompt_obj[key] && key!='name') { + prompt_obj[key].$input.val(value) + } + }) + + if(!prompt_obj.full_name.$input.val()) { + prompt_obj.full_name.$input.val(this.frm.doc.customer) + } + }, + + get_address_from_localstorage: function() { + this.address_details = this.get_customers_details() + return this.address_details[this.frm.doc.customer] + }, + make_offline_customer: function() { - this.frm.doc.customer = this.customer_doc.get_values().full_name; - this.frm.doc.contact_details = JSON.stringify(this.customer_doc.get_values()); + this.frm.doc.customer = this.frm.doc.customer || this.customer_doc.get_values().full_name; + this.customer_details[this.frm.doc.customer] = this.get_prompt_details(); this.party_field.$input.val(this.frm.doc.customer); this.customers.push({ name: this.frm.doc.customer, customer_name: this.frm.doc.customer }); - + this.update_customer_in_localstorage() + this.update_customer_in_localstorage() this.customer_doc.hide() }, + get_prompt_details: function() { + this.prompt_details = this.customer_doc.get_values(); + this.prompt_details['country'] = this.frm.doc.country; + return JSON.stringify(this.prompt_details) + }, + update_customer_data: function (doc) { var me = this; this.frm.doc.customer = doc.label || doc.name; @@ -1368,20 +1424,24 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ var me = this; this.si_docs = this.get_submitted_invoice() || []; this.email_queue_list = this.get_email_queue() || {}; + this.customers_list = this.get_customers_details() || {}; if (this.si_docs.length || this.email_queue_list) { frappe.call({ method: "erpnext.accounts.doctype.sales_invoice.pos.make_invoice", args: { doc_list: me.si_docs, - email_queue_list: me.email_queue_list + email_queue_list: me.email_queue_list, + customers_list: me.customers_list }, callback: function (r) { if (r.message) { me.removed_items = r.message.invoice; me.removed_email = r.message.email_queue + me.removed_customers = r.message.customers me.remove_doc_from_localstorage(); me.remove_email_queue_from_localstorage(); + me.remove_customer_from_localstorage(); } } }) @@ -1437,6 +1497,19 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ } }, + remove_customer_from_localstorage: function() { + var me = this; + this.customer_details = this.get_customers_details() + if (this.removed_customers) { + $.each(this.customers_list, function (index, data) { + if (in_list(me.removed_customers, index)) { + delete me.customer_details[index] + } + }) + this.update_customer_in_localstorage(); + } + }, + validate: function () { var me = this; this.customer_validate(); @@ -1621,5 +1694,14 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ } return this.actual_qty + }, + + update_customer_in_localstorage: function() { + var me = this; + try { + localStorage.setItem('customer_details', JSON.stringify(this.customer_details)); + } catch (e) { + frappe.throw(__("LocalStorage is full , did not save")) + } } }) \ No newline at end of file diff --git a/erpnext/public/js/pos/pos.html b/erpnext/public/js/pos/pos.html index 3dbf03c15e8..827c79467aa 100644 --- a/erpnext/public/js/pos/pos.html +++ b/erpnext/public/js/pos/pos.html @@ -1,23 +1,68 @@
    -
    -
    -
    -
    {%= __("Net Total") %}
    -
    -
    -
    -
    -
    {%= __("Taxes") %}
    -
    +
    +
    +
    Item Cart
    +
    +
    +
    + + + {{ __("Item Name")}} + + {{ __("Quantity") }} + {{ __("Discount") }} + {{ __("Rate") }} +
    +
    +
    + + +

    Tap items to add them here

    +
    -
    - {% if (apply_discount_on) { %} -
    -
    {%= __("Discount") %}
    -
    -
    - % - +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    {%= __("Net Total") %}
    +
    +
    +
    +
    +
    +
    {%= __("Taxes") %}
    +
    +
    + {% if (apply_discount_on) { %} +
    +
    {%= __("Discount") %}
    +
    +
    + % + +
    +
    +
    +
    + {%= get_currency_symbol(currency) %} + +
    +
    +
    + {% } %} +
    +
    +
    {%= __("Grand Total") %}
    +
    +
    +
    +
    +
    -
    +
    + +
    +
    Stock Items
    -
    -
    + +
    -
    All Item Groups
    -
    -
    -
    +
    + +
    +
    -<<<<<<< 889e91312e9cfe10a2fd38ba7864e7c7546f4de8 -
    +
    -======= - -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    - -
    -
    -
    ->>>>>>> offline email for POS -
    +
    \ No newline at end of file