diff --git a/accounts/doctype/sales_invoice/pos.js b/accounts/doctype/sales_invoice/pos.js index e19652d25f5..c68b9915c88 100644 --- a/accounts/doctype/sales_invoice/pos.js +++ b/accounts/doctype/sales_invoice/pos.js @@ -213,8 +213,8 @@ erpnext.POS = Class.extend({ }); // if form is local then allow this function - if (me.frm.doc.docstatus===0) { - $("div.pos-item").on("click", function() { + $(me.wrapper).find("div.pos-item").on("click", function() { + if(me.frm.doc.docstatus==0) { if(!me.frm.doc[me.party.toLowerCase()] && ((me.frm.doctype == "Quotation" && me.frm.doc.quotation_to == "Customer") || me.frm.doctype != "Quotation")) { @@ -223,8 +223,8 @@ erpnext.POS = Class.extend({ } else me.add_to_cart($(this).attr("data-item_code")); - }); - } + } + }); } }); }, @@ -313,7 +313,7 @@ erpnext.POS = Class.extend({ // taxes 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") + $(this.wrapper).find(".tax-table") .toggle((taxes && taxes.length) ? true : false) .find("tbody").empty(); @@ -345,18 +345,18 @@ erpnext.POS = Class.extend({ // if form is local then only run all these functions if (this.frm.doc.docstatus===0) { - $("input.qty").on("focus", function() { + $(this.wrapper).find("input.qty").on("focus", function() { $(this).select(); }); // append quantity to the respective item after change from input box - $("input.qty").on("change", function() { + $(this.wrapper).find("input.qty").on("change", function() { var item_code = $(this).closest("tr")[0].id; me.update_qty(item_code, $(this).val(), true); }); // on td click toggle the highlighting of row - me.wrapper.find("#cart tbody tr td").on("click", function() { + $(this.wrapper).find("#cart tbody tr td").on("click", function() { var row = $(this).closest("tr"); if (row.attr("data-selected") == "false") { row.attr("class", "warning"); @@ -371,21 +371,27 @@ erpnext.POS = Class.extend({ }); me.refresh_delete_btn(); - this.frm.pos.barcode.$input.focus(); + this.barcode.$input.focus(); } // if form is submitted & cancelled then disable all input box & buttons if (this.frm.doc.docstatus>=1) { - me.wrapper.find('input, button').each(function () { + $(this.wrapper).find('input, button').each(function () { $(this).prop('disabled', true); }); - $(".delete-items").hide(); - $(".make-payment").hide(); + $(this.wrapper).find(".delete-items").hide(); + $(this.wrapper).find(".make-payment").hide(); + } + else { + $(this.wrapper).find('input, button').each(function () { + $(this).prop('disabled', false); + }); + $(this.wrapper).find(".make-payment").show(); } // Show Make Payment button only in Sales Invoice if (this.frm.doctype != "Sales Invoice") - $(".make-payment").hide(); + $(this.wrapper).find(".make-payment").hide(); // If quotation to is not Customer then remove party if (this.frm.doctype == "Quotation") { @@ -395,7 +401,7 @@ erpnext.POS = Class.extend({ } }, refresh_delete_btn: function() { - $(".delete-items").toggle($(".item-cart .warning").length ? true : false); + $(this.wrapper).find(".delete-items").toggle($(".item-cart .warning").length ? true : false); }, add_item_thru_barcode: function() { var me = this; @@ -417,9 +423,9 @@ erpnext.POS = Class.extend({ remove_selected_item: function() { var me = this; var selected_items = []; - var no_of_items = me.wrapper.find("#cart tbody tr").length; + var no_of_items = $(this.wrapper).find("#cart tbody tr").length; for(var x=0; x<=no_of_items - 1; x++) { - var row = me.wrapper.find("#cart tbody tr:eq(" + x + ")"); + var row = $(this.wrapper).find("#cart tbody tr:eq(" + x + ")"); if(row.attr("data-selected") == "true") { selected_items.push(row.attr("id")); } @@ -442,7 +448,7 @@ erpnext.POS = Class.extend({ }, make_payment: function() { var me = this; - var no_of_items = me.wrapper.find("#cart tbody tr").length; + var no_of_items = $(this.wrapper).find("#cart tbody tr").length; var mode_of_payment = []; if (no_of_items == 0) @@ -470,7 +476,7 @@ erpnext.POS = Class.extend({ "total_amount": $(".grand-total").text() }); dialog.show(); - me.frm.pos.barcode.$input.focus(); + me.barcode.$input.focus(); dialog.get_input("total_amount").prop("disabled", true); diff --git a/accounts/doctype/sales_invoice/sales_invoice.js b/accounts/doctype/sales_invoice/sales_invoice.js index 6639e65e6c5..5220c0fa20c 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.js +++ b/accounts/doctype/sales_invoice/sales_invoice.js @@ -29,9 +29,10 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte // toggle to pos view if is_pos is 1 in user_defaults if ((cint(wn.defaults.get_user_defaults("is_pos"))===1 || cur_frm.doc.is_pos) && cint(wn.defaults.get_user_defaults("fs_pos_view"))===1) { - this.frm.set_value("is_pos", 1); - this.is_pos(); - cur_frm.cscript.toggle_pos(true); + if(this.frm.doc.__islocal && !this.frm.doc.amended_from) { + this.frm.set_value("is_pos", 1); + this.is_pos(function() {cur_frm.cscript.toggle_pos(true);}); + } } // if document is POS then change default print format to "POS Invoice" @@ -126,7 +127,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte this.get_terms(); }, - is_pos: function() { + is_pos: function(callback_fn) { cur_frm.cscript.hide_fields(this.frm.doc); if(cint(this.frm.doc.is_pos)) { if(!this.frm.doc.company) { @@ -140,6 +141,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte callback: function(r) { if(!r.exc) { me.frm.script_manager.trigger("update_stock"); + if(callback_fn) callback_fn() } } }); diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py index 12deed73a87..2eb9ae84cb0 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.py +++ b/accounts/doctype/sales_invoice/sales_invoice.py @@ -195,7 +195,7 @@ class DocType(SellingController): pos = get_pos_settings(self.doc.company) if pos: - if not for_validate: + if not for_validate and not self.doc.customer: self.doc.customer = pos.customer self.set_customer_defaults() diff --git a/accounts/doctype/sales_invoice/sales_invoice.txt b/accounts/doctype/sales_invoice/sales_invoice.txt index 00c6c2cc5c5..516d1925a8a 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-19 11:42:13", + "modified": "2013-10-03 18:54:31", "modified_by": "Administrator", "owner": "Administrator" }, @@ -180,7 +180,6 @@ "search_index": 1 }, { - "default": "Today", "description": "Enter the date by which payments from customer is expected against this invoice.", "doctype": "DocField", "fieldname": "due_date", diff --git a/patches/august_2013/p02_rename_price_list.py b/patches/august_2013/p02_rename_price_list.py index 41efb273069..0a1929925ba 100644 --- a/patches/august_2013/p02_rename_price_list.py +++ b/patches/august_2013/p02_rename_price_list.py @@ -6,6 +6,7 @@ import webnotes def execute(): webnotes.reload_doc("selling", "doctype", "shopping_cart_price_list") + webnotes.reload_doc("setup", "doctype", "item_price") for t in [ ("Supplier Quotation", "price_list_name", "buying_price_list"), diff --git a/patches/october_2013/__init__.py b/patches/october_2013/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/patches/october_2013/fix_is_cancelled_in_sle.py b/patches/october_2013/fix_is_cancelled_in_sle.py new file mode 100644 index 00000000000..cb51b5d7ca1 --- /dev/null +++ b/patches/october_2013/fix_is_cancelled_in_sle.py @@ -0,0 +1,13 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes + +def execute(): + webnotes.conn.sql("""update `tabStock Ledger Entry` set is_cancelled = 'No' + where ifnull(is_cancelled, '') = ''""") + + webnotes.conn.sql("""update tabBin b set b.stock_uom = + (select i.stock_uom from tabItem i where i.name = b.item_code) + where b.creation>='2013-09-01'""") \ No newline at end of file diff --git a/patches/october_2013/perpetual_inventory_stock_transfer_utility.py b/patches/october_2013/perpetual_inventory_stock_transfer_utility.py new file mode 100644 index 00000000000..8cee29a824a --- /dev/null +++ b/patches/october_2013/perpetual_inventory_stock_transfer_utility.py @@ -0,0 +1,84 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes +from webnotes.utils import nowdate, nowtime, cstr +from accounts.utils import get_fiscal_year + +def execute(): + item_map = {} + for item in webnotes.conn.sql("""select * from tabItem""", as_dict=1): + item_map.setdefault(item.name, item) + + warehouse_map = get_warehosue_map() + naming_series = "STE/13/" + + for company in webnotes.conn.sql("select name from tabCompany"): + stock_entry = [{ + "doctype": "Stock Entry", + "naming_series": naming_series, + "posting_date": nowdate(), + "posting_time": nowtime(), + "purpose": "Material Transfer", + "company": company[0], + "remarks": "Material Transfer to activate perpetual inventory", + "fiscal_year": get_fiscal_year(nowdate())[0] + }] + expense_account = "Cost of Goods Sold - NISL" + cost_center = "Default CC Ledger - NISL" + + for bin in webnotes.conn.sql("""select * from tabBin bin where ifnull(item_code, '')!='' + and ifnull(warehouse, '')!='' and ifnull(actual_qty, 0) != 0 + and (select company from tabWarehouse where name=bin.warehouse)=%s""", + company[0], as_dict=1): + item_details = item_map[bin.item_code] + new_warehouse = warehouse_map[bin.warehouse].get("fixed_asset_warehouse") \ + if cstr(item_details.is_asset_item) == "Yes" \ + else warehouse_map[bin.warehouse].get("current_asset_warehouse") + + if item_details.has_serial_no == "Yes": + serial_no = "\n".join([d[0] for d in webnotes.conn.sql("""select name + from `tabSerial No` where item_code = %s and warehouse = %s + and status='Available'""", (bin.item_code, bin.warehouse))]) + else: + serial_no = None + + stock_entry.append({ + "doctype": "Stock Entry Detail", + "parentfield": "mtn_details", + "s_warehouse": bin.warehouse, + "t_warehouse": new_warehouse, + "item_code": bin.item_code, + "description": item_details.description, + "qty": bin.actual_qty, + "transfer_qty": bin.actual_qty, + "uom": item_details.stock_uom, + "stock_uom": item_details.stock_uom, + "conversion_factor": 1, + "expense_account": expense_account, + "cost_center": cost_center, + "serial_no": serial_no + }) + + webnotes.bean(stock_entry).insert() + +def get_warehosue_map(): + return { + "MAHAPE": { + "current_asset_warehouse": "Mahape-New - NISL", + "fixed_asset_warehouse": "" + }, + "DROP SHIPMENT": { + "current_asset_warehouse": "Drop Shipment-New - NISL", + "fixed_asset_warehouse": "" + }, + "TRANSIT": { + "current_asset_warehouse": "Transit-New - NISL", + "fixed_asset_warehouse": "" + }, + "ASSET - MAHAPE": { + "current_asset_warehouse": "", + "fixed_asset_warehouse": "Assets-New - NISL" + } + } \ No newline at end of file diff --git a/patches/october_2013/set_stock_value_diff_in_sle.py b/patches/october_2013/set_stock_value_diff_in_sle.py new file mode 100644 index 00000000000..25f95e0e6da --- /dev/null +++ b/patches/october_2013/set_stock_value_diff_in_sle.py @@ -0,0 +1,10 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes +from webnotes.utils import cint + +def execute(): + from patches.september_2012 import repost_stock + repost_stock.execute() \ No newline at end of file diff --git a/patches/patch_list.py b/patches/patch_list.py index 7041ba88585..f228acf97e7 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -218,4 +218,6 @@ patch_list = [ "execute:webnotes.bean('Style Settings').save() #2013-09-19", "execute:webnotes.conn.set_value('Accounts Settings', None, 'frozen_accounts_modifier', 'Accounts Manager') # 2013-09-24", "patches.september_2013.p04_unsubmit_serial_nos", + "patches.september_2013.p05_fix_customer_in_pos", + "patches.october_2013.fix_is_cancelled_in_sle", ] \ No newline at end of file diff --git a/patches/september_2013/p05_fix_customer_in_pos.py b/patches/september_2013/p05_fix_customer_in_pos.py new file mode 100644 index 00000000000..60210dab24e --- /dev/null +++ b/patches/september_2013/p05_fix_customer_in_pos.py @@ -0,0 +1,22 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import webnotes +def execute(): + si_list = webnotes.conn.sql("""select name, debit_to from `tabSales Invoice` + where ifnull(is_pos, 1)=1 and docstatus=1 and modified > '2013-09-03'""", as_dict=1) + + for si in si_list: + if not webnotes.conn.get_value("GL Entry", {"voucher_type": "Sales Invoice", + "voucher_no": si.name, "account": si.debit_to}): + debit_to = webnotes.conn.sql("""select account from `tabGL Entry` gle + where voucher_type='Sales Invoice' and voucher_no=%s + and (select master_type from tabAccount where name=gle.account)='Customer' + """, si.name) + if debit_to: + si_bean = webnotes.bean("Sales Invoice", si.name) + si_bean.doc.debit_to = debit_to[0][0] + si_bean.doc.customer = None + si_bean.run_method("set_customer_defaults") + si_bean.update_after_submit() \ No newline at end of file diff --git a/public/js/stock_grid_report.js b/public/js/stock_grid_report.js index 8b79b5e1eea..46370d27f60 100644 --- a/public/js/stock_grid_report.js +++ b/public/js/stock_grid_report.js @@ -29,6 +29,8 @@ erpnext.StockGridReport = wn.views.TreeGridReport.extend({ if(add_qty) wh.fifo_stack.push([add_qty, sl.incoming_rate, sl.posting_date]); + + if(sl.serial_no) value_diff = this.get_serialized_value_diff(sl); } else { // outgoing if(sl.serial_no) { @@ -98,7 +100,7 @@ erpnext.StockGridReport = wn.views.TreeGridReport.extend({ $.each(sl.serial_no.trim().split("\n"), function(i, sr) { if(sr) { - value_diff += flt(me.serialized_buying_rates[sr.trim()]); + value_diff += flt(me.serialized_buying_rates[sr.trim().toLowerCase()]); } }); @@ -112,7 +114,7 @@ erpnext.StockGridReport = wn.views.TreeGridReport.extend({ if(sle.qty > 0 && sle.serial_no) { $.each(sle.serial_no.trim().split("\n"), function(i, sr) { if(sr && sle.incoming_rate !== undefined) { - serialized_buying_rates[sr.trim()] = flt(sle.incoming_rate); + serialized_buying_rates[sr.trim().toLowerCase()] = flt(sle.incoming_rate); } }); } diff --git a/setup/doctype/backup_manager/backup_dropbox.py b/setup/doctype/backup_manager/backup_dropbox.py index 8d163539522..b4a8f66d4c0 100644 --- a/setup/doctype/backup_manager/backup_dropbox.py +++ b/setup/doctype/backup_manager/backup_dropbox.py @@ -96,6 +96,7 @@ def backup_to_dropbox(): error_log = [] path = os.path.join(get_base_path(), "public", "files") for filename in os.listdir(path): + filename = cstr(filename) if filename in ignore_list: continue diff --git a/setup/doctype/backup_manager/backup_googledrive.py b/setup/doctype/backup_manager/backup_googledrive.py index 5d7b6ad0fa1..440d907f2ed 100644 --- a/setup/doctype/backup_manager/backup_googledrive.py +++ b/setup/doctype/backup_manager/backup_googledrive.py @@ -85,6 +85,7 @@ def backup_to_gdrive(): webnotes.conn.close() path = os.path.join(get_base_path(), "public", "files") for filename in os.listdir(path): + filename = cstr(filename) found = False filepath = os.path.join(path, filename) ext = filename.split('.')[-1] diff --git a/setup/doctype/company/charts/import_from_openerp.py b/setup/doctype/company/charts/import_from_openerp.py index 894c2d739d8..ef800086c94 100644 --- a/setup/doctype/company/charts/import_from_openerp.py +++ b/setup/doctype/company/charts/import_from_openerp.py @@ -9,6 +9,7 @@ from __future__ import unicode_literals import os, json from xml.etree import ElementTree as ET from webnotes.utils.datautils import read_csv_content +from webnotes.utils import cstr path = "/Users/rmehta/Downloads/openerp/openerp/addons" chart_roots = [] @@ -108,6 +109,7 @@ def find_charts(): basename = os.path.basename(basepath) if basename.startswith("l10n"): for fname in files: + fname = cstr(fname) filepath = os.path.join(basepath, fname) if fname.endswith(".xml"): tree = ET.parse(filepath) diff --git a/setup/doctype/price_list/price_list.css b/setup/doctype/price_list/price_list.css new file mode 100644 index 00000000000..61b069442f8 --- /dev/null +++ b/setup/doctype/price_list/price_list.css @@ -0,0 +1,7 @@ +.table-grid tbody tr { + cursor: pointer; +} + +.table-grid thead tr { + height: 50px; +} \ No newline at end of file diff --git a/setup/doctype/price_list/price_list.js b/setup/doctype/price_list/price_list.js index f3adc727579..67090bcbc16 100644 --- a/setup/doctype/price_list/price_list.js +++ b/setup/doctype/price_list/price_list.js @@ -5,4 +5,253 @@ $.extend(cur_frm.cscript, { onload: function() { erpnext.add_for_territory(); }, +}); + +cur_frm.cscript.refresh = function(doc, cdt, cdn) { + cur_frm.cscript.show_item_prices(); +} + +cur_frm.cscript.show_item_prices = function() { + var item_price = wn.model.get("Item Price", {parent: cur_frm.doc.name}); + + $(cur_frm.fields_dict.item_prices_html.wrapper).empty(); + + new wn.ui.form.TableGrid({ + parent: cur_frm.fields_dict.item_prices_html.wrapper, + frm: cur_frm, + table_field: wn.meta.get_docfield("Price List", "item_prices", cur_frm.doc.name) + }); +} + +wn.ui.form.TableGrid = Class.extend({ + init: function(opts) { + $.extend(this, opts); + this.fields = wn.meta.get_docfields("Item Price", cur_frm.doc.name); + this.make_table(); + }, + make_table: function() { + var me = this; + // Creating table & assigning attributes + var grid_table = document.createElement("table"); + grid_table.className = "table table-hover table-bordered table-grid"; + + // Appending header & rows to table + grid_table.appendChild(this.make_table_headers()); + grid_table.appendChild(this.make_table_rows()); + + // Creating button to add new row + var btn_div = document.createElement("div"); + var new_row_btn = document.createElement("button"); + new_row_btn.className = "btn btn-success table-new-row"; + new_row_btn.title = "Add new row"; + + var btn_icon = document.createElement("i"); + btn_icon.className = "icon-plus"; + new_row_btn.appendChild(btn_icon); + new_row_btn.innerHTML += " Add new row"; + btn_div.appendChild(new_row_btn); + + // Appending table & button to parent + var $grid_table = $(grid_table).appendTo($(this.parent)); + var $btn_div = $(btn_div).appendTo($(this.parent)); + + $btn_div.on("click", ".table-new-row", function() { + me.make_dialog(); + return false; + }); + + $grid_table.on("click", ".table-row", function() { + me.make_dialog(this); + return false; + }); + }, + make_table_headers: function() { + var me = this; + var header = document.createElement("thead"); + + // Creating header row + var row = document.createElement("tr"); + row.className = "active"; + + // Creating head first cell + var th = document.createElement("th"); + th.width = "8%"; + th.className = "text-center"; + th.innerHTML = "#"; + row.appendChild(th); + + // Make other headers with label as heading + for(var i=0, l=this.fields.length; i