Merge pull request #5197 from KanchanChauhan/UXChanges_ERPNext
[WIP] No not merge
diff --git a/erpnext/__version__.py b/erpnext/__version__.py
index 71066ea..4298574 100644
--- a/erpnext/__version__.py
+++ b/erpnext/__version__.py
@@ -1,2 +1,2 @@
from __future__ import unicode_literals
-__version__ = '6.27.9'
+__version__ = '6.27.10'
diff --git a/erpnext/buying/doctype/supplier/supplier.js b/erpnext/buying/doctype/supplier/supplier.js
index 5088f2e..db8ab02 100644
--- a/erpnext/buying/doctype/supplier/supplier.js
+++ b/erpnext/buying/doctype/supplier/supplier.js
@@ -7,6 +7,8 @@
frappe.setup_language_field(frm);
},
refresh: function(frm) {
+ frm.dashboard.show_heatmap = true;
+ frm.dashboard.heatmap_message = __('This is based on transactions against this Supplier. See timeline below for details');
frm.dashboard.show_dashboard();
if(frappe.defaults.get_default("supp_master_name")!="Naming Series") {
diff --git a/erpnext/config/desktop.py b/erpnext/config/desktop.py
index a3cb5d4..68bf768 100644
--- a/erpnext/config/desktop.py
+++ b/erpnext/config/desktop.py
@@ -28,14 +28,6 @@
"link": "List/Supplier"
},
{
- "module_name": "Income Statement",
- "_doctype": "Account",
- "color": "#3498db",
- "icon": "octicon octicon-repo",
- "type": "link",
- "link": "query-report/Profit and Loss Statement"
- },
- {
"_doctype": "Employee",
"module_name": "Employee",
"color": "#2ecc71",
@@ -67,6 +59,14 @@
"type": "link",
"link": "List/Lead"
},
+ {
+ "module_name": "Profit and Loss Statment",
+ "_doctype": "Account",
+ "color": "#3498db",
+ "icon": "octicon octicon-repo",
+ "type": "link",
+ "link": "query-report/Profit and Loss Statement"
+ },
# old
{
diff --git a/erpnext/crm/doctype/lead/lead.json b/erpnext/crm/doctype/lead/lead.json
index ecca722..7cd9d60 100644
--- a/erpnext/crm/doctype/lead/lead.json
+++ b/erpnext/crm/doctype/lead/lead.json
@@ -205,7 +205,7 @@
"in_list_view": 0,
"label": "Source",
"length": 0,
- "no_copy": 1,
+ "no_copy": 0,
"oldfieldname": "source",
"oldfieldtype": "Select",
"options": "\nAdvertisement\nBlog Post\nCampaign\nCall\nCustomer\nExhibition\nSupplier\nWebsite\nEmail",
@@ -909,7 +909,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2016-04-04 07:23:47.804915",
+ "modified": "2016-04-20 11:01:14.179325",
"modified_by": "Administrator",
"module": "CRM",
"name": "Lead",
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index be19aff..0baf604 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -7,7 +7,7 @@
app_description = """ERP made simple"""
app_icon = "icon-th"
app_color = "#e74c3c"
-app_version = "6.27.9"
+app_version = "6.27.10"
app_email = "info@erpnext.com"
app_license = "GNU General Public License (v3)"
source_link = "https://github.com/frappe/erpnext"
diff --git a/erpnext/hr/doctype/employee/employee.js b/erpnext/hr/doctype/employee/employee.js
index cb26154..a7198e3 100755
--- a/erpnext/hr/doctype/employee/employee.js
+++ b/erpnext/hr/doctype/employee/employee.js
@@ -25,6 +25,8 @@
refresh: function() {
var me = this;
erpnext.toggle_naming_series();
+ this.frm.dashboard.show_heatmap = true;
+ this.frm.dashboard.heatmap_message = __('This is based on the attendance of this Employee');
this.frm.dashboard.show_dashboard();
},
diff --git a/erpnext/manufacturing/doctype/production_order/production_order_list.js b/erpnext/manufacturing/doctype/production_order/production_order_list.js
index f08158c..cce56cf 100644
--- a/erpnext/manufacturing/doctype/production_order/production_order_list.js
+++ b/erpnext/manufacturing/doctype/production_order/production_order_list.js
@@ -9,6 +9,7 @@
return [__(doc.status), {
"Draft": "red",
"Stopped": "red",
+ "Not Started": "red",
"In Process": "orange",
"Completed": "green",
"Cancelled": "darkgrey"
diff --git a/erpnext/projects/doctype/project/project.js b/erpnext/projects/doctype/project/project.js
index e4ac864..6f0da36 100644
--- a/erpnext/projects/doctype/project/project.js
+++ b/erpnext/projects/doctype/project/project.js
@@ -3,6 +3,8 @@
frappe.ui.form.on("Project", {
onload: function(frm) {
+ frm.hide_first = true;
+
var so = frappe.meta.get_docfield("Project", "sales_order");
so.get_route_options_for_new_doc = function(field) {
if(frm.is_new()) return;
@@ -40,26 +42,23 @@
frappe.route_options = {"project": frm.doc.name,
"start": frm.doc.expected_start_date, "end": frm.doc.expected_end_date};
frappe.set_route("Gantt", "Task");
- }, __("View"), true);
- frm.add_custom_button(__("Tasks"), function() {
- frappe.route_options = {"project": frm.doc.name}
- frappe.set_route("List", "Task");
- }, __("View"), true);
+ });
}
- if(frappe.model.can_read("Time Log")) {
- frm.add_custom_button(__("Time Logs"), function() {
- frappe.route_options = {"project": frm.doc.name}
- frappe.set_route("List", "Time Log");
- }, __("View"), true);
- }
+ frm.dashboard.show_dashboard();
+ frm.dashboard.add_section(frappe.render_template('project_dashboard', {project: frm.doc}));
- if(frappe.model.can_read("Expense Claim")) {
- frm.add_custom_button(__("Expense Claims"), function() {
- frappe.route_options = {"project": frm.doc.name}
- frappe.set_route("List", "Expense Claim");
- }, __("View"), true);
- }
+ // var bars = [];
+ // bars.push({
+ // 'title': __('Percent Complete'),
+ // 'width': (frm.doc.percent_complete || 1) + '%',
+ // 'progress_class': 'progress-bar-success'
+ // })
+ //
+ // var message = __("{0}% complete", [frm.doc.percent_complete]);
+ //
+ // frm.dashboard.add_progress(__('Status'), bars, message);
+
}
}
diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py
index ffeedd6..2cca7e2 100644
--- a/erpnext/projects/doctype/project/project.py
+++ b/erpnext/projects/doctype/project/project.py
@@ -26,6 +26,8 @@
"task_id": task.name
})
+ self.set_onload('links', self.meta.get_links_setup())
+
def __setup__(self):
self.onload()
@@ -144,6 +146,16 @@
user.welcome_email_sent=1
+@frappe.whitelist()
+def get_dashboard_data(name):
+ '''load dashboard related data'''
+ frappe.has_permission(doc=frappe.get_doc('Project', name), throw=True)
+
+ from frappe.desk.notifications import get_open_count
+ return {
+ 'count': get_open_count('Project', name),
+ }
+
def get_project_list(doctype, txt, filters, limit_start, limit_page_length=20):
return frappe.db.sql('''select distinct project.*
from tabProject project, `tabProject User` project_user
diff --git a/erpnext/projects/doctype/project/project_dashboard.html b/erpnext/projects/doctype/project/project_dashboard.html
new file mode 100644
index 0000000..efd6861
--- /dev/null
+++ b/erpnext/projects/doctype/project/project_dashboard.html
@@ -0,0 +1,10 @@
+<h5 style="margin-top: 0px;">Tasks</h5>
+{% if(project.tasks.length) { %}
+ {% project.tasks.forEach(function(d) { %}
+ <p><span class="indicator {{
+ {"Open": "red", "Closed": "green", "Cancelled": "darkgrey"}[d.status] || "orange" }}"><a style="font-weight: normal"
+ href="#Form/Task/{{ d.task_id }}">{{ d.title }}</a></span></p>
+ {% }); %}
+{% } else { %}
+ <p class="text-muted small">No Tasks Defined</p>
+{% } %}
\ No newline at end of file
diff --git a/erpnext/projects/doctype/project/project_links.py b/erpnext/projects/doctype/project/project_links.py
new file mode 100644
index 0000000..6c16378
--- /dev/null
+++ b/erpnext/projects/doctype/project/project_links.py
@@ -0,0 +1,23 @@
+from frappe import _
+
+links = {
+ 'fieldname': 'project',
+ 'transactions': [
+ {
+ 'label': _('Project'),
+ 'items': ['Task', 'Time Log', 'Expense Claim', 'Issue']
+ },
+ {
+ 'label': _('Material'),
+ 'items': ['Material Request', 'BOM', 'Stock Entry']
+ },
+ {
+ 'label': _('Sales'),
+ 'items': ['Sales Order', 'Delivery Note', 'Sales Invoice']
+ },
+ {
+ 'label': _('Purchase'),
+ 'items': ['Purchase Order', 'Purchase Receipt', 'Purchase Invoice']
+ },
+ ]
+}
diff --git a/erpnext/projects/doctype/task/task.js b/erpnext/projects/doctype/task/task.js
index a0bbe26..605ed8d 100644
--- a/erpnext/projects/doctype/task/task.js
+++ b/erpnext/projects/doctype/task/task.js
@@ -34,12 +34,12 @@
frm.add_custom_button(__("Close"), function() {
frm.set_value("status", "Closed");
frm.save();
- }, __("Status"));
+ });
} else {
frm.add_custom_button(__("Reopen"), function() {
frm.set_value("status", "Open");
frm.save();
- }, __("Status"));
+ });
}
}
}
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index 15c98f4..392f140 100644
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -101,6 +101,11 @@
task.exp_end_date = add_days(task.exp_start_date, task_duration)
task.flags.ignore_recursion_check = True
task.save()
+
+ def has_webform_permission(doc):
+ project_user = frappe.db.get_value("Project User", {"parent": doc.project, "user":frappe.session.user} , "user")
+ if project_user:
+ return True
@frappe.whitelist()
def get_events(start, end, filters=None):
@@ -134,7 +139,7 @@
order by name
limit %(start)s, %(page_len)s """ % {'key': searchfield,
'txt': "%%%s%%" % frappe.db.escape(txt), 'mcond':get_match_cond(doctype),
- 'start': start, 'page_len': page_len})
+ 'start': start, 'page_len': page_len})
@frappe.whitelist()
@@ -150,3 +155,6 @@
where exp_end_date is not null
and exp_end_date < CURDATE()
and `status` not in ('Closed', 'Cancelled')""")
+
+
+
diff --git a/erpnext/projects/doctype/time_log/time_log.py b/erpnext/projects/doctype/time_log/time_log.py
index 1d523d9..e2641eb 100644
--- a/erpnext/projects/doctype/time_log/time_log.py
+++ b/erpnext/projects/doctype/time_log/time_log.py
@@ -247,6 +247,11 @@
elif self.project:
frappe.get_doc("Project", self.project).update_project()
+
+ def has_webform_permission(doc):
+ project_user = frappe.db.get_value("Project User", {"parent": doc.project, "user":frappe.session.user} , "user")
+ if project_user:
+ return True
@frappe.whitelist()
diff --git a/erpnext/projects/report/daily_time_log_summary/daily_time_log_summary.py b/erpnext/projects/report/daily_time_log_summary/daily_time_log_summary.py
index 74436a3..028fd77 100644
--- a/erpnext/projects/report/daily_time_log_summary/daily_time_log_summary.py
+++ b/erpnext/projects/report/daily_time_log_summary/daily_time_log_summary.py
@@ -18,6 +18,7 @@
_("Task Subject") + "::180", _("Project") + ":Link/Project:120", _("Status") + "::70"]
user_map = get_user_map()
+ employee_map = get_employee_map()
task_map = get_task_map()
conditions = build_conditions(filters)
@@ -30,12 +31,16 @@
data = []
total_hours = total_employee_hours = count = 0
for tl in time_logs:
+ if tl.employee:
+ employee=employee_map[tl.employee]
+ else:
+ employee=user_map[tl.owner]
if tl.owner not in users:
users.append(tl.owner)
data.append(["", "", "", "Total", total_employee_hours, "", "", "", "", ""])
total_employee_hours = 0
- data.append([tl.name, user_map[tl.owner], tl.from_time, tl.to_time, tl.hours,
+ data.append([tl.name, employee, tl.from_time, tl.to_time, tl.hours,
tl.activity_type, tl.task, task_map.get(tl.task), tl.project, tl.status])
count += 1
@@ -59,6 +64,16 @@
user_map.setdefault(p.name, []).append(p.fullname)
return user_map
+
+def get_employee_map():
+ employees = frappe.db.sql("""select name,
+ employee_name as fullname
+ from tabEmployee""", as_dict=1)
+ employee_map = {}
+ for p in employees:
+ employee_map.setdefault(p.name, []).append(p.fullname)
+
+ return employee_map
def get_task_map():
tasks = frappe.db.sql("""select name, subject from tabTask""", as_dict=1)
diff --git a/erpnext/selling/doctype/customer/customer.js b/erpnext/selling/doctype/customer/customer.js
index d30924e..5645280 100644
--- a/erpnext/selling/doctype/customer/customer.js
+++ b/erpnext/selling/doctype/customer/customer.js
@@ -7,6 +7,8 @@
frappe.setup_language_field(frm);
},
refresh: function(frm) {
+ frm.dashboard.show_heatmap = true;
+ frm.dashboard.heatmap_message = __('This is based on transactions against this Customer. See timeline below for details');
frm.dashboard.show_dashboard();
if(frappe.defaults.get_default("cust_master_name")!="Naming Series") {
diff --git a/erpnext/selling/doctype/customer/customer_links.py b/erpnext/selling/doctype/customer/customer_links.py
index 3ae139b..32bedde 100644
--- a/erpnext/selling/doctype/customer/customer_links.py
+++ b/erpnext/selling/doctype/customer/customer_links.py
@@ -12,6 +12,10 @@
'items': ['Sales Order', 'Delivery Note', 'Sales Invoice']
},
{
+ 'label': _('Support'),
+ 'items': ['Issue']
+ },
+ {
'label': _('Projects'),
'items': ['Project']
}
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index 4a4de4c..092bb31 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -76,6 +76,9 @@
erpnext.item.toggle_attributes(frm);
+ frm.dashboard.show_heatmap = frm.doc.is_stock_item;
+ frm.dashboard.heatmap_message = __('This is based on stock movement. See {0} for details',
+ ['<a href="#query-report/Stock Ledger">' + __('Stock Ledger') + '</a>']);
frm.dashboard.show_dashboard();
},
diff --git a/erpnext/stock/doctype/item/item_dashboard.html b/erpnext/stock/doctype/item/item_dashboard.html
index cef209a..3ce6b57 100644
--- a/erpnext/stock/doctype/item/item_dashboard.html
+++ b/erpnext/stock/doctype/item/item_dashboard.html
@@ -1,6 +1,6 @@
-<div style="padding-left: 15px; padding-right: 15px;">
- <h5>Stock Levels</h5>
- <ul class="list-group">
+<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">
diff --git a/erpnext/templates/pages/projects.py b/erpnext/templates/pages/projects.py
index 06c43bb..f10b2fb 100644
--- a/erpnext/templates/pages/projects.py
+++ b/erpnext/templates/pages/projects.py
@@ -6,6 +6,10 @@
import json
def get_context(context):
+ project_user = frappe.db.get_value("Project User", {"parent": frappe.form_dict.project, "user": frappe.session.user} , "user")
+ if not project_user or frappe.session.user == 'Guest':
+ raise frappe.PermissionError
+
context.no_cache = 1
context.show_search = True
context.show_sidebar = True
diff --git a/setup.py b/setup.py
index 4b31d06..cf95371 100644
--- a/setup.py
+++ b/setup.py
@@ -1,7 +1,7 @@
from setuptools import setup, find_packages
from pip.req import parse_requirements
-version = "6.27.9"
+version = "6.27.10"
requirements = parse_requirements("requirements.txt", session="")
setup(