diff --git a/accounts/page/general_ledger/general_ledger.js b/accounts/page/general_ledger/general_ledger.js index ff72104e08..1f8618f20a 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); } } } @@ -320,13 +319,14 @@ 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(), - function(j, voucher) { + $.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" + voucher + voucher_dict.row.id = "entry_grouped_by_" + voucher out = out.concat(voucher_dict.row); } }); diff --git a/accounts/report/budget_variance_report/budget_variance_report.py b/accounts/report/budget_variance_report/budget_variance_report.py index 99e303bd20..42bc6639ed 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 @@ -147,22 +115,16 @@ def get_costcenter_account_month_map(filters): for month in tdd: cam_map.setdefault(ccd.name, {}).setdefault(ccd.account, {})\ .setdefault(month, webnotes._dict({ - "target": 0.0, "actual": 0.0, "variance": 0.0 + "target": 0.0, "actual": 0.0 })) 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/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) 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 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/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/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 94% rename from stock/doctype/sales_bom/sales_bom.txt rename to selling/doctype/sales_bom/sales_bom.txt index 031f255919..bf8fa479c2 100644 --- a/stock/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/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/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 93% rename from stock/doctype/sales_bom_item/sales_bom_item.txt rename to selling/doctype/sales_bom_item/sales_bom_item.txt index 98285af104..f7906b72d8 100644 --- a/stock/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/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'): diff --git a/selling/page/selling_home/selling_home.js b/selling/page/selling_home/selling_home.js index 91848b52fa..388fa42f84 100644 --- a/selling/page/selling_home/selling_home.js +++ b/selling/page/selling_home/selling_home.js @@ -173,13 +173,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"), @@ -196,6 +194,10 @@ 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", + }, { "label":wn._("Pending SO Items For Purchase Request"), route: "query-report/Pending SO Items For Purchase Request" diff --git a/selling/report/sales_person_target_variance_(item_group_wise)/__init__.py b/selling/report/available_stock_for_packing_items/__init__.py similarity index 100% rename from selling/report/sales_person_target_variance_(item_group_wise)/__init__.py rename to selling/report/available_stock_for_packing_items/__init__.py 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..171c3bb8d9 --- /dev/null +++ b/selling/report/available_stock_for_packing_items/available_stock_for_packing_items.py @@ -0,0 +1,92 @@ +# 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 flt + +def execute(filters=None): + if not filters: filters = {} + + columns = get_columns() + iwq_map = get_item_warehouse_quantity_map() + item_map = get_item_details() + + data = [] + for sbom, warehouse in iwq_map.items(): + total = 0 + total_qty = 0 + + for wh, item_qty in warehouse.items(): + total += 1 + 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 + +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_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_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_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(): + 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) + + return sbom_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 diff --git a/selling/report/territory_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/territory_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 66% 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..ae3819c2cb 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(fiscal_year = filters["fiscal_year"])[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 @@ -149,35 +117,27 @@ def get_salesperson_item_month_map(filters): for month in tdd: sim_map.setdefault(sd.name, {}).setdefault(sd.item_group, {})\ .setdefault(month, webnotes._dict({ - "target": 0.0, "achieved": 0.0, "variance": 0.0 + "target": 0.0, "achieved": 0.0 })) tav_dict = sim_map[sd.name][sd.item_group][month] 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 new file mode 100644 index 0000000000..e69de29bb2 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 77% 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 022d19ecf6..109acbdbe8 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,19 +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(): @@ -40,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 +63,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,41 +72,6 @@ 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_fiscal_year(fiscal_year = filters["fiscal_year"])[1:] - - - 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, @@ -112,7 +79,7 @@ def get_territory_details(filters): 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""", - filters.get("fiscal_year"), as_dict=1) + (filters["fiscal_year"]), as_dict=1) #Get target distribution details of item group def get_target_distribution_details(filters): @@ -121,7 +88,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, \ `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 @@ -155,7 +122,8 @@ def get_territory_item_month_map(filters): for ad in achieved_details: if (filters["target_on"] == "Quantity"): - tav_dict.target = flt(td.target_qty) * (tdd[month]["percentage_allocation"]/100) + 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 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/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": { diff --git a/stock/page/stock_balance/stock_balance.js b/stock/page/stock_balance/stock_balance.js index 4467b98712..4abd533b43 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); } } diff --git a/stock/report/item_prices/item_prices.py b/stock/report/item_prices/item_prices.py index 3bdb746510..fb69086252 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"], precision) ]) 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,25 +90,61 @@ 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, sum(actual_qty*valuation_rate)/sum(actual_qty) as val_rate from tabBin where actual_qty > 0 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, d.val_rate) - return val_rate_map \ No newline at end of file + return item_val_rate_map