[enhancement] stock balance page
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index 99d080a..c534415 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -2,7 +2,7 @@
// License: GNU General Public License v3. See license.txt
frappe.provide("erpnext.accounts");
-{% include 'buying/doctype/purchase_common/purchase_common.js' %};
+{% include 'erpnext/buying/doctype/purchase_common/purchase_common.js' %};
erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.js b/erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.js
index 56a2955..433cda7 100644
--- a/erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.js
+++ b/erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.js
@@ -3,7 +3,7 @@
cur_frm.cscript.tax_table = "Purchase Taxes and Charges";
-{% include "public/js/controllers/accounts.js" %}
+{% include "erpnext/public/js/controllers/accounts.js" %}
frappe.ui.form.on("Purchase Taxes and Charges", "add_deduct_tax", function(doc, cdt, cdn) {
var d = locals[cdt][cdn];
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
index 038d7e6..c3c91a0 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js
@@ -4,7 +4,7 @@
// print heading
cur_frm.pformat.print_heading = 'Invoice';
-{% include 'selling/sales_common.js' %};
+{% include 'erpnext/selling/sales_common.js' %};
frappe.provide("erpnext.accounts");
erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.extend({
diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.js b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.js
index 8828e0c..97a6fdd 100644
--- a/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.js
+++ b/erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.js
@@ -3,5 +3,5 @@
cur_frm.cscript.tax_table = "Sales Taxes and Charges";
-{% include "public/js/controllers/accounts.js" %}
+{% include "erpnext/public/js/controllers/accounts.js" %}
diff --git a/erpnext/buying/doctype/purchase_common/purchase_common.js b/erpnext/buying/doctype/purchase_common/purchase_common.js
index 79eaeeb..b38b90e 100644
--- a/erpnext/buying/doctype/purchase_common/purchase_common.js
+++ b/erpnext/buying/doctype/purchase_common/purchase_common.js
@@ -4,7 +4,7 @@
frappe.provide("erpnext.buying");
cur_frm.cscript.tax_table = "Purchase Taxes and Charges";
-{% include 'accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.js' %}
+{% include 'erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.js' %}
frappe.require("assets/erpnext/js/controllers/transaction.js");
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js
index b6026fd..ddaa5b4 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.js
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.js
@@ -3,7 +3,7 @@
frappe.provide("erpnext.buying");
-{% include 'buying/doctype/purchase_common/purchase_common.js' %};
+{% include 'erpnext/buying/doctype/purchase_common/purchase_common.js' %};
frappe.ui.form.on("Purchase Order", {
onload: function(frm) {
diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
index a072bd7..b8002dd 100644
--- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
+++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
@@ -2,7 +2,7 @@
// License: GNU General Public License v3. See license.txt
-{% include 'buying/doctype/purchase_common/purchase_common.js' %};
+{% include 'erpnext/buying/doctype/purchase_common/purchase_common.js' %};
frappe.require("assets/erpnext/js/utils.js");
diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
index 96d6911..8587a9f 100644
--- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
+++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
@@ -2,7 +2,7 @@
// License: GNU General Public License v3. See license.txt
// attach required files
-{% include 'buying/doctype/purchase_common/purchase_common.js' %};
+{% include 'erpnext/buying/doctype/purchase_common/purchase_common.js' %};
erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.extend({
refresh: function() {
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index 9c287e7..f08cf42 100644
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -86,7 +86,7 @@
$(frm.fields_dict['address_html'].wrapper).html("");
frm.fields_dict['contact_html'] && $(frm.fields_dict['contact_html'].wrapper).html("");
},
-
+
render_address_and_contact: function(frm) {
// render address
$(frm.fields_dict['address_html'].wrapper)
@@ -132,3 +132,22 @@
});
}
});
+
+erpnext.get_item_dashboard_data = function(data, max_count) {
+ if(!max_count) max_count = 0;
+ data.forEach(function(d) {
+ d.actual_or_pending = d.projected_qty + d.reserved_qty + d.reserved_qty_for_production;
+ d.pending_qty = 0;
+ d.total_reserved = d.reserved_qty + d.reserved_qty_for_production;
+ if(d.actual_or_pending > d.actual_qty) {
+ d.pending_qty = d.actual_or_pending - d.actual_qty;
+ }
+
+ max_count = Math.max(d.actual_or_pending, d.actual_qty,
+ d.total_reserved, max_count);
+ });
+ return {
+ data: data,
+ max_count: max_count
+ }
+}
diff --git a/erpnext/selling/doctype/quotation/quotation.js b/erpnext/selling/doctype/quotation/quotation.js
index 7c46983..9e5283c 100644
--- a/erpnext/selling/doctype/quotation/quotation.js
+++ b/erpnext/selling/doctype/quotation/quotation.js
@@ -2,7 +2,7 @@
// License: GNU General Public License v3. See license.txt
-{% include 'selling/sales_common.js' %}
+{% include 'erpnext/selling/sales_common.js' %}
erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
onload: function(doc, dt, dn) {
diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js
index 22800b7..17050ca 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.js
+++ b/erpnext/selling/doctype/sales_order/sales_order.js
@@ -1,7 +1,7 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
-{% include 'selling/sales_common.js' %}
+{% include 'erpnext/selling/sales_common.js' %}
frappe.ui.form.on("Sales Order", {
onload: function(frm) {
diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js
index 607aa41..167024b 100644
--- a/erpnext/selling/sales_common.js
+++ b/erpnext/selling/sales_common.js
@@ -3,7 +3,7 @@
cur_frm.cscript.tax_table = "Sales Taxes and Charges";
-{% include 'accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.js' %}
+{% include 'erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.js' %}
frappe.provide("erpnext.selling");
frappe.require("assets/erpnext/js/controllers/transaction.js");
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js
index 813133d..6d31386 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.js
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.js
@@ -1,7 +1,7 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
-{% include 'selling/sales_common.js' %};
+{% include 'erpnext/selling/sales_common.js' %};
frappe.provide("erpnext.stock");
frappe.provide("erpnext.stock.delivery_note");
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index 092bb31..2cde790 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -84,19 +84,10 @@
dashboard_update: function(frm) {
if(frm.dashboard_data.stock_data && frm.dashboard_data.stock_data.length) {
- var max_count = 0;
- frm.dashboard_data.stock_data.forEach(function(d) {
- d.actual_or_pending = d.projected_qty - d.reserved_qty;
- d.pending_qty = 0;
- if(d.actual_or_pending > d.actual_qty) {
- d.pending_qty = d.actual_or_pending - d.actual_qty;
- }
-
- max_count = Math.max(d.actual_or_pending, d.actual_qty,
- d.reserved_qty, max_count);
- })
- frm.dashboard.add_stats(frappe.render_template('item_dashboard',
- {data: frm.dashboard_data.stock_data, max_count: max_count}));
+ var context = erpnext.get_item_dashboard_data(frm.dashboard_data.stock_data, 0);
+ frm.dashboard.add_section('<h5 style="margin-top: 0px;">Stock Levels</h5>\
+ <ul class="list-group">' + frappe.render_template('item_dashboard', context), true)
+ + '</ul>';
}
},
diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py
index f013f3a..114bbab 100644
--- a/erpnext/stock/doctype/item/item.py
+++ b/erpnext/stock/doctype/item/item.py
@@ -628,7 +628,8 @@
group by posting_date''', name))
def get_stock_data(name):
- return frappe.get_all('Bin', fields=['warehouse', 'actual_qty', 'projected_qty', 'reserved_qty'],
+ return frappe.get_all('Bin', fields=['warehouse', 'actual_qty', 'projected_qty',
+ 'reserved_qty', 'reserved_qty_for_production'],
filters={'item_code': name}, order_by = 'warehouse asc')
def validate_end_of_life(item_code, end_of_life=None, disabled=None, verbose=1):
diff --git a/erpnext/stock/doctype/item/item_dashboard.html b/erpnext/stock/doctype/item/item_dashboard.html
index 3ce6b57..ac78e79 100644
--- a/erpnext/stock/doctype/item/item_dashboard.html
+++ b/erpnext/stock/doctype/item/item_dashboard.html
@@ -1,39 +1,42 @@
-<div>
- <h5 style="margin-top: 0px;">Stock Levels</h5>
- <ul class="list-group" style="margin: 0px;">
- {% for(var i=0; i < data.length; i++) { var d = data[i]; %}
- <li class="list-group-item" style="background-color: inherit;">
- <div class="row">
- <div class="col-sm-8 small" style="margin-top: 8px;">{{ d.warehouse }}</div>
- <div class="col-sm-4 small">
- <span class="inline-graph">
- <span class="inline-graph-half" title="{{ __("Reserved Qty") }}">
- <span class="inline-graph-count">{{ d.reserved_qty }}</span>
- <span class="inline-graph-bar">
- <span class="inline-graph-bar-inner"
- style="width: {{ cint(Math.abs(d.reserved_qty)/max_count * 100) || 5 }}%">
- </span>
- </span>
- </span>
- <span class="inline-graph-half" title="{{ __("Acutal Qty {0} / Waiting Qty {1}", [d.actual_qty, d.pending_qty]) }}">
- <span class="inline-graph-count">
- {{ d.actual_qty }} {{ (d.pending_qty > 0) ? ("(" + d.pending_qty+ ")") : "" }}
- </span>
- <span class="inline-graph-bar">
- <span class="inline-graph-bar-inner dark"
- style="width: {{ cint(d.actual_qty/max_count * 100) }}%">
- </span>
- {% if(d.pending_qty > 0) { %}
- <span class="inline-graph-bar-inner" title="{{ __("Projected Qty") }}"
- style="width: {{ cint(d.pending_qty/max_count * 100) }}%">
- </span>
- {% } %}
+{% for d in data %}
+ <li class="list-group-item" style="background-color: inherit;">
+ <div class="row">
+ <div class="col-sm-4 small" style="margin-top: 8px;">
+ <a data-type="warehouse" data-name="{{ d.warehouse }}">{{ d.warehouse }}</a>
+ </div>
+ <div class="col-sm-4 small" style="margin-top: 8px;">
+ {% if d.item_code %}
+ <a data-type="item"
+ data-name="{{ d.item_code }}">{{ d.item_code }}</a>
+ {% endif %}
+ </div>
+ <div class="col-sm-4 small">
+ <span class="inline-graph">
+ <span class="inline-graph-half" title="{{ __("Reserved Qty") }}">
+ <span class="inline-graph-count">{{ d.total_reserved }}</span>
+ <span class="inline-graph-bar">
+ <span class="inline-graph-bar-inner"
+ style="width: {{ cint(Math.abs(d.total_reserved)/max_count * 100) || 5 }}%">
</span>
</span>
</span>
- </div>
+ <span class="inline-graph-half" title="{{ __("Acutal Qty {0} / Waiting Qty {1}", [d.actual_qty, d.pending_qty]) }}">
+ <span class="inline-graph-count">
+ {{ d.actual_qty }} {{ (d.pending_qty > 0) ? ("(" + d.pending_qty+ ")") : "" }}
+ </span>
+ <span class="inline-graph-bar">
+ <span class="inline-graph-bar-inner dark"
+ style="width: {{ cint(d.actual_qty/max_count * 100) }}%">
+ </span>
+ {% if d.pending_qty > 0 %}
+ <span class="inline-graph-bar-inner" title="{{ __("Projected Qty") }}"
+ style="width: {{ cint(d.pending_qty/max_count * 100) }}%">
+ </span>
+ {% endif %}
+ </span>
+ </span>
+ </span>
</div>
- </li>
- {% } %}
- </ul>
-</div>
\ No newline at end of file
+ </div>
+ </li>
+{% endfor %}
\ No newline at end of file
diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js
index 5efb8e4..a4bae78 100644
--- a/erpnext/stock/doctype/material_request/material_request.js
+++ b/erpnext/stock/doctype/material_request/material_request.js
@@ -1,7 +1,7 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
-{% include 'buying/doctype/purchase_common/purchase_common.js' %};
+{% include 'erpnext/buying/doctype/purchase_common/purchase_common.js' %};
frappe.require("assets/erpnext/js/utils.js");
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
index 9b9581b..a967b5b 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js
@@ -1,7 +1,7 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
-{% include 'buying/doctype/purchase_common/purchase_common.js' %};
+{% include 'erpnext/buying/doctype/purchase_common/purchase_common.js' %};
frappe.provide("erpnext.stock");
diff --git a/erpnext/stock/page/stock_balance/__init__.py b/erpnext/stock/page/stock_balance/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/stock/page/stock_balance/__init__.py
diff --git a/erpnext/stock/page/stock_balance/stock_balance.html b/erpnext/stock/page/stock_balance/stock_balance.html
new file mode 100644
index 0000000..505fc8d
--- /dev/null
+++ b/erpnext/stock/page/stock_balance/stock_balance.html
@@ -0,0 +1,32 @@
+<div class="padding">
+ <div class="row" style="margin-bottom: 15px;">
+ <div class="col-sm-8"></div>
+ <div class="col-sm-4">
+ <button class="btn btn-default btn-xs pull-right btn-order"
+ data-value="desc" style="margin-left: 10px;">
+ <span class="octicon octicon-triangle-down"></span></button>
+ <div class="dropdown pull-right" data-value="actual_qty">
+ <a class="text-muted dropdown-toggle small"
+ data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
+ {{ __("Actual quantity") }}
+ </a>
+ <ul class="dropdown-menu">
+ <li><a class="option" data-value="actual_qty">
+ {{ __("Actual quantity") }}</a></li>
+ <li><a class="option" data-value="reserved_qty">
+ {{ __("Reserved for sale") }}</a></li>
+ <li><a class="option" data-value="reserved_qty_for_production">
+ {{ __("Reserved for manufacturing") }}</a></li>
+ <li><a class="option" data-value="projected_qty">
+ {{ __("Projected quantity") }}</a></li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ <div class="result list-group">
+
+ </div>
+ <div class="more hidden" style="padding-top: 15px;">
+ <a class="btn btn-default btn-xs btn-more">More</a>
+ </div>
+</div>
\ No newline at end of file
diff --git a/erpnext/stock/page/stock_balance/stock_balance.js b/erpnext/stock/page/stock_balance/stock_balance.js
new file mode 100644
index 0000000..4140e91
--- /dev/null
+++ b/erpnext/stock/page/stock_balance/stock_balance.js
@@ -0,0 +1,109 @@
+{% include 'erpnext/stock/doctype/item/item_dashboard.html' %}
+
+frappe.pages['stock-balance'].on_page_load = function(wrapper) {
+ var page = frappe.ui.make_app_page({
+ parent: wrapper,
+ title: 'Stock Balance',
+ single_column: true
+ });
+
+ var warehouse_field = page.add_field({
+ fieldname: 'wareshouse',
+ label: __('Warehouse'),
+ fieldtype:'Link',
+ options:'Warehouse',
+ change: function() {
+ page.start = 0;
+ refresh()
+ }
+ });
+
+ var item_field = page.add_field({
+ fieldname: 'item_code',
+ label: __('Item'),
+ fieldtype:'Link',
+ options:'Item',
+ change: function() {
+ page.start = 0;
+ refresh()
+ }
+ });
+
+ page.start = 0;
+ page.sort_by = 'actual_qty';
+ page.sort_order = 'desc';
+
+ page.content = $(frappe.render_template('stock_balance')).appendTo(page.main);
+ page.result = page.content.find('.result');
+
+ // more
+ page.content.find('.btn-more').on('click', function() {
+ page.start += 20;
+ refresh();
+ });
+
+ // order
+ page.content.find('.btn-order').on('click', function() {
+ var btn = $(this);
+ var order = $(this).attr('data-value')==='desc' ? 'asc' : 'desc';
+
+ btn.attr('data-value', order);
+ page.sort_order = order;
+ btn.find('.octicon')
+ .removeClass('octicon-triangle-' + (order==='asc' ? 'down' : 'up'))
+ .addClass('octicon-triangle-' + (order==='desc' ? 'down' : 'up'));
+ page.start = 0;
+ refresh();
+ });
+
+ // select field
+ page.content.find('.dropdown a.option').on('click', function() {
+ page.sort_by = $(this).attr('data-value');
+ page.content.find('.dropdown .dropdown-toggle').html($(this).html());
+ refresh();
+ });
+
+ var refresh = function() {
+ var item_code = item_field.get_value();
+ var warehouse = warehouse_field.get_value();
+ frappe.call({
+ method: 'erpnext.stock.page.stock_balance.stock_balance.get_data',
+ args: {
+ item_code: item_code,
+ warehouse: warehouse,
+ start: page.start,
+ sort_by: page.sort_by,
+ sort_order: page.sort_order,
+ },
+ callback: function(r) {
+ render(r.message);
+ }
+ });
+ }
+
+ var render = function(data) {
+ if(page.start===0) {
+ page.max_count = 0;
+ page.result.empty();
+ }
+
+ var context = erpnext.get_item_dashboard_data(data, page.max_count);
+ page.max_count = context.max_count;
+
+ // show more button
+ if(data.length===21) {
+ page.content.find('.more').removeClass('hidden');
+
+ // remove the last element
+ data.splice(-1);
+ } else {
+ page.content.find('.more').addClass('hidden');
+ }
+
+ $(frappe.render_template('item_dashboard', context)).appendTo(page.result);
+
+ }
+
+ refresh();
+
+}
\ No newline at end of file
diff --git a/erpnext/stock/page/stock_balance/stock_balance.json b/erpnext/stock/page/stock_balance/stock_balance.json
new file mode 100644
index 0000000..d908875
--- /dev/null
+++ b/erpnext/stock/page/stock_balance/stock_balance.json
@@ -0,0 +1,22 @@
+{
+ "content": null,
+ "creation": "2016-04-21 04:59:00.141546",
+ "docstatus": 0,
+ "doctype": "Page",
+ "idx": 0,
+ "modified": "2016-04-21 05:04:30.228526",
+ "modified_by": "Administrator",
+ "module": "Stock",
+ "name": "stock-balance",
+ "owner": "Administrator",
+ "page_name": "stock-balance",
+ "roles": [
+ {
+ "role": "Stock User"
+ }
+ ],
+ "script": null,
+ "standard": "Yes",
+ "style": null,
+ "title": "Stock Balance"
+}
\ No newline at end of file
diff --git a/erpnext/stock/page/stock_balance/stock_balance.py b/erpnext/stock/page/stock_balance/stock_balance.py
new file mode 100644
index 0000000..1f67401
--- /dev/null
+++ b/erpnext/stock/page/stock_balance/stock_balance.py
@@ -0,0 +1,14 @@
+from __future__ import unicode_literals
+
+import frappe
+
+@frappe.whitelist()
+def get_data(item_code=None, warehouse=None, start=0, sort_by='actual_qty', sort_order='desc'):
+ filters = {}
+ if item_code:
+ filters = {'item_code': item_code }
+ if warehouse:
+ filters = {'warehouse': warehouse }
+ return frappe.get_list("Bin", filters=filters, fields=['item_code', 'warehouse',
+ 'projected_qty', 'reserved_qty', 'reserved_qty_for_production', 'actual_qty'],
+ order_by='{0} {1}'.format(sort_by, sort_order), start=start, page_length = 21)
\ No newline at end of file
diff --git a/erpnext/utilities/doctype/address/address.js b/erpnext/utilities/doctype/address/address.js
index b374293..1e874c3 100644
--- a/erpnext/utilities/doctype/address/address.js
+++ b/erpnext/utilities/doctype/address/address.js
@@ -1,7 +1,7 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
-{% include 'controllers/js/contact_address_common.js' %};
+{% include 'erpnext/controllers/js/contact_address_common.js' %};
frappe.ui.form.on("Address", "validate", function(frm) {
// clear linked customer / supplier / sales partner on saving...
diff --git a/erpnext/utilities/doctype/contact/contact.js b/erpnext/utilities/doctype/contact/contact.js
index 7b64b76..07d9d6f 100644
--- a/erpnext/utilities/doctype/contact/contact.js
+++ b/erpnext/utilities/doctype/contact/contact.js
@@ -1,7 +1,7 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
-{% include 'controllers/js/contact_address_common.js' %};
+{% include 'erpnext/controllers/js/contact_address_common.js' %};
cur_frm.email_field = "email_id";
frappe.ui.form.on("Contact", {