From 9166335649f478bce70d9026d29d99f7057ce303 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 29 Jul 2013 12:18:32 +0530 Subject: [PATCH 1/7] [minor] [bom] allow updating cost even after submit --- manufacturing/doctype/bom/bom.js | 5 ++--- manufacturing/doctype/bom/bom.py | 8 ++++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/manufacturing/doctype/bom/bom.js b/manufacturing/doctype/bom/bom.js index ce246d921a..87bc4aa0a2 100644 --- a/manufacturing/doctype/bom/bom.js +++ b/manufacturing/doctype/bom/bom.js @@ -18,10 +18,9 @@ cur_frm.cscript.refresh = function(doc,dt,dn){ cur_frm.toggle_enable("item", doc.__islocal); - if (!doc.__islocal && doc.docstatus==0) { - cur_frm.set_intro("Submit the BOM to use it for manufacturing or repacking."); + if (!doc.__islocal && doc.docstatus<2) { cur_frm.add_custom_button("Update Cost", cur_frm.cscript.update_cost); - } else cur_frm.set_intro(""); + } cur_frm.cscript.with_operations(doc); set_operation_no(doc); diff --git a/manufacturing/doctype/bom/bom.py b/manufacturing/doctype/bom/bom.py index e4c81ff0db..15f59ec042 100644 --- a/manufacturing/doctype/bom/bom.py +++ b/manufacturing/doctype/bom/bom.py @@ -144,8 +144,12 @@ class DocType: 'qty': d.qty })["rate"] - self.on_update() - + if self.doc.docstatus == 0: + webnotes.bean(self.doclist).save() + elif self.doc.docstatus == 1: + self.calculate_cost() + self.update_exploded_items() + webnotes.bean(self.doclist).update_after_submit() def get_bom_unitcost(self, bom_no): bom = sql("""select name, total_cost/quantity as unit_cost from `tabBOM` From 10c773dc1cc14ebda2a092ade40e33c0d0484deb Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Mon, 29 Jul 2013 12:27:47 +0530 Subject: [PATCH 2/7] [fix] [minor] [sales invoice] don't hide warehouse and delivered_qty --- accounts/doctype/sales_invoice/sales_invoice.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/accounts/doctype/sales_invoice/sales_invoice.js b/accounts/doctype/sales_invoice/sales_invoice.js index aa21d5dd7e..a4bbb2ac34 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.js +++ b/accounts/doctype/sales_invoice/sales_invoice.js @@ -171,8 +171,7 @@ cur_frm.cscript.hide_fields = function(doc) { 'total_commission', 'advances']; item_flds_normal = ['sales_order', 'delivery_note'] - item_flds_pos = ['warehouse', 'serial_no', 'batch_no', 'actual_qty', - 'delivered_qty', 'expense_account'] + item_flds_pos = ['serial_no', 'batch_no', 'actual_qty', 'expense_account'] if(cint(doc.is_pos) == 1) { hide_field(par_flds); @@ -185,7 +184,7 @@ cur_frm.cscript.hide_fields = function(doc) { } cur_frm.fields_dict['entries'].grid.set_column_disp(item_flds_pos, (cint(doc.update_stock)==1?true:false)); - + // India related fields var cp = wn.control_panel; if (cp.country == 'India') unhide_field(['c_form_applicable', 'c_form_no']); From ef0ab5d9aab2390de7ef041b1f73309428ce1545 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Mon, 29 Jul 2013 13:06:50 +0530 Subject: [PATCH 3/7] [patch] [minor] set price list currency, where only one currency is used for item price --- patches/july_2013/p11_update_price_list_currency.py | 9 +++++++++ patches/patch_list.py | 1 + 2 files changed, 10 insertions(+) create mode 100644 patches/july_2013/p11_update_price_list_currency.py diff --git a/patches/july_2013/p11_update_price_list_currency.py b/patches/july_2013/p11_update_price_list_currency.py new file mode 100644 index 0000000000..887149da15 --- /dev/null +++ b/patches/july_2013/p11_update_price_list_currency.py @@ -0,0 +1,9 @@ +import webnotes + +def execute(): + for price_list_name in webnotes.conn.sql_list("""select name from `tabPrice List` + where ifnull(currency, '')=''"""): + res = webnotes.conn.sql("""select distinct ref_currency from `tabItem Price` + where price_list_name=%s""", price_list_name) + if res and len(res)==1 and res[0][0]: + webnotes.conn.set_value("Price List", price_list_name, "currency", res[0][0]) diff --git a/patches/patch_list.py b/patches/patch_list.py index 9b6bb0f2dd..b60ca13779 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -262,4 +262,5 @@ patch_list = [ "patches.july_2013.p08_custom_print_format_net_total_export", "patches.july_2013.p09_remove_website_pyc", "patches.july_2013.p10_change_partner_user_to_website_user", + "patches.july_2013.p11_update_price_list_currency", ] \ No newline at end of file From 9eb2868bf13632980788a0e64eb4601980e33d75 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Mon, 29 Jul 2013 13:07:30 +0530 Subject: [PATCH 4/7] [fix] [minor] remove end of life condition from item query --- controllers/queries.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/controllers/queries.py b/controllers/queries.py index 478971a148..219fc743d1 100644 --- a/controllers/queries.py +++ b/controllers/queries.py @@ -169,15 +169,13 @@ def item_query(doctype, txt, searchfield, start, page_len, filters): if(length(tabItem.description) > 40, \ concat(substr(tabItem.description, 1, 40), "..."), description) as decription from tabItem - where tabItem.docstatus!=2 - and (ifnull(`tabItem`.`end_of_life`,"") in ("", "0000-00-00") - or `tabItem`.`end_of_life` > NOW()) + where tabItem.docstatus<2 and (tabItem.%(key)s LIKE "%(txt)s" or tabItem.item_name LIKE "%(txt)s") %(fcond)s %(mcond)s limit %(start)s,%(page_len)s """ % {'key': searchfield, 'txt': "%%%s%%" % txt, 'fcond': get_filters_cond(doctype, filters, conditions), - 'mcond':get_match_cond(doctype, searchfield), 'start': start, 'page_len': page_len}) + 'mcond': get_match_cond(doctype, searchfield), 'start': start, 'page_len': page_len}) def bom(doctype, txt, searchfield, start, page_len, filters): conditions = [] From 90d74d4bfa2a2822b16f61d0bc8eb2324ee0f1ac Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 29 Jul 2013 13:27:18 +0530 Subject: [PATCH 5/7] [minor] sales invoice to delivery note mapping and prevdoc validation --- .../doctype/sales_invoice/sales_invoice.js | 2 +- .../doctype/sales_invoice/sales_invoice.py | 46 +++++++++++++++++++ patches/patch_list.py | 1 + .../selling_settings/selling_settings.py | 2 +- stock/doctype/delivery_note/delivery_note.py | 29 ++++++------ 5 files changed, 65 insertions(+), 15 deletions(-) diff --git a/accounts/doctype/sales_invoice/sales_invoice.js b/accounts/doctype/sales_invoice/sales_invoice.js index a4bbb2ac34..35ea831124 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.js +++ b/accounts/doctype/sales_invoice/sales_invoice.js @@ -60,7 +60,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms); - if(doc.is_pos==1 && doc.update_stock!=1) + if(cint(doc.update_stock)!=1) cur_frm.add_custom_button('Make Delivery', cur_frm.cscript['Make Delivery Note']); if(doc.outstanding_amount!=0) diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py index ceab40ac12..d8752478d4 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.py +++ b/accounts/doctype/sales_invoice/sales_invoice.py @@ -983,3 +983,49 @@ def get_income_account(doctype, txt, searchfield, start, page_len, filters): and tabAccount.%(key)s LIKE '%(txt)s' %(mcond)s""" % {'company': filters['company'], 'key': searchfield, 'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype, searchfield)}) + + +@webnotes.whitelist() +def make_delivery_note(source_name, target_doclist=None): + from webnotes.model.mapper import get_mapped_doclist + + def set_missing_values(source, target): + bean = webnotes.bean(target) + bean.run_method("onload_post_render") + + def update_item(obj, target, source_parent): + target.amount = (flt(obj.qty) - flt(obj.delivered_qty)) * flt(obj.basic_rate) + target.export_amount = (flt(obj.qty) - flt(obj.delivered_qty)) * flt(obj.export_rate) + target.qty = flt(obj.qty) - flt(obj.delivered_qty) + + doclist = get_mapped_doclist("Sales Invoice", source_name, { + "Sales Invoice": { + "doctype": "Delivery Note", + "validation": { + "docstatus": ["=", 1] + } + }, + "Sales Invoice Item": { + "doctype": "Delivery Note Item", + "field_map": { + "name": "prevdoc_detail_docname", + "parent": "prevdoc_docname", + "parenttype": "prevdoc_doctype", + "serial_no": "serial_no" + }, + "postprocess": update_item + }, + "Sales Taxes and Charges": { + "doctype": "Sales Taxes and Charges", + "add_if_empty": True + }, + "Sales Team": { + "doctype": "Sales Team", + "field_map": { + "incentives": "incentives" + }, + "add_if_empty": True + } + }, target_doclist, set_missing_values) + + return [d.fields for d in doclist] \ No newline at end of file diff --git a/patches/patch_list.py b/patches/patch_list.py index 9b6bb0f2dd..dc9f34d1ce 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -262,4 +262,5 @@ patch_list = [ "patches.july_2013.p08_custom_print_format_net_total_export", "patches.july_2013.p09_remove_website_pyc", "patches.july_2013.p10_change_partner_user_to_website_user", + "execute:webnotes.bean('Selling Settings').save()", ] \ No newline at end of file diff --git a/selling/doctype/selling_settings/selling_settings.py b/selling/doctype/selling_settings/selling_settings.py index 47162287ab..febf3754ef 100644 --- a/selling/doctype/selling_settings/selling_settings.py +++ b/selling/doctype/selling_settings/selling_settings.py @@ -8,5 +8,5 @@ class DocType: self.doc, self.doclist = d, dl def validate(self): - for key in ["cust_master_name", "customer_group", "territory", "allow_same_sales_rate"]: + for key in ["cust_master_name", "customer_group", "territory", "maintain_same_sales_rate"]: webnotes.conn.set_default(key, self.doc.fields.get(key, "")) diff --git a/stock/doctype/delivery_note/delivery_note.py b/stock/doctype/delivery_note/delivery_note.py index f7283eb862..3f8a43883f 100644 --- a/stock/doctype/delivery_note/delivery_note.py +++ b/stock/doctype/delivery_note/delivery_note.py @@ -113,21 +113,24 @@ class DocType(SellingController): if not self.doc.installation_status: self.doc.installation_status = 'Not Installed' def validate_with_previous_doc(self): - super(DocType, self).validate_with_previous_doc(self.tname, { - "Sales Order": { - "ref_dn_field": "prevdoc_docname", - "compare_fields": [["customer", "="], ["company", "="], ["project_name", "="], - ["currency", "="]], - }, - }) - if cint(webnotes.defaults.get_global_default('maintain_same_sales_rate')): + prev_doctype = [d.prevdoc_doctype for d in self.doclist.get({ + "parentfield": "delivery_note_details", "prevdoc_doctype": ["!=", ""]})] + if prev_doctype: super(DocType, self).validate_with_previous_doc(self.tname, { - "Sales Order Item": { - "ref_dn_field": "prevdoc_detail_docname", - "compare_fields": [["export_rate", "="]], - "is_child_table": True - } + prev_doctype[0]: { + "ref_dn_field": "prevdoc_docname", + "compare_fields": [["customer", "="], ["company", "="], ["project_name", "="], + ["currency", "="]], + }, }) + if cint(webnotes.defaults.get_global_default('maintain_same_sales_rate')): + super(DocType, self).validate_with_previous_doc(self.tname, { + prev_doctype[0] + " Item": { + "ref_dn_field": "prevdoc_detail_docname", + "compare_fields": [["export_rate", "="]], + "is_child_table": True + } + }) def validate_proj_cust(self): From d5d39ac5ec0494f9672da5d5bd3711f607607eb3 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Mon, 29 Jul 2013 13:28:37 +0530 Subject: [PATCH 6/7] [fix] [minor] sales and purchase get_queries --- .../purchase_common/purchase_common.js | 8 ++++ public/js/queries.js | 9 +++++ selling/doctype/sales_common/sales_common.js | 37 +++++-------------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/buying/doctype/purchase_common/purchase_common.js b/buying/doctype/purchase_common/purchase_common.js index 148ba1c920..87f79a021f 100644 --- a/buying/doctype/purchase_common/purchase_common.js +++ b/buying/doctype/purchase_common/purchase_common.js @@ -49,6 +49,14 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ }); } + $.each([["supplier", "supplier"], + ["contact_person", "supplier_filter"], + ["supplier_address", "supplier_filter"]], + function(i, opts) { + if(me.frm.fields_dict[opts[0]]) + me.frm.set_query(opts[0], erpnext.queries[opts[1]]); + }); + if(this.frm.fields_dict.supplier) { this.frm.set_query("supplier", function() { return{ query:"controllers.queries.supplier_query" }}); diff --git a/public/js/queries.js b/public/js/queries.js index 8c3dd01203..090c393e05 100644 --- a/public/js/queries.js +++ b/public/js/queries.js @@ -58,6 +58,15 @@ $.extend(erpnext.queries, { return { filters: { customer: doc.customer } }; }, + supplier_filter: function(doc) { + if(!doc.supplier) { + wn.throw(wn._("Please specify a") + " " + + wn._(wn.meta.get_label(doc.doctype, "supplier", doc.name))); + } + + return { filters: { supplier: doc.supplier } }; + }, + not_a_group_filter: function() { return { filters: { is_group: "No" } }; }, diff --git a/selling/doctype/sales_common/sales_common.js b/selling/doctype/sales_common/sales_common.js index dbd0a1aace..d2461aff4a 100644 --- a/selling/doctype/sales_common/sales_common.js +++ b/selling/doctype/sales_common/sales_common.js @@ -36,22 +36,15 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ this.frm.add_fetch("sales_partner", "commission_rate", "commission_rate"); - if(this.frm.fields_dict.shipping_address_name && this.frm.fields_dict.customer_address) { - this.frm.fields_dict.shipping_address_name.get_query = - this.frm.fields_dict['customer_address'].get_query; - } - - this.frm.set_query("customer_address", function() { - return { - filters: {'customer': me.frm.doc.customer } - } - }); - - this.frm.set_query("contact_person", function() { - return { - filters: {'customer': me.frm.doc.customer } - } - }); + $.each([["customer_address", "customer_filter"], + ["shipping_address_name", "customer_filter"], + ["contact_person", "customer_filter"], + ["customer", "customer"], + ["lead", "lead"]], + function(i, opts) { + if(me.frm.fields_dict[opts[0]]) + me.frm.set_query(opts[0], erpnext.queries[opts[1]]); + }); if(this.frm.fields_dict.charge) { this.frm.set_query("charge", function() { @@ -63,13 +56,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ } }); } - - this.frm.fields_dict.customer.get_query = function(doc,cdt,cdn) { - return{ query:"controllers.queries.customer_query" } } - this.frm.fields_dict.lead && this.frm.set_query("lead", function(doc,cdt,cdn) { - return{ query:"controllers.queries.lead_query" } }); - if(this.frm.fields_dict.price_list_name) { this.frm.set_query("price_list_name", function() { return { filters: { buying_or_selling: "Selling" } }; @@ -130,11 +117,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ } if(this.frm.fields_dict.sales_team && this.frm.fields_dict.sales_team.grid.get_field("sales_person")) { - this.frm.set_query("sales_person", "sales_team", function() { - return { - filters: { is_group: "No" } - }; - }); + this.frm.set_query("sales_person", "sales_team", erpnext.queries.not_a_group_filter); } }, From 5e200e43a66941c909662f83d3d58c234b522a2b Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 29 Jul 2013 15:29:51 +0530 Subject: [PATCH 7/7] [minor] duplicate row id from same prevdoc --- accounts/doctype/purchase_invoice/purchase_invoice.py | 6 ++++-- accounts/doctype/sales_invoice/sales_invoice.py | 3 ++- accounts/doctype/sales_invoice/test_sales_invoice.py | 2 -- utilities/transaction_base.py | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.py b/accounts/doctype/purchase_invoice/purchase_invoice.py index fac976ebe1..539cef5e46 100644 --- a/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -196,7 +196,8 @@ class DocType(BuyingController): "Purchase Order Item": { "ref_dn_field": "po_detail", "compare_fields": [["project_name", "="], ["item_code", "="], ["uom", "="]], - "is_child_table": True + "is_child_table": True, + "allow_duplicate_prev_row_id": True }, "Purchase Receipt": { "ref_dn_field": "purchase_receipt", @@ -214,7 +215,8 @@ class DocType(BuyingController): "Purchase Order Item": { "ref_dn_field": "po_detail", "compare_fields": [["import_rate", "="]], - "is_child_table": True + "is_child_table": True, + "allow_duplicate_prev_row_id": True }, "Purchase Receipt Item": { "ref_dn_field": "pr_detail", diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py index d8752478d4..8f33eb3ccd 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.py +++ b/accounts/doctype/sales_invoice/sales_invoice.py @@ -388,7 +388,8 @@ class DocType(SellingController): "Sales Order Item": { "ref_dn_field": "so_detail", "compare_fields": [["export_rate", "="]], - "is_child_table": True + "is_child_table": True, + "allow_duplicate_prev_row_id": True }, "Delivery Note Item": { "ref_dn_field": "dn_detail", diff --git a/accounts/doctype/sales_invoice/test_sales_invoice.py b/accounts/doctype/sales_invoice/test_sales_invoice.py index ec4535b226..7b32ea07a3 100644 --- a/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -607,8 +607,6 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(new_si.doc.invoice_period_to_date, unicode(add_months(base_si.doc.invoice_period_to_date, no_of_months))) - self.assertEquals(getdate(new_si.doc.posting_date).day, - base_si.doc.repeat_on_day_of_month) return new_si diff --git a/utilities/transaction_base.py b/utilities/transaction_base.py index 6628601c25..b688200b59 100644 --- a/utilities/transaction_base.py +++ b/utilities/transaction_base.py @@ -308,7 +308,7 @@ class TransactionBase(StatusUpdater): self.compare_values({key: [ref_dn]}, val["compare_fields"], d) if ref_dn not in item_ref_dn: item_ref_dn.append(ref_dn) - else: + elif not val.get("allow_duplicate_prev_row_id"): webnotes.msgprint(_("Row ") + cstr(d.idx + 1) + _(": Duplicate row from same ") + key, raise_exception=1) elif ref_dn: