From 1ded5c618ee73166dfcba4671cd9b041baa1cd4f Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Fri, 21 Jun 2013 12:47:51 +0530 Subject: [PATCH 01/13] [Report]Cleanup of territory target variance, sales person target variance & budget variance reports --- .../budget_variance_report.py | 59 +++------------ selling/page/selling_home/selling_home.js | 4 +- .../__init__.py | 0 ...person_target_variance_item_group_wise.js} | 2 +- ...person_target_variance_item_group_wise.py} | 74 ++++--------------- ...erson_target_variance_item_group_wise.txt} | 8 +- .../__init__.py | 0 ...ritory_target_variance_item_group_wise.js} | 2 +- ...ritory_target_variance_item_group_wise.py} | 74 ++++--------------- ...itory_target_variance_item_group_wise.txt} | 8 +- stock/report/item_prices/item_prices.py | 62 +++++++++++++--- 11 files changed, 106 insertions(+), 187 deletions(-) rename selling/report/{sales_person_target_variance_(item_group_wise) => sales_person_target_variance_item_group_wise}/__init__.py (100%) rename selling/report/{sales_person_target_variance_(item_group_wise)/sales_person_target_variance_(item_group_wise).js => sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.js} (86%) rename selling/report/{sales_person_target_variance_(item_group_wise)/sales_person_target_variance_(item_group_wise).py => sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.py} (67%) rename selling/report/{sales_person_target_variance_(item_group_wise)/sales_person_target_variance_(item_group_wise).txt => sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.txt} (57%) rename selling/report/{territory_target_variance_(item_group_wise) => territory_target_variance_item_group_wise}/__init__.py (100%) rename selling/report/{territory_target_variance_(item_group_wise)/territory_target_variance_(item_group_wise).js => territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.js} (87%) rename selling/report/{territory_target_variance_(item_group_wise)/territory_target_variance_(item_group_wise).py => territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.py} (66%) rename selling/report/{territory_target_variance_(item_group_wise)/territory_target_variance_(item_group_wise).txt => territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.txt} (57%) diff --git a/accounts/report/budget_variance_report/budget_variance_report.py b/accounts/report/budget_variance_report/budget_variance_report.py index 99e303bd20..b4959aa667 100644 --- a/accounts/report/budget_variance_report/budget_variance_report.py +++ b/accounts/report/budget_variance_report/budget_variance_report.py @@ -16,18 +16,21 @@ from __future__ import unicode_literals import webnotes -import calendar from webnotes import _, msgprint from webnotes.utils import flt import time +from accounts.utils import get_fiscal_year +from controllers.trends import get_period_date_ranges, get_period_month_ranges def execute(filters=None): if not filters: filters = {} columns = get_columns(filters) - period_month_ranges = get_period_month_ranges(filters) + 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(): @@ -39,7 +42,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)) + value = flt(month_data.get(fieldname), precision) period_data[i] += value totals[i] += value period_data[2] = period_data[0] - period_data[1] @@ -61,7 +64,7 @@ def get_columns(filters): group_months = False if filters["period"] == "Monthly" else True - for from_date, to_date in get_period_date_ranges(filters): + for from_date, to_date in get_period_date_ranges(filters["period"], filters["fiscal_year"]): for label in ["Target (%s)", "Actual (%s)", "Variance (%s)"]: if group_months: columns.append(label % (from_date.strftime("%b") + " - " + to_date.strftime("%b"))) @@ -70,41 +73,6 @@ def get_columns(filters): return columns + ["Total Target::80", "Total Actual::80", "Total Variance::80"] -def get_period_date_ranges(filters): - from dateutil.relativedelta import relativedelta - - year_start_date, year_end_date = get_year_start_end_date(filters) - - increment = { - "Monthly": 1, - "Quarterly": 3, - "Half-Yearly": 6, - "Yearly": 12 - }.get(filters["period"]) - - period_date_ranges = [] - for i in xrange(1, 13, increment): - period_end_date = year_start_date + relativedelta(months=increment, - days=-1) - period_date_ranges.append([year_start_date, period_end_date]) - year_start_date = period_end_date + relativedelta(days=1) - - return period_date_ranges - -def get_period_month_ranges(filters): - from dateutil.relativedelta import relativedelta - period_month_ranges = [] - - for start_date, end_date in get_period_date_ranges(filters): - months_in_this_period = [] - while start_date <= end_date: - months_in_this_period.append(start_date.strftime("%B")) - start_date += relativedelta(months=1) - period_month_ranges.append(months_in_this_period) - - return period_month_ranges - - #Get cost center & target details def get_costcenter_target_details(filters): return webnotes.conn.sql("""select cc.name, cc.distribution_id, @@ -122,7 +90,7 @@ def get_target_distribution_details(filters): for d in webnotes.conn.sql("""select bdd.month, bdd.percentage_allocation \ from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd, \ `tabCost Center` cc where bdd.parent=bd.name and cc.distribution_id=bd.name and \ - bd.fiscal_year=%s""" % ('%s'), (filters.get("fiscal_year")), as_dict=1): + bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1): target_details.setdefault(d.month, d) return target_details @@ -151,18 +119,11 @@ def get_costcenter_account_month_map(filters): })) tav_dict = cam_map[ccd.name][ccd.account][month] - tav_dict.target = ccd.budget_allocated*(tdd[month]["percentage_allocation"]/100) + tav_dict.target = flt(ccd.budget_allocated)*(tdd[month]["percentage_allocation"]/100) for ad in actual_details: if ad.month_name == month and ad.account == ccd.account \ and ad.cost_center == ccd.name: tav_dict.actual += ad.debit - ad.credit - return cam_map - -def get_year_start_end_date(filters): - return webnotes.conn.sql("""select year_start_date, - subdate(adddate(year_start_date, interval 1 year), interval 1 day) - as year_end_date - from `tabFiscal Year` - where name=%s""", filters["fiscal_year"])[0] \ No newline at end of file + return cam_map \ No newline at end of file diff --git a/selling/page/selling_home/selling_home.js b/selling/page/selling_home/selling_home.js index 87e12db904..7a0848e931 100644 --- a/selling/page/selling_home/selling_home.js +++ b/selling/page/selling_home/selling_home.js @@ -167,12 +167,12 @@ wn.module_page["Selling"] = [ }, { "label":wn._("Territory Target Variance (Item Group-Wise)"), - route: "query-report/Territory Target Variance (Item Group-Wise)", + route: "query-report/Territory Target Variance Item Group-Wise", doctype: "Sales Order" }, { "label":wn._("Sales Person Target Variance (Item Group-Wise)"), - route: "query-report/Sales Person Target Variance (Item Group-Wise)", + route: "query-report/Sales Person Target Variance Item Group-Wise", doctype: "Sales Order" }, { diff --git a/selling/report/sales_person_target_variance_(item_group_wise)/__init__.py b/selling/report/sales_person_target_variance_item_group_wise/__init__.py similarity index 100% rename from selling/report/sales_person_target_variance_(item_group_wise)/__init__.py rename to selling/report/sales_person_target_variance_item_group_wise/__init__.py diff --git a/selling/report/sales_person_target_variance_(item_group_wise)/sales_person_target_variance_(item_group_wise).js b/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.js similarity index 86% rename from selling/report/sales_person_target_variance_(item_group_wise)/sales_person_target_variance_(item_group_wise).js rename to selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.js index 09f0d55aed..c7a5d668c4 100644 --- a/selling/report/sales_person_target_variance_(item_group_wise)/sales_person_target_variance_(item_group_wise).js +++ b/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.js @@ -1,4 +1,4 @@ -wn.query_reports["Sales Person Target Variance (Item Group-Wise)"] = { +wn.query_reports["Sales Person Target Variance Item Group-Wise"] = { "filters": [ { fieldname: "fiscal_year", 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 similarity index 67% rename from selling/report/sales_person_target_variance_(item_group_wise)/sales_person_target_variance_(item_group_wise).py rename to selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.py index 8f5931d826..6e39143f2e 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 @@ -16,18 +16,21 @@ from __future__ import unicode_literals import webnotes -import calendar from webnotes import _, msgprint from webnotes.utils import flt import time +from accounts.utils import get_fiscal_year +from controllers.trends import get_period_date_ranges, get_period_month_ranges def execute(filters=None): if not filters: filters = {} columns = get_columns(filters) - period_month_ranges = get_period_month_ranges(filters) + period_month_ranges = get_period_month_ranges(filters["period"], filters["fiscal_year"]) sim_map = get_salesperson_item_month_map(filters) + precision = webnotes.conn.get_value("Global Defaults", None, "float_precision") or 2 + data = [] for salesperson, salesperson_items in sim_map.items(): @@ -39,7 +42,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)) + value = flt(month_data.get(fieldname), precision) period_data[i] += value totals[i] += value period_data[2] = period_data[0] - period_data[1] @@ -61,7 +64,7 @@ def get_columns(filters): group_months = False if filters["period"] == "Monthly" else True - for from_date, to_date in get_period_date_ranges(filters): + for from_date, to_date in get_period_date_ranges(filters["period"], filters["fiscal_year"]): for label in ["Target (%s)", "Achieved (%s)", "Variance (%s)"]: if group_months: columns.append(label % (from_date.strftime("%b") + " - " + to_date.strftime("%b"))) @@ -70,49 +73,14 @@ def get_columns(filters): return columns + ["Total Target::80", "Total Achieved::80", "Total Variance::80"] -def get_period_date_ranges(filters): - from dateutil.relativedelta import relativedelta - - year_start_date, year_end_date = get_year_start_end_date(filters) - - increment = { - "Monthly": 1, - "Quarterly": 3, - "Half-Yearly": 6, - "Yearly": 12 - }.get(filters["period"]) - - period_date_ranges = [] - for i in xrange(1, 13, increment): - period_end_date = year_start_date + relativedelta(months=increment, - days=-1) - period_date_ranges.append([year_start_date, period_end_date]) - year_start_date = period_end_date + relativedelta(days=1) - - return period_date_ranges - -def get_period_month_ranges(filters): - from dateutil.relativedelta import relativedelta - period_month_ranges = [] - - for start_date, end_date in get_period_date_ranges(filters): - months_in_this_period = [] - while start_date <= end_date: - months_in_this_period.append(start_date.strftime("%B")) - start_date += relativedelta(months=1) - period_month_ranges.append(months_in_this_period) - - return period_month_ranges - - #Get sales person & item group details def get_salesperson_details(filters): return webnotes.conn.sql("""select sp.name, td.item_group, td.target_qty, td.target_amount, sp.distribution_id from `tabSales Person` sp, `tabTarget Detail` td where td.parent=sp.name and td.fiscal_year=%s and - ifnull(sp.distribution_id, '')!='' order by sp.name""" % - ('%s'), (filters.get("fiscal_year")), as_dict=1) + ifnull(sp.distribution_id, '')!='' order by sp.name""", + (filters["fiscal_year"]), as_dict=1) #Get target distribution details of item group def get_target_distribution_details(filters): @@ -121,14 +89,14 @@ def get_target_distribution_details(filters): for d in webnotes.conn.sql("""select bdd.month, bdd.percentage_allocation \ from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd, \ `tabTerritory` t where bdd.parent=bd.name and t.distribution_id=bd.name and \ - bd.fiscal_year=%s """ % ('%s'), (filters.get("fiscal_year")), as_dict=1): + bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1): target_details.setdefault(d.month, d) return target_details #Get achieved details from sales order def get_achieved_details(filters): - start_date, end_date = get_year_start_end_date(filters) + start_date, end_date = get_fiscal_year(filters)[1:] return webnotes.conn.sql("""select soi.item_code, soi.qty, soi.amount, so.transaction_date, st.sales_person, MONTHNAME(so.transaction_date) as month_name @@ -156,28 +124,18 @@ def get_salesperson_item_month_map(filters): for ad in achieved_details: if (filters["target_on"] == "Quantity"): - tav_dict.target = sd.target_qty*(tdd[month]["percentage_allocation"]/100) - if ad.month_name == month and ''.join(get_item_group(ad.item_code)) == sd.item_group \ + tav_dict.target = flt(sd.target_qty)*(tdd[month]["percentage_allocation"]/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 = sd.target_amount*(tdd[month]["percentage_allocation"]/100) - if ad.month_name == month and ''.join(get_item_group(ad.item_code)) == sd.item_group \ + tav_dict.target = flt(sd.target_amount)*(tdd[month]["percentage_allocation"]/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 return sim_map -def get_year_start_end_date(filters): - return webnotes.conn.sql("""select year_start_date, - subdate(adddate(year_start_date, interval 1 year), interval 1 day) - as year_end_date - from `tabFiscal Year` - where name=%s""", filters["fiscal_year"])[0] - def get_item_group(item_name): - """Get Item Group of an item""" - - return webnotes.conn.sql_list("select item_group from `tabItem` where name=%s""" % - ('%s'), (item_name)) \ No newline at end of file + return webnotes.conn.get_value("Item", item_name, item_group) \ 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).txt b/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.txt similarity index 57% rename from selling/report/sales_person_target_variance_(item_group_wise)/sales_person_target_variance_(item_group_wise).txt rename to selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.txt index 955cdec477..e587c2c084 100644 --- a/selling/report/sales_person_target_variance_(item_group_wise)/sales_person_target_variance_(item_group_wise).txt +++ b/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.txt @@ -1,8 +1,8 @@ [ { - "creation": "2013-06-18 12:09:40", + "creation": "2013-06-21 12:14:15", "docstatus": 0, - "modified": "2013-06-18 12:09:40", + "modified": "2013-06-21 12:14:15", "modified_by": "Administrator", "owner": "Administrator" }, @@ -11,11 +11,11 @@ "is_standard": "Yes", "name": "__common__", "ref_doctype": "Sales Order", - "report_name": "Sales Person Target Variance (Item Group-Wise)", + "report_name": "Sales Person Target Variance Item Group-Wise", "report_type": "Script Report" }, { "doctype": "Report", - "name": "Sales Person Target Variance (Item Group-Wise)" + "name": "Sales Person Target Variance Item Group-Wise" } ] \ No newline at end of file diff --git a/selling/report/territory_target_variance_(item_group_wise)/__init__.py b/selling/report/territory_target_variance_item_group_wise/__init__.py similarity index 100% rename from selling/report/territory_target_variance_(item_group_wise)/__init__.py rename to selling/report/territory_target_variance_item_group_wise/__init__.py diff --git a/selling/report/territory_target_variance_(item_group_wise)/territory_target_variance_(item_group_wise).js b/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.js similarity index 87% rename from selling/report/territory_target_variance_(item_group_wise)/territory_target_variance_(item_group_wise).js rename to selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.js index 58718a4e0b..146b17d02b 100644 --- a/selling/report/territory_target_variance_(item_group_wise)/territory_target_variance_(item_group_wise).js +++ b/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.js @@ -1,4 +1,4 @@ -wn.query_reports["Territory Target Variance (Item Group-Wise)"] = { +wn.query_reports["Territory Target Variance Item Group-Wise"] = { "filters": [ { fieldname: "fiscal_year", 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 similarity index 66% rename from selling/report/territory_target_variance_(item_group_wise)/territory_target_variance_(item_group_wise).py rename to selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.py index 079f8e82a2..e7ddc6e6f9 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 @@ -16,18 +16,21 @@ from __future__ import unicode_literals import webnotes -import calendar from webnotes import _, msgprint from webnotes.utils import flt import time +from accounts.utils import get_fiscal_year +from controllers.trends import get_period_date_ranges, get_period_month_ranges def execute(filters=None): if not filters: filters = {} columns = get_columns(filters) - period_month_ranges = get_period_month_ranges(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(): @@ -39,7 +42,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)) + value = flt(month_data.get(fieldname), precision) period_data[i] += value totals[i] += value period_data[2] = period_data[0] - period_data[1] @@ -61,7 +64,7 @@ def get_columns(filters): group_months = False if filters["period"] == "Monthly" else True - for from_date, to_date in get_period_date_ranges(filters): + for from_date, to_date in get_period_date_ranges(filters["period"], filters["fiscal_year"]): for label in ["Target (%s)", "Achieved (%s)", "Variance (%s)"]: if group_months: columns.append(label % (from_date.strftime("%b") + " - " + to_date.strftime("%b"))) @@ -70,49 +73,14 @@ def get_columns(filters): return columns + ["Total Target::80", "Total Achieved::80", "Total Variance::80"] -def get_period_date_ranges(filters): - from dateutil.relativedelta import relativedelta - - year_start_date, year_end_date = get_year_start_end_date(filters) - - increment = { - "Monthly": 1, - "Quarterly": 3, - "Half-Yearly": 6, - "Yearly": 12 - }.get(filters["period"]) - - period_date_ranges = [] - for i in xrange(1, 13, increment): - period_end_date = year_start_date + relativedelta(months=increment, - days=-1) - period_date_ranges.append([year_start_date, period_end_date]) - year_start_date = period_end_date + relativedelta(days=1) - - return period_date_ranges - -def get_period_month_ranges(filters): - from dateutil.relativedelta import relativedelta - period_month_ranges = [] - - for start_date, end_date in get_period_date_ranges(filters): - months_in_this_period = [] - while start_date <= end_date: - months_in_this_period.append(start_date.strftime("%B")) - start_date += relativedelta(months=1) - period_month_ranges.append(months_in_this_period) - - return period_month_ranges - - #Get territory & item group details def get_territory_details(filters): return webnotes.conn.sql("""select t.name, td.item_group, td.target_qty, td.target_amount, t.distribution_id from `tabTerritory` t, `tabTarget Detail` td where td.parent=t.name and td.fiscal_year=%s and - ifnull(t.distribution_id, '')!='' order by t.name""" % - ('%s'), (filters.get("fiscal_year")), as_dict=1) + ifnull(t.distribution_id, '')!='' order by t.name""", + (filters["fiscal_year"]), as_dict=1) #Get target distribution details of item group def get_target_distribution_details(filters): @@ -121,14 +89,14 @@ def get_target_distribution_details(filters): for d in webnotes.conn.sql("""select bdd.month, bdd.percentage_allocation \ from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd, \ `tabTerritory` t where bdd.parent=bd.name and t.distribution_id=bd.name and \ - bd.fiscal_year=%s""" % ('%s'), (filters.get("fiscal_year")), as_dict=1): + bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1): target_details.setdefault(d.month, d) return target_details #Get achieved details from sales order def get_achieved_details(filters): - start_date, end_date = get_year_start_end_date(filters) + start_date, end_date = get_fiscal_year(filters)[1:] return webnotes.conn.sql("""select soi.item_code, soi.qty, soi.amount, so.transaction_date, so.territory, MONTHNAME(so.transaction_date) as month_name @@ -155,28 +123,18 @@ def get_territory_item_month_map(filters): for ad in achieved_details: if (filters["target_on"] == "Quantity"): - tav_dict.target = td.target_qty*(tdd[month]["percentage_allocation"]/100) - if ad.month_name == month and ''.join(get_item_group(ad.item_code)) == td.item_group \ + tav_dict.target = flt(td.target_qty)*(tdd[month]["percentage_allocation"]/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 = td.target_amount*(tdd[month]["percentage_allocation"]/100) - if ad.month_name == month and ''.join(get_item_group(ad.item_code)) == td.item_group \ + tav_dict.target = flt(td.target_amount)*(tdd[month]["percentage_allocation"]/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 return tim_map -def get_year_start_end_date(filters): - return webnotes.conn.sql("""select year_start_date, - subdate(adddate(year_start_date, interval 1 year), interval 1 day) - as year_end_date - from `tabFiscal Year` - where name=%s""", filters["fiscal_year"])[0] - def get_item_group(item_name): - """Get Item Group of an item""" - - return webnotes.conn.sql_list("select item_group from `tabItem` where name=%s""" % - ('%s'), (item_name)) \ No newline at end of file + return webnotes.conn.get_value("Item", item_name, item_group) \ No newline at end of file diff --git a/selling/report/territory_target_variance_(item_group_wise)/territory_target_variance_(item_group_wise).txt b/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.txt similarity index 57% rename from selling/report/territory_target_variance_(item_group_wise)/territory_target_variance_(item_group_wise).txt rename to selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.txt index 7fff64a861..6e16b64d4e 100644 --- a/selling/report/territory_target_variance_(item_group_wise)/territory_target_variance_(item_group_wise).txt +++ b/selling/report/territory_target_variance_item_group_wise/territory_target_variance_item_group_wise.txt @@ -1,8 +1,8 @@ [ { - "creation": "2013-06-07 15:13:13", + "creation": "2013-06-21 12:15:00", "docstatus": 0, - "modified": "2013-06-07 15:13:13", + "modified": "2013-06-21 12:15:00", "modified_by": "Administrator", "owner": "Administrator" }, @@ -11,11 +11,11 @@ "is_standard": "Yes", "name": "__common__", "ref_doctype": "Sales Order", - "report_name": "Territory Target Variance (Item Group-Wise)", + "report_name": "Territory Target Variance Item Group-Wise", "report_type": "Script Report" }, { "doctype": "Report", - "name": "Territory Target Variance (Item Group-Wise)" + "name": "Territory Target Variance Item Group-Wise" } ] \ No newline at end of file diff --git a/stock/report/item_prices/item_prices.py b/stock/report/item_prices/item_prices.py index 86ae085ce7..7a3877bcca 100644 --- a/stock/report/item_prices/item_prices.py +++ b/stock/report/item_prices/item_prices.py @@ -24,16 +24,22 @@ def execute(filters=None): columns = get_columns(filters) item_map = get_item_details() pl = get_price_list() + last_purchase_rate = get_last_purchase_rate() bom_rate = get_item_bom_rate() val_rate_map = get_valuation_rate() + + precision = webnotes.conn.get_value("Global Defaults", None, "float_precision") or 2 data = [] for item in sorted(item_map): data.append([item, item_map[item]["item_name"], item_map[item]["description"], item_map[item]["stock_uom"], - flt(item_map[item]["last_purchase_rate"]), val_rate_map.get(item, 0), - pl.get(item, {}).get("selling"), pl.get(item, {}).get("buying"), - bom_rate.get(item, 0), flt(item_map[item]["standard_rate"]) + flt(last_purchase_rate.get(item, 0), precision), + flt(val_rate_map.get(item, 0), precision), + pl.get(item, {}).get("selling"), + pl.get(item, {}).get("buying"), + flt(bom_rate.get(item, 0), precision), + flt(item_map[item]["standard_rate"]) ]) return columns, data @@ -53,7 +59,7 @@ def get_item_details(): item_map = {} for i in webnotes.conn.sql("select name, item_name, description, \ - stock_uom, standard_rate, last_purchase_rate from tabItem \ + stock_uom, standard_rate from tabItem \ order by item_code", as_dict=1): item_map.setdefault(i.name, i) @@ -84,24 +90,60 @@ def get_price_list(): return item_rate_map +def get_last_purchase_rate(): + + item_last_purchase_rate_map = {} + + query = """select * from (select + result.item_code, + result.purchase_rate + from ( + (select + po_item.item_code, + po_item.item_name, + po.transaction_date as posting_date, + po_item.purchase_ref_rate, + po_item.discount_rate, + po_item.purchase_rate + from `tabPurchase Order` po, `tabPurchase Order Item` po_item + where po.name = po_item.parent and po.docstatus = 1) + union + (select + pr_item.item_code, + pr_item.item_name, + pr.posting_date, + pr_item.purchase_ref_rate, + pr_item.discount_rate, + pr_item.purchase_rate + from `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pr_item + where pr.name = pr_item.parent and pr.docstatus = 1) + ) result + order by result.item_code asc, result.posting_date desc) result_wrapper + group by item_code""" + + for d in webnotes.conn.sql(query, as_dict=1): + item_last_purchase_rate_map.setdefault(d.item_code, d.purchase_rate) + + return item_last_purchase_rate_map + def get_item_bom_rate(): """Get BOM rate of an item from BOM""" - bom_map = {} + item_bom_map = {} for b in webnotes.conn.sql("""select item, (total_cost/quantity) as bom_rate from `tabBOM` where is_active=1 and is_default=1""", as_dict=1): - bom_map.setdefault(b.item, flt(b.bom_rate)) + item_bom_map.setdefault(b.item, flt(b.bom_rate)) - return bom_map + return item_bom_map def get_valuation_rate(): """Get an average valuation rate of an item from all warehouses""" - val_rate_map = {} + item_val_rate_map = {} for d in webnotes.conn.sql("""select item_code, avg(valuation_rate) as val_rate from tabBin group by item_code""", as_dict=1): - val_rate_map.setdefault(d.item_code, d.val_rate) + item_val_rate_map.setdefault(d.item_code, flt(d.val_rate)) - return val_rate_map \ No newline at end of file + return item_val_rate_map \ No newline at end of file From 3e8eca35a259021e982c1003ddac50fa6d47d016 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 24 Jun 2013 17:18:24 +0530 Subject: [PATCH 02/13] [report][fix] stock balance --- accounts/page/general_ledger/general_ledger.js | 2 +- startup/report_data_map.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/accounts/page/general_ledger/general_ledger.js b/accounts/page/general_ledger/general_ledger.js index ffab56831a..e612bd8a41 100644 --- a/accounts/page/general_ledger/general_ledger.js +++ b/accounts/page/general_ledger/general_ledger.js @@ -326,7 +326,7 @@ erpnext.GeneralLedger = wn.views.GridReport.extend({ if(voucher_dict.totals.debit || voucher_dict.totals.credit) { voucher_dict.row.debit = voucher_dict.totals.debit; voucher_dict.row.credit = voucher_dict.totals.credit; - voucher_dict.row.id = "entry" + voucher + voucher_dict.row.id = "entry_grouped_by_" + voucher out = out.concat(voucher_dict.row); } }); diff --git a/startup/report_data_map.py b/startup/report_data_map.py index 068e470045..c3a5dd2cce 100644 --- a/startup/report_data_map.py +++ b/startup/report_data_map.py @@ -72,7 +72,7 @@ data_map = { }, "Item Group": { "columns": ["name", "parent_item_group"], - "conditions": ["docstatus < 2"], + # "conditions": ["docstatus < 2"], "order_by": "lft" }, "Brand": { From a19014a8469938ea38169fba9280aadb998e6760 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Mon, 24 Jun 2013 19:05:16 +0530 Subject: [PATCH 03/13] Moved Sales BOM & Sales BOM Item to Selling module, completed 'Available Stock for packing Items' report --- .../doctype/sales_bom/__init__.py | 0 .../sales_bom/locale/_messages_doc.json | 0 .../doctype/sales_bom/locale/ar-doc.json | 0 .../doctype/sales_bom/locale/de-doc.json | 0 .../doctype/sales_bom/locale/es-doc.json | 0 .../doctype/sales_bom/locale/fr-doc.json | 0 .../doctype/sales_bom/locale/hi-doc.json | 0 .../doctype/sales_bom/locale/hr-doc.json | 0 .../doctype/sales_bom/locale/nl-doc.json | 0 .../doctype/sales_bom/locale/pt-BR-doc.json | 0 .../doctype/sales_bom/locale/pt-doc.json | 0 .../doctype/sales_bom/locale/sr-doc.json | 0 .../doctype/sales_bom/locale/ta-doc.json | 0 .../doctype/sales_bom/locale/th-doc.json | 0 .../doctype/sales_bom/sales_bom.js | 0 .../doctype/sales_bom/sales_bom.py | 0 .../doctype/sales_bom/sales_bom.txt | 0 .../doctype/sales_bom/test_sales_bom.py | 0 .../doctype/sales_bom_item/__init__.py | 0 .../sales_bom_item/locale/_messages_doc.json | 0 .../doctype/sales_bom_item/locale/ar-doc.json | 0 .../doctype/sales_bom_item/locale/de-doc.json | 0 .../doctype/sales_bom_item/locale/es-doc.json | 0 .../doctype/sales_bom_item/locale/fr-doc.json | 0 .../doctype/sales_bom_item/locale/hi-doc.json | 0 .../doctype/sales_bom_item/locale/hr-doc.json | 0 .../doctype/sales_bom_item/locale/nl-doc.json | 0 .../sales_bom_item/locale/pt-BR-doc.json | 0 .../doctype/sales_bom_item/locale/pt-doc.json | 0 .../doctype/sales_bom_item/locale/sr-doc.json | 0 .../doctype/sales_bom_item/locale/ta-doc.json | 0 .../doctype/sales_bom_item/locale/th-doc.json | 0 .../doctype/sales_bom_item/sales_bom_item.py | 0 .../doctype/sales_bom_item/sales_bom_item.txt | 0 selling/locale/_messages_js.json | 1 + selling/locale/_messages_py.json | 7 ++ selling/locale/ar-py.json | 7 ++ selling/locale/de-py.json | 7 ++ selling/locale/es-py.json | 7 ++ selling/locale/fr-py.json | 7 ++ selling/locale/hi-py.json | 7 ++ selling/locale/hr-py.json | 7 ++ selling/locale/nl-py.json | 7 ++ selling/locale/pt-BR-py.json | 7 ++ selling/locale/pt-py.json | 7 ++ selling/locale/sr-py.json | 7 ++ selling/locale/ta-py.json | 7 ++ selling/locale/th-py.json | 7 ++ selling/page/selling_home/selling_home.js | 11 ++- .../__init__.py | 0 .../available_stock_for_packing_items.py | 89 +++++++++++++++++++ .../available_stock_for_packing_items.txt | 21 +++++ 52 files changed, 209 insertions(+), 4 deletions(-) rename {stock => selling}/doctype/sales_bom/__init__.py (100%) rename {stock => selling}/doctype/sales_bom/locale/_messages_doc.json (100%) rename {stock => selling}/doctype/sales_bom/locale/ar-doc.json (100%) rename {stock => selling}/doctype/sales_bom/locale/de-doc.json (100%) rename {stock => selling}/doctype/sales_bom/locale/es-doc.json (100%) rename {stock => selling}/doctype/sales_bom/locale/fr-doc.json (100%) rename {stock => selling}/doctype/sales_bom/locale/hi-doc.json (100%) rename {stock => selling}/doctype/sales_bom/locale/hr-doc.json (100%) rename {stock => selling}/doctype/sales_bom/locale/nl-doc.json (100%) rename {stock => selling}/doctype/sales_bom/locale/pt-BR-doc.json (100%) rename {stock => selling}/doctype/sales_bom/locale/pt-doc.json (100%) rename {stock => selling}/doctype/sales_bom/locale/sr-doc.json (100%) rename {stock => selling}/doctype/sales_bom/locale/ta-doc.json (100%) rename {stock => selling}/doctype/sales_bom/locale/th-doc.json (100%) rename {stock => selling}/doctype/sales_bom/sales_bom.js (100%) rename {stock => selling}/doctype/sales_bom/sales_bom.py (100%) rename {stock => selling}/doctype/sales_bom/sales_bom.txt (100%) rename {stock => selling}/doctype/sales_bom/test_sales_bom.py (100%) rename {stock => selling}/doctype/sales_bom_item/__init__.py (100%) rename {stock => selling}/doctype/sales_bom_item/locale/_messages_doc.json (100%) rename {stock => selling}/doctype/sales_bom_item/locale/ar-doc.json (100%) rename {stock => selling}/doctype/sales_bom_item/locale/de-doc.json (100%) rename {stock => selling}/doctype/sales_bom_item/locale/es-doc.json (100%) rename {stock => selling}/doctype/sales_bom_item/locale/fr-doc.json (100%) rename {stock => selling}/doctype/sales_bom_item/locale/hi-doc.json (100%) rename {stock => selling}/doctype/sales_bom_item/locale/hr-doc.json (100%) rename {stock => selling}/doctype/sales_bom_item/locale/nl-doc.json (100%) rename {stock => selling}/doctype/sales_bom_item/locale/pt-BR-doc.json (100%) rename {stock => selling}/doctype/sales_bom_item/locale/pt-doc.json (100%) rename {stock => selling}/doctype/sales_bom_item/locale/sr-doc.json (100%) rename {stock => selling}/doctype/sales_bom_item/locale/ta-doc.json (100%) rename {stock => selling}/doctype/sales_bom_item/locale/th-doc.json (100%) rename {stock => selling}/doctype/sales_bom_item/sales_bom_item.py (100%) rename {stock => selling}/doctype/sales_bom_item/sales_bom_item.txt (100%) create mode 100644 selling/locale/_messages_js.json create mode 100644 selling/locale/_messages_py.json create mode 100644 selling/locale/ar-py.json create mode 100644 selling/locale/de-py.json create mode 100644 selling/locale/es-py.json create mode 100644 selling/locale/fr-py.json create mode 100644 selling/locale/hi-py.json create mode 100644 selling/locale/hr-py.json create mode 100644 selling/locale/nl-py.json create mode 100644 selling/locale/pt-BR-py.json create mode 100644 selling/locale/pt-py.json create mode 100644 selling/locale/sr-py.json create mode 100644 selling/locale/ta-py.json create mode 100644 selling/locale/th-py.json create mode 100644 selling/report/available_stock_for_packing_items/__init__.py create mode 100644 selling/report/available_stock_for_packing_items/available_stock_for_packing_items.py create mode 100644 selling/report/available_stock_for_packing_items/available_stock_for_packing_items.txt diff --git a/stock/doctype/sales_bom/__init__.py b/selling/doctype/sales_bom/__init__.py similarity index 100% rename from stock/doctype/sales_bom/__init__.py rename to selling/doctype/sales_bom/__init__.py diff --git a/stock/doctype/sales_bom/locale/_messages_doc.json b/selling/doctype/sales_bom/locale/_messages_doc.json similarity index 100% rename from stock/doctype/sales_bom/locale/_messages_doc.json rename to selling/doctype/sales_bom/locale/_messages_doc.json diff --git a/stock/doctype/sales_bom/locale/ar-doc.json b/selling/doctype/sales_bom/locale/ar-doc.json similarity index 100% rename from stock/doctype/sales_bom/locale/ar-doc.json rename to selling/doctype/sales_bom/locale/ar-doc.json diff --git a/stock/doctype/sales_bom/locale/de-doc.json b/selling/doctype/sales_bom/locale/de-doc.json similarity index 100% rename from stock/doctype/sales_bom/locale/de-doc.json rename to selling/doctype/sales_bom/locale/de-doc.json diff --git a/stock/doctype/sales_bom/locale/es-doc.json b/selling/doctype/sales_bom/locale/es-doc.json similarity index 100% rename from stock/doctype/sales_bom/locale/es-doc.json rename to selling/doctype/sales_bom/locale/es-doc.json diff --git a/stock/doctype/sales_bom/locale/fr-doc.json b/selling/doctype/sales_bom/locale/fr-doc.json similarity index 100% rename from stock/doctype/sales_bom/locale/fr-doc.json rename to selling/doctype/sales_bom/locale/fr-doc.json diff --git a/stock/doctype/sales_bom/locale/hi-doc.json b/selling/doctype/sales_bom/locale/hi-doc.json similarity index 100% rename from stock/doctype/sales_bom/locale/hi-doc.json rename to selling/doctype/sales_bom/locale/hi-doc.json diff --git a/stock/doctype/sales_bom/locale/hr-doc.json b/selling/doctype/sales_bom/locale/hr-doc.json similarity index 100% rename from stock/doctype/sales_bom/locale/hr-doc.json rename to selling/doctype/sales_bom/locale/hr-doc.json diff --git a/stock/doctype/sales_bom/locale/nl-doc.json b/selling/doctype/sales_bom/locale/nl-doc.json similarity index 100% rename from stock/doctype/sales_bom/locale/nl-doc.json rename to selling/doctype/sales_bom/locale/nl-doc.json diff --git a/stock/doctype/sales_bom/locale/pt-BR-doc.json b/selling/doctype/sales_bom/locale/pt-BR-doc.json similarity index 100% rename from stock/doctype/sales_bom/locale/pt-BR-doc.json rename to selling/doctype/sales_bom/locale/pt-BR-doc.json diff --git a/stock/doctype/sales_bom/locale/pt-doc.json b/selling/doctype/sales_bom/locale/pt-doc.json similarity index 100% rename from stock/doctype/sales_bom/locale/pt-doc.json rename to selling/doctype/sales_bom/locale/pt-doc.json diff --git a/stock/doctype/sales_bom/locale/sr-doc.json b/selling/doctype/sales_bom/locale/sr-doc.json similarity index 100% rename from stock/doctype/sales_bom/locale/sr-doc.json rename to selling/doctype/sales_bom/locale/sr-doc.json diff --git a/stock/doctype/sales_bom/locale/ta-doc.json b/selling/doctype/sales_bom/locale/ta-doc.json similarity index 100% rename from stock/doctype/sales_bom/locale/ta-doc.json rename to selling/doctype/sales_bom/locale/ta-doc.json diff --git a/stock/doctype/sales_bom/locale/th-doc.json b/selling/doctype/sales_bom/locale/th-doc.json similarity index 100% rename from stock/doctype/sales_bom/locale/th-doc.json rename to selling/doctype/sales_bom/locale/th-doc.json diff --git a/stock/doctype/sales_bom/sales_bom.js b/selling/doctype/sales_bom/sales_bom.js similarity index 100% rename from stock/doctype/sales_bom/sales_bom.js rename to selling/doctype/sales_bom/sales_bom.js diff --git a/stock/doctype/sales_bom/sales_bom.py b/selling/doctype/sales_bom/sales_bom.py similarity index 100% rename from stock/doctype/sales_bom/sales_bom.py rename to selling/doctype/sales_bom/sales_bom.py diff --git a/stock/doctype/sales_bom/sales_bom.txt b/selling/doctype/sales_bom/sales_bom.txt similarity index 100% rename from stock/doctype/sales_bom/sales_bom.txt rename to selling/doctype/sales_bom/sales_bom.txt diff --git a/stock/doctype/sales_bom/test_sales_bom.py b/selling/doctype/sales_bom/test_sales_bom.py similarity index 100% rename from stock/doctype/sales_bom/test_sales_bom.py rename to selling/doctype/sales_bom/test_sales_bom.py diff --git a/stock/doctype/sales_bom_item/__init__.py b/selling/doctype/sales_bom_item/__init__.py similarity index 100% rename from stock/doctype/sales_bom_item/__init__.py rename to selling/doctype/sales_bom_item/__init__.py diff --git a/stock/doctype/sales_bom_item/locale/_messages_doc.json b/selling/doctype/sales_bom_item/locale/_messages_doc.json similarity index 100% rename from stock/doctype/sales_bom_item/locale/_messages_doc.json rename to selling/doctype/sales_bom_item/locale/_messages_doc.json diff --git a/stock/doctype/sales_bom_item/locale/ar-doc.json b/selling/doctype/sales_bom_item/locale/ar-doc.json similarity index 100% rename from stock/doctype/sales_bom_item/locale/ar-doc.json rename to selling/doctype/sales_bom_item/locale/ar-doc.json diff --git a/stock/doctype/sales_bom_item/locale/de-doc.json b/selling/doctype/sales_bom_item/locale/de-doc.json similarity index 100% rename from stock/doctype/sales_bom_item/locale/de-doc.json rename to selling/doctype/sales_bom_item/locale/de-doc.json diff --git a/stock/doctype/sales_bom_item/locale/es-doc.json b/selling/doctype/sales_bom_item/locale/es-doc.json similarity index 100% rename from stock/doctype/sales_bom_item/locale/es-doc.json rename to selling/doctype/sales_bom_item/locale/es-doc.json diff --git a/stock/doctype/sales_bom_item/locale/fr-doc.json b/selling/doctype/sales_bom_item/locale/fr-doc.json similarity index 100% rename from stock/doctype/sales_bom_item/locale/fr-doc.json rename to selling/doctype/sales_bom_item/locale/fr-doc.json diff --git a/stock/doctype/sales_bom_item/locale/hi-doc.json b/selling/doctype/sales_bom_item/locale/hi-doc.json similarity index 100% rename from stock/doctype/sales_bom_item/locale/hi-doc.json rename to selling/doctype/sales_bom_item/locale/hi-doc.json diff --git a/stock/doctype/sales_bom_item/locale/hr-doc.json b/selling/doctype/sales_bom_item/locale/hr-doc.json similarity index 100% rename from stock/doctype/sales_bom_item/locale/hr-doc.json rename to selling/doctype/sales_bom_item/locale/hr-doc.json diff --git a/stock/doctype/sales_bom_item/locale/nl-doc.json b/selling/doctype/sales_bom_item/locale/nl-doc.json similarity index 100% rename from stock/doctype/sales_bom_item/locale/nl-doc.json rename to selling/doctype/sales_bom_item/locale/nl-doc.json diff --git a/stock/doctype/sales_bom_item/locale/pt-BR-doc.json b/selling/doctype/sales_bom_item/locale/pt-BR-doc.json similarity index 100% rename from stock/doctype/sales_bom_item/locale/pt-BR-doc.json rename to selling/doctype/sales_bom_item/locale/pt-BR-doc.json diff --git a/stock/doctype/sales_bom_item/locale/pt-doc.json b/selling/doctype/sales_bom_item/locale/pt-doc.json similarity index 100% rename from stock/doctype/sales_bom_item/locale/pt-doc.json rename to selling/doctype/sales_bom_item/locale/pt-doc.json diff --git a/stock/doctype/sales_bom_item/locale/sr-doc.json b/selling/doctype/sales_bom_item/locale/sr-doc.json similarity index 100% rename from stock/doctype/sales_bom_item/locale/sr-doc.json rename to selling/doctype/sales_bom_item/locale/sr-doc.json diff --git a/stock/doctype/sales_bom_item/locale/ta-doc.json b/selling/doctype/sales_bom_item/locale/ta-doc.json similarity index 100% rename from stock/doctype/sales_bom_item/locale/ta-doc.json rename to selling/doctype/sales_bom_item/locale/ta-doc.json diff --git a/stock/doctype/sales_bom_item/locale/th-doc.json b/selling/doctype/sales_bom_item/locale/th-doc.json similarity index 100% rename from stock/doctype/sales_bom_item/locale/th-doc.json rename to selling/doctype/sales_bom_item/locale/th-doc.json diff --git a/stock/doctype/sales_bom_item/sales_bom_item.py b/selling/doctype/sales_bom_item/sales_bom_item.py similarity index 100% rename from stock/doctype/sales_bom_item/sales_bom_item.py rename to selling/doctype/sales_bom_item/sales_bom_item.py diff --git a/stock/doctype/sales_bom_item/sales_bom_item.txt b/selling/doctype/sales_bom_item/sales_bom_item.txt similarity index 100% rename from stock/doctype/sales_bom_item/sales_bom_item.txt rename to selling/doctype/sales_bom_item/sales_bom_item.txt diff --git a/selling/locale/_messages_js.json b/selling/locale/_messages_js.json new file mode 100644 index 0000000000..0637a088a0 --- /dev/null +++ b/selling/locale/_messages_js.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/selling/locale/_messages_py.json b/selling/locale/_messages_py.json new file mode 100644 index 0000000000..f5b4a010f5 --- /dev/null +++ b/selling/locale/_messages_py.json @@ -0,0 +1,7 @@ +[ + "is not a Stock Item", + "Item", + "Please check", + "reached its end of life on", + "is a cancelled Item" +] \ No newline at end of file diff --git a/selling/locale/ar-py.json b/selling/locale/ar-py.json new file mode 100644 index 0000000000..b8dd151cf9 --- /dev/null +++ b/selling/locale/ar-py.json @@ -0,0 +1,7 @@ +{ + "Item": "\u0628\u0646\u062f", + "Please check": "\u064a\u0631\u062c\u0649 \u0645\u0631\u0627\u062c\u0639\u0629", + "is a cancelled Item": "\u0647\u0648 \u0628\u0646\u062f \u0625\u0644\u063a\u0627\u0621", + "is not a Stock Item": "\u0644\u064a\u0633 \u0627\u0644\u0625\u063a\u0644\u0627\u0642 \u0644\u0644\u0633\u0647\u0645", + "reached its end of life on": "\u0648\u0635\u0644 \u0625\u0644\u0649 \u0646\u0647\u0627\u064a\u062a\u0647 \u0645\u0646 \u0627\u0644\u062d\u064a\u0627\u0629 \u0639\u0644\u0649" +} \ No newline at end of file diff --git a/selling/locale/de-py.json b/selling/locale/de-py.json new file mode 100644 index 0000000000..68b58d7a4b --- /dev/null +++ b/selling/locale/de-py.json @@ -0,0 +1,7 @@ +{ + "Item": "Artikel", + "Please check": "Bitte \u00fcberpr\u00fcfen Sie", + "is a cancelled Item": "ist ein gestempeltes", + "is not a Stock Item": "ist kein Lagerartikel", + "reached its end of life on": "erreichte Ende des Lebens auf" +} \ No newline at end of file diff --git a/selling/locale/es-py.json b/selling/locale/es-py.json new file mode 100644 index 0000000000..7d145d1e4c --- /dev/null +++ b/selling/locale/es-py.json @@ -0,0 +1,7 @@ +{ + "Item": "Art\u00edculo", + "Please check": "Por favor, compruebe", + "is a cancelled Item": "Es un Tema cancelado", + "is not a Stock Item": "no es un elemento de serie", + "reached its end of life on": "llegado al final de su vida en la" +} \ No newline at end of file diff --git a/selling/locale/fr-py.json b/selling/locale/fr-py.json new file mode 100644 index 0000000000..c466df4c7f --- /dev/null +++ b/selling/locale/fr-py.json @@ -0,0 +1,7 @@ +{ + "Item": "Article", + "Please check": "S'il vous pla\u00eet v\u00e9rifier", + "is a cancelled Item": "est un \u00e9l\u00e9ment annul\u00e9e", + "is not a Stock Item": "n'est pas un \u00e9l\u00e9ment de Stock", + "reached its end of life on": "atteint la fin de sa vie sur" +} \ No newline at end of file diff --git a/selling/locale/hi-py.json b/selling/locale/hi-py.json new file mode 100644 index 0000000000..58d4e65411 --- /dev/null +++ b/selling/locale/hi-py.json @@ -0,0 +1,7 @@ +{ + "Item": "\u092e\u0926", + "Please check": "\u0915\u0943\u092a\u092f\u093e \u091c\u093e\u0901\u091a \u0915\u0930\u0947\u0902", + "is a cancelled Item": "\u0930\u0926\u094d\u0926 \u0906\u0907\u091f\u092e", + "is not a Stock Item": "\u0938\u094d\u091f\u0949\u0915 \u0906\u0907\u091f\u092e \u0928\u0939\u0940\u0902 \u0939\u0948", + "reached its end of life on": "\u092a\u0930 \u0905\u092a\u0928\u0947 \u091c\u0940\u0935\u0928 \u0915\u0947 \u0905\u0902\u0924 \u0924\u0915 \u092a\u0939\u0941\u0901\u091a" +} \ No newline at end of file diff --git a/selling/locale/hr-py.json b/selling/locale/hr-py.json new file mode 100644 index 0000000000..24f60bb1c4 --- /dev/null +++ b/selling/locale/hr-py.json @@ -0,0 +1,7 @@ +{ + "Item": "Stavka", + "Please check": "Molimo provjerite", + "is a cancelled Item": "je otkazan artikla", + "is not a Stock Item": "nije katalo\u0161ki artikla", + "reached its end of life on": "dosegla svoj kraj \u017eivota na" +} \ No newline at end of file diff --git a/selling/locale/nl-py.json b/selling/locale/nl-py.json new file mode 100644 index 0000000000..7964d37f6e --- /dev/null +++ b/selling/locale/nl-py.json @@ -0,0 +1,7 @@ +{ + "Item": "Item", + "Please check": "Controleer", + "is a cancelled Item": "is een geannuleerde artikel", + "is not a Stock Item": "is niet een Stock Item", + "reached its end of life on": "het einde van zijn leven op" +} \ No newline at end of file diff --git a/selling/locale/pt-BR-py.json b/selling/locale/pt-BR-py.json new file mode 100644 index 0000000000..0bf350cad0 --- /dev/null +++ b/selling/locale/pt-BR-py.json @@ -0,0 +1,7 @@ +{ + "Item": "Item", + "Please check": "Por favor, verifique", + "is a cancelled Item": "\u00e9 um Item cancelado", + "is not a Stock Item": "n\u00e3o \u00e9 um Item de Estoque", + "reached its end of life on": "chegou ao fim de vida em" +} \ No newline at end of file diff --git a/selling/locale/pt-py.json b/selling/locale/pt-py.json new file mode 100644 index 0000000000..cfcbcec8df --- /dev/null +++ b/selling/locale/pt-py.json @@ -0,0 +1,7 @@ +{ + "Item": "Item", + "Please check": "Por favor, verifique", + "is a cancelled Item": "\u00e9 um item cancelado", + "is not a Stock Item": "n\u00e3o \u00e9 um item de estoque", + "reached its end of life on": "chegou ao fim da vida na" +} \ No newline at end of file diff --git a/selling/locale/sr-py.json b/selling/locale/sr-py.json new file mode 100644 index 0000000000..ed1672fc6c --- /dev/null +++ b/selling/locale/sr-py.json @@ -0,0 +1,7 @@ +{ + "Item": "\u0421\u0442\u0430\u0432\u043a\u0430", + "Please check": "\u041c\u043e\u043b\u0438\u043c\u043e \u0432\u0430\u0441 \u0434\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u0435", + "is a cancelled Item": "\u0458\u0435 \u043e\u0442\u043a\u0430\u0437\u0430\u043d\u0430 \u0448\u0438\u0444\u0440\u0430", + "is not a Stock Item": "\u043d\u0438\u0458\u0435 \u0431\u0435\u0440\u0437\u0430 \u0448\u0438\u0444\u0440\u0430", + "reached its end of life on": "\u0434\u043e\u0441\u0442\u0438\u0433\u0430\u043e \u0441\u0432\u043e\u0458 \u043a\u0440\u0430\u0458 \u0436\u0438\u0432\u043e\u0442\u0430 \u043d\u0430" +} \ No newline at end of file diff --git a/selling/locale/ta-py.json b/selling/locale/ta-py.json new file mode 100644 index 0000000000..355cc0e7ce --- /dev/null +++ b/selling/locale/ta-py.json @@ -0,0 +1,7 @@ +{ + "Item": "\u0b89\u0bb0\u0bc1\u0baa\u0bcd\u0baa\u0b9f\u0bbf", + "Please check": "\u0b9a\u0bb0\u0bbf\u0baa\u0bbe\u0bb0\u0bcd\u0b95\u0bcd\u0b95\u0bb5\u0bc1\u0bae\u0bcd", + "is a cancelled Item": "\u0b92\u0bb0\u0bc1 \u0bb0\u0ba4\u0bcd\u0ba4\u0bc1 \u0b89\u0bb0\u0bc1\u0baa\u0bcd\u0baa\u0b9f\u0bbf \u0b89\u0bb3\u0bcd\u0bb3\u0ba4\u0bc1", + "is not a Stock Item": "\u0b92\u0bb0\u0bc1 \u0baa\u0b99\u0bcd\u0b95\u0bc1 \u0baa\u0bc6\u0bbe\u0bb0\u0bc1\u0bb3\u0bcd \u0b85\u0bb2\u0bcd\u0bb2", + "reached its end of life on": "\u0bb5\u0bbe\u0bb4\u0bcd\u0b95\u0bcd\u0b95\u0bc8 \u0b85\u0ba4\u0ba9\u0bcd \u0b87\u0bb1\u0bc1\u0ba4\u0bbf\u0baf\u0bbf\u0bb2\u0bcd \u0b85\u0b9f\u0bc8\u0ba8\u0bcd\u0ba4\u0ba4\u0bc1" +} \ No newline at end of file diff --git a/selling/locale/th-py.json b/selling/locale/th-py.json new file mode 100644 index 0000000000..5f31a59373 --- /dev/null +++ b/selling/locale/th-py.json @@ -0,0 +1,7 @@ +{ + "Item": "\u0e0a\u0e34\u0e49\u0e19", + "Please check": "\u0e01\u0e23\u0e38\u0e13\u0e32\u0e15\u0e23\u0e27\u0e08\u0e2a\u0e2d\u0e1a", + "is a cancelled Item": "\u0e23\u0e32\u0e22\u0e01\u0e32\u0e23\u0e22\u0e01\u0e40\u0e25\u0e34\u0e01\u0e40\u0e1b\u0e47\u0e19", + "is not a Stock Item": "\u0e44\u0e21\u0e48\u0e44\u0e14\u0e49\u0e40\u0e1b\u0e47\u0e19\u0e23\u0e32\u0e22\u0e01\u0e32\u0e23\u0e2a\u0e15\u0e47\u0e2d\u0e01", + "reached its end of life on": "\u0e16\u0e36\u0e07\u0e08\u0e38\u0e14\u0e2a\u0e34\u0e49\u0e19\u0e2a\u0e38\u0e14\u0e02\u0e2d\u0e07\u0e0a\u0e35\u0e27\u0e34\u0e15\u0e40\u0e21\u0e37\u0e48\u0e2d" +} \ No newline at end of file diff --git a/selling/page/selling_home/selling_home.js b/selling/page/selling_home/selling_home.js index 7a0848e931..4157bbb809 100644 --- a/selling/page/selling_home/selling_home.js +++ b/selling/page/selling_home/selling_home.js @@ -167,13 +167,11 @@ wn.module_page["Selling"] = [ }, { "label":wn._("Territory Target Variance (Item Group-Wise)"), - route: "query-report/Territory Target Variance Item Group-Wise", - doctype: "Sales Order" + route: "query-report/Territory Target Variance Item Group-Wise" }, { "label":wn._("Sales Person Target Variance (Item Group-Wise)"), - route: "query-report/Sales Person Target Variance Item Group-Wise", - doctype: "Sales Order" + route: "query-report/Sales Person Target Variance Item Group-Wise" }, { "label":wn._("Customers Not Buying Since Long Time"), @@ -190,6 +188,11 @@ wn.module_page["Selling"] = [ route: "query-report/Sales Order Trends", doctype: "Sales Order" }, + { + "label":wn._("Available Stock for Packing Items"), + route: "query-report/Available Stock for Packing Items", + + }, ] } ] diff --git a/selling/report/available_stock_for_packing_items/__init__.py b/selling/report/available_stock_for_packing_items/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/selling/report/available_stock_for_packing_items/available_stock_for_packing_items.py b/selling/report/available_stock_for_packing_items/available_stock_for_packing_items.py new file mode 100644 index 0000000000..d766c4487d --- /dev/null +++ b/selling/report/available_stock_for_packing_items/available_stock_for_packing_items.py @@ -0,0 +1,89 @@ +# ERPNext - web based ERP (http://erpnext.com) +# Copyright (C) 2012 Web Notes Technologies Pvt Ltd +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from __future__ import unicode_literals +import webnotes +from webnotes.utils import cint + +def execute(filters=None): + if not filters: filters = {} + + columns = get_columns() + item_warehouse_quantity_map = get_item_warehouse_quantity_map() + + data = [] + for item, warehouse in item_warehouse_quantity_map.items(): + item_details = get_item_details(item)[0] + total = 0 + total_qty = 0 + for wh, item_qty in warehouse.items(): + total += 1 + row = [item, item_details.item_name, item_details.description, \ + item_details.stock_uom, wh] + for quantity in item_qty.items(): + max_qty = [] + max_qty.append(quantity[1]) + max_qty = min(max_qty) + total_qty += cint(max_qty.qty) + row += [max_qty.qty] + data.append(row) + if (total == len(warehouse)): + row = ["", "", "Total", "", "", total_qty] + data.append(row) + + return columns, data + +def get_columns(): + columns = ["Item Code:Link/Item:100", "Item Name::100", "Description::120", \ + "UOM:Link/UOM:80", "Warehouse:Link/Warehouse:100", "Quantity::100"] + + return columns + +def get_sales_bom(): + return webnotes.conn.sql("""select name from `tabSales BOM`""", as_dict=1) + +def get_sales_bom_items(item): + return webnotes.conn.sql("""select parent, item_code, qty from `tabSales BOM Item` + where parent=%s""", (item), as_dict=1) + +def get_item_details(item): + return webnotes.conn.sql("""select name, item_name, description, stock_uom + from `tabItem` where name=%s""", (item), as_dict=1) + +def get_item_warehouse_quantity(item): + return webnotes.conn.sql("""select item_code, warehouse, actual_qty from `tabBin` + where item_code=%s""", (item), as_dict=1) + +def get_item_warehouse_quantity_map(): + iwq_map = {} + + sales_bom = get_sales_bom() + + for item in sales_bom: + child_item = get_sales_bom_items(item.name) + for child in child_item: + item_warehouse_quantity = get_item_warehouse_quantity(child.item_code) + for iwq in item_warehouse_quantity: + iwq_map.setdefault(item.name, {}).setdefault(iwq.warehouse, {}).\ + setdefault(child.item_code, webnotes._dict({ + "qty" : 0 + })) + + q_dict = iwq_map[item.name][iwq.warehouse][child.item_code] + + q_dict.qty = cint(iwq.actual_qty / child.qty) + + return iwq_map \ No newline at end of file diff --git a/selling/report/available_stock_for_packing_items/available_stock_for_packing_items.txt b/selling/report/available_stock_for_packing_items/available_stock_for_packing_items.txt new file mode 100644 index 0000000000..5cf413393f --- /dev/null +++ b/selling/report/available_stock_for_packing_items/available_stock_for_packing_items.txt @@ -0,0 +1,21 @@ +[ + { + "creation": "2013-06-21 13:40:05", + "docstatus": 0, + "modified": "2013-06-21 15:06:40", + "modified_by": "Administrator", + "owner": "Administrator" + }, + { + "doctype": "Report", + "is_standard": "Yes", + "name": "__common__", + "ref_doctype": "Sales BOM", + "report_name": "Available Stock for Packing Items", + "report_type": "Script Report" + }, + { + "doctype": "Report", + "name": "Available Stock for Packing Items" + } +] \ No newline at end of file From ec1f69ddb96955b7d10b55e2523472eca67ea910 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 25 Jun 2013 12:17:43 +0530 Subject: [PATCH 04/13] [reports][fix] removed old reports --- patches/august_2012/remove_cash_flow_statement.py | 4 ---- patches/december_2012/deprecate_tds.py | 1 - .../reload_debtors_creditors_ledger.py | 5 ----- patches/february_2013/p03_material_request.py | 2 -- .../remove_sales_order_pending_items.py | 3 --- .../deprecate_stock_search_criteria.py | 9 --------- .../january_2013/remove_support_search_criteria.py | 4 ---- patches/july_2012/sync_trial_balance.py | 5 ----- patches/june_2012/reports_list_permission.py | 1 - .../may_2012/reload_customer_address_contact.py | 5 ----- patches/may_2012/reload_reports.py | 7 ------- patches/may_2012/reload_so_pending_items.py | 9 --------- patches/patch_list.py | 14 -------------- 13 files changed, 69 deletions(-) delete mode 100644 patches/august_2012/remove_cash_flow_statement.py delete mode 100644 patches/december_2012/reload_debtors_creditors_ledger.py delete mode 100644 patches/february_2013/remove_sales_order_pending_items.py delete mode 100644 patches/january_2013/deprecate_stock_search_criteria.py delete mode 100644 patches/january_2013/remove_support_search_criteria.py delete mode 100644 patches/july_2012/sync_trial_balance.py delete mode 100644 patches/may_2012/reload_customer_address_contact.py delete mode 100644 patches/may_2012/reload_reports.py delete mode 100644 patches/may_2012/reload_so_pending_items.py diff --git a/patches/august_2012/remove_cash_flow_statement.py b/patches/august_2012/remove_cash_flow_statement.py deleted file mode 100644 index 739a4f2709..0000000000 --- a/patches/august_2012/remove_cash_flow_statement.py +++ /dev/null @@ -1,4 +0,0 @@ -from __future__ import unicode_literals -def execute(): - import webnotes - webnotes.conn.sql("delete from `tabSearch Criteria` where name = 'cash_flow_statement'") \ No newline at end of file diff --git a/patches/december_2012/deprecate_tds.py b/patches/december_2012/deprecate_tds.py index e351fd9f75..f3daeb0db7 100644 --- a/patches/december_2012/deprecate_tds.py +++ b/patches/december_2012/deprecate_tds.py @@ -15,7 +15,6 @@ def execute(): webnotes.conn.sql("drop table if exists `tab%s`" % dt) webnotes.conn.begin() - delete_doc("Search Criteria", "tds_return") # Add tds entry in tax table for purchase invoice pi_list = webnotes.conn.sql("""select name from `tabPurchase Invoice` diff --git a/patches/december_2012/reload_debtors_creditors_ledger.py b/patches/december_2012/reload_debtors_creditors_ledger.py deleted file mode 100644 index 7f88a6f47d..0000000000 --- a/patches/december_2012/reload_debtors_creditors_ledger.py +++ /dev/null @@ -1,5 +0,0 @@ -def execute(): - import webnotes - from webnotes.modules import reload_doc - reload_doc("accounts", "search_criteria", "debtors_ledger") - reload_doc("accounts", "search_criteria", "creditors_ledger") \ No newline at end of file diff --git a/patches/february_2013/p03_material_request.py b/patches/february_2013/p03_material_request.py index f0373bdffb..d85710d2a8 100644 --- a/patches/february_2013/p03_material_request.py +++ b/patches/february_2013/p03_material_request.py @@ -8,8 +8,6 @@ def execute(): webnotes.rename_doc("DocType", "Purchase Request Item", "Material Request Item", force=True) if not "tabMaterial Request" in tables: webnotes.rename_doc("DocType", "Purchase Request", "Material Request", force=True) - webnotes.reload_doc("buying", "search_criteria", "pending_po_items_to_bill") - webnotes.reload_doc("buying", "search_criteria", "pending_po_items_to_receive") webnotes.reload_doc("stock", "doctype", "material_request") webnotes.reload_doc("stock", "doctype", "material_request_item") diff --git a/patches/february_2013/remove_sales_order_pending_items.py b/patches/february_2013/remove_sales_order_pending_items.py deleted file mode 100644 index bde6a7b240..0000000000 --- a/patches/february_2013/remove_sales_order_pending_items.py +++ /dev/null @@ -1,3 +0,0 @@ -def execute(): - import webnotes - webnotes.delete_doc("Search Criteria", "sales_order_pending_items") \ No newline at end of file diff --git a/patches/january_2013/deprecate_stock_search_criteria.py b/patches/january_2013/deprecate_stock_search_criteria.py deleted file mode 100644 index d51aadb5cf..0000000000 --- a/patches/january_2013/deprecate_stock_search_criteria.py +++ /dev/null @@ -1,9 +0,0 @@ -import webnotes - -def execute(): - for sc in ["itemwise_price_list", "itemwise_receipt_details", - "shortage_to_purchase_request", "stock_aging_report", - "stock_ledger", "stock_level", "stock_report", - "custom_test2", "custom_test3", "custom_test4", - "test_so2", "test_so3"]: - webnotes.delete_doc("Search Criteria", sc) \ No newline at end of file diff --git a/patches/january_2013/remove_support_search_criteria.py b/patches/january_2013/remove_support_search_criteria.py deleted file mode 100644 index 0443afeeda..0000000000 --- a/patches/january_2013/remove_support_search_criteria.py +++ /dev/null @@ -1,4 +0,0 @@ -import webnotes -def execute(): - for sc in ["warranty-amc_expiry_details", "warranty-amc_summary"]: - webnotes.delete_doc("Search Criteria", sc) \ No newline at end of file diff --git a/patches/july_2012/sync_trial_balance.py b/patches/july_2012/sync_trial_balance.py deleted file mode 100644 index 3755ed442b..0000000000 --- a/patches/july_2012/sync_trial_balance.py +++ /dev/null @@ -1,5 +0,0 @@ -from __future__ import unicode_literals -def execute(): - import webnotes - from webnotes.modules import reload_doc - reload_doc('accounts', 'search_criteria', 'trial_balance') \ No newline at end of file diff --git a/patches/june_2012/reports_list_permission.py b/patches/june_2012/reports_list_permission.py index e34eb5ae46..e88e8fbc60 100644 --- a/patches/june_2012/reports_list_permission.py +++ b/patches/june_2012/reports_list_permission.py @@ -8,7 +8,6 @@ def execute(): webnotes.conn.commit() - webnotes.reload_doc('core', 'doctype', 'search_criteria') webnotes.reload_doc('core', 'doctype', 'report') webnotes.conn.begin() \ No newline at end of file diff --git a/patches/may_2012/reload_customer_address_contact.py b/patches/may_2012/reload_customer_address_contact.py deleted file mode 100644 index 4aec19d02d..0000000000 --- a/patches/may_2012/reload_customer_address_contact.py +++ /dev/null @@ -1,5 +0,0 @@ -from __future__ import unicode_literals -def execute(): - import webnotes - import webnotes.modules - webnotes.modules.reload_doc('selling', 'search_criteria', 'customer_address_contact') \ No newline at end of file diff --git a/patches/may_2012/reload_reports.py b/patches/may_2012/reload_reports.py deleted file mode 100644 index 1cee3a0061..0000000000 --- a/patches/may_2012/reload_reports.py +++ /dev/null @@ -1,7 +0,0 @@ -from __future__ import unicode_literals -def execute(): - import webnotes - from webnotes.modules import reload_doc - reload_doc('selling', 'search_criteria', 'itemwise_sales_details') - reload_doc('selling', 'search_criteria', 'itemwise_delivery_details') - diff --git a/patches/may_2012/reload_so_pending_items.py b/patches/may_2012/reload_so_pending_items.py deleted file mode 100644 index 999004e1fe..0000000000 --- a/patches/may_2012/reload_so_pending_items.py +++ /dev/null @@ -1,9 +0,0 @@ -from __future__ import unicode_literals -def execute(): - import webnotes - from webnotes.model import delete_doc - delete_doc("Search Criteria", "sales_order_pending_items1") - - webnotes.conn.sql("update `tabSearch Criteria` set module = 'Selling' where module = 'CRM'") - from webnotes.modules import reload_doc - reload_doc('selling', 'search_criteria', 'sales_order_pending_items') \ No newline at end of file diff --git a/patches/patch_list.py b/patches/patch_list.py index 0353c74b1e..efd4d51cce 100644 --- a/patches/patch_list.py +++ b/patches/patch_list.py @@ -38,19 +38,15 @@ patch_list = [ "patches.may_2012.cleanup_property_setter", "patches.may_2012.rename_prev_doctype", "patches.may_2012.cleanup_notification_control", - "patches.may_2012.renamedt_in_custom_search_criteria", "patches.may_2012.stock_reco_patch", - "patches.may_2012.reload_reports", "patches.may_2012.page_role_series_fix", "patches.may_2012.reload_sales_invoice_pf", "patches.may_2012.std_pf_readonly", - "patches.may_2012.reload_so_pending_items", "patches.may_2012.customize_form_cleanup", "patches.may_2012.cs_server_readonly", "patches.may_2012.clear_session_cache", "patches.may_2012.same_purchase_rate_patch", "patches.may_2012.create_report_manager_role", - "patches.may_2012.reload_customer_address_contact", "patches.may_2012.profile_perm_patch", "patches.may_2012.remove_euro_currency", "patches.may_2012.remove_communication_log", @@ -81,7 +77,6 @@ patch_list = [ "patches.august_2012.task_allocated_to_assigned", "patches.august_2012.change_profile_permission", "patches.august_2012.repost_billed_amt", - "patches.august_2012.remove_cash_flow_statement", "patches.september_2012.stock_report_permissions_for_accounts", "patches.september_2012.communication_delete_permission", "patches.september_2012.all_permissions_patch", @@ -123,7 +118,6 @@ patch_list = [ "patches.december_2012.expense_leave_reload", "patches.december_2012.repost_ordered_qty", "patches.december_2012.repost_projected_qty", - "patches.december_2012.reload_debtors_creditors_ledger", "patches.december_2012.website_cache_refactor", "patches.december_2012.production_cleanup", "patches.december_2012.fix_default_print_format", @@ -138,8 +132,6 @@ patch_list = [ "patches.december_2012.remove_project_mapper", "patches.december_2012.update_print_width", "patches.january_2013.remove_bad_permissions", - "patches.january_2013.deprecate_stock_search_criteria", - "patches.january_2013.remove_support_search_criteria", "patches.january_2013.holiday_list_patch", "patches.january_2013.stock_reconciliation_patch", "patches.january_2013.report_permission", @@ -163,7 +155,6 @@ patch_list = [ "patches.february_2013.remove_gl_mapper", "patches.february_2013.reload_bom_replace_tool_permission", "patches.february_2013.payment_reconciliation_reset_values", - "patches.february_2013.remove_sales_order_pending_items", "patches.february_2013.account_negative_balance", "patches.february_2013.remove_account_utils_folder", "patches.february_2013.update_company_in_leave_application", @@ -187,14 +178,11 @@ patch_list = [ "execute:webnotes.delete_doc('DocType', 'Service Quotation Detail')", "patches.february_2013.p06_material_request_mappers", "execute:webnotes.delete_doc('Page', 'Query Report')", - "execute:webnotes.delete_doc('Search Criteria', 'employeewise_balance_leave_report')", - "execute:webnotes.delete_doc('Search Criteria', 'employee_leave_balance_report')", "patches.february_2013.repost_reserved_qty", "execute:webnotes.reload_doc('core', 'doctype', 'report') # 2013-02-25", "execute:webnotes.conn.sql(\"update `tabReport` set report_type=if(ifnull(query, '')='', 'Report Builder', 'Query Report') where is_standard='No'\")", "execute:webnotes.conn.sql(\"update `tabReport` set report_name=name where ifnull(report_name,'')='' and is_standard='No'\")", "patches.february_2013.p08_todo_query_report", - "execute:webnotes.delete_doc('Search Criteria', 'gross_profit') # 2013-02-26", 'execute:webnotes.reload_doc("accounts", "Print Format", "Sales Invoice Classic") # 2013-02-26', 'execute:webnotes.reload_doc("accounts", "Print Format", "Sales Invoice Modern") # 2013-02-26', 'execute:webnotes.reload_doc("accounts", "Print Format", "Sales Invoice Spartan") # 2013-02-26', @@ -208,7 +196,6 @@ patch_list = [ "execute:webnotes.delete_doc('DocType', 'Attendance Control Panel')", "patches.march_2013.p02_get_global_default", "patches.march_2013.p03_rename_blog_to_blog_post", - "execute:webnotes.reload_doc('hr', 'search_criteria', 'monthly_attendance_details')", "patches.march_2013.p04_pos_update_stock_check", "patches.march_2013.p05_payment_reconciliation", "patches.march_2013.p06_remove_sales_purchase_return_tool", @@ -234,7 +221,6 @@ patch_list = [ 'execute:webnotes.reload_doc("selling", "Print Format", "Quotation Modern") # 2013-04-02', 'execute:webnotes.reload_doc("selling", "Print Format", "Quotation Spartan") # 2013-04-02', "patches.april_2013.p04_reverse_modules_list", - "execute:webnotes.delete_doc('Search Criteria', 'time_log_summary')", "patches.april_2013.p04_update_role_in_pages", "patches.april_2013.p05_update_file_data", "patches.april_2013.p06_update_file_size", From 909e8b120f62507ec65afd14592248cf6cc4c619 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 25 Jun 2013 14:08:18 +0530 Subject: [PATCH 05/13] [fix][report] general ledger --- accounts/page/general_ledger/general_ledger.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/accounts/page/general_ledger/general_ledger.js b/accounts/page/general_ledger/general_ledger.js index e612bd8a41..d30772acfd 100644 --- a/accounts/page/general_ledger/general_ledger.js +++ b/accounts/page/general_ledger/general_ledger.js @@ -232,7 +232,6 @@ erpnext.GeneralLedger = wn.views.GridReport.extend({ grouped_ledgers[item.account].totals.debit += item.debit; grouped_ledgers[item.account].totals.credit += item.credit; - grouped_ledgers[item.account].entries_group_by_voucher[item.voucher_no] .totals.debit += item.debit; grouped_ledgers[item.account].entries_group_by_voucher[item.voucher_no] @@ -248,8 +247,8 @@ erpnext.GeneralLedger = wn.views.GridReport.extend({ grouped_ledgers[item.account].entries.push(item); if(grouped_ledgers[item.account].entries_group_by_voucher[item.voucher_no].row){ - grouped_ledgers[item.account]. - entries_group_by_voucher[item.voucher_no].row = item; + grouped_ledgers[item.account].entries_group_by_voucher[item.voucher_no] + .row = jQuery.extend({}, item); } } } @@ -321,7 +320,7 @@ erpnext.GeneralLedger = wn.views.GridReport.extend({ $.each(Object.keys(grouped_ledgers).sort(), function(i, account) { if(grouped_ledgers[account].entries.length) { $.each(Object.keys(grouped_ledgers[account].entries_group_by_voucher).sort(), - function(j, voucher) { + function(j, voucher) { voucher_dict = grouped_ledgers[account].entries_group_by_voucher[voucher]; if(voucher_dict.totals.debit || voucher_dict.totals.credit) { voucher_dict.row.debit = voucher_dict.totals.debit; From cca41a172cf397747f5300cf49e3ad3ca6331002 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 25 Jun 2013 14:14:32 +0530 Subject: [PATCH 06/13] [fix][report] general ledger --- accounts/page/general_ledger/general_ledger.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/accounts/page/general_ledger/general_ledger.js b/accounts/page/general_ledger/general_ledger.js index d30772acfd..269ed5e3f2 100644 --- a/accounts/page/general_ledger/general_ledger.js +++ b/accounts/page/general_ledger/general_ledger.js @@ -319,10 +319,11 @@ erpnext.GeneralLedger = wn.views.GridReport.extend({ var out = [] $.each(Object.keys(grouped_ledgers).sort(), function(i, account) { if(grouped_ledgers[account].entries.length) { - $.each(Object.keys(grouped_ledgers[account].entries_group_by_voucher).sort(), + $.each(Object.keys(grouped_ledgers[account].entries_group_by_voucher), function(j, voucher) { voucher_dict = grouped_ledgers[account].entries_group_by_voucher[voucher]; - if(voucher_dict.totals.debit || voucher_dict.totals.credit) { + if(voucher_dict && + (voucher_dict.totals.debit || voucher_dict.totals.credit)) { voucher_dict.row.debit = voucher_dict.totals.debit; voucher_dict.row.credit = voucher_dict.totals.credit; voucher_dict.row.id = "entry_grouped_by_" + voucher From 50899d2bd4c53826356d76cb24c6ed13ebc0a28c Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 25 Jun 2013 15:17:38 +0530 Subject: [PATCH 07/13] [fix][patch] bom exploded items --- patches/june_2013/p01_update_bom_exploded_items.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches/june_2013/p01_update_bom_exploded_items.py b/patches/june_2013/p01_update_bom_exploded_items.py index eff0931e4d..f53eb5bc68 100644 --- a/patches/june_2013/p01_update_bom_exploded_items.py +++ b/patches/june_2013/p01_update_bom_exploded_items.py @@ -23,7 +23,7 @@ def execute(): if bom[0] not in updated_bom: try: bom_obj = webnotes.get_obj("BOM", bom[0], with_children=1) - updated_bom = bom_obj.update_cost_and_exploded_items(updated_bom) + updated_bom += bom_obj.update_cost_and_exploded_items(bom[0]) webnotes.conn.commit() except: pass \ No newline at end of file From e05e6a114eab33efb5e1acb03e1ba2662b803bd9 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Tue, 25 Jun 2013 18:00:30 +0530 Subject: [PATCH 08/13] [Fix]SMS Center Cell Number --- selling/doctype/sms_center/sms_center.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/selling/doctype/sms_center/sms_center.py b/selling/doctype/sms_center/sms_center.py index c5db7383f7..7d50e71232 100644 --- a/selling/doctype/sms_center/sms_center.py +++ b/selling/doctype/sms_center/sms_center.py @@ -24,7 +24,7 @@ from webnotes.model.code import get_obj from webnotes import msgprint sql = webnotes.conn.sql - + # ---------- class DocType: @@ -45,17 +45,16 @@ class DocType: elif self.doc.send_to == 'All Lead (Open)': rec = sql("select lead_name, mobile_no from tabLead where ifnull(mobile_no,'')!='' and docstatus != 2 and status = 'Open'") elif self.doc.send_to == 'All Employee (Active)': - where_clause = self.doc.department and " and t1.department = '%s'" % self.doc.department or "" - where_clause += self.doc.branch and " and t1.branch = '%s'" % self.doc.branch or "" - rec = sql("select t1.employee_name, t2.cell_number from `tabEmployee` t1, `tabEmployee Profile` t2 where t2.employee = t1.name and t1.status = 'Active' and t1.docstatus != 2 and ifnull(t2.cell_number,'')!='' %s" % where_clause) + where_clause = self.doc.department and " and department = '%s'" % self.doc.department or "" + where_clause += self.doc.branch and " and branch = '%s'" % self.doc.branch or "" + rec = sql("select employee_name, cell_number from `tabEmployee` where status = 'Active' and docstatus < 2 and ifnull(cell_number,'')!='' %s" % where_clause) elif self.doc.send_to == 'All Sales Person': rec = sql("select sales_person_name, mobile_no from `tabSales Person` where docstatus != 2 and ifnull(mobile_no,'')!=''") - rec_list = '' for d in rec: rec_list += d[0] + ' - ' + d[1] + '\n' self.doc.receiver_list = rec_list - + webnotes.errprint(rec_list) def get_receiver_nos(self): receiver_nos = [] for d in self.doc.receiver_list.split('\n'): From 4c819edf24207c522b3289155f6be92afc54b909 Mon Sep 17 00:00:00 2001 From: Akhilesh Darjee Date: Wed, 26 Jun 2013 11:28:53 +0530 Subject: [PATCH 09/13] [Report] Added rounded_total & outstanding_amount to Sales & Purchase Register --- .../purchase_register/purchase_register.py | 23 +++++++++++-------- .../report/sales_register/sales_register.py | 16 +++++++------ 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/accounts/report/purchase_register/purchase_register.py b/accounts/report/purchase_register/purchase_register.py index 548b561344..d6233a41e0 100644 --- a/accounts/report/purchase_register/purchase_register.py +++ b/accounts/report/purchase_register/purchase_register.py @@ -38,11 +38,12 @@ def execute(filters=None): data = [] for inv in invoice_list: # invoice details - purchase_order = ", ".join(invoice_po_pr_map.get(inv.name, {}).get("purchase_order", [])) - purchase_receipt = ", ".join(invoice_po_pr_map.get(inv.name, {}).get("purchase_receipt", [])) + purchase_order = list(set(invoice_po_pr_map.get(inv.name, {}).get("purchase_order", []))) + purchase_receipt = list(set(invoice_po_pr_map.get(inv.name, {}).get("purchase_receipt", []))) + row = [inv.name, inv.posting_date, inv.supplier, inv.credit_to, account_map.get(inv.credit_to), inv.project_name, inv.bill_no, inv.bill_date, - inv.remarks, purchase_order, purchase_receipt] + inv.remarks, ", ".join(purchase_order), ", ".join(purchase_receipt)] # map expense values for expense_acc in expense_accounts: @@ -55,8 +56,9 @@ def execute(filters=None): for tax_acc in tax_accounts: row.append(invoice_tax_map.get(inv.name, {}).get(tax_acc)) - # total tax, grand total - row += [inv.total_tax, inv.grand_total] + # total tax, grand total, outstanding amount & rounded total + row += [inv.other_charges_total, inv.grand_total, flt(inv.grand_total, 2), \ + inv.outstanding_amount] data.append(row) return columns, data @@ -85,7 +87,8 @@ def get_columns(invoice_list): columns = columns + [(account + ":Currency:120") for account in expense_accounts] + \ ["Net Total:Currency:120"] + [(account + ":Currency:120") for account in tax_accounts] + \ - ["Total Tax:Currency:120"] + ["Grand Total:Currency:120"] + ["Total Tax:Currency:120"] + ["Grand Total:Currency:120"] + \ + ["Rounded Total:Currency:120"] + ["Outstanding Amount:Currency:120"] return columns, expense_accounts, tax_accounts @@ -102,9 +105,11 @@ def get_conditions(filters): def get_invoices(filters): conditions = get_conditions(filters) - return webnotes.conn.sql("""select name, posting_date, credit_to, project_name, supplier, - bill_no, bill_date, remarks, net_total, total_tax, grand_total - from `tabPurchase Invoice` where docstatus = 1 %s + return webnotes.conn.sql("""select pi.name, pi.posting_date, pi.credit_to, + pii.project_name, pi.supplier, pi.bill_no, pi.bill_date, pi.remarks, pi.net_total, + pi.total_tax, pi.grand_total, pi.outstanding_amount + from `tabPurchase Invoice` pi, `tabPurchase Invoice Item` pii + where pii.parent = pi.name and pi.docstatus = 1 %s order by posting_date desc, name desc""" % conditions, filters, as_dict=1) diff --git a/accounts/report/sales_register/sales_register.py b/accounts/report/sales_register/sales_register.py index 99057f9a2e..3eebc33e9c 100644 --- a/accounts/report/sales_register/sales_register.py +++ b/accounts/report/sales_register/sales_register.py @@ -39,12 +39,12 @@ def execute(filters=None): data = [] for inv in invoice_list: # invoice details - sales_order = ", ".join(invoice_so_dn_map.get(inv.name, {}).get("sales_order", [])) - delivery_note = ", ".join(invoice_so_dn_map.get(inv.name, {}).get("delivery_note", [])) + sales_order = list(set(invoice_so_dn_map.get(inv.name, {}).get("sales_order", []))) + delivery_note = list(set(invoice_so_dn_map.get(inv.name, {}).get("delivery_note", []))) row = [inv.name, inv.posting_date, inv.customer, inv.debit_to, account_map.get(inv.debit_to), customer_map.get(inv.customer), inv.project_name, - inv.remarks, sales_order, delivery_note] + inv.remarks, ", ".join(sales_order), ", ".join(delivery_note)] # map income values for income_acc in income_accounts: @@ -57,8 +57,8 @@ def execute(filters=None): for tax_acc in tax_accounts: row.append(invoice_tax_map.get(inv.name, {}).get(tax_acc)) - # total tax, grand total - row += [inv.other_charges_total, inv.grand_total] + # total tax, grand total, outstanding amount & rounded total + row += [inv.other_charges_total, inv.grand_total, inv.rounded_total, inv.outstanding_amount] data.append(row) @@ -88,7 +88,8 @@ def get_columns(invoice_list): columns = columns + [(account + ":Currency:120") for account in income_accounts] + \ ["Net Total:Currency:120"] + [(account + ":Currency:120") for account in tax_accounts] + \ - ["Total Tax:Currency:120"] + ["Grand Total:Currency:120"] + ["Total Tax:Currency:120"] + ["Grand Total:Currency:120"] + \ + ["Rounded Total:Currency:120"] + ["Outstanding Amount:Currency:120"] return columns, income_accounts, tax_accounts @@ -106,7 +107,8 @@ def get_conditions(filters): def get_invoices(filters): conditions = get_conditions(filters) return webnotes.conn.sql("""select name, posting_date, debit_to, project_name, customer, - remarks, net_total, other_charges_total, grand_total from `tabSales Invoice` + remarks, net_total, other_charges_total, grand_total, rounded_total, + outstanding_amount from `tabSales Invoice` where docstatus = 1 %s order by posting_date desc, name desc""" % conditions, filters, as_dict=1) From b802050cd4935ff1722234556595737223ce2afc Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Wed, 26 Jun 2013 12:05:37 +0530 Subject: [PATCH 10/13] [grid report] round currency values --- public/js/stock_analytics.js | 2 ++ stock/page/stock_balance/stock_balance.js | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/public/js/stock_analytics.js b/public/js/stock_analytics.js index c3ed1cb232..91384f61ed 100644 --- a/public/js/stock_analytics.js +++ b/public/js/stock_analytics.js @@ -162,6 +162,8 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({ } else { break; } + + me.round_item_values(item); } } }, diff --git a/stock/page/stock_balance/stock_balance.js b/stock/page/stock_balance/stock_balance.js index 163b74f629..f4deb4fcd4 100644 --- a/stock/page/stock_balance/stock_balance.js +++ b/stock/page/stock_balance/stock_balance.js @@ -119,7 +119,7 @@ erpnext.StockBalance = erpnext.StockAnalytics.extend({ var qty_diff = sl.qty; var value_diff = me.get_value_diff(wh, sl, is_fifo); - + if(sl_posting_date < from_date) { item.opening_qty += qty_diff; item.opening_value += value_diff; @@ -146,6 +146,8 @@ erpnext.StockBalance = erpnext.StockAnalytics.extend({ } else { break; } + + me.round_item_values(item); } } From e26acffcfe593d6a4c688536d40aa83903e69fe1 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 26 Jun 2013 13:47:11 +0530 Subject: [PATCH 11/13] [report] available qty for packing items --- selling/doctype/sales_bom/sales_bom.txt | 10 +- .../doctype/sales_bom_item/sales_bom_item.txt | 6 +- .../available_stock_for_packing_items.py | 95 ++++++++++--------- 3 files changed, 58 insertions(+), 53 deletions(-) diff --git a/selling/doctype/sales_bom/sales_bom.txt b/selling/doctype/sales_bom/sales_bom.txt index 031f255919..bf8fa479c2 100644 --- a/selling/doctype/sales_bom/sales_bom.txt +++ b/selling/doctype/sales_bom/sales_bom.txt @@ -1,8 +1,8 @@ [ { - "creation": "2013-01-10 16:34:29", + "creation": "2013-06-20 11:53:21", "docstatus": 0, - "modified": "2013-01-22 14:57:23", + "modified": "2013-06-25 16:43:18", "modified_by": "Administrator", "owner": "Administrator" }, @@ -11,7 +11,7 @@ "doctype": "DocType", "document_type": "Master", "is_submittable": 0, - "module": "Stock", + "module": "Selling", "name": "__common__" }, { @@ -23,7 +23,6 @@ "permlevel": 0 }, { - "amend": 0, "doctype": "DocPerm", "name": "__common__", "parent": "Sales BOM", @@ -74,6 +73,7 @@ "reqd": 1 }, { + "amend": 1, "cancel": 1, "create": 1, "doctype": "DocPerm", @@ -81,6 +81,7 @@ "write": 1 }, { + "amend": 0, "cancel": 0, "create": 0, "doctype": "DocPerm", @@ -88,6 +89,7 @@ "write": 0 }, { + "amend": 0, "cancel": 1, "create": 1, "doctype": "DocPerm", diff --git a/selling/doctype/sales_bom_item/sales_bom_item.txt b/selling/doctype/sales_bom_item/sales_bom_item.txt index 98285af104..f7906b72d8 100644 --- a/selling/doctype/sales_bom_item/sales_bom_item.txt +++ b/selling/doctype/sales_bom_item/sales_bom_item.txt @@ -1,15 +1,15 @@ [ { - "creation": "2013-02-22 01:28:03", + "creation": "2013-05-23 16:55:51", "docstatus": 0, - "modified": "2013-03-07 07:03:30", + "modified": "2013-06-26 13:45:41", "modified_by": "Administrator", "owner": "Administrator" }, { "doctype": "DocType", "istable": 1, - "module": "Stock", + "module": "Selling", "name": "__common__" }, { diff --git a/selling/report/available_stock_for_packing_items/available_stock_for_packing_items.py b/selling/report/available_stock_for_packing_items/available_stock_for_packing_items.py index d766c4487d..171c3bb8d9 100644 --- a/selling/report/available_stock_for_packing_items/available_stock_for_packing_items.py +++ b/selling/report/available_stock_for_packing_items/available_stock_for_packing_items.py @@ -16,33 +16,33 @@ from __future__ import unicode_literals import webnotes -from webnotes.utils import cint +from webnotes.utils import flt def execute(filters=None): if not filters: filters = {} columns = get_columns() - item_warehouse_quantity_map = get_item_warehouse_quantity_map() + iwq_map = get_item_warehouse_quantity_map() + item_map = get_item_details() - data = [] - for item, warehouse in item_warehouse_quantity_map.items(): - item_details = get_item_details(item)[0] + data = [] + for sbom, warehouse in iwq_map.items(): total = 0 total_qty = 0 + for wh, item_qty in warehouse.items(): total += 1 - row = [item, item_details.item_name, item_details.description, \ - item_details.stock_uom, wh] - for quantity in item_qty.items(): - max_qty = [] - max_qty.append(quantity[1]) - max_qty = min(max_qty) - total_qty += cint(max_qty.qty) - row += [max_qty.qty] - data.append(row) - if (total == len(warehouse)): - row = ["", "", "Total", "", "", total_qty] + row = [sbom, item_map.get(sbom).item_name, item_map.get(sbom).description, + item_map.get(sbom).stock_uom, wh] + available_qty = min(item_qty.values()) + total_qty += flt(available_qty) + row += [available_qty] + + if available_qty: data.append(row) + if (total == len(warehouse)): + row = ["", "", "Total", "", "", total_qty] + data.append(row) return columns, data @@ -52,38 +52,41 @@ def get_columns(): return columns -def get_sales_bom(): - return webnotes.conn.sql("""select name from `tabSales BOM`""", as_dict=1) +def get_sales_bom_items(): + sbom_item_map = {} + for sbom in webnotes.conn.sql("""select parent, item_code, qty from `tabSales BOM Item` + where docstatus < 2""", as_dict=1): + sbom_item_map.setdefault(sbom.parent, {}).setdefault(sbom.item_code, sbom.qty) + + return sbom_item_map -def get_sales_bom_items(item): - return webnotes.conn.sql("""select parent, item_code, qty from `tabSales BOM Item` - where parent=%s""", (item), as_dict=1) +def get_item_details(): + item_map = {} + for item in webnotes.conn.sql("""select name, item_name, description, stock_uom + from `tabItem`""", as_dict=1): + item_map.setdefault(item.name, item) + + return item_map -def get_item_details(item): - return webnotes.conn.sql("""select name, item_name, description, stock_uom - from `tabItem` where name=%s""", (item), as_dict=1) - -def get_item_warehouse_quantity(item): - return webnotes.conn.sql("""select item_code, warehouse, actual_qty from `tabBin` - where item_code=%s""", (item), as_dict=1) +def get_item_warehouse_quantity(): + iwq_map = {} + bin = webnotes.conn.sql("""select item_code, warehouse, actual_qty from `tabBin` + where actual_qty > 0""") + for item, wh, qty in bin: + iwq_map.setdefault(item, {}).setdefault(wh, qty) + + return iwq_map def get_item_warehouse_quantity_map(): - iwq_map = {} + sbom_map = {} + iwq_map = get_item_warehouse_quantity() + sbom_item_map = get_sales_bom_items() + + for sbom, sbom_items in sbom_item_map.items(): + for item, child_qty in sbom_items.items(): + for wh, qty in iwq_map.get(item, {}).items(): + avail_qty = flt(qty) / flt(child_qty) + sbom_map.setdefault(sbom, {}).setdefault(wh, {}) \ + .setdefault(item, avail_qty) - sales_bom = get_sales_bom() - - for item in sales_bom: - child_item = get_sales_bom_items(item.name) - for child in child_item: - item_warehouse_quantity = get_item_warehouse_quantity(child.item_code) - for iwq in item_warehouse_quantity: - iwq_map.setdefault(item.name, {}).setdefault(iwq.warehouse, {}).\ - setdefault(child.item_code, webnotes._dict({ - "qty" : 0 - })) - - q_dict = iwq_map[item.name][iwq.warehouse][child.item_code] - - q_dict.qty = cint(iwq.actual_qty / child.qty) - - return iwq_map \ No newline at end of file + return sbom_map \ No newline at end of file From bd7218979e81f289ffd0ff00612cdb893285a9eb Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Wed, 26 Jun 2013 13:53:01 +0530 Subject: [PATCH 12/13] [shipping rule] added doctypes shipping rule and shipping rule conditions --- .../sales_taxes_and_charges_master.txt | 19 ++- accounts/doctype/shipping_rule/__init__.py | 0 .../doctype/shipping_rule/shipping_rule.py | 25 +++ .../doctype/shipping_rule/shipping_rule.txt | 151 ++++++++++++++++++ .../shipping_rule_condition/__init__.py | 0 .../shipping_rule_condition.py | 8 + .../shipping_rule_condition.txt | 50 ++++++ accounts/page/accounts_home/accounts_home.js | 5 + selling/page/selling_home/selling_home.js | 5 + setup/doctype/price_list/price_list.txt | 9 +- 10 files changed, 254 insertions(+), 18 deletions(-) create mode 100644 accounts/doctype/shipping_rule/__init__.py create mode 100644 accounts/doctype/shipping_rule/shipping_rule.py create mode 100644 accounts/doctype/shipping_rule/shipping_rule.txt create mode 100644 accounts/doctype/shipping_rule_condition/__init__.py create mode 100644 accounts/doctype/shipping_rule_condition/shipping_rule_condition.py create mode 100644 accounts/doctype/shipping_rule_condition/shipping_rule_condition.txt diff --git a/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.txt b/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.txt index 5de944204c..9aa7053661 100644 --- a/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.txt +++ b/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.txt @@ -2,7 +2,7 @@ { "creation": "2013-01-10 16:34:09", "docstatus": 0, - "modified": "2013-06-20 16:49:12", + "modified": "2013-06-25 12:06:45", "modified_by": "Administrator", "owner": "Administrator" }, @@ -30,8 +30,7 @@ "parenttype": "DocType", "permlevel": 0, "read": 1, - "report": 1, - "submit": 0 + "report": 1 }, { "doctype": "DocType", @@ -101,21 +100,20 @@ "create": 0, "doctype": "DocPerm", "role": "Sales User", + "submit": 0, "write": 0 }, + { + "doctype": "DocPerm", + "role": "Accounts User" + }, { "amend": 0, "cancel": 1, "create": 1, "doctype": "DocPerm", "role": "Accounts Manager", - "write": 1 - }, - { - "cancel": 1, - "create": 1, - "doctype": "DocPerm", - "role": "System Manager", + "submit": 0, "write": 1 }, { @@ -124,6 +122,7 @@ "create": 1, "doctype": "DocPerm", "role": "Sales Master Manager", + "submit": 0, "write": 1 } ] \ No newline at end of file diff --git a/accounts/doctype/shipping_rule/__init__.py b/accounts/doctype/shipping_rule/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/accounts/doctype/shipping_rule/shipping_rule.py b/accounts/doctype/shipping_rule/shipping_rule.py new file mode 100644 index 0000000000..5ed4ed38e0 --- /dev/null +++ b/accounts/doctype/shipping_rule/shipping_rule.py @@ -0,0 +1,25 @@ +# For license information, please see license.txt + +from __future__ import unicode_literals +import webnotes +from webnotes import _, msgprint + +class DocType: + def __init__(self, d, dl): + self.doc, self.doclist = d, dl + + def validate(self): + self.validate_to_value_of_shipping_rule_conditions() + self.validate_overlapping_shipping_rule_conditions() + + + def validate_to_value_of_shipping_rule_conditions(self): + """check if more than two or more rows has To Value = 0""" + shipping_rule_conditions_with_0_to_value = self.doclist.get({ + "parentfield": "shipping_rule_conditions", "to_value": ["in", [0, None]]}) + if len(shipping_rule_conditions_with_0_to_value) >= 2: + msgprint(_('''There can only be one shipping rule with 0 or blank value for "To Value"'''), + raise_exception=True) + + def validate_overlapping_shipping_rule_conditions(self): + pass \ No newline at end of file diff --git a/accounts/doctype/shipping_rule/shipping_rule.txt b/accounts/doctype/shipping_rule/shipping_rule.txt new file mode 100644 index 0000000000..dd4fe8dfed --- /dev/null +++ b/accounts/doctype/shipping_rule/shipping_rule.txt @@ -0,0 +1,151 @@ +[ + { + "creation": "2013-06-25 11:48:03", + "docstatus": 0, + "modified": "2013-06-25 12:15:21", + "modified_by": "Administrator", + "owner": "Administrator" + }, + { + "description": "Specify conditions to calculate shipping amount", + "doctype": "DocType", + "module": "Accounts", + "name": "__common__" + }, + { + "doctype": "DocField", + "name": "__common__", + "parent": "Shipping Rule", + "parentfield": "fields", + "parenttype": "DocType", + "permlevel": 0 + }, + { + "doctype": "DocPerm", + "name": "__common__", + "parent": "Shipping Rule", + "parentfield": "permissions", + "parenttype": "DocType", + "permlevel": 0, + "read": 1, + "report": 1 + }, + { + "doctype": "DocType", + "name": "Shipping Rule" + }, + { + "description": "example: Next Day Shipping", + "doctype": "DocField", + "fieldname": "shipping_rule_label", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Shipping Rule Label", + "reqd": 1 + }, + { + "doctype": "DocField", + "fieldname": "column_break_2", + "fieldtype": "Column Break" + }, + { + "default": "Amount", + "doctype": "DocField", + "fieldname": "calculate_based_on", + "fieldtype": "Select", + "in_list_view": 1, + "label": "Calculate Based On", + "options": "Amount\nNet Weight", + "reqd": 1 + }, + { + "doctype": "DocField", + "fieldname": "rule_conditions_section", + "fieldtype": "Section Break", + "label": "Shipping Rule Conditions" + }, + { + "doctype": "DocField", + "fieldname": "shipping_rule_conditions", + "fieldtype": "Table", + "label": "Shipping Rule Conditions", + "options": "Shipping Rule Condition", + "reqd": 1 + }, + { + "doctype": "DocField", + "fieldname": "section_break_6", + "fieldtype": "Section Break" + }, + { + "description": "Specify a list of Territories, for which, this Shipping Rule is valid", + "doctype": "DocField", + "fieldname": "valid_for_territories", + "fieldtype": "Table", + "label": "Valid For Territories", + "options": "For Territory", + "reqd": 1 + }, + { + "doctype": "DocField", + "fieldname": "column_break_8", + "fieldtype": "Column Break" + }, + { + "doctype": "DocField", + "fieldname": "company", + "fieldtype": "Link", + "in_list_view": 0, + "label": "Company", + "options": "Company", + "reqd": 1 + }, + { + "doctype": "DocField", + "fieldname": "section_break_10", + "fieldtype": "Section Break" + }, + { + "doctype": "DocField", + "fieldname": "account", + "fieldtype": "Link", + "label": "Shipping Account", + "options": "Account", + "reqd": 1 + }, + { + "doctype": "DocField", + "fieldname": "column_break_12", + "fieldtype": "Column Break" + }, + { + "doctype": "DocField", + "fieldname": "cost_center", + "fieldtype": "Link", + "label": "Cost Center", + "options": "Cost Center", + "reqd": 1 + }, + { + "doctype": "DocPerm", + "role": "Accounts User" + }, + { + "doctype": "DocPerm", + "role": "Sales User" + }, + { + "cancel": 1, + "create": 1, + "doctype": "DocPerm", + "role": "Accounts Manager", + "write": 1 + }, + { + "cancel": 1, + "create": 1, + "doctype": "DocPerm", + "role": "Sales Master Manager", + "write": 1 + } +] \ No newline at end of file diff --git a/accounts/doctype/shipping_rule_condition/__init__.py b/accounts/doctype/shipping_rule_condition/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/accounts/doctype/shipping_rule_condition/shipping_rule_condition.py b/accounts/doctype/shipping_rule_condition/shipping_rule_condition.py new file mode 100644 index 0000000000..928aa9ff9f --- /dev/null +++ b/accounts/doctype/shipping_rule_condition/shipping_rule_condition.py @@ -0,0 +1,8 @@ +# For license information, please see license.txt + +from __future__ import unicode_literals +import webnotes + +class DocType: + def __init__(self, d, dl): + self.doc, self.doclist = d, dl \ No newline at end of file diff --git a/accounts/doctype/shipping_rule_condition/shipping_rule_condition.txt b/accounts/doctype/shipping_rule_condition/shipping_rule_condition.txt new file mode 100644 index 0000000000..2fe43db24d --- /dev/null +++ b/accounts/doctype/shipping_rule_condition/shipping_rule_condition.txt @@ -0,0 +1,50 @@ +[ + { + "creation": "2013-06-25 11:54:50", + "docstatus": 0, + "modified": "2013-06-25 11:58:04", + "modified_by": "Administrator", + "owner": "Administrator" + }, + { + "description": "A condition for a Shipping Rule", + "doctype": "DocType", + "istable": 1, + "module": "Accounts", + "name": "__common__" + }, + { + "doctype": "DocField", + "name": "__common__", + "parent": "Shipping Rule Condition", + "parentfield": "fields", + "parenttype": "DocType", + "permlevel": 0 + }, + { + "doctype": "DocType", + "name": "Shipping Rule Condition" + }, + { + "doctype": "DocField", + "fieldname": "from_value", + "fieldtype": "Float", + "label": "From Value", + "reqd": 1 + }, + { + "doctype": "DocField", + "fieldname": "to_value", + "fieldtype": "Float", + "label": "To Value", + "reqd": 0 + }, + { + "doctype": "DocField", + "fieldname": "shipping_amount", + "fieldtype": "Currency", + "label": "Shipping Amount", + "options": "Company:company:default_currency", + "reqd": 1 + } +] \ No newline at end of file diff --git a/accounts/page/accounts_home/accounts_home.js b/accounts/page/accounts_home/accounts_home.js index a998818767..f7e476af30 100644 --- a/accounts/page/accounts_home/accounts_home.js +++ b/accounts/page/accounts_home/accounts_home.js @@ -100,6 +100,11 @@ wn.module_page["Accounts"] = [ "doctype":"Purchase Taxes and Charges Master", "description": wn._("Tax Template for Purchase") }, + { + "label": wn._("Shipping Rules"), + "doctype":"Shipping Rule", + "description": wn._("Rules to calculate shipping amount for a sale") + }, { "label": wn._("Point-of-Sale Setting"), "doctype":"POS Setting", diff --git a/selling/page/selling_home/selling_home.js b/selling/page/selling_home/selling_home.js index 73cc7185c8..3b3156d5c8 100644 --- a/selling/page/selling_home/selling_home.js +++ b/selling/page/selling_home/selling_home.js @@ -63,6 +63,11 @@ wn.module_page["Selling"] = [ description: wn._("Sales taxes template."), doctype:"Sales Taxes and Charges Master" }, + { + label: wn._("Shipping Rules"), + description: wn._("Rules to calculate shipping amount for a sale"), + doctype:"Shipping Rule" + }, { label: wn._("Price List"), description: wn._("Mupltiple Item prices."), diff --git a/setup/doctype/price_list/price_list.txt b/setup/doctype/price_list/price_list.txt index 9bc18dc062..5113a3e080 100644 --- a/setup/doctype/price_list/price_list.txt +++ b/setup/doctype/price_list/price_list.txt @@ -2,7 +2,7 @@ { "creation": "2013-01-25 11:35:09", "docstatus": 0, - "modified": "2013-06-20 12:53:10", + "modified": "2013-06-25 12:05:12", "modified_by": "Administrator", "owner": "Administrator" }, @@ -116,13 +116,6 @@ "label": "How to upload", "options": "
Use the Data Import Tool to upload, update Item Prices in bulk:\n
    \n
  1. Go to Data Import Tool.\n
  2. Select \"Item\"\n
  3. Check on \"With Data\"\n
  4. Download \"Item Price\" from Child Tables.\n
  5. Update the prices required and add new rows if required.\n
  6. Check on \"Overwrite\"\n
  7. Upload the modified sheet.\n
\n" }, - { - "cancel": 0, - "create": 0, - "doctype": "DocPerm", - "role": "Sales Manager", - "write": 0 - }, { "cancel": 0, "create": 0, From 922bb1af468d8578d7279bf58bb1bdb5f4fd27aa Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Wed, 26 Jun 2013 17:14:40 +0530 Subject: [PATCH 13/13] [shipping rule] validations and test cases --- .../doctype/shipping_rule/shipping_rule.py | 77 ++++++++++++++++--- .../shipping_rule/test_shipping_rule.py | 66 ++++++++++++++++ 2 files changed, 133 insertions(+), 10 deletions(-) create mode 100644 accounts/doctype/shipping_rule/test_shipping_rule.py diff --git a/accounts/doctype/shipping_rule/shipping_rule.py b/accounts/doctype/shipping_rule/shipping_rule.py index 5ed4ed38e0..87148656df 100644 --- a/accounts/doctype/shipping_rule/shipping_rule.py +++ b/accounts/doctype/shipping_rule/shipping_rule.py @@ -3,23 +3,80 @@ from __future__ import unicode_literals import webnotes from webnotes import _, msgprint +from webnotes.utils import flt, fmt_money +from webnotes.model.controller import DocListController +from setup.utils import get_company_currency -class DocType: +class OverlappingConditionError(webnotes.ValidationError): pass +class FromGreaterThanToError(webnotes.ValidationError): pass +class ManyBlankToValuesError(webnotes.ValidationError): pass + +class DocType(DocListController): def __init__(self, d, dl): self.doc, self.doclist = d, dl def validate(self): - self.validate_to_value_of_shipping_rule_conditions() + self.shipping_rule_conditions = self.doclist.get({"parentfield": "shipping_rule_conditions"}) + self.validate_from_to_values() + self.sort_shipping_rule_conditions() self.validate_overlapping_shipping_rule_conditions() + def validate_from_to_values(self): + zero_to_values = [] - def validate_to_value_of_shipping_rule_conditions(self): - """check if more than two or more rows has To Value = 0""" - shipping_rule_conditions_with_0_to_value = self.doclist.get({ - "parentfield": "shipping_rule_conditions", "to_value": ["in", [0, None]]}) - if len(shipping_rule_conditions_with_0_to_value) >= 2: - msgprint(_('''There can only be one shipping rule with 0 or blank value for "To Value"'''), - raise_exception=True) + for d in self.shipping_rule_conditions: + self.round_floats_in(d) + + # values cannot be negative + self.validate_value("from_value", ">=", 0.0, d) + self.validate_value("to_value", ">=", 0.0, d) + + if d.to_value == 0: + zero_to_values.append(d) + elif d.from_value >= d.to_value: + msgprint(_("Error") + ": " + _("Row") + " # %d: " % d.idx + + _("From Value should be less than To Value"), + raise_exception=FromGreaterThanToError) + + # check if more than two or more rows has To Value = 0 + if len(zero_to_values) >= 2: + msgprint(_('''There can only be one Shipping Rule Condition with 0 or blank value for "To Value"'''), + raise_exception=ManyBlankToValuesError) + def sort_shipping_rule_conditions(self): + """Sort Shipping Rule Conditions based on increasing From Value""" + self.shipping_rules_conditions = sorted(self.shipping_rule_conditions, key=lambda d: flt(d.from_value)) + for i, d in enumerate(self.shipping_rule_conditions): + d.idx = i + 1 + def validate_overlapping_shipping_rule_conditions(self): - pass \ No newline at end of file + def overlap_exists_between((x1, x2), (y1, y2)): + """ + (x1, x2) and (y1, y2) are two ranges + if condition x = 100 to 300 + then condition y can only be like 50 to 99 or 301 to 400 + hence, non-overlapping condition = (x1 <= x2 < y1 <= y2) or (y1 <= y2 < x1 <= x2) + """ + separate = (x1 <= x2 < y1 <= y2) or (y1 <= y2 < x1 <= x2) + return (not separate) + + overlaps = [] + for i in xrange(0, len(self.shipping_rule_conditions)): + for j in xrange(i+1, len(self.shipping_rule_conditions)): + d1, d2 = self.shipping_rule_conditions[i], self.shipping_rule_conditions[j] + if d1.fields != d2.fields: + # in our case, to_value can be zero, hence pass the from_value if so + range_a = (d1.from_value, d1.to_value or d1.from_value) + range_b = (d2.from_value, d2.to_value or d2.from_value) + if overlap_exists_between(range_a, range_b): + overlaps.append([d1, d2]) + + if overlaps: + company_currency = get_company_currency(self.doc.company) + msgprint(_("Error") + ": " + _("Overlapping Conditions found between") + ":") + messages = [] + for d1, d2 in overlaps: + messages.append("%s-%s = %s " % (d1.from_value, d1.to_value, fmt_money(d1.shipping_amount, currency=company_currency)) + + _("and") + " %s-%s = %s" % (d2.from_value, d2.to_value, fmt_money(d2.shipping_amount, currency=company_currency))) + + msgprint("\n".join(messages), raise_exception=OverlappingConditionError) \ No newline at end of file diff --git a/accounts/doctype/shipping_rule/test_shipping_rule.py b/accounts/doctype/shipping_rule/test_shipping_rule.py new file mode 100644 index 0000000000..ff217bc5a7 --- /dev/null +++ b/accounts/doctype/shipping_rule/test_shipping_rule.py @@ -0,0 +1,66 @@ +import webnotes +import unittest +from accounts.doctype.shipping_rule.shipping_rule import FromGreaterThanToError, ManyBlankToValuesError, OverlappingConditionError + +class TestShippingRule(unittest.TestCase): + def test_from_greater_than_to(self): + shipping_rule = webnotes.bean(copy=test_records[0]) + shipping_rule.doclist[1].from_value = 101 + self.assertRaises(FromGreaterThanToError, shipping_rule.insert) + + def test_many_zero_to_values(self): + shipping_rule = webnotes.bean(copy=test_records[0]) + shipping_rule.doclist[1].to_value = 0 + self.assertRaises(ManyBlankToValuesError, shipping_rule.insert) + + def test_overlapping_conditions(self): + for range_a, range_b in [ + ((50, 150), (0, 100)), + ((50, 150), (100, 200)), + ((50, 150), (75, 125)), + ((50, 150), (25, 175)), + ((50, 150), (50, 150)), + ]: + shipping_rule = webnotes.bean(copy=test_records[0]) + shipping_rule.doclist[1].from_value = range_a[0] + shipping_rule.doclist[1].to_value = range_a[1] + shipping_rule.doclist[2].from_value = range_b[0] + shipping_rule.doclist[2].to_value = range_b[1] + self.assertRaises(OverlappingConditionError, shipping_rule.insert) + +test_records = [ + [ + { + "doctype": "Shipping Rule", + "calculate_based_on": "Amount", + "company": "_Test Company", + "account": "_Test Account Shipping Charges - _TC", + "cost_center": "_Test Cost Center - _TC" + }, + { + "doctype": "Shipping Rule Condition", + "parentfield": "shipping_rule_conditions", + "from_value": 0, + "to_value": 100, + "shipping_amount": 50.0 + }, + { + "doctype": "Shipping Rule Condition", + "parentfield": "shipping_rule_conditions", + "from_value": 101, + "to_value": 200, + "shipping_amount": 100.0 + }, + { + "doctype": "Shipping Rule Condition", + "parentfield": "shipping_rule_conditions", + "from_value": 201, + "shipping_amount": 0.0 + }, + { + "doctype": "For Territory", + "parentfield": "valid_for_territories", + "territory": "_Test Territory" + } + ] +] \ No newline at end of file