From 6773bc251273855b5352c332116c13e68c0e8847 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Tue, 17 Sep 2013 11:56:17 +0530 Subject: [PATCH 1/8] [pos] [minor] added pos in sales order for testing --- .../doctype/sales_invoice/sales_invoice.js | 82 +++++++++---------- .../p03_buying_selling_for_price_list.py | 2 +- public/js/transaction.js | 58 ++++++++++++- selling/doctype/sales_order/sales_order.js | 1 + 4 files changed, 95 insertions(+), 48 deletions(-) diff --git a/accounts/doctype/sales_invoice/sales_invoice.js b/accounts/doctype/sales_invoice/sales_invoice.js index 60f73b5a19..73958fb672 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.js +++ b/accounts/doctype/sales_invoice/sales_invoice.js @@ -82,10 +82,6 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte cur_frm.cscript.sales_order_btn(); cur_frm.cscript.delivery_note_btn(); } - - // Show POS button only if it enabled from features setup - if(cint(sys_defaults.fs_pos_view)===1) - cur_frm.cscript.pos_btn(); }, sales_order_btn: function() { @@ -125,53 +121,53 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte }); }, - pos_btn: function() { - if(cur_frm.$pos_btn) - cur_frm.$pos_btn.remove(); + // pos_btn: function() { + // if(cur_frm.$pos_btn) + // cur_frm.$pos_btn.remove(); - if(!cur_frm.pos_active) { - var btn_label = wn._("POS View"), - icon = "icon-desktop"; + // if(!cur_frm.pos_active) { + // var btn_label = wn._("POS View"), + // icon = "icon-desktop"; - cur_frm.cscript.sales_order_btn(); - cur_frm.cscript.delivery_note_btn(); - } else { - var btn_label = wn._("Invoice View"), - icon = "icon-file-text"; + // cur_frm.cscript.sales_order_btn(); + // cur_frm.cscript.delivery_note_btn(); + // } else { + // var btn_label = wn._("Invoice View"), + // icon = "icon-file-text"; - if (cur_frm.doc.docstatus===0) { - this.$delivery_note_btn.remove(); - this.$sales_order_btn.remove(); - } - } + // if (cur_frm.doc.docstatus===0) { + // this.$delivery_note_btn.remove(); + // this.$sales_order_btn.remove(); + // } + // } - cur_frm.$pos_btn = cur_frm.add_custom_button(btn_label, function() { - cur_frm.cscript.toggle_pos(); - cur_frm.cscript.pos_btn(); - }, icon); - }, + // cur_frm.$pos_btn = cur_frm.add_custom_button(btn_label, function() { + // cur_frm.cscript.toggle_pos(); + // cur_frm.cscript.pos_btn(); + // }, icon); + // }, - toggle_pos: function(show) { - if (!this.frm.doc.selling_price_list) - msgprint(wn._("Please select Price List")) - else { - if((show===true && cur_frm.pos_active) || (show===false && !cur_frm.pos_active)) return; + // toggle_pos: function(show) { + // if (!this.frm.doc.selling_price_list) + // msgprint(wn._("Please select Price List")) + // else { + // if((show===true && cur_frm.pos_active) || (show===false && !cur_frm.pos_active)) return; - // make pos - if(!cur_frm.pos) { - cur_frm.layout.add_view("pos"); - cur_frm.pos = new erpnext.POS(cur_frm.layout.views.pos, cur_frm); - } + // // make pos + // if(!cur_frm.pos) { + // cur_frm.layout.add_view("pos"); + // cur_frm.pos = new erpnext.POS(cur_frm.layout.views.pos, cur_frm); + // } - // toggle view - cur_frm.layout.set_view(cur_frm.pos_active ? "" : "pos"); - cur_frm.pos_active = !cur_frm.pos_active; + // // toggle view + // cur_frm.layout.set_view(cur_frm.pos_active ? "" : "pos"); + // cur_frm.pos_active = !cur_frm.pos_active; - // refresh - if(cur_frm.pos_active) - cur_frm.pos.refresh(); - } - }, + // // refresh + // if(cur_frm.pos_active) + // cur_frm.pos.refresh(); + // } + // }, tc_name: function() { this.get_terms(); diff --git a/patches/june_2013/p03_buying_selling_for_price_list.py b/patches/june_2013/p03_buying_selling_for_price_list.py index c251712437..7d222c8e8a 100644 --- a/patches/june_2013/p03_buying_selling_for_price_list.py +++ b/patches/june_2013/p03_buying_selling_for_price_list.py @@ -22,6 +22,6 @@ def execute(): webnotes.conn.set_value("Price List", price_list, "buying_or_selling", buying_or_selling) except MySQLdb.OperationalError, e: if e.args[0] == 1054: - webnotes.conn.set_value("Price List", price_list, "buying_or_selling", "Selling") + webnotes.conn.sql("""update `tabItem Price` set buying_or_selling='Selling' """) else: raise e \ No newline at end of file diff --git a/public/js/transaction.js b/public/js/transaction.js index 387140472c..f7caded328 100644 --- a/public/js/transaction.js +++ b/public/js/transaction.js @@ -62,6 +62,56 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ erpnext.hide_company(); this.show_item_wise_taxes(); this.set_dynamic_labels(); + + // Show POS button only if it is enabled from features setup + if(cint(sys_defaults.fs_pos_view)===1 && this.frm.doctype!="Material Request") + this.pos_btn(); + }, + + pos_btn: function() { + if(this.$pos_btn) + this.$pos_btn.remove(); + + if(!this.pos_active) { + var btn_label = wn._("POS View"), + icon = "icon-desktop"; + } else { + var btn_label = wn._(this.frm.doctype) + wn._(" View"), + icon = "icon-file-text"; + + + if (this.frm.doc.docstatus===0) { + this.frm.clear_custom_buttons(); + } + } + var me = this; + + this.$pos_btn = this.frm.add_custom_button(btn_label, function() { + me.toggle_pos(); + me.pos_btn(); + }, icon); + }, + + toggle_pos: function(show) { + if (!this.frm.doc.selling_price_list) + msgprint(wn._("Please select Price List")) + else { + if((show===true && this.pos_active) || (show===false && !this.pos_active)) return; + + // make pos + if(!this.pos) { + this.frm.layout.add_view("pos"); + this.frm.pos = new erpnext.POS(this.frm.layout.views.pos, this.frm); + } + + // toggle view + this.frm.layout.set_view(this.pos_active ? "" : "pos"); + this.pos_active = !this.pos_active; + + // refresh + if(this.pos_active) + this.frm.pos.refresh(); + } }, validate: function() { @@ -418,10 +468,10 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ (this.frm.doc.currency != company_currency && this.frm.doc.conversion_rate != 1.0)) : false; - // if(!valid_conversion_rate) { - // wn.throw(wn._("Please enter valid") + " " + wn._(conversion_rate_label) + - // " 1 " + this.frm.doc.currency + " = [?] " + company_currency); - // } + if(!valid_conversion_rate) { + wn.throw(wn._("Please enter valid") + " " + wn._(conversion_rate_label) + + " 1 " + this.frm.doc.currency + " = [?] " + company_currency); + } }, calculate_taxes_and_totals: function() { diff --git a/selling/doctype/sales_order/sales_order.js b/selling/doctype/sales_order/sales_order.js index 33699f05d8..161e10fe4e 100644 --- a/selling/doctype/sales_order/sales_order.js +++ b/selling/doctype/sales_order/sales_order.js @@ -12,6 +12,7 @@ cur_frm.cscript.sales_team_fname = "sales_team"; wn.require('app/selling/doctype/sales_common/sales_common.js'); wn.require('app/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js'); wn.require('app/utilities/doctype/sms_control/sms_control.js'); +wn.require('app/accounts/doctype/sales_invoice/pos.js'); erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend({ refresh: function(doc, dt, dn) { From a550e7443fa9c1a6ff6f0224db0764dcf7271179 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Tue, 17 Sep 2013 18:52:00 +0530 Subject: [PATCH 2/8] [pos] moved pos realted code from sales_invoice.js to transaction.js --- accounts/doctype/sales_invoice/pos.js | 23 ++++++++++--------- .../doctype/sales_invoice/sales_invoice.js | 2 +- public/js/transaction.js | 5 ---- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/accounts/doctype/sales_invoice/pos.js b/accounts/doctype/sales_invoice/pos.js index 8837aed14b..67c4b93186 100644 --- a/accounts/doctype/sales_invoice/pos.js +++ b/accounts/doctype/sales_invoice/pos.js @@ -96,6 +96,7 @@ erpnext.POS = Class.extend({ }, make_customer: function() { var me = this; + console.log(this.frm); this.customer = wn.ui.form.make_control({ df: { "fieldtype": "Link", @@ -109,7 +110,7 @@ erpnext.POS = Class.extend({ this.customer.make_input(); this.customer.$input.on("change", function() { if(!me.customer.autocomplete_open) - wn.model.set_value("Sales Invoice", me.frm.docname, "customer", this.value); + wn.model.set_value(this.frm.doctype, me.frm.docname, "customer", this.value); }); }, make_item_group: function() { @@ -221,8 +222,8 @@ erpnext.POS = Class.extend({ // check whether the item is already added if (no_of_items != 0) { - $.each(wn.model.get_children("Sales Invoice Item", this.frm.doc.name, "entries", - "Sales Invoice"), function(i, d) { + $.each(wn.model.get_children(this.frm.doctype + " Item", this.frm.doc.name, "entries", + this.frm.doctype), function(i, d) { if (d.item_code == item_code) caught = true; }); @@ -233,15 +234,15 @@ erpnext.POS = Class.extend({ me.update_qty(item_code, 1); } else { - var child = wn.model.add_child(me.frm.doc, "Sales Invoice Item", "entries"); + var child = wn.model.add_child(me.frm.doc, this.frm.doctype + " Item", "entries"); child.item_code = item_code; me.frm.cscript.item_code(me.frm.doc, child.doctype, child.name); } }, update_qty: function(item_code, qty, textbox_qty) { var me = this; - $.each(wn.model.get_children("Sales Invoice Item", this.frm.doc.name, "entries", - "Sales Invoice"), function(i, d) { + $.each(wn.model.get_children(this.frm.doctype + " Item", this.frm.doc.name, "entries", + this.frm.doctype), function(i, d) { if (d.item_code == item_code) { if (textbox_qty) { if (qty == 0 && d.item_code == item_code) @@ -265,8 +266,8 @@ erpnext.POS = Class.extend({ // add items var $items = me.wrapper.find("#cart tbody").empty(); - $.each(wn.model.get_children("Sales Invoice Item", this.frm.doc.name, "entries", - "Sales Invoice"), function(i, d) { + $.each(wn.model.get_children(this.frm.doctype + " Item", this.frm.doc.name, "entries", + this.frm.doctype), function(i, d) { $(repl('\ %(item_code)s%(item_name)s\ Date: Wed, 18 Sep 2013 18:35:12 +0530 Subject: [PATCH 3/8] [pos] pos.js included in all selling & purchase cycle --- .../purchase_invoice/purchase_invoice.js | 1 + accounts/doctype/sales_invoice/pos.js | 67 +++++++++++-------- accounts/doctype/sales_invoice/pos.py | 15 +++-- .../doctype/sales_invoice/sales_invoice.css | 15 ----- .../doctype/sales_invoice/sales_invoice.js | 1 + .../doctype/purchase_order/purchase_order.js | 1 + .../supplier_quotation/supplier_quotation.js | 1 + public/js/startup.css | 17 +++++ public/js/transaction.js | 7 +- selling/doctype/quotation/quotation.js | 1 + stock/doctype/delivery_note/delivery_note.js | 1 + .../purchase_receipt/purchase_receipt.js | 1 + 12 files changed, 78 insertions(+), 50 deletions(-) delete mode 100644 accounts/doctype/sales_invoice/sales_invoice.css diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.js b/accounts/doctype/purchase_invoice/purchase_invoice.js index 2428a7dae9..fb5569a5f0 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -8,6 +8,7 @@ cur_frm.cscript.other_fname = "purchase_tax_details"; wn.provide("erpnext.accounts"); wn.require('app/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js'); wn.require('app/buying/doctype/purchase_common/purchase_common.js'); +wn.require('app/accounts/doctype/sales_invoice/pos.js'); erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({ onload: function() { diff --git a/accounts/doctype/sales_invoice/pos.js b/accounts/doctype/sales_invoice/pos.js index 67c4b93186..ee34440b35 100644 --- a/accounts/doctype/sales_invoice/pos.js +++ b/accounts/doctype/sales_invoice/pos.js @@ -7,7 +7,7 @@ erpnext.POS = Class.extend({ this.frm = frm; this.wrapper.html('
\
\ -
\ +
\
\
\
\ @@ -88,29 +88,31 @@ erpnext.POS = Class.extend({ }); }, make: function() { - this.make_customer(); + this.make_party(); this.make_item_group(); this.make_search(); this.make_barcode(); this.make_item_list(); }, - make_customer: function() { + make_party: function() { var me = this; - console.log(this.frm); - this.customer = wn.ui.form.make_control({ + this.party = wn.meta.has_field(cur_frm.doc.doctype, "customer") ?"Customer" : "Supplier"; + + this.party_field = wn.ui.form.make_control({ df: { "fieldtype": "Link", - "options": "Customer", - "label": "Customer", - "fieldname": "pos_customer", - "placeholder": "Customer" + "options": this.party, + "label": this.party, + "fieldname": "pos_party", + "placeholder": this.party }, - parent: this.wrapper.find(".customer-area") + parent: this.wrapper.find(".party-area") }); - this.customer.make_input(); - this.customer.$input.on("change", function() { - if(!me.customer.autocomplete_open) - wn.model.set_value(this.frm.doctype, me.frm.docname, "customer", this.value); + this.party_field.make_input(); + this.party_field.$input.on("change", function() { + if(!me.party_field.autocomplete_open) + wn.model.set_value(me.frm.doctype, me.frm.docname, + me.party.toLowerCase(), this.value); }); }, make_item_group: function() { @@ -169,10 +171,17 @@ erpnext.POS = Class.extend({ }, make_item_list: function() { var me = this; + var price_list = wn.meta.has_field(this.frm.doc.doctype, "selling_price_list") ? + this.frm.doc.selling_price_list : this.frm.doc.buying_price_list; + + var sales_or_purchase = wn.meta.has_field(this.frm.doc.doctype, "selling_price_list") ? + "Sales" : "Purchase"; + wn.call({ method: 'accounts.doctype.sales_invoice.pos.get_items', args: { - price_list: cur_frm.doc.selling_price_list, + sales_or_purchase: sales_or_purchase, + price_list: price_list, item_group: this.item_group.$input.val(), item: this.search.$input.val() }, @@ -203,8 +212,8 @@ erpnext.POS = Class.extend({ // if form is local then allow this function if (cur_frm.doc.docstatus===0) { $("div.pos-item").on("click", function() { - if(!cur_frm.doc.customer) { - msgprint("Please select customer first."); + if(!cur_frm.doc[me.party.toLowerCase()]) { + msgprint("Please select " + me.party + " first."); return; } me.add_to_cart($(this).attr("data-item_code")); @@ -222,8 +231,8 @@ erpnext.POS = Class.extend({ // check whether the item is already added if (no_of_items != 0) { - $.each(wn.model.get_children(this.frm.doctype + " Item", this.frm.doc.name, "entries", - this.frm.doctype), function(i, d) { + $.each(wn.model.get_children(this.frm.doctype + " Item", this.frm.doc.name, + this.frm.cscript.fname, this.frm.doctype), function(i, d) { if (d.item_code == item_code) caught = true; }); @@ -234,15 +243,16 @@ erpnext.POS = Class.extend({ me.update_qty(item_code, 1); } else { - var child = wn.model.add_child(me.frm.doc, this.frm.doctype + " Item", "entries"); + var child = wn.model.add_child(me.frm.doc, this.frm.doctype + " Item", + this.frm.cscript.fname); child.item_code = item_code; me.frm.cscript.item_code(me.frm.doc, child.doctype, child.name); } }, update_qty: function(item_code, qty, textbox_qty) { var me = this; - $.each(wn.model.get_children(this.frm.doctype + " Item", this.frm.doc.name, "entries", - this.frm.doctype), function(i, d) { + $.each(wn.model.get_children(this.frm.doctype + " Item", this.frm.doc.name, + this.frm.cscript.fname, this.frm.doctype), function(i, d) { if (d.item_code == item_code) { if (textbox_qty) { if (qty == 0 && d.item_code == item_code) @@ -260,14 +270,14 @@ erpnext.POS = Class.extend({ }, refresh: function() { var me = this; - this.customer.set_input(this.frm.doc.customer); + this.party_field.set_input(this.frm.doc[this.party.toLowerCase()]); this.barcode.set_input(""); // add items var $items = me.wrapper.find("#cart tbody").empty(); - $.each(wn.model.get_children(this.frm.doctype + " Item", this.frm.doc.name, "entries", - this.frm.doctype), function(i, d) { + $.each(wn.model.get_children(this.frm.doctype + " Item", this.frm.doc.name, + this.frm.cscript.fname, this.frm.doctype), function(i, d) { $(repl('\ %(item_code)s%(item_name)s\ Date: Thu, 19 Sep 2013 16:14:16 +0530 Subject: [PATCH 4/8] [fix] set qty=1 for all purchase cycle --- buying/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buying/utils.py b/buying/utils.py index f4fb2f3ff8..179db9bf46 100644 --- a/buying/utils.py +++ b/buying/utils.py @@ -65,7 +65,7 @@ def _get_basic_details(args, item_bean): out = webnotes._dict({ "description": item.description_html or item.description, - "qty": 0.0, + "qty": 1.0, "uom": item.stock_uom, "conversion_factor": 1.0, "warehouse": args.warehouse or item.default_warehouse, From e9470815523489006445247435cc24eb350a9757 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Thu, 19 Sep 2013 19:09:15 +0530 Subject: [PATCH 5/8] [pos] pos view in all sales & purchase cycle finished --- accounts/doctype/sales_invoice/pos.js | 71 +++++++++++-------- .../doctype/sales_invoice/sales_invoice.txt | 5 +- buying/utils.py | 2 +- 3 files changed, 46 insertions(+), 32 deletions(-) diff --git a/accounts/doctype/sales_invoice/pos.js b/accounts/doctype/sales_invoice/pos.js index ee34440b35..c76db1394f 100644 --- a/accounts/doctype/sales_invoice/pos.js +++ b/accounts/doctype/sales_invoice/pos.js @@ -71,7 +71,18 @@ erpnext.POS = Class.extend({
\
\ '); - + + if (wn.meta.has_field(cur_frm.doc.doctype, "customer")) { + this.party = "Customer"; + this.price_list = this.frm.doc.selling_price_list; + this.sales_or_purchase = "Sales"; + } + else if (wn.meta.has_field(cur_frm.doc.doctype, "supplier")) { + this.party = "Supplier"; + this.price_list = this.frm.doc.buying_price_list; + this.sales_or_purchase = "Purchase"; + } + this.make(); var me = this; @@ -95,9 +106,7 @@ erpnext.POS = Class.extend({ this.make_item_list(); }, make_party: function() { - var me = this; - this.party = wn.meta.has_field(cur_frm.doc.doctype, "customer") ?"Customer" : "Supplier"; - + var me = this; this.party_field = wn.ui.form.make_control({ df: { "fieldtype": "Link", @@ -170,18 +179,12 @@ erpnext.POS = Class.extend({ }); }, make_item_list: function() { - var me = this; - var price_list = wn.meta.has_field(this.frm.doc.doctype, "selling_price_list") ? - this.frm.doc.selling_price_list : this.frm.doc.buying_price_list; - - var sales_or_purchase = wn.meta.has_field(this.frm.doc.doctype, "selling_price_list") ? - "Sales" : "Purchase"; - + var me = this; wn.call({ method: 'accounts.doctype.sales_invoice.pos.get_items', args: { - sales_or_purchase: sales_or_purchase, - price_list: price_list, + sales_or_purchase: this.sales_or_purchase, + price_list: this.price_list, item_group: this.item_group.$input.val(), item: this.search.$input.val() }, @@ -216,7 +219,8 @@ erpnext.POS = Class.extend({ msgprint("Please select " + me.party + " first."); return; } - me.add_to_cart($(this).attr("data-item_code")); + else + me.add_to_cart($(this).attr("data-item_code")); }); } } @@ -227,8 +231,8 @@ erpnext.POS = Class.extend({ var caught = false; // get no_of_items - no_of_items = me.wrapper.find("#cart tbody").length; - + var no_of_items = me.wrapper.find("#cart tbody tr").length; + // check whether the item is already added if (no_of_items != 0) { $.each(wn.model.get_children(this.frm.doctype + " Item", this.frm.doc.name, @@ -288,15 +292,15 @@ erpnext.POS = Class.extend({ item_code: d.item_code, item_name: d.item_name===d.item_code ? "" : ("
" + d.item_name), qty: d.qty, - rate: format_currency(d.ref_rate, cur_frm.doc.price_list_currency), - amount: format_currency(d.export_amount, cur_frm.doc.price_list_currency) + rate: format_currency(d.ref_rate, cur_frm.doc.currency), + amount: format_currency(d.export_amount, cur_frm.doc.currency) } )).appendTo($items); }); // taxes - var taxes = wn.model.get_children("Sales Taxes and Charges", this.frm.doc.name, "other_charges", - this.frm.doctype); + var taxes = wn.model.get_children(this.sales_or_purchase + " Taxes and Charges", + this.frm.doc.name, this.frm.cscript.other_fname, this.frm.doctype); $(".tax-table") .toggle((taxes && taxes.length) ? true : false) .find("tbody").empty(); @@ -308,15 +312,15 @@ erpnext.POS = Class.extend({ ', { description: d.description, rate: d.rate, - tax_amount: format_currency(d.tax_amount, me.frm.doc.price_list_currency) + tax_amount: format_currency(d.tax_amount, me.frm.doc.currency) })).appendTo(".tax-table tbody"); }); // set totals this.wrapper.find(".net-total").text(format_currency(this.frm.doc.net_total_export, - cur_frm.doc.price_list_currency)); + cur_frm.doc.currency)); this.wrapper.find(".grand-total").text(format_currency(this.frm.doc.grand_total_export, - cur_frm.doc.price_list_currency)); + cur_frm.doc.currency)); // if form is local then only run all these functions if (cur_frm.doc.docstatus===0) { @@ -331,7 +335,7 @@ erpnext.POS = Class.extend({ }); // on td click toggle the highlighting of row - $("#cart tbody tr td").on("click", function() { + me.wrapper.find("#cart tbody tr td").on("click", function() { var row = $(this).closest("tr"); if (row.attr("data-selected") == "false") { row.attr("class", "warning"); @@ -345,18 +349,26 @@ erpnext.POS = Class.extend({ }); + this.make_item_list(); me.refresh_delete_btn(); cur_frm.pos.barcode.$input.focus(); } // if form is submitted & cancelled then disable all input box & buttons - if (cur_frm.doc.docstatus>=1 && cint(cur_frm.doc.is_pos)) { + if (cur_frm.doc.docstatus>=1) { me.wrapper.find('input, button').each(function () { $(this).prop('disabled', true); }); $(".delete-items").hide(); $(".make-payment").hide(); } + + // Show Make Payment button only in Sales Invoice + if (this.frm.doctype != "Sales Invoice") + $(".make-payment").hide(); + + if (this.frm.doctype == "Quotation") + $(".party-area").toggle(cur_frm.doc.quotation_to=="Customer" ? true : false) }, refresh_delete_btn: function() { $(".delete-items").toggle($(".item-cart .warning").length ? true : false); @@ -381,16 +393,17 @@ erpnext.POS = Class.extend({ remove_selected_item: function() { var me = this; var selected_items = []; - var no_of_items = $("#cart tbody tr").length; + var no_of_items = me.wrapper.find("#cart tbody tr").length; for(var x=0; x<=no_of_items - 1; x++) { - var row = $("#cart tbody tr:eq(" + x + ")"); + var row = me.wrapper.find("#cart tbody tr:eq(" + x + ")"); if(row.attr("data-selected") == "true") { selected_items.push(row.attr("id")); } } - + var child = wn.model.get_children(this.frm.doctype + " Item", this.frm.doc.name, this.frm.cscript.fname, this.frm.doctype); + $.each(child, function(i, d) { for (var i in selected_items) { if (d.item_code == selected_items[i]) { @@ -405,7 +418,7 @@ erpnext.POS = Class.extend({ }, make_payment: function() { var me = this; - var no_of_items = $("#cart tbody tr").length; + var no_of_items = me.wrapper.find("#cart tbody tr").length; var mode_of_payment = []; if (no_of_items == 0) diff --git a/accounts/doctype/sales_invoice/sales_invoice.txt b/accounts/doctype/sales_invoice/sales_invoice.txt index f921f24223..00c6c2cc5c 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.txt +++ b/accounts/doctype/sales_invoice/sales_invoice.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-24 19:29:05", "docstatus": 0, - "modified": "2013-09-01 05:26:13", + "modified": "2013-09-19 11:42:13", "modified_by": "Administrator", "owner": "Administrator" }, @@ -180,6 +180,7 @@ "search_index": 1 }, { + "default": "Today", "description": "Enter the date by which payments from customer is expected against this invoice.", "doctype": "DocField", "fieldname": "due_date", @@ -411,7 +412,7 @@ "doctype": "DocField", "fieldname": "other_charges", "fieldtype": "Table", - "label": "Taxes and Charges1", + "label": "Sales Taxes and Charges", "oldfieldname": "other_charges", "oldfieldtype": "Table", "options": "Sales Taxes and Charges", diff --git a/buying/utils.py b/buying/utils.py index f4fb2f3ff8..179db9bf46 100644 --- a/buying/utils.py +++ b/buying/utils.py @@ -65,7 +65,7 @@ def _get_basic_details(args, item_bean): out = webnotes._dict({ "description": item.description_html or item.description, - "qty": 0.0, + "qty": 1.0, "uom": item.stock_uom, "conversion_factor": 1.0, "warehouse": args.warehouse or item.default_warehouse, From f624ffa40abcf5aca9c4d0c6295f5bb00c856ca9 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Mon, 23 Sep 2013 12:27:16 +0530 Subject: [PATCH 6/8] [pos] refresh() to be called at minimum --- accounts/doctype/sales_invoice/pos.js | 8 +-- .../doctype/sales_invoice/sales_invoice.js | 50 +------------------ public/js/transaction.js | 2 +- 3 files changed, 6 insertions(+), 54 deletions(-) diff --git a/accounts/doctype/sales_invoice/pos.js b/accounts/doctype/sales_invoice/pos.js index c76db1394f..4ef239744b 100644 --- a/accounts/doctype/sales_invoice/pos.js +++ b/accounts/doctype/sales_invoice/pos.js @@ -106,7 +106,7 @@ erpnext.POS = Class.extend({ this.make_item_list(); }, make_party: function() { - var me = this; + var me = this; this.party_field = wn.ui.form.make_control({ df: { "fieldtype": "Link", @@ -179,7 +179,7 @@ erpnext.POS = Class.extend({ }); }, make_item_list: function() { - var me = this; + var me = this; wn.call({ method: 'accounts.doctype.sales_invoice.pos.get_items', args: { @@ -349,7 +349,6 @@ erpnext.POS = Class.extend({ }); - this.make_item_list(); me.refresh_delete_btn(); cur_frm.pos.barcode.$input.focus(); } @@ -368,7 +367,8 @@ erpnext.POS = Class.extend({ $(".make-payment").hide(); if (this.frm.doctype == "Quotation") - $(".party-area").toggle(cur_frm.doc.quotation_to=="Customer" ? true : false) + if (cur_frm.doc.quotation_to=="Customer") + this.party_field.remove(); }, refresh_delete_btn: function() { $(".delete-items").toggle($(".item-cart .warning").length ? true : false); diff --git a/accounts/doctype/sales_invoice/sales_invoice.js b/accounts/doctype/sales_invoice/sales_invoice.js index e07ed2816d..13cbc634dd 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.js +++ b/accounts/doctype/sales_invoice/sales_invoice.js @@ -121,54 +121,6 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte }); }); }, - - // pos_btn: function() { - // if(cur_frm.$pos_btn) - // cur_frm.$pos_btn.remove(); - - // if(!cur_frm.pos_active) { - // var btn_label = wn._("POS View"), - // icon = "icon-desktop"; - - // cur_frm.cscript.sales_order_btn(); - // cur_frm.cscript.delivery_note_btn(); - // } else { - // var btn_label = wn._("Invoice View"), - // icon = "icon-file-text"; - - // if (cur_frm.doc.docstatus===0) { - // this.$delivery_note_btn.remove(); - // this.$sales_order_btn.remove(); - // } - // } - - // cur_frm.$pos_btn = cur_frm.add_custom_button(btn_label, function() { - // cur_frm.cscript.toggle_pos(); - // cur_frm.cscript.pos_btn(); - // }, icon); - // }, - - // toggle_pos: function(show) { - // if (!this.frm.doc.selling_price_list) - // msgprint(wn._("Please select Price List")) - // else { - // if((show===true && cur_frm.pos_active) || (show===false && !cur_frm.pos_active)) return; - - // // make pos - // if(!cur_frm.pos) { - // cur_frm.layout.add_view("pos"); - // cur_frm.pos = new erpnext.POS(cur_frm.layout.views.pos, cur_frm); - // } - - // // toggle view - // cur_frm.layout.set_view(cur_frm.pos_active ? "" : "pos"); - // cur_frm.pos_active = !cur_frm.pos_active; - - // // refresh - // if(cur_frm.pos_active) - // cur_frm.pos.refresh(); - // } - // }, tc_name: function() { this.get_terms(); @@ -176,7 +128,6 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte is_pos: function() { cur_frm.cscript.hide_fields(this.frm.doc); - if(cint(this.frm.doc.is_pos)) { if(!this.frm.doc.company) { this.frm.set_value("is_pos", 0); @@ -194,6 +145,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte }); } } + }, debit_to: function() { diff --git a/public/js/transaction.js b/public/js/transaction.js index a38e3a777c..1a1c98ca6b 100644 --- a/public/js/transaction.js +++ b/public/js/transaction.js @@ -98,7 +98,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ if((show===true && this.pos_active) || (show===false && !this.pos_active)) return; // make pos - if(!this.pos) { + if(!this.frm.pos) { this.frm.layout.add_view("pos"); this.frm.pos = new erpnext.POS(this.frm.layout.views.pos, this.frm); } From 10dce341c823d107d81246a87c07a82bcf1ca90b Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Wed, 25 Sep 2013 11:09:33 +0530 Subject: [PATCH 7/8] [pos] pos view fixed for all purchase & sales cycle --- .../purchase_invoice/purchase_invoice.py | 25 ++++----- accounts/doctype/sales_invoice/pos.js | 52 ++++++++++++++----- accounts/doctype/sales_invoice/pos.py | 6 ++- .../purchase_common/purchase_common.js | 3 +- public/js/transaction.js | 23 ++++++++ selling/doctype/sales_common/sales_common.js | 3 +- selling/utils/__init__.py | 1 + utilities/transaction_base.py | 1 + 8 files changed, 83 insertions(+), 31 deletions(-) diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.py b/accounts/doctype/purchase_invoice/purchase_invoice.py index 0538323561..ad7ebd90de 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -62,19 +62,20 @@ class DocType(BuyingController): "purchase_receipt_details") def get_credit_to(self): - acc_head = sql("""select name, credit_days from `tabAccount` - where (name = %s or (master_name = %s and master_type = 'supplier')) - and docstatus != 2 and company = %s""", - (cstr(self.doc.supplier) + " - " + self.company_abbr, - self.doc.supplier, self.doc.company)) - ret = {} - if acc_head and acc_head[0][0]: - ret['credit_to'] = acc_head[0][0] - if not self.doc.due_date: - ret['due_date'] = add_days(cstr(self.doc.posting_date), acc_head and cint(acc_head[0][1]) or 0) - elif not acc_head: - msgprint("%s does not have an Account Head in %s. You must first create it from the Supplier Master" % (self.doc.supplier, self.doc.company)) + if self.doc.supplier: + acc_head = sql("""select name, credit_days from `tabAccount` + where (name = %s or (master_name = %s and master_type = 'supplier')) + and docstatus != 2 and company = %s""", + (cstr(self.doc.supplier) + " - " + self.company_abbr, + self.doc.supplier, self.doc.company)) + + if acc_head and acc_head[0][0]: + ret['credit_to'] = acc_head[0][0] + if not self.doc.due_date: + ret['due_date'] = add_days(cstr(self.doc.posting_date), acc_head and cint(acc_head[0][1]) or 0) + elif not acc_head: + msgprint("%s does not have an Account Head in %s. You must first create it from the Supplier Master" % (self.doc.supplier, self.doc.company)) return ret def set_supplier_defaults(self): diff --git a/accounts/doctype/sales_invoice/pos.js b/accounts/doctype/sales_invoice/pos.js index 4ef239744b..ca5618b345 100644 --- a/accounts/doctype/sales_invoice/pos.js +++ b/accounts/doctype/sales_invoice/pos.js @@ -132,7 +132,7 @@ erpnext.POS = Class.extend({ "options": "Item Group", "label": "Item Group", "fieldname": "pos_item_group", - "placeholder": "Filter by Item Group" + "placeholder": "Item Group" }, parent: this.wrapper.find(".item-group-area") }); @@ -150,7 +150,7 @@ erpnext.POS = Class.extend({ "options": "Item", "label": "Item", "fieldname": "pos_item", - "placeholder": "Select Item" + "placeholder": "Item" }, parent: this.wrapper.find(".search-area") }); @@ -167,7 +167,7 @@ erpnext.POS = Class.extend({ "fieldtype": "Data", "label": "Barcode", "fieldname": "pos_barcode", - "placeholder": "Select Barcode" + "placeholder": "Barcode" }, parent: this.wrapper.find(".barcode-area") }); @@ -215,7 +215,9 @@ erpnext.POS = Class.extend({ // if form is local then allow this function if (cur_frm.doc.docstatus===0) { $("div.pos-item").on("click", function() { - if(!cur_frm.doc[me.party.toLowerCase()]) { + if(!cur_frm.doc[me.party.toLowerCase()] && ((me.frm.doctype == "Quotation" && + cur_frm.doc.quotation_to == "Customer") + || me.frm.doctype != "Quotation")) { msgprint("Please select " + me.party + " first."); return; } @@ -282,6 +284,16 @@ erpnext.POS = Class.extend({ $.each(wn.model.get_children(this.frm.doctype + " Item", this.frm.doc.name, this.frm.cscript.fname, this.frm.doctype), function(i, d) { + + if (me.sales_or_purchase == "Sales") { + item_amount = d.export_amount; + rate = d.export_rate; + } + else { + item_amount = d.import_amount; + rate = d.import_rate; + } + $(repl('\ %(item_code)s%(item_name)s\ " + d.item_name), qty: d.qty, - rate: format_currency(d.ref_rate, cur_frm.doc.currency), - amount: format_currency(d.export_amount, cur_frm.doc.currency) + rate: format_currency(rate, cur_frm.doc.currency), + amount: format_currency(item_amount, cur_frm.doc.currency) } )).appendTo($items); }); @@ -312,15 +324,24 @@ erpnext.POS = Class.extend({ ', { description: d.description, rate: d.rate, - tax_amount: format_currency(d.tax_amount, me.frm.doc.currency) + tax_amount: format_currency(flt(d.tax_amount)/flt(me.frm.doc.conversion_rate), + me.frm.doc.currency) })).appendTo(".tax-table tbody"); }); // set totals - this.wrapper.find(".net-total").text(format_currency(this.frm.doc.net_total_export, - cur_frm.doc.currency)); - this.wrapper.find(".grand-total").text(format_currency(this.frm.doc.grand_total_export, - cur_frm.doc.currency)); + if (this.sales_or_purchase == "Sales") { + this.wrapper.find(".net-total").text(format_currency(this.frm.doc.net_total_export, + cur_frm.doc.currency)); + this.wrapper.find(".grand-total").text(format_currency(this.frm.doc.grand_total_export, + cur_frm.doc.currency)); + } + else { + this.wrapper.find(".net-total").text(format_currency(this.frm.doc.net_total_import, + cur_frm.doc.currency)); + this.wrapper.find(".grand-total").text(format_currency(this.frm.doc.grand_total_import, + cur_frm.doc.currency)); + } // if form is local then only run all these functions if (cur_frm.doc.docstatus===0) { @@ -366,9 +387,12 @@ erpnext.POS = Class.extend({ if (this.frm.doctype != "Sales Invoice") $(".make-payment").hide(); - if (this.frm.doctype == "Quotation") - if (cur_frm.doc.quotation_to=="Customer") - this.party_field.remove(); + // If quotation to is not Customer then remove party + if (this.frm.doctype == "Quotation") { + this.party_field.$wrapper.remove(); + if (cur_frm.doc.quotation_to == "Customer") + this.make_party(); + } }, refresh_delete_btn: function() { $(".delete-items").toggle($(".item-cart .warning").length ? true : false); diff --git a/accounts/doctype/sales_invoice/pos.py b/accounts/doctype/sales_invoice/pos.py index d919c1b548..44fe40d8de 100644 --- a/accounts/doctype/sales_invoice/pos.py +++ b/accounts/doctype/sales_invoice/pos.py @@ -3,7 +3,6 @@ from __future__ import unicode_literals import webnotes -from webnotes import msgprint, errprint @webnotes.whitelist() def get_items(price_list, sales_or_purchase, item=None, item_group=None): @@ -36,6 +35,11 @@ def get_item_from_barcode(barcode): return webnotes.conn.sql("""select name from `tabItem` where barcode=%s""", (barcode), as_dict=1) +@webnotes.whitelist() +def get_item_from_serial_no(serial_no): + return webnotes.conn.sql("""select name, item_code from `tabSerial No` where + name=%s""", (serial_no), as_dict=1) + @webnotes.whitelist() def get_mode_of_payment(): return webnotes.conn.sql("""select name from `tabMode of Payment`""", as_dict=1) \ No newline at end of file diff --git a/buying/doctype/purchase_common/purchase_common.js b/buying/doctype/purchase_common/purchase_common.js index 2dfe65515a..433a76fba7 100644 --- a/buying/doctype/purchase_common/purchase_common.js +++ b/buying/doctype/purchase_common/purchase_common.js @@ -108,8 +108,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ var item = wn.model.get_doc(cdt, cdn); if(item.item_code) { if(!this.validate_company_and_party("supplier")) { - item.item_code = null; - refresh_field("item_code", item.name, item.parentfield); + cur_frm.fields_dict[me.frm.cscript.fname].grid.grid_rows[item.idx - 1].remove(); } else { return this.frm.call({ method: "buying.utils.get_item_details", diff --git a/public/js/transaction.js b/public/js/transaction.js index 1a1c98ca6b..e12d1084e9 100644 --- a/public/js/transaction.js +++ b/public/js/transaction.js @@ -232,6 +232,29 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ tax_rate: function(doc, cdt, cdn) { this.calculate_taxes_and_totals(); }, + + // serial_no: function(doc, cdt, cdn) { + // var me = this; + // var item = wn.model.get_doc(cdt, cdn); + // if (!item.item_code) { + // wn.call({ + // method: 'accounts.doctype.sales_invoice.pos.get_item_from_serial_no', + // args: {serial_no: this.serial_no.$input.val()}, + // callback: function(r) { + // if (r.message) { + // var item_code = r.message[0].item_code; + // var child = wn.model.add_child(me.frm.doc, this.frm.doctype + " Item", + // this.frm.cscript.fname); + // child.item_code = item_code; + // me.frm.cscript.item_code(me.frm.doc, child.doctype, child.name); + // } + // else + // msgprint(wn._("Invalid Serial No.")); + // me.refresh(); + // } + // }); + // } + // }, row_id: function(doc, cdt, cdn) { var tax = wn.model.get_doc(cdt, cdn); diff --git a/selling/doctype/sales_common/sales_common.js b/selling/doctype/sales_common/sales_common.js index dc58377e4b..c87e823dba 100644 --- a/selling/doctype/sales_common/sales_common.js +++ b/selling/doctype/sales_common/sales_common.js @@ -162,8 +162,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ var item = wn.model.get_doc(cdt, cdn); if(item.item_code || item.barcode) { if(!this.validate_company_and_party("customer")) { - item.item_code = null; - refresh_field("item_code", item.name, item.parentfield); + cur_frm.fields_dict[me.frm.cscript.fname].grid.grid_rows[item.idx - 1].remove(); } else { return this.frm.call({ method: "selling.utils.get_item_details", diff --git a/selling/utils/__init__.py b/selling/utils/__init__.py index 224944dd88..801d82bf40 100644 --- a/selling/utils/__init__.py +++ b/selling/utils/__init__.py @@ -34,6 +34,7 @@ def get_item_details(args): "plc_conversion_rate": 1.0 } """ + if isinstance(args, basestring): args = json.loads(args) args = webnotes._dict(args) diff --git a/utilities/transaction_base.py b/utilities/transaction_base.py index 2535db7ab5..57591fd321 100644 --- a/utilities/transaction_base.py +++ b/utilities/transaction_base.py @@ -425,6 +425,7 @@ def get_address_territory(address_doc): def validate_conversion_rate(currency, conversion_rate, conversion_rate_label, company): """common validation for currency and price list currency""" + if conversion_rate == 0: msgprint(conversion_rate_label + _(' cannot be 0'), raise_exception=True) From 2428e8d1b7ce13c5b60bb38bd590e6466d678c31 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Fri, 27 Sep 2013 12:32:26 +0530 Subject: [PATCH 8/8] [pos] [minor] fix for cur_frm --- accounts/doctype/sales_invoice/pos.js | 40 +++++++++++++------------- selling/doctype/quotation/quotation.js | 6 ++-- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/accounts/doctype/sales_invoice/pos.js b/accounts/doctype/sales_invoice/pos.js index ca5618b345..e19652d25f 100644 --- a/accounts/doctype/sales_invoice/pos.js +++ b/accounts/doctype/sales_invoice/pos.js @@ -213,10 +213,10 @@ erpnext.POS = Class.extend({ }); // if form is local then allow this function - if (cur_frm.doc.docstatus===0) { + if (me.frm.doc.docstatus===0) { $("div.pos-item").on("click", function() { - if(!cur_frm.doc[me.party.toLowerCase()] && ((me.frm.doctype == "Quotation" && - cur_frm.doc.quotation_to == "Customer") + if(!me.frm.doc[me.party.toLowerCase()] && ((me.frm.doctype == "Quotation" && + me.frm.doc.quotation_to == "Customer") || me.frm.doctype != "Quotation")) { msgprint("Please select " + me.party + " first."); return; @@ -304,8 +304,8 @@ erpnext.POS = Class.extend({ item_code: d.item_code, item_name: d.item_name===d.item_code ? "" : ("
" + d.item_name), qty: d.qty, - rate: format_currency(rate, cur_frm.doc.currency), - amount: format_currency(item_amount, cur_frm.doc.currency) + rate: format_currency(rate, me.frm.doc.currency), + amount: format_currency(item_amount, me.frm.doc.currency) } )).appendTo($items); }); @@ -332,19 +332,19 @@ erpnext.POS = Class.extend({ // set totals if (this.sales_or_purchase == "Sales") { this.wrapper.find(".net-total").text(format_currency(this.frm.doc.net_total_export, - cur_frm.doc.currency)); + me.frm.doc.currency)); this.wrapper.find(".grand-total").text(format_currency(this.frm.doc.grand_total_export, - cur_frm.doc.currency)); + me.frm.doc.currency)); } else { this.wrapper.find(".net-total").text(format_currency(this.frm.doc.net_total_import, - cur_frm.doc.currency)); + me.frm.doc.currency)); this.wrapper.find(".grand-total").text(format_currency(this.frm.doc.grand_total_import, - cur_frm.doc.currency)); + me.frm.doc.currency)); } // if form is local then only run all these functions - if (cur_frm.doc.docstatus===0) { + if (this.frm.doc.docstatus===0) { $("input.qty").on("focus", function() { $(this).select(); }); @@ -371,11 +371,11 @@ erpnext.POS = Class.extend({ }); me.refresh_delete_btn(); - cur_frm.pos.barcode.$input.focus(); + this.frm.pos.barcode.$input.focus(); } // if form is submitted & cancelled then disable all input box & buttons - if (cur_frm.doc.docstatus>=1) { + if (this.frm.doc.docstatus>=1) { me.wrapper.find('input, button').each(function () { $(this).prop('disabled', true); }); @@ -390,7 +390,7 @@ erpnext.POS = Class.extend({ // If quotation to is not Customer then remove party if (this.frm.doctype == "Quotation") { this.party_field.$wrapper.remove(); - if (cur_frm.doc.quotation_to == "Customer") + if (this.frm.doc.quotation_to == "Customer") this.make_party(); } }, @@ -435,8 +435,8 @@ erpnext.POS = Class.extend({ } } }); - cur_frm.fields_dict[this.frm.cscript.fname].grid.refresh(); - cur_frm.script_manager.trigger("calculate_taxes_and_totals"); + this.frm.fields_dict[this.frm.cscript.fname].grid.refresh(); + this.frm.script_manager.trigger("calculate_taxes_and_totals"); me.frm.dirty(); me.refresh(); }, @@ -470,15 +470,15 @@ erpnext.POS = Class.extend({ "total_amount": $(".grand-total").text() }); dialog.show(); - cur_frm.pos.barcode.$input.focus(); + me.frm.pos.barcode.$input.focus(); dialog.get_input("total_amount").prop("disabled", true); dialog.fields_dict.pay.input.onclick = function() { - cur_frm.set_value("mode_of_payment", dialog.get_values().mode_of_payment); - cur_frm.set_value("paid_amount", dialog.get_values().total_amount); - cur_frm.cscript.mode_of_payment(cur_frm.doc); - cur_frm.save(); + me.frm.set_value("mode_of_payment", dialog.get_values().mode_of_payment); + me.frm.set_value("paid_amount", dialog.get_values().total_amount); + me.frm.cscript.mode_of_payment(me.frm.doc); + me.frm.save(); dialog.hide(); me.refresh(); }; diff --git a/selling/doctype/quotation/quotation.js b/selling/doctype/quotation/quotation.js index 33ba0933bb..e20308f18e 100644 --- a/selling/doctype/quotation/quotation.js +++ b/selling/doctype/quotation/quotation.js @@ -83,12 +83,12 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({ }, validate_company_and_party: function(party_field) { - if(this.frm.doc.quotation_to == "Lead") { - return true; - } else if(!this.frm.doc.quotation_to) { + if(!this.frm.doc.quotation_to) { msgprint(wn._("Please select a value for" + " " + wn.meta.get_label(this.frm.doc.doctype, "quotation_to", this.frm.doc.name))); return false; + } else if (this.frm.doc.quotation_to == "Lead") { + return true; } else { return this._super(party_field); }