From 113b4c1a218674f944934c229551a2d81a0f3d9b Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 11 Nov 2013 18:25:12 +0530 Subject: [PATCH 01/13] [fix] [minor] accounts payable ageing data --- accounts/report/accounts_payable/accounts_payable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accounts/report/accounts_payable/accounts_payable.py b/accounts/report/accounts_payable/accounts_payable.py index d9a0ca2a4ca..c1a106924fd 100644 --- a/accounts/report/accounts_payable/accounts_payable.py +++ b/accounts/report/accounts_payable/accounts_payable.py @@ -54,7 +54,7 @@ def execute(filters=None): else: ageing_based_on_date = gle.posting_date - row += get_ageing_data(ageing_based_on_date, age_on, outstanding_amount) + row += get_ageing_data(age_on, ageing_based_on_date, outstanding_amount) data.append(row) return columns, data From fbfefd3dcd88cbf9e50d806aaeaf17ca503486a1 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Tue, 12 Nov 2013 11:24:56 +0530 Subject: [PATCH 02/13] [fix] [minor] budget variance report fixed --- accounts/report/budget_variance_report/budget_variance_report.py | 1 + 1 file changed, 1 insertion(+) diff --git a/accounts/report/budget_variance_report/budget_variance_report.py b/accounts/report/budget_variance_report/budget_variance_report.py index ee4f6fe20a9..941fb8adbf6 100644 --- a/accounts/report/budget_variance_report/budget_variance_report.py +++ b/accounts/report/budget_variance_report/budget_variance_report.py @@ -92,6 +92,7 @@ def get_actual_details(filters): (filters.get("fiscal_year"), filters.get("company")), as_dict=1) def get_costcenter_account_month_map(filters): + import datetime costcenter_target_details = get_costcenter_target_details(filters) tdd = get_target_distribution_details(filters) actual_details = get_actual_details(filters) From e0b32824ff0e8313d0a15896b2145d0ba14268f5 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Tue, 12 Nov 2013 19:27:16 +0530 Subject: [PATCH 03/13] [fix] [minor] updated message for conversion rate --- public/js/transaction.js | 16 +++++++++------- utilities/transaction_base.py | 14 +++++++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/public/js/transaction.js b/public/js/transaction.js index d52b742228a..4b941e33b1e 100644 --- a/public/js/transaction.js +++ b/public/js/transaction.js @@ -499,16 +499,18 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ this.frm.doc.conversion_rate = flt(this.frm.doc.conversion_rate, precision("conversion_rate")); var conversion_rate_label = wn.meta.get_label(this.frm.doc.doctype, "conversion_rate", this.frm.doc.name); - - if(this.frm.doc.conversion_rate == 0) { - wn.throw(wn._(conversion_rate_label) + " " + wn._("cannot be 0")); - } - var company_currency = this.get_company_currency(); if(!this.frm.doc.conversion_rate) { - wn.throw(wn._("Please enter valid") + " " + wn._(conversion_rate_label) + - " 1 " + this.frm.doc.currency + " = [?] " + company_currency); + var msg = $(repl('%(conversion_rate_label)s is mandatory. Maybe Currency Exchange \ + record is not created for %(from_currency)s to %(to_currency)s', + { + "conversion_rate_label": conversion_rate_label, + "from_currency": self.doc.currency, + "to_currency": company_currency + })); + + wn.throw(wn._(msg)); } }, diff --git a/utilities/transaction_base.py b/utilities/transaction_base.py index 0f4d6bcacd5..684da467951 100644 --- a/utilities/transaction_base.py +++ b/utilities/transaction_base.py @@ -426,15 +426,15 @@ 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) - company_currency = webnotes.conn.get_value("Company", company, "default_currency") - + if not conversion_rate: - msgprint(_('Please enter valid ') + conversion_rate_label + (': ') - + ("1 %s = [?] %s" % (currency, company_currency)), - raise_exception=True) + msgprint(_('%(conversion_rate_label)s is mandatory. Maybe Currency Exchange \ + record is not created for %(from_currency)s to %(to_currency)s') % { + "conversion_rate_label": conversion_rate_label, + "from_currency": currency, + "to_currency": company_currency + }, raise_exception=True) def validate_item_fetch(args, item): from stock.utils import validate_end_of_life From e1cf3453b4df7d6eaf3c6f094fef94f42a967c0f Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Tue, 12 Nov 2013 19:49:10 +0530 Subject: [PATCH 04/13] [fix] [minor] conversion rate validation message update --- public/js/transaction.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/public/js/transaction.js b/public/js/transaction.js index 4b941e33b1e..664bbe2f9ef 100644 --- a/public/js/transaction.js +++ b/public/js/transaction.js @@ -502,15 +502,13 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ var company_currency = this.get_company_currency(); if(!this.frm.doc.conversion_rate) { - var msg = $(repl('%(conversion_rate_label)s is mandatory. Maybe Currency Exchange \ - record is not created for %(from_currency)s to %(to_currency)s', + wn.throw(wn._('%(conversion_rate_label)s is mandatory. Maybe Currency Exchange \ + record is not created for %(from_currency)s to %(to_currency)s'), { "conversion_rate_label": conversion_rate_label, "from_currency": self.doc.currency, "to_currency": company_currency - })); - - wn.throw(wn._(msg)); + }); } }, From 49f2bafa0fd6153ec1037a890a3266739fb849d8 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 13 Nov 2013 15:32:12 +0530 Subject: [PATCH 05/13] [fix] [minor] budget variance report logic + loading time --- .../budget_variance_report.py | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/accounts/report/budget_variance_report/budget_variance_report.py b/accounts/report/budget_variance_report/budget_variance_report.py index 941fb8adbf6..c1c4bc1ae85 100644 --- a/accounts/report/budget_variance_report/budget_variance_report.py +++ b/accounts/report/budget_variance_report/budget_variance_report.py @@ -29,7 +29,7 @@ def execute(filters=None): for month in relevant_months: month_data = monthwise_data.get(month, {}) for i, fieldname in enumerate(["target", "actual", "variance"]): - value = flt(month_data.get(fieldname), precision) + value = flt(month_data.get(fieldname)) period_data[i] += value totals[i] += value period_data[2] = period_data[0] - period_data[1] @@ -60,7 +60,8 @@ def get_columns(filters): columns.append(label+":Float:120") - return columns + ["Total Target::120", "Total Actual::120", "Total Variance::120"] + return columns + ["Total Target:Float:120", "Total Actual:Float:120", + "Total Variance:Float:120"] #Get cost center & target details def get_costcenter_target_details(filters): @@ -84,12 +85,18 @@ def get_target_distribution_details(filters): #Get actual details from gl entry def get_actual_details(filters): - return webnotes.conn.sql("""select gl.account, gl.debit, gl.credit, + ac_details = webnotes.conn.sql("""select gl.account, gl.debit, gl.credit, gl.cost_center, MONTHNAME(gl.posting_date) as month_name from `tabGL Entry` gl, `tabBudget Detail` bd where gl.fiscal_year=%s and company=%s - and bd.account=gl.account""" % ('%s', '%s'), + and bd.account=gl.account and bd.parent=gl.cost_center""" % ('%s', '%s'), (filters.get("fiscal_year"), filters.get("company")), as_dict=1) + + cc_actual_details = {} + for d in ac_details: + cc_actual_details.setdefault(d.cost_center, {}).setdefault(d.account, []).append(d) + + return cc_actual_details def get_costcenter_account_month_map(filters): import datetime @@ -112,9 +119,9 @@ def get_costcenter_account_month_map(filters): month_percentage = ccd.distribution_id and \ tdd.get(ccd.distribution_id, {}).get(month, 0) or 100.0/12 - tav_dict.target = flt(flt(ccd.budget_allocated) * month_percentage /100) - - for ad in actual_details: + tav_dict.target = flt(ccd.budget_allocated) * month_percentage /100 + + for ad in actual_details.get(ccd.name, {}).get(ccd.account, []): if ad.month_name == month and ad.account == ccd.account \ and ad.cost_center == ccd.name: tav_dict.actual += ad.debit - ad.credit From bfe264be8c4ce1c9f42a45f8b3d9f104396cab5d Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Wed, 13 Nov 2013 16:45:11 +0530 Subject: [PATCH 06/13] [fix] [minor] all types of variance reports fixed --- .../budget_variance_report.py | 3 --- ..._person_target_variance_item_group_wise.py | 18 +++++++++---- ...rritory_target_variance_item_group_wise.py | 26 ++++++++++++------- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/accounts/report/budget_variance_report/budget_variance_report.py b/accounts/report/budget_variance_report/budget_variance_report.py index c1c4bc1ae85..f4665ece6bb 100644 --- a/accounts/report/budget_variance_report/budget_variance_report.py +++ b/accounts/report/budget_variance_report/budget_variance_report.py @@ -16,10 +16,7 @@ def execute(filters=None): period_month_ranges = get_period_month_ranges(filters["period"], filters["fiscal_year"]) cam_map = get_costcenter_account_month_map(filters) - precision = webnotes.conn.get_value("Global Defaults", None, "float_precision") or 2 - data = [] - for cost_center, cost_center_items in cam_map.items(): for account, monthwise_data in cost_center_items.items(): row = [cost_center, account] diff --git a/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.py b/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.py index 6fdafe083d7..d2220f4cd76 100644 --- a/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.py +++ b/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.py @@ -58,7 +58,8 @@ def get_columns(filters): columns.append(label+":Float:120") - return columns + ["Total Target::120", "Total Achieved::120", "Total Variance::120"] + return columns + ["Total Target:Float:120", "Total Achieved:Float:120", + "Total Variance:Float:120"] #Get sales person & item group details def get_salesperson_details(filters): @@ -83,7 +84,7 @@ def get_target_distribution_details(filters): def get_achieved_details(filters): start_date, end_date = get_fiscal_year(fiscal_year = filters["fiscal_year"])[1:] - return webnotes.conn.sql("""select soi.item_code, soi.qty, soi.amount, so.transaction_date, + item_details = webnotes.conn.sql("""select soi.item_code, soi.qty, soi.amount, so.transaction_date, st.sales_person, MONTHNAME(so.transaction_date) as month_name from `tabSales Order Item` soi, `tabSales Order` so, `tabSales Team` st where soi.parent=so.name and so.docstatus=1 and @@ -91,6 +92,13 @@ def get_achieved_details(filters): so.transaction_date<=%s""" % ('%s', '%s'), (start_date, end_date), as_dict=1) + item_actual_details = {} + for d in item_details: + item_actual_details.setdefault(d.sales_person, {}).setdefault(\ + get_item_group(d.item_code), []).append(d) + + return item_actual_details + def get_salesperson_item_month_map(filters): import datetime salesperson_details = get_salesperson_details(filters) @@ -110,15 +118,15 @@ def get_salesperson_item_month_map(filters): month_percentage = sd.distribution_id and \ tdd.get(sd.distribution_id, {}).get(month, 0) or 100.0/12 - for ad in achieved_details: + for ad in achieved_details.get(sd.name, {}).get(sd.item_group, []): if (filters["target_on"] == "Quantity"): - tav_dict.target = flt(flt(sd.target_qty) * month_percentage/100, 2) + tav_dict.target = flt(sd.target_qty) * month_percentage / 100 if ad.month_name == month and get_item_group(ad.item_code) == sd.item_group \ and ad.sales_person == sd.name: tav_dict.achieved += ad.qty if (filters["target_on"] == "Amount"): - tav_dict.target = flt(flt(sd.target_amount) * month_percentage/100, 2) + tav_dict.target = flt(sd.target_amount) * month_percentage / 100 if ad.month_name == month and get_item_group(ad.item_code) == sd.item_group \ and ad.sales_person == sd.name: tav_dict.achieved += ad.amount diff --git a/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.py b/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.py index 829f7818e32..72657f0dbab 100644 --- a/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.py +++ b/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.py @@ -15,11 +15,8 @@ def execute(filters=None): columns = get_columns(filters) period_month_ranges = get_period_month_ranges(filters["period"], filters["fiscal_year"]) tim_map = get_territory_item_month_map(filters) - - precision = webnotes.conn.get_value("Global Defaults", None, "float_precision") or 2 - + data = [] - for territory, territory_items in tim_map.items(): for item_group, monthwise_data in territory_items.items(): row = [territory, item_group] @@ -29,7 +26,7 @@ def execute(filters=None): for month in relevant_months: month_data = monthwise_data.get(month, {}) for i, fieldname in enumerate(["target", "achieved", "variance"]): - value = flt(month_data.get(fieldname), precision) + value = flt(month_data.get(fieldname)) period_data[i] += value totals[i] += value period_data[2] = period_data[0] - period_data[1] @@ -58,7 +55,8 @@ def get_columns(filters): label = label % from_date.strftime("%b") columns.append(label+":Float:120") - return columns + ["Total Target::120", "Total Achieved::120", "Total Variance::120"] + return columns + ["Total Target:Float:120", "Total Achieved:Float:120", + "Total Variance:Float:120"] #Get territory & item group details def get_territory_details(filters): @@ -83,14 +81,22 @@ def get_target_distribution_details(filters): def get_achieved_details(filters): start_date, end_date = get_fiscal_year(fiscal_year = filters["fiscal_year"])[1:] - return webnotes.conn.sql("""select soi.item_code, soi.qty, soi.amount, so.transaction_date, + item_details = webnotes.conn.sql("""select soi.item_code, soi.qty, soi.amount, so.transaction_date, so.territory, MONTHNAME(so.transaction_date) as month_name from `tabSales Order Item` soi, `tabSales Order` so where soi.parent=so.name and so.docstatus=1 and so.transaction_date>=%s and so.transaction_date<=%s""" % ('%s', '%s'), (start_date, end_date), as_dict=1) + item_actual_details = {} + for d in item_details: + item_actual_details.setdefault(d.territory, {}).setdefault(\ + get_item_group(d.item_code), []).append(d) + + return item_actual_details + def get_territory_item_month_map(filters): + import datetime territory_details = get_territory_details(filters) tdd = get_target_distribution_details(filters) achieved_details = get_achieved_details(filters) @@ -110,15 +116,15 @@ def get_territory_item_month_map(filters): month_percentage = td.distribution_id and \ tdd.get(td.distribution_id, {}).get(month, 0) or 100.0/12 - for ad in achieved_details: + for ad in achieved_details.get(td.name, {}).get(td.item_group, []): if (filters["target_on"] == "Quantity"): - tav_dict.target = flt(flt(td.target_qty) * month_percentage /100) + tav_dict.target = flt(td.target_qty) * month_percentage / 100 if ad.month_name == month and get_item_group(ad.item_code) == td.item_group \ and ad.territory == td.name: tav_dict.achieved += ad.qty if (filters["target_on"] == "Amount"): - tav_dict.target = flt(flt(td.target_amount) * month_percentage / 100) + tav_dict.target = flt(td.target_amount) * month_percentage / 100 if ad.month_name == month and get_item_group(ad.item_code) == td.item_group \ and ad.territory == td.name: tav_dict.achieved += ad.amount From d2d210dc686541a7b3a51c2eeb83e37b71d8fb27 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Wed, 13 Nov 2013 17:27:35 +0530 Subject: [PATCH 07/13] [fix] [minor] variance reports fixes --- .../report/budget_variance_report/budget_variance_report.py | 3 +-- .../sales_person_target_variance_item_group_wise.py | 6 ++---- .../territory_target_variance_item_group_wise.py | 6 ++---- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/accounts/report/budget_variance_report/budget_variance_report.py b/accounts/report/budget_variance_report/budget_variance_report.py index f4665ece6bb..0e241dea1d6 100644 --- a/accounts/report/budget_variance_report/budget_variance_report.py +++ b/accounts/report/budget_variance_report/budget_variance_report.py @@ -119,8 +119,7 @@ def get_costcenter_account_month_map(filters): tav_dict.target = flt(ccd.budget_allocated) * month_percentage /100 for ad in actual_details.get(ccd.name, {}).get(ccd.account, []): - if ad.month_name == month and ad.account == ccd.account \ - and ad.cost_center == ccd.name: + if ad.month_name == month: tav_dict.actual += ad.debit - ad.credit return cam_map \ No newline at end of file diff --git a/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.py b/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.py index d2220f4cd76..ebb2d9f96fe 100644 --- a/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.py +++ b/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.py @@ -121,14 +121,12 @@ def get_salesperson_item_month_map(filters): for ad in achieved_details.get(sd.name, {}).get(sd.item_group, []): if (filters["target_on"] == "Quantity"): tav_dict.target = flt(sd.target_qty) * month_percentage / 100 - if ad.month_name == month and get_item_group(ad.item_code) == sd.item_group \ - and ad.sales_person == sd.name: + if ad.month_name == month: tav_dict.achieved += ad.qty if (filters["target_on"] == "Amount"): tav_dict.target = flt(sd.target_amount) * month_percentage / 100 - if ad.month_name == month and get_item_group(ad.item_code) == sd.item_group \ - and ad.sales_person == sd.name: + if ad.month_name == month: tav_dict.achieved += ad.amount return sim_map diff --git a/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.py b/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.py index 72657f0dbab..2aafe3c6bdc 100644 --- a/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.py +++ b/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.py @@ -119,14 +119,12 @@ def get_territory_item_month_map(filters): for ad in achieved_details.get(td.name, {}).get(td.item_group, []): if (filters["target_on"] == "Quantity"): tav_dict.target = flt(td.target_qty) * month_percentage / 100 - if ad.month_name == month and get_item_group(ad.item_code) == td.item_group \ - and ad.territory == td.name: + if ad.month_name == month: tav_dict.achieved += ad.qty if (filters["target_on"] == "Amount"): tav_dict.target = flt(td.target_amount) * month_percentage / 100 - if ad.month_name == month and get_item_group(ad.item_code) == td.item_group \ - and ad.territory == td.name: + if ad.month_name == month: tav_dict.achieved += ad.amount return tim_map From 65e974096f4969303081c76d0067fabae1f84269 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Thu, 14 Nov 2013 14:50:43 +0530 Subject: [PATCH 08/13] [fix] showing customer dashboard headline to users with account related roles --- buying/doctype/supplier/supplier.js | 21 ++++++++++----------- selling/doctype/customer/customer.js | 17 ++++++++++------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/buying/doctype/supplier/supplier.js b/buying/doctype/supplier/supplier.js index 75542c82579..58045f5aa94 100644 --- a/buying/doctype/supplier/supplier.js +++ b/buying/doctype/supplier/supplier.js @@ -3,10 +3,6 @@ wn.require('app/setup/doctype/contact_control/contact_control.js'); -cur_frm.cscript.onload = function(doc,dt,dn){ - -} - cur_frm.cscript.refresh = function(doc,dt,dn) { cur_frm.cscript.make_dashboard(doc); if(sys_defaults.supp_master_name == 'Supplier Name') @@ -35,7 +31,8 @@ cur_frm.cscript.make_dashboard = function(doc) { cur_frm.dashboard.reset(); if(doc.__islocal) return; - cur_frm.dashboard.set_headline('Loading...') + if (in_list(user_roles, "Accounts User") || in_list(user_roles, "Accounts Manager")) + cur_frm.dashboard.set_headline('Loading...') cur_frm.dashboard.add_doctype_badge("Supplier Quotation", "supplier"); cur_frm.dashboard.add_doctype_badge("Purchase Order", "supplier"); @@ -49,12 +46,14 @@ cur_frm.cscript.make_dashboard = function(doc) { supplier: cur_frm.doc.name }, callback: function(r) { - cur_frm.dashboard.set_headline( - wn._("Total Billing This Year: ") + "" - + format_currency(r.message.total_billing, cur_frm.doc.default_currency) - + ' / ' + wn._("Unpaid") + ": " - + format_currency(r.message.total_unpaid, cur_frm.doc.default_currency) - + ''); + if (in_list(user_roles, "Accounts User") || in_list(user_roles, "Accounts Manager")) { + cur_frm.dashboard.set_headline( + wn._("Total Billing This Year: ") + "" + + format_currency(r.message.total_billing, cur_frm.doc.default_currency) + + ' / ' + wn._("Unpaid") + ": " + + format_currency(r.message.total_unpaid, cur_frm.doc.default_currency) + + ''); + } cur_frm.dashboard.set_badge_count(r.message); } }) diff --git a/selling/doctype/customer/customer.js b/selling/doctype/customer/customer.js index d2c632530b3..014efe6dbd5 100644 --- a/selling/doctype/customer/customer.js +++ b/selling/doctype/customer/customer.js @@ -45,7 +45,8 @@ cur_frm.cscript.setup_dashboard = function(doc) { cur_frm.dashboard.reset(doc); if(doc.__islocal) return; - cur_frm.dashboard.set_headline(''+ wn._('Loading...')+ '') + if (in_list(user_roles, "Accounts User") || in_list(user_roles, "Accounts Manager")) + cur_frm.dashboard.set_headline(''+ wn._('Loading...')+ '') cur_frm.dashboard.add_doctype_badge("Opportunity", "customer"); cur_frm.dashboard.add_doctype_badge("Quotation", "customer"); @@ -60,12 +61,14 @@ cur_frm.cscript.setup_dashboard = function(doc) { customer: cur_frm.doc.name }, callback: function(r) { - cur_frm.dashboard.set_headline( - wn._("Total Billing This Year: ") + "" - + format_currency(r.message.total_billing, cur_frm.doc.default_currency) - + ' / ' + wn._("Unpaid") + ": " - + format_currency(r.message.total_unpaid, cur_frm.doc.default_currency) - + ''); + if (in_list(user_roles, "Accounts User") || in_list(user_roles, "Accounts Manager")) { + cur_frm.dashboard.set_headline( + wn._("Total Billing This Year: ") + "" + + format_currency(r.message.total_billing, cur_frm.doc.default_currency) + + ' / ' + wn._("Unpaid") + ": " + + format_currency(r.message.total_unpaid, cur_frm.doc.default_currency) + + ''); + } cur_frm.dashboard.set_badge_count(r.message); } }) From 155232e04e30c400d7fec0dd100c62627b5fde34 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 14 Nov 2013 18:37:33 +0530 Subject: [PATCH 09/13] [fix] credit limit validation --- accounts/doctype/account/account.py | 24 ++++++------------- accounts/doctype/gl_entry/gl_entry.py | 16 ------------- .../journal_voucher/journal_voucher.py | 8 +++++++ .../budget_variance_report.py | 2 -- selling/doctype/sales_common/sales_common.py | 9 ++----- 5 files changed, 17 insertions(+), 42 deletions(-) diff --git a/accounts/doctype/account/account.py b/accounts/doctype/account/account.py index fba51a9f72e..37e165a97b7 100644 --- a/accounts/doctype/account/account.py +++ b/accounts/doctype/account/account.py @@ -32,16 +32,6 @@ class DocType: self.validate_root_details() self.validate_mandatory() self.validate_warehouse_account() - - if not self.doc.parent_account: - self.doc.parent_account = '' - - def validate(self): - self.validate_master_name() - self.validate_parent() - self.validate_duplicate_account() - self.validate_root_details() - self.validate_mandatory() self.validate_frozen_accounts_modifier() if not self.doc.parent_account: @@ -177,24 +167,24 @@ class DocType: in webnotes.user.get_roles(): return 1 - def check_credit_limit(self, account, company, tot_outstanding): + def check_credit_limit(self, total_outstanding): # Get credit limit credit_limit_from = 'Customer' cr_limit = sql("""select t1.credit_limit from tabCustomer t1, `tabAccount` t2 - where t2.name=%s and t1.name = t2.master_name""", account) + where t2.name=%s and t1.name = t2.master_name""", self.doc.name) credit_limit = cr_limit and flt(cr_limit[0][0]) or 0 if not credit_limit: - credit_limit = webnotes.conn.get_value('Company', company, 'credit_limit') - credit_limit_from = 'global settings in the Company' + credit_limit = webnotes.conn.get_value('Company', self.doc.company, 'credit_limit') + credit_limit_from = 'Company' # If outstanding greater than credit limit and not authorized person raise exception - if credit_limit > 0 and flt(tot_outstanding) > credit_limit \ + if credit_limit > 0 and flt(total_outstanding) > credit_limit \ and not self.get_authorized_user(): msgprint("""Total Outstanding amount (%s) for %s can not be \ greater than credit limit (%s). To change your credit limit settings, \ - please update the %s""" % (fmt_money(tot_outstanding), - account, fmt_money(credit_limit), credit_limit_from), raise_exception=1) + please update in the %s master""" % (fmt_money(total_outstanding), + self.doc.name, fmt_money(credit_limit), credit_limit_from), raise_exception=1) def validate_trash(self): """checks gl entries and if child exists""" diff --git a/accounts/doctype/gl_entry/gl_entry.py b/accounts/doctype/gl_entry/gl_entry.py index dfac6b64693..e0babdf7230 100644 --- a/accounts/doctype/gl_entry/gl_entry.py +++ b/accounts/doctype/gl_entry/gl_entry.py @@ -16,7 +16,6 @@ class DocType: self.check_mandatory() self.pl_must_have_cost_center() self.validate_posting_date() - self.check_credit_limit() self.check_pl_account() self.validate_cost_center() @@ -55,21 +54,6 @@ class DocType: from accounts.utils import validate_fiscal_year validate_fiscal_year(self.doc.posting_date, self.doc.fiscal_year, "Posting Date") - def check_credit_limit(self): - master_type, master_name = webnotes.conn.get_value("Account", - self.doc.account, ["master_type", "master_name"]) - - tot_outstanding = 0 #needed when there is no GL Entry in the system for that acc head - if (self.doc.voucher_type=='Journal Voucher' or self.doc.voucher_type=='Sales Invoice') \ - and (master_type =='Customer' and master_name): - dbcr = webnotes.conn.sql("""select sum(debit), sum(credit) from `tabGL Entry` - where account = %s""", self.doc.account) - if dbcr: - tot_outstanding = flt(dbcr[0][0]) - flt(dbcr[0][1]) + \ - flt(self.doc.debit) - flt(self.doc.credit) - get_obj('Account',self.doc.account).check_credit_limit(self.doc.account, - self.doc.company, tot_outstanding) - def check_pl_account(self): if self.doc.is_opening=='Yes' and \ webnotes.conn.get_value("Account", self.doc.account, "is_pl_account") == "Yes": diff --git a/accounts/doctype/journal_voucher/journal_voucher.py b/accounts/doctype/journal_voucher/journal_voucher.py index ed4a0d79c7c..8fb47f74397 100644 --- a/accounts/doctype/journal_voucher/journal_voucher.py +++ b/accounts/doctype/journal_voucher/journal_voucher.py @@ -44,6 +44,7 @@ class DocType(AccountsController): self.check_credit_days() self.check_account_against_entries() self.make_gl_entries() + self.check_credit_limit() def on_cancel(self): from accounts.utils import remove_against_link_from_jv @@ -259,6 +260,13 @@ class DocType(AccountsController): ) if gl_map: make_gl_entries(gl_map, cancel=cancel, adv_adj=adv_adj) + + def check_credit_limit(self): + for d in self.doclist.get({"parentfield": "entries"}): + master_type, master_name = webnotes.conn.get_value("Account", d.account, + ["master_type", "master_name"]) + if master_type == "Customer" and master_name: + super(DocType, self).check_credit_limit(d.account) def get_outstanding(self, args): args = eval(args) diff --git a/accounts/report/budget_variance_report/budget_variance_report.py b/accounts/report/budget_variance_report/budget_variance_report.py index c1c4bc1ae85..50593bc718a 100644 --- a/accounts/report/budget_variance_report/budget_variance_report.py +++ b/accounts/report/budget_variance_report/budget_variance_report.py @@ -16,8 +16,6 @@ def execute(filters=None): period_month_ranges = get_period_month_ranges(filters["period"], filters["fiscal_year"]) cam_map = get_costcenter_account_month_map(filters) - precision = webnotes.conn.get_value("Global Defaults", None, "float_precision") or 2 - data = [] for cost_center, cost_center_items in cam_map.items(): diff --git a/selling/doctype/sales_common/sales_common.py b/selling/doctype/sales_common/sales_common.py index ad626da4600..3be27b225fb 100644 --- a/selling/doctype/sales_common/sales_common.py +++ b/selling/doctype/sales_common/sales_common.py @@ -9,9 +9,6 @@ from webnotes.model.doc import addchild from webnotes.model.bean import getlist from webnotes.model.code import get_obj from webnotes import msgprint, _ -from setup.utils import get_company_currency - -get_value = webnotes.conn.get_value from utilities.transaction_base import TransactionBase @@ -295,14 +292,12 @@ class DocType(TransactionBase): def check_credit(self,obj,grand_total): acc_head = webnotes.conn.sql("select name from `tabAccount` where company = '%s' and master_name = '%s'"%(obj.doc.company, obj.doc.customer)) if acc_head: - tot_outstanding = 0 dbcr = webnotes.conn.sql("""select sum(debit), sum(credit) from `tabGL Entry` where account = %s""", acc_head[0][0]) - if dbcr: - tot_outstanding = flt(dbcr[0][0])-flt(dbcr[0][1]) + tot_outstanding = flt(dbcr[0][0])-flt(dbcr[0][1]) if dbcr else 0 exact_outstanding = flt(tot_outstanding) + flt(grand_total) - get_obj('Account',acc_head[0][0]).check_credit_limit(acc_head[0][0], obj.doc.company, exact_outstanding) + get_obj('Account',acc_head[0][0]).check_credit_limit(exact_outstanding) def get_prevdoc_date(self, obj): for d in getlist(obj.doclist, obj.fname): From e83069cb3235f9cdb966abb144e5fa9790356a90 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 14 Nov 2013 18:40:08 +0530 Subject: [PATCH 10/13] [fix] update future gl entries for stock --- .../doctype/sales_invoice/sales_invoice.py | 37 ++++++----- .../sales_invoice/test_sales_invoice.py | 64 +++++++++++++++++-- accounts/general_ledger.py | 5 +- controllers/accounts_controller.py | 10 +++ controllers/stock_controller.py | 15 ++--- .../purchase_receipt/purchase_receipt.py | 5 +- stock/doctype/stock_entry/stock_entry.py | 4 +- .../stock_reconciliation.py | 4 +- stock/doctype/warehouse/test_warehouse.py | 7 +- 9 files changed, 112 insertions(+), 39 deletions(-) diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py index 6c02bbea661..eb46d1adc41 100644 --- a/accounts/doctype/sales_invoice/sales_invoice.py +++ b/accounts/doctype/sales_invoice/sales_invoice.py @@ -95,6 +95,7 @@ class DocType(SellingController): # this sequence because outstanding may get -ve self.make_gl_entries() + self.check_credit_limit(self.doc.debit_to) if not cint(self.doc.is_pos) == 1: self.update_against_document_in_jv() @@ -533,32 +534,39 @@ class DocType(SellingController): self.make_sl_entries(sl_entries) - def make_gl_entries(self): - from accounts.general_ledger import make_gl_entries, merge_similar_entries + def make_gl_entries(self, update_gl_entries_after=True): + gl_entries = self.get_gl_entries() + + if gl_entries: + from accounts.general_ledger import make_gl_entries + + update_outstanding = cint(self.doc.is_pos) and self.doc.write_off_account \ + and 'No' or 'Yes' + make_gl_entries(gl_entries, cancel=(self.doc.docstatus == 2), + update_outstanding=update_outstanding, merge_entries=False) + + if update_gl_entries_after and cint(self.doc.update_stock) \ + and cint(webnotes.defaults.get_global_default("auto_accounting_for_stock")): + self.update_gl_entries_after() + + def get_gl_entries(self, warehouse_account=None): + from accounts.general_ledger import merge_similar_entries gl_entries = [] self.make_customer_gl_entry(gl_entries) - + self.make_tax_gl_entries(gl_entries) self.make_item_gl_entries(gl_entries) # merge gl entries before adding pos entries gl_entries = merge_similar_entries(gl_entries) - + self.make_pos_gl_entries(gl_entries) - update_outstanding = cint(self.doc.is_pos) and self.doc.write_off_account and 'No' or 'Yes' + return gl_entries - if gl_entries: - make_gl_entries(gl_entries, cancel=(self.doc.docstatus == 2), - update_outstanding=update_outstanding, merge_entries=False) - - if cint(webnotes.defaults.get_global_default("auto_accounting_for_stock")) \ - and cint(self.doc.update_stock): - self.update_gl_entries_after() - def make_customer_gl_entry(self, gl_entries): if self.doc.grand_total: gl_entries.append( @@ -602,7 +610,7 @@ class DocType(SellingController): # expense account gl entries if cint(webnotes.defaults.get_global_default("auto_accounting_for_stock")) \ and cint(self.doc.update_stock): - gl_entries += self.get_gl_entries_for_stock() + gl_entries += super(DocType, self).get_gl_entries() def make_pos_gl_entries(self, gl_entries): if cint(self.doc.is_pos) and self.doc.cash_bank_account and self.doc.paid_amount: @@ -866,7 +874,6 @@ def send_notification(new_rv): def notify_errors(inv, owner): import webnotes - import website exception_msg = """ Dear User, diff --git a/accounts/doctype/sales_invoice/test_sales_invoice.py b/accounts/doctype/sales_invoice/test_sales_invoice.py index fbb344ec943..435ba12d42a 100644 --- a/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -3,7 +3,7 @@ import webnotes import unittest, json -from webnotes.utils import flt, cint +from webnotes.utils import flt from webnotes.model.bean import DocstatusTransitionError, TimestampMismatchError from accounts.utils import get_stock_and_account_difference from stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory @@ -364,6 +364,7 @@ class TestSalesInvoice(unittest.TestCase): from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s order by account asc, debit asc""", si.doc.name, as_dict=1) self.assertTrue(gl_entries) + # print gl_entries stock_in_hand = webnotes.conn.get_value("Account", {"master_name": "_Test Warehouse - _TC"}) @@ -382,9 +383,6 @@ class TestSalesInvoice(unittest.TestCase): self.assertEquals(expected_gl_entries[i][1], gle.debit) self.assertEquals(expected_gl_entries[i][2], gle.credit) - - - # cancel si.cancel() gle = webnotes.conn.sql("""select * from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s""", si.doc.name) @@ -395,6 +393,62 @@ class TestSalesInvoice(unittest.TestCase): set_perpetual_inventory(0) + def test_si_gl_entry_with_aii_and_update_stock_with_warehouse_but_no_account(self): + self.clear_stock_account_balance() + set_perpetual_inventory() + webnotes.delete_doc("Account", "_Test Warehouse No Account - _TC") + + # insert purchase receipt + from stock.doctype.purchase_receipt.test_purchase_receipt import test_records \ + as pr_test_records + pr = webnotes.bean(copy=pr_test_records[0]) + pr.doc.naming_series = "_T-Purchase Receipt-" + pr.doclist[1].warehouse = "_Test Warehouse No Account - _TC" + pr.run_method("calculate_taxes_and_totals") + pr.insert() + pr.submit() + + si_doclist = webnotes.copy_doclist(test_records[1]) + si_doclist[0]["update_stock"] = 1 + si_doclist[0]["posting_time"] = "12:05" + si_doclist[1]["warehouse"] = "_Test Warehouse No Account - _TC" + + si = webnotes.bean(copy=si_doclist) + si.insert() + si.submit() + + # check stock ledger entries + sle = webnotes.conn.sql("""select * from `tabStock Ledger Entry` + where voucher_type = 'Sales Invoice' and voucher_no = %s""", + si.doc.name, as_dict=1)[0] + self.assertTrue(sle) + self.assertEquals([sle.item_code, sle.warehouse, sle.actual_qty], + ["_Test Item", "_Test Warehouse No Account - _TC", -1.0]) + + # check gl entries + gl_entries = webnotes.conn.sql("""select account, debit, credit + from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s + order by account asc, debit asc""", si.doc.name, as_dict=1) + self.assertTrue(gl_entries) + + expected_gl_entries = sorted([ + [si.doc.debit_to, 630.0, 0.0], + [si_doclist[1]["income_account"], 0.0, 500.0], + [si_doclist[2]["account_head"], 0.0, 80.0], + [si_doclist[3]["account_head"], 0.0, 50.0], + ]) + for i, gle in enumerate(gl_entries): + self.assertEquals(expected_gl_entries[i][0], gle.account) + self.assertEquals(expected_gl_entries[i][1], gle.debit) + self.assertEquals(expected_gl_entries[i][2], gle.credit) + + si.cancel() + gle = webnotes.conn.sql("""select * from `tabGL Entry` + where voucher_type='Sales Invoice' and voucher_no=%s""", si.doc.name) + + self.assertFalse(gle) + set_perpetual_inventory(0) + def test_sales_invoice_gl_entry_with_aii_no_item_code(self): self.clear_stock_account_balance() set_perpetual_inventory() @@ -599,7 +653,7 @@ class TestSalesInvoice(unittest.TestCase): self._test_recurring_invoice(si7, True) def _test_recurring_invoice(self, base_si, first_and_last_day): - from webnotes.utils import add_months, get_last_day, getdate + from webnotes.utils import add_months, get_last_day from accounts.doctype.sales_invoice.sales_invoice import manage_recurring_invoices no_of_months = ({"Monthly": 1, "Quarterly": 3, "Yearly": 12})[base_si.doc.recurring_type] diff --git a/accounts/general_ledger.py b/accounts/general_ledger.py index b0c585a3a38..9afcf94b2c7 100644 --- a/accounts/general_ledger.py +++ b/accounts/general_ledger.py @@ -3,9 +3,8 @@ from __future__ import unicode_literals import webnotes -from webnotes.utils import flt, cstr, now -from webnotes.model.doc import Document -from webnotes import msgprint, _ +from webnotes.utils import flt, cstr +from webnotes import _ from accounts.utils import validate_expense_against_budget diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py index 2b6a21f5ede..0c5ce2a9a34 100644 --- a/controllers/accounts_controller.py +++ b/controllers/accounts_controller.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import webnotes from webnotes import _, msgprint from webnotes.utils import flt, cint, today, cstr +from webnotes.model.code import get_obj from setup.utils import get_company_currency from accounts.utils import get_fiscal_year, validate_fiscal_year from utilities.transaction_base import TransactionBase, validate_conversion_rate @@ -422,3 +423,12 @@ class AccountsController(TransactionBase): self._abbr = webnotes.conn.get_value("Company", self.doc.company, "abbr") return self._abbr + + def check_credit_limit(self, account): + total_outstanding = webnotes.conn.sql(""" + select sum(ifnull(debit, 0)) - sum(ifnull(credit, 0)) + from `tabGL Entry` where account = %s""", account) + + total_outstanding = flt(total_outstanding[0][0]) if total_outstanding else 0 + if total_outstanding: + get_obj('Account', account).check_credit_limit(total_outstanding) \ No newline at end of file diff --git a/controllers/stock_controller.py b/controllers/stock_controller.py index 359dc9e86ff..e07e752c7e4 100644 --- a/controllers/stock_controller.py +++ b/controllers/stock_controller.py @@ -11,7 +11,7 @@ from controllers.accounts_controller import AccountsController from accounts.general_ledger import make_gl_entries, delete_gl_entries class StockController(AccountsController): - def make_gl_entries(self): + def make_gl_entries(self, update_gl_entries_after=True): if self.doc.docstatus == 2: delete_gl_entries(voucher_type=self.doc.doctype, voucher_no=self.doc.name) @@ -19,12 +19,13 @@ class StockController(AccountsController): warehouse_account = self.get_warehouse_account() if self.doc.docstatus==1: - gl_entries = self.get_gl_entries_for_stock(warehouse_account) + gl_entries = self.get_gl_entries(warehouse_account) make_gl_entries(gl_entries) - self.update_gl_entries_after(warehouse_account) + if update_gl_entries_after: + self.update_gl_entries_after(warehouse_account) - def get_gl_entries_for_stock(self, warehouse_account=None, default_expense_account=None, + def get_gl_entries(self, warehouse_account=None, default_expense_account=None, default_cost_center=None): from accounts.general_ledger import process_gl_map if not warehouse_account: @@ -99,12 +100,10 @@ class StockController(AccountsController): gle = self.get_voucherwise_gl_entries(future_stock_vouchers) if not warehouse_account: warehouse_account = self.get_warehouse_account() - for voucher_type, voucher_no in future_stock_vouchers: existing_gle = gle.get((voucher_type, voucher_no), []) voucher_obj = webnotes.get_obj(voucher_type, voucher_no) - expected_gle = voucher_obj.get_gl_entries_for_stock(warehouse_account) - + expected_gle = voucher_obj.get_gl_entries(warehouse_account) if expected_gle: matched = True if existing_gle: @@ -121,7 +120,7 @@ class StockController(AccountsController): if not matched: self.delete_gl_entries(voucher_type, voucher_no) - make_gl_entries(expected_gle) + voucher_obj.make_gl_entries(update_gl_entries_after=False) else: self.delete_gl_entries(voucher_type, voucher_no) diff --git a/stock/doctype/purchase_receipt/purchase_receipt.py b/stock/doctype/purchase_receipt/purchase_receipt.py index 6d4320fe187..1d91c4b7270 100644 --- a/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/stock/doctype/purchase_receipt/purchase_receipt.py @@ -294,11 +294,10 @@ class DocType(BuyingController): def get_rate(self,arg): return get_obj('Purchase Common').get_rate(arg,self) - def get_gl_entries_for_stock(self, warehouse_account=None): + def get_gl_entries(self, warehouse_account=None): against_stock_account = self.get_company_default("stock_received_but_not_billed") - gl_entries = super(DocType, self).get_gl_entries_for_stock(warehouse_account, - against_stock_account) + gl_entries = super(DocType, self).get_gl_entries(warehouse_account, against_stock_account) return gl_entries diff --git a/stock/doctype/stock_entry/stock_entry.py b/stock/doctype/stock_entry/stock_entry.py index 12b0f514a31..c91239d22ac 100644 --- a/stock/doctype/stock_entry/stock_entry.py +++ b/stock/doctype/stock_entry/stock_entry.py @@ -478,7 +478,7 @@ class DocType(StockController): self.doc.from_warehouse = "" item = webnotes.conn.sql("""select name, item_name, description, - uom, purchase_account, cost_center from `tabItem` + stock_uom, purchase_account, cost_center from `tabItem` where name=(select item from tabBOM where name=%s)""", self.doc.bom_no, as_dict=1) self.add_to_stock_entry_detail({ @@ -486,7 +486,7 @@ class DocType(StockController): "qty": self.doc.fg_completed_qty, "item_name": item[0].item_name, "description": item[0]["description"], - "stock_uom": item[0]["uom"], + "stock_uom": item[0]["stock_uom"], "from_warehouse": "", "expense_account": item[0].purchase_account, "cost_center": item[0].cost_center, diff --git a/stock/doctype/stock_reconciliation/stock_reconciliation.py b/stock/doctype/stock_reconciliation/stock_reconciliation.py index 9feb57e716b..22d011765ff 100644 --- a/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -275,11 +275,11 @@ class DocType(StockController): "posting_time": self.doc.posting_time }) - def get_gl_entries_for_stock(self, warehouse_account=None): + def get_gl_entries(self, warehouse_account=None): if not self.doc.cost_center: msgprint(_("Please enter Cost Center"), raise_exception=1) - return super(DocType, self).get_gl_entries_for_stock(warehouse_account, + return super(DocType, self).get_gl_entries(warehouse_account, self.doc.expense_account, self.doc.cost_center) diff --git a/stock/doctype/warehouse/test_warehouse.py b/stock/doctype/warehouse/test_warehouse.py index 76b18180e21..43b260011c6 100644 --- a/stock/doctype/warehouse/test_warehouse.py +++ b/stock/doctype/warehouse/test_warehouse.py @@ -23,5 +23,10 @@ test_records = [ "doctype": "Warehouse User", "parentfield": "warehouse_users", "user": "test2@example.com" - }] + }], + [{ + "doctype": "Warehouse", + "warehouse_name": "_Test Warehouse No Account", + "company": "_Test Company", + }], ] From 9e5da835ecc666186a24041b7150022fa714b6b3 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 14 Nov 2013 18:41:09 +0530 Subject: [PATCH 11/13] [patch] make gl entries for submitted sales invoice where no gl entries exists --- patches/november_2013/__init__.py | 0 patches/november_2013/p01_make_gl_entries_for_si.py | 12 ++++++++++++ patches/patch_list.py | 1 + 3 files changed, 13 insertions(+) create mode 100644 patches/november_2013/__init__.py create mode 100644 patches/november_2013/p01_make_gl_entries_for_si.py diff --git a/patches/november_2013/__init__.py b/patches/november_2013/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/patches/november_2013/p01_make_gl_entries_for_si.py b/patches/november_2013/p01_make_gl_entries_for_si.py new file mode 100644 index 00000000000..cfe107a4d77 --- /dev/null +++ b/patches/november_2013/p01_make_gl_entries_for_si.py @@ -0,0 +1,12 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. +# License: GNU General Public License v3. See license.txt + +import webnotes + +def execute(): + si_no_gle = webnotes.conn.sql("""select si.name from `tabSales Invoice` si + where docstatus=1 and not exists(select name from `tabGL Entry` + where voucher_type='Sales Invoice' and voucher_no=si.name)""") + + for si in si_no_gle: + webnotes.get_obj("Sales Invoice", si[0]).make_gl_entries() \ No newline at end of file diff --git a/patches/patch_list.py b/patches/patch_list.py index 0cc393e02ec..82eb6e45602 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -230,4 +230,5 @@ patch_list = [ "patches.october_2013.p07_rename_for_territory", "patches.june_2013.p07_taxes_price_list_for_territory", "patches.october_2013.p08_cleanup_after_item_price_module_change", + "patches.november_2013.p01_make_gl_entries_for_si", ] \ No newline at end of file From c10621a5be587f531de9de61c8a185e4f2ade59a Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 15 Nov 2013 10:32:47 +0530 Subject: [PATCH 12/13] [patch] make gl entries for submitted sales invoice where no gl entries exists --- patches/november_2013/p01_make_gl_entries_for_si.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/patches/november_2013/p01_make_gl_entries_for_si.py b/patches/november_2013/p01_make_gl_entries_for_si.py index cfe107a4d77..84e0712b60f 100644 --- a/patches/november_2013/p01_make_gl_entries_for_si.py +++ b/patches/november_2013/p01_make_gl_entries_for_si.py @@ -6,7 +6,8 @@ import webnotes def execute(): si_no_gle = webnotes.conn.sql("""select si.name from `tabSales Invoice` si where docstatus=1 and not exists(select name from `tabGL Entry` - where voucher_type='Sales Invoice' and voucher_no=si.name)""") + where voucher_type='Sales Invoice' and voucher_no=si.name) + and modified >= '2013-08-01'""") for si in si_no_gle: webnotes.get_obj("Sales Invoice", si[0]).make_gl_entries() \ No newline at end of file From e505fbea54c156e724f73a0668b21667d9e711f3 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 15 Nov 2013 13:38:23 +0530 Subject: [PATCH 13/13] [fix] [minor] stock balance report for serialized item --- public/js/stock_grid_report.js | 17 +++++++---------- public/js/transaction.js | 9 +++++---- startup/report_data_map.py | 5 +++++ stock/page/stock_balance/stock_balance.js | 2 +- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/public/js/stock_grid_report.js b/public/js/stock_grid_report.js index 495ea43e405..e87228fde76 100644 --- a/public/js/stock_grid_report.js +++ b/public/js/stock_grid_report.js @@ -25,7 +25,11 @@ erpnext.StockGridReport = wn.views.TreeGridReport.extend({ add_qty = 0; } } - var value_diff = (rate * add_qty); + if(sl.serial_no) { + var value_diff = this.get_serialized_value_diff(sl); + } else { + var value_diff = (rate * add_qty); + } if(add_qty) wh.fifo_stack.push([add_qty, sl.incoming_rate, sl.posting_date]); @@ -108,15 +112,8 @@ erpnext.StockGridReport = wn.views.TreeGridReport.extend({ get_serialized_buying_rates: function() { var serialized_buying_rates = {}; - $.each(wn.report_dump.data["Stock Ledger Entry"], function(i, sle) { - 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().toLowerCase()]) { - serialized_buying_rates[sr.trim().toLowerCase()] = flt(sle.incoming_rate); - } - }); - } + $.each(wn.report_dump.data["Serial No"], function(i, sn) { + serialized_buying_rates[sn.name.toLowerCase()] = flt(sn.incoming_rate); }); return serialized_buying_rates; diff --git a/public/js/transaction.js b/public/js/transaction.js index 664bbe2f9ef..29fe32b9612 100644 --- a/public/js/transaction.js +++ b/public/js/transaction.js @@ -502,13 +502,14 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({ var company_currency = this.get_company_currency(); if(!this.frm.doc.conversion_rate) { - wn.throw(wn._('%(conversion_rate_label)s is mandatory. Maybe Currency Exchange \ - record is not created for %(from_currency)s to %(to_currency)s'), + wn.throw(repl('%(conversion_rate_label)s' + + wn._(' is mandatory. Maybe Currency Exchange record is not created for ') + + '%(from_currency)s' + wn._(" to ") + '%(to_currency)s', { "conversion_rate_label": conversion_rate_label, - "from_currency": self.doc.currency, + "from_currency": this.frm.doc.currency, "to_currency": company_currency - }); + })); } }, diff --git a/startup/report_data_map.py b/startup/report_data_map.py index 54453f68bbd..12ceae421a2 100644 --- a/startup/report_data_map.py +++ b/startup/report_data_map.py @@ -88,6 +88,11 @@ data_map = { }, "force_index": "posting_sort_index" }, + "Serial No": { + "columns": ["name", "purchase_rate as incoming_rate"], + "conditions": ["docstatus < 2"], + "order_by": "name" + }, "Stock Entry": { "columns": ["name", "purpose"], "conditions": ["docstatus=1"], diff --git a/stock/page/stock_balance/stock_balance.js b/stock/page/stock_balance/stock_balance.js index b45a610be88..7db3b6c5ba7 100644 --- a/stock/page/stock_balance/stock_balance.js +++ b/stock/page/stock_balance/stock_balance.js @@ -22,7 +22,7 @@ erpnext.StockBalance = erpnext.StockAnalytics.extend({ this._super(wrapper, { title: "Stock Balance", doctypes: ["Item", "Item Group", "Warehouse", "Stock Ledger Entry", "Brand", - "Stock Entry", "Project"], + "Stock Entry", "Project", "Serial No"], }); }, setup_columns: function() {