From 88ac48554103ef37f5137d08995fb6e10a01bc16 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Mon, 11 Mar 2013 14:57:45 +0530 Subject: [PATCH 1/5] minor fixes in utils, purchase common and task --- .../purchase_common/purchase_common.js | 8 +++--- projects/doctype/task/task.js | 3 ++- public/js/utils.js | 26 +------------------ 3 files changed, 7 insertions(+), 30 deletions(-) diff --git a/buying/doctype/purchase_common/purchase_common.js b/buying/doctype/purchase_common/purchase_common.js index 05b7bcbef8..136ddef383 100644 --- a/buying/doctype/purchase_common/purchase_common.js +++ b/buying/doctype/purchase_common/purchase_common.js @@ -68,15 +68,15 @@ erpnext.buying.BuyingController = erpnext.utils.Controller.extend({ callback: function(r) { if(!r.exc) { me.price_list_currency(); - if (callback_fn) callback_fn(me.frm.doc, me.frm.doc.doctype, - me.frm.doc.name); + if (typeof callback_fn === "function") + callback_fn(me.frm.doc, me.frm.doc.doctype, me.frm.doc.name); } } }); } else { me.price_list_currency(); - if (callback_fn) callback_fn(me.frm.doc, me.frm.doc.doctype, - me.frm.doc.name); + if (typeof callback_fn === "function") + callback_fn(me.frm.doc, me.frm.doc.doctype, me.frm.doc.name); } } }, diff --git a/projects/doctype/task/task.js b/projects/doctype/task/task.js index 472ca6b98c..ea3dd6d772 100644 --- a/projects/doctype/task/task.js +++ b/projects/doctype/task/task.js @@ -29,7 +29,8 @@ erpnext.projects.Task = erpnext.utils.Controller.extend({ project: function() { if(this.frm.doc.project) { - get_server_fields('get_project_details', '','', doc, cdt, cdn, 1); + get_server_fields('get_project_details', '','', this.frm.doc, this.frm.doc.doctype, + this.frm.doc.name, 1); } }, diff --git a/public/js/utils.js b/public/js/utils.js index 0f78705294..7340cdcb04 100644 --- a/public/js/utils.js +++ b/public/js/utils.js @@ -26,31 +26,7 @@ erpnext.get_currency = function(company) { } // TODO -erpnext.utils.Controller = Class.extend({ - init: function(opts) { - $.extend(this, opts); - this.setup && this.setup(); - }, - - onload_post_render: function() { - if(this.frm.doc.__islocal) { - this.setup_defaults(); - } - }, - - setup_defaults: function() { - var me = this; - - var defaults = { - posting_date: wn.datetime.get_today(), - posting_time: wn.datetime.now_time() - } - - $.each(defaults, function(k, v) { - if(!me.frm.doc[k]) me.frm.set_value(k, v); - }); - }, - +erpnext.utils.Controller = wn.ui.form.Controller.extend({ refresh: function() { erpnext.hide_naming_series(); } From df6ff1385fabd100bc70ce60803b0c942e1d6ccb Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Mon, 11 Mar 2013 19:44:52 +0530 Subject: [PATCH 2/5] fixes in warehouse validation --- .../doctype/sales_invoice/sales_invoice.py | 3 +-- .../purchase_common/purchase_common.js | 2 +- .../doctype/purchase_order/purchase_order.py | 4 ++++ hr/doctype/employee/employee.py | 4 ++-- .../upload_attendance/upload_attendance.js | 2 +- projects/doctype/task/task.js | 2 +- public/js/controllers/stock_controller.js | 2 +- public/js/utils.js | 9 +-------- selling/doctype/sales_order/sales_order.py | 10 +++++----- stock/doctype/delivery_note/delivery_note.py | 19 +++++++++++++----- stock/doctype/item/item.py | 20 +++++++++++++------ .../purchase_receipt/purchase_receipt.py | 5 ++++- stock/doctype/stock_entry/stock_entry.py | 12 +++++++++-- 13 files changed, 59 insertions(+), 35 deletions(-) diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py index b31d54919c..a4924ac187 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.py +++ b/accounts/doctype/sales_invoice/sales_invoice.py @@ -537,8 +537,7 @@ class DocType(SellingController): if not w: ps = webnotes.conn.sql("select name, warehouse from `tabPOS Setting` where ifnull(user,'') = '' and company = '%s'" % self.doc.company) if not ps: - msgprint("To make POS entry, please create POS Setting from Accounts --> POS Setting page and refresh the system.") - raise Exception + msgprint("To make POS entry, please create POS Setting from Accounts --> POS Setting page and refresh the system.", raise_exception=True) elif not ps[0][1]: msgprint("Please enter warehouse in POS Setting") else: diff --git a/buying/doctype/purchase_common/purchase_common.js b/buying/doctype/purchase_common/purchase_common.js index 136ddef383..dacee80e55 100644 --- a/buying/doctype/purchase_common/purchase_common.js +++ b/buying/doctype/purchase_common/purchase_common.js @@ -21,7 +21,7 @@ wn.provide("erpnext.buying"); -erpnext.buying.BuyingController = erpnext.utils.Controller.extend({ +erpnext.buying.BuyingController = wn.ui.form.Controller.extend({ setup: function() { var me = this; diff --git a/buying/doctype/purchase_order/purchase_order.py b/buying/doctype/purchase_order/purchase_order.py index 438442cf24..218d4bfeee 100644 --- a/buying/doctype/purchase_order/purchase_order.py +++ b/buying/doctype/purchase_order/purchase_order.py @@ -132,6 +132,10 @@ class DocType(BuyingController): for d in getlist(self.doclist, 'po_details'): #1. Check if is_stock_item == 'Yes' if webnotes.conn.get_value("Item", d.item_code, "is_stock_item") == "Yes": + # this happens when item is changed from non-stock to stock item + if not d.warehouse: + continue + ind_qty, po_qty = 0, flt(d.qty) * flt(d.conversion_factor) if is_stopped: po_qty = flt(d.qty) > flt(d.received_qty) and \ diff --git a/hr/doctype/employee/employee.py b/hr/doctype/employee/employee.py index 2bd7998159..d98c8a7754 100644 --- a/hr/doctype/employee/employee.py +++ b/hr/doctype/employee/employee.py @@ -17,7 +17,7 @@ from __future__ import unicode_literals import webnotes -from webnotes.utils import getdate, validate_email_add +from webnotes.utils import getdate, validate_email_add, cstr from webnotes.model.doc import make_autoname from webnotes import msgprint, _ @@ -104,7 +104,7 @@ class DocType: fname, fid = file_args.split(",") if self.doc.image == fname: new_file_args = fname + "," + fid - file_list = profile_wrapper.doc.file_list.split("\n") + file_list = cstr(profile_wrapper.doc.file_list).split("\n") if new_file_args not in file_list: file_list += [new_file_args] profile_wrapper.doc.file_list = "\n".join(file_list) diff --git a/hr/doctype/upload_attendance/upload_attendance.js b/hr/doctype/upload_attendance/upload_attendance.js index 008e1cd878..0c1d7b2574 100644 --- a/hr/doctype/upload_attendance/upload_attendance.js +++ b/hr/doctype/upload_attendance/upload_attendance.js @@ -18,7 +18,7 @@ wn.require("public/app/js/utils.js"); wn.provide("erpnext.hr"); -erpnext.hr.AttendanceControlPanel = erpnext.utils.Controller.extend({ +erpnext.hr.AttendanceControlPanel = wn.ui.form.Controller.extend({ onload: function() { this.frm.set_value("att_fr_date", get_today()); this.frm.set_value("att_to_date", get_today()); diff --git a/projects/doctype/task/task.js b/projects/doctype/task/task.js index ea3dd6d772..8493920540 100644 --- a/projects/doctype/task/task.js +++ b/projects/doctype/task/task.js @@ -18,7 +18,7 @@ wn.provide("erpnext.projects"); cur_frm.add_fetch("project", "company", "company"); -erpnext.projects.Task = erpnext.utils.Controller.extend({ +erpnext.projects.Task = wn.ui.form.Controller.extend({ setup: function() { this.frm.fields_dict.project.get_query = function() { return "select name from `tabProject` \ diff --git a/public/js/controllers/stock_controller.js b/public/js/controllers/stock_controller.js index d3511e1c03..15d34e0e33 100644 --- a/public/js/controllers/stock_controller.js +++ b/public/js/controllers/stock_controller.js @@ -16,7 +16,7 @@ wn.provide("erpnext.stock"); -erpnext.stock.StockController = erpnext.utils.Controller.extend({ +erpnext.stock.StockController = wn.ui.form.Controller.extend({ show_stock_ledger: function() { var me = this; this.frm.add_custom_button("Show Stock Ledger", function() { diff --git a/public/js/utils.js b/public/js/utils.js index 7340cdcb04..4df9555ae9 100644 --- a/public/js/utils.js +++ b/public/js/utils.js @@ -23,11 +23,4 @@ erpnext.get_currency = function(company) { return wn.model.get(":Company", company).default_currency || wn.boot.sysdefaults.currency; else return wn.boot.sysdefaults.currency; -} - -// TODO -erpnext.utils.Controller = wn.ui.form.Controller.extend({ - refresh: function() { - erpnext.hide_naming_series(); - } -}); \ No newline at end of file +} \ No newline at end of file diff --git a/selling/doctype/sales_order/sales_order.py b/selling/doctype/sales_order/sales_order.py index 8205afbd44..5009c4ee26 100644 --- a/selling/doctype/sales_order/sales_order.py +++ b/selling/doctype/sales_order/sales_order.py @@ -156,9 +156,13 @@ class DocType(SellingController): f = [d.item_code, d.description] #check item is stock item - st_itm = sql("select is_stock_item from `tabItem` where name = '%s'"%d.item_code) + st_itm = sql("select is_stock_item from `tabItem` where name = %s", d.item_code) if st_itm and st_itm[0][0] == 'Yes': + if not d.reserved_warehouse: + msgprint("""Please enter Reserved Warehouse for item %s + as it is stock Item""" % d.item_code, raise_exception=1) + if e in check_list: msgprint("Item %s has been entered twice." % d.item_code) else: @@ -333,10 +337,6 @@ class DocType(SellingController): def update_stock_ledger(self, update_stock, is_stopped = 0): for d in self.get_item_list(is_stopped): if webnotes.conn.get_value("Item", d['item_code'], "is_stock_item") == "Yes": - if not d['reserved_warehouse']: - msgprint("""Please enter Reserved Warehouse for item %s - as it is stock Item""" % d['item_code'], raise_exception=1) - args = { "item_code": d['item_code'], "reserved_qty": flt(update_stock) * flt(d['reserved_qty']), diff --git a/stock/doctype/delivery_note/delivery_note.py b/stock/doctype/delivery_note/delivery_note.py index c0b99166ee..52f96ab7a5 100644 --- a/stock/doctype/delivery_note/delivery_note.py +++ b/stock/doctype/delivery_note/delivery_note.py @@ -156,7 +156,7 @@ class DocType(SellingController): if not self.doc.billing_status: self.doc.billing_status = 'Not Billed' if not self.doc.installation_status: self.doc.installation_status = 'Not Installed' - + def validate_mandatory(self): if self.doc.amended_from and not self.doc.amendment_date: msgprint("Please Enter Amendment Date") @@ -332,10 +332,10 @@ class DocType(SellingController): self.values = [] for d in self.get_item_list(): if webnotes.conn.get_value("Item", d['item_code'], "is_stock_item") == "Yes": - if not d['warehouse']: - msgprint("Please enter Warehouse for item %s as it is stock item" - % d['item_code'], raise_exception=1) - + # this happens when item is changed from non-stock to stock item + if not d["warehouse"]: + continue + if d['reserved_qty'] < 0 : # Reduce reserved qty from reserved warehouse mentioned in so args = { @@ -395,6 +395,15 @@ class DocType(SellingController): sl.scrub_serial_nos(self) sl.scrub_serial_nos(self, 'packing_details') + self.validate_warehouse() + + def validate_warehouse(self): + for d in self.get_item_list(): + if webnotes.conn.get_value("Item", d['item_code'], "is_stock_item") == "Yes": + if not d['warehouse']: + msgprint("Please enter Warehouse for item %s as it is stock item" + % d['item_code'], raise_exception=1) + def make_gl_entries(self): if not cint(webnotes.defaults.get_global_default("auto_inventory_accounting")): return diff --git a/stock/doctype/item/item.py b/stock/doctype/item/item.py index 334af298e9..74bf3f308c 100644 --- a/stock/doctype/item/item.py +++ b/stock/doctype/item/item.py @@ -20,15 +20,12 @@ import webnotes from webnotes.utils import cstr, flt from webnotes.model.doc import addchild from webnotes.model.bean import getlist -from webnotes import msgprint +from webnotes import msgprint, _ sql = webnotes.conn.sql -class DocType: - def __init__(self, doc, doclist=[]): - self.doc = doc - self.doclist = doclist - +from webnotes.model.controller import DocListController +class DocType(DocListController): def get_tax_rate(self, tax_type): rate = sql("select tax_rate from tabAccount where name = %s", tax_type) ret = { @@ -196,6 +193,8 @@ class DocType: if self.doc.name: self.old_page_name = webnotes.conn.get_value('Item', self.doc.name, 'page_name') + + self.validate_is_stock_item() def check_non_asset_warehouse(self): if self.doc.is_asset_item == "Yes": @@ -215,6 +214,15 @@ class DocType: 'description' : file and file[0]['description'] or '' } return ret + + def validate_is_stock_item(self): + if not self.doc.fields.get("__islocal"): + if webnotes.conn.get_value("Item", self.doc.name, "is_stock_item")=="Yes" and \ + ((not self.doc.is_stock_item) or self.doc.is_stock_item == "No"): + if self.check_if_sle_exists() == "exists": + webnotes.msgprint(self.meta.get_label("is_stock_item") + ": " + + _("""Cannot change to Yes. Reason: Stock Ledger Entries exist for""") + + """ "%s" """ % self.doc.name, raise_exception=True) def check_if_sle_exists(self): sle = sql("select name from `tabStock Ledger Entry` where item_code = %s and ifnull(is_cancelled, 'No') = 'No'", self.doc.name) diff --git a/stock/doctype/purchase_receipt/purchase_receipt.py b/stock/doctype/purchase_receipt/purchase_receipt.py index 12da0a6ee8..cce1493141 100644 --- a/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/stock/doctype/purchase_receipt/purchase_receipt.py @@ -125,7 +125,7 @@ class DocType(BuyingController): self.update_raw_materials_supplied("pr_raw_material_details") self.update_valuation_rate("purchase_receipt_details") - + def on_update(self): if self.doc.rejected_warehouse: for d in getlist(self.doclist,'purchase_receipt_details'): @@ -146,6 +146,9 @@ class DocType(BuyingController): self.values = [] for d in getlist(self.doclist, 'purchase_receipt_details'): if webnotes.conn.get_value("Item", d.item_code, "is_stock_item") == "Yes": + if not d.warehouse: + continue + ord_qty = 0 pr_qty = flt(d.qty) * flt(d.conversion_factor) diff --git a/stock/doctype/stock_entry/stock_entry.py b/stock/doctype/stock_entry/stock_entry.py index 278c283284..74b71d97b3 100644 --- a/stock/doctype/stock_entry/stock_entry.py +++ b/stock/doctype/stock_entry/stock_entry.py @@ -29,9 +29,9 @@ import json sql = webnotes.conn.sql -from utilities.transaction_base import TransactionBase +from controllers.accounts_controller import AccountsController -class DocType(TransactionBase): +class DocType(AccountsController): def __init__(self, doc, doclist=[]): self.doc = doc self.doclist = doclist @@ -44,12 +44,14 @@ class DocType(TransactionBase): pro_obj = self.doc.production_order and \ get_obj('Production Order', self.doc.production_order) or None + self.validate_item() self.validate_warehouse(pro_obj) self.validate_production_order(pro_obj) self.get_stock_and_rate() self.validate_incoming_rate() self.validate_bom() self.validate_finished_goods() + self.validate_return_reference_doc() self.validate_with_material_request() @@ -78,6 +80,12 @@ class DocType(TransactionBase): sl_obj.scrub_serial_nos(self) sl_obj.validate_serial_no(self, 'mtn_details') + def validate_item(self): + for item in self.doclist.get({"parentfield": "mtn_details"}): + if item.item_code not in self.stock_items: + msgprint(_("""Only Stock Items are allowed for Stock Entry"""), + raise_exception=True) + def validate_warehouse(self, pro_obj): """perform various (sometimes conditional) validations on warehouse""" From 9e4b1e691315b5f9f673d1cb301697449f9ab8b0 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 12 Mar 2013 10:44:35 +0530 Subject: [PATCH 3/5] patch fix: published on should be date of creation --- patches/march_2013/p03_rename_blog_to_blog_post.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches/march_2013/p03_rename_blog_to_blog_post.py b/patches/march_2013/p03_rename_blog_to_blog_post.py index 7520f9cf8b..69902f34be 100644 --- a/patches/march_2013/p03_rename_blog_to_blog_post.py +++ b/patches/march_2013/p03_rename_blog_to_blog_post.py @@ -6,4 +6,4 @@ def execute(): webnotes.reload_doc('website', 'doctype', 'blog_post') webnotes.conn.sql('''update tabBlogger set posts=(select count(*) from `tabBlog Post` where ifnull(blogger,"")=tabBlogger.name)''') - webnotes.conn.sql("""update `tabBlog Post` set published_on=creation""") + webnotes.conn.sql("""update `tabBlog Post` set published_on=date(creation)""") From 0cfbc5feb5d8e381892834e403b6334e3eb7c964 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 12 Mar 2013 11:34:56 +0530 Subject: [PATCH 4/5] fixes in sales order test cases and set_buying_amount --- .../doctype/sales_order/test_sales_order.py | 22 +++++++++---------- stock/utils.py | 6 +++-- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/selling/doctype/sales_order/test_sales_order.py b/selling/doctype/sales_order/test_sales_order.py index 5d820fe769..40a10b439c 100644 --- a/selling/doctype/sales_order/test_sales_order.py +++ b/selling/doctype/sales_order/test_sales_order.py @@ -65,7 +65,7 @@ class TestSalesOrder(unittest.TestCase): # submit dn dn = self.create_dn_against_so(so) - self.check_reserved_qty(so.doclist[1].item_code, so.doclist[1].reserved_warehouse, 6.0) + self.check_reserved_qty(so.doclist[1].item_code, so.doclist[1].reserved_warehouse, 5.0) # stop so so.load_from_db() @@ -75,7 +75,7 @@ class TestSalesOrder(unittest.TestCase): # unstop so so.load_from_db() so.obj.unstop_sales_order() - self.check_reserved_qty(so.doclist[1].item_code, so.doclist[1].reserved_warehouse, 6.0) + self.check_reserved_qty(so.doclist[1].item_code, so.doclist[1].reserved_warehouse, 5.0) # cancel dn dn.cancel() @@ -151,9 +151,9 @@ class TestSalesOrder(unittest.TestCase): dn = self.create_dn_against_so(so) self.check_reserved_qty(sbom_test_records[0][1]["item_code"], - so.doclist[1].reserved_warehouse, 30.0) + so.doclist[1].reserved_warehouse, 25.0) self.check_reserved_qty(sbom_test_records[0][2]["item_code"], - so.doclist[1].reserved_warehouse, 12.0) + so.doclist[1].reserved_warehouse, 10.0) # stop so so.load_from_db() @@ -168,9 +168,9 @@ class TestSalesOrder(unittest.TestCase): so.load_from_db() so.obj.unstop_sales_order() self.check_reserved_qty(sbom_test_records[0][1]["item_code"], - so.doclist[1].reserved_warehouse, 30.0) + so.doclist[1].reserved_warehouse, 25.0) self.check_reserved_qty(sbom_test_records[0][2]["item_code"], - so.doclist[1].reserved_warehouse, 12.0) + so.doclist[1].reserved_warehouse, 10.0) # cancel dn dn.cancel() @@ -234,8 +234,8 @@ test_records = [ "price_list_name": "_Test Price List", "territory": "_Test Territory", "transaction_date": "2013-02-21", - "grand_total": 500.0, - "grand_total_export": 500.0, + "grand_total": 1000.0, + "grand_total_export": 1000.0, }, { "description": "CPU", @@ -244,9 +244,9 @@ test_records = [ "item_name": "CPU", "parentfield": "sales_order_details", "qty": 10.0, - "basic_rate": 50.0, - "export_rate": 50.0, - "amount": 500.0, + "basic_rate": 100.0, + "export_rate": 100.0, + "amount": 1000.0, "reserved_warehouse": "_Test Warehouse", } ], diff --git a/stock/utils.py b/stock/utils.py index bc6054f70b..20d08ea3eb 100644 --- a/stock/utils.py +++ b/stock/utils.py @@ -181,11 +181,13 @@ def get_buying_amount(item_code, warehouse, qty, voucher_type, voucher_no, vouch def _get_buying_amount(voucher_type, voucher_no, item_row, item_code, warehouse, qty, stock_ledger_entries): for i, sle in enumerate(stock_ledger_entries): - if sle.voucher_type == voucher_type and sle.voucher_no == voucher_no: + if sle.voucher_type == voucher_type and sle.voucher_no == voucher_no and \ + len(stock_ledger_entries) > i+1: if (sle.voucher_detail_no == item_row) or \ (sle.item_code == item_code and sle.warehouse == warehouse and \ abs(flt(sle.qty)) == qty): - buying_amount = flt(stock_ledger_entries[i+1].stock_value) - flt(sle.stock_value) + buying_amount = flt(stock_ledger_entries[i+1].stock_value) - \ + flt(sle.stock_value) return buying_amount From 6dc6e7c84a0f32f89ac962f902c8744295d1e2e7 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 12 Mar 2013 12:51:53 +0530 Subject: [PATCH 5/5] minor fixes in stock entry js --- stock/doctype/stock_entry/stock_entry.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stock/doctype/stock_entry/stock_entry.js b/stock/doctype/stock_entry/stock_entry.js index 55a86a3799..ba1f64802a 100644 --- a/stock/doctype/stock_entry/stock_entry.js +++ b/stock/doctype/stock_entry/stock_entry.js @@ -19,7 +19,6 @@ wn.provide("erpnext.stock"); erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ onload_post_render: function() { - this._super(); if(this.frm.doc.__islocal && (this.frm.doc.production_order || this.frm.doc.bom_no) && !getchildren('Stock Entry Detail', this.frm.doc.name, 'mtn_details').length) { // if production order / bom is mentioned, get items @@ -28,7 +27,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({ }, refresh: function() { - this._super(); + erpnext.hide_naming_series(); this.toggle_related_fields(this.frm.doc); this.toggle_enable_bom(); if (this.frm.doc.docstatus==1) {