diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 1ae0a952a76..03919bc647c 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -74,3 +74,4 @@ execute:frappe.delete_doc("Page", "trial-balance") #2014-07-22
erpnext.patches.v4_2.delete_old_print_formats #2014-07-29
erpnext.patches.v4_2.toggle_rounded_total #2014-07-30
erpnext.patches.v4_2.fix_account_master_type
+erpnext.patches.v4_2.update_project_milestones
diff --git a/erpnext/patches/v4_2/update_project_milestones.py b/erpnext/patches/v4_2/update_project_milestones.py
new file mode 100644
index 00000000000..24a520ecd17
--- /dev/null
+++ b/erpnext/patches/v4_2/update_project_milestones.py
@@ -0,0 +1,7 @@
+import frappe
+
+def execute():
+ for project in frappe.db.sql_list("select name from tabProject"):
+ p = frappe.get_doc("Project", project)
+ p.update_milestones_completed()
+ p.db_set("percent_milestones_completed", p.percent_milestones_completed)
diff --git a/erpnext/projects/doctype/project/project.js b/erpnext/projects/doctype/project/project.js
index 5d899865968..9b2c6d07eb2 100644
--- a/erpnext/projects/doctype/project/project.js
+++ b/erpnext/projects/doctype/project/project.js
@@ -4,7 +4,7 @@
// show tasks
cur_frm.cscript.refresh = function(doc) {
if(!doc.__islocal) {
- cur_frm.appframe.add_button(__("Gantt Chart"), function() {
+ cur_frm.add_custom_button(__("Gantt Chart"), function() {
frappe.route_options = {"project": doc.name}
frappe.set_route("Gantt", "Task");
}, "icon-tasks");
@@ -19,4 +19,4 @@ cur_frm.fields_dict.customer.get_query = function(doc,cdt,cdn) {
return{
query: "erpnext.controllers.queries.customer_query"
}
-}
\ No newline at end of file
+}
diff --git a/erpnext/projects/doctype/project/project.json b/erpnext/projects/doctype/project/project.json
index c894bb8b26b..b20914cdc12 100644
--- a/erpnext/projects/doctype/project/project.json
+++ b/erpnext/projects/doctype/project/project.json
@@ -136,6 +136,13 @@
"permlevel": 0,
"search_index": 0
},
+ {
+ "fieldname": "percent_milestones_completed",
+ "fieldtype": "Percent",
+ "label": "% Milestones Completed",
+ "permlevel": 0,
+ "read_only": 1
+ },
{
"fieldname": "section_break0",
"fieldtype": "Section Break",
@@ -158,7 +165,7 @@
"fieldname": "percent_complete",
"fieldtype": "Percent",
"in_list_view": 1,
- "label": "Percent Complete",
+ "label": "% Tasks Completed",
"permlevel": 0,
"read_only": 1
},
@@ -259,7 +266,7 @@
"icon": "icon-puzzle-piece",
"idx": 1,
"max_attachments": 4,
- "modified": "2014-06-24 12:44:19.530707",
+ "modified": "2014-08-04 03:22:11.416219",
"modified_by": "Administrator",
"module": "Projects",
"name": "Project",
diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py
index 4a14c55c3ae..547e12aebc5 100644
--- a/erpnext/projects/doctype/project/project.py
+++ b/erpnext/projects/doctype/project/project.py
@@ -26,6 +26,13 @@ class Project(Document):
if getdate(self.completion_date) < getdate(self.project_start_date):
frappe.throw(_("Expected Completion Date can not be less than Project Start Date"))
+ self.update_milestones_completed()
+
+ def update_milestones_completed(self):
+ if self.project_milestones:
+ completed = filter(lambda x: x.status=="Completed", self.project_milestones)
+ self.percent_milestones_completed = len(completed) * 100 / len(self.project_milestones)
+
def on_update(self):
self.add_calendar_event()
@@ -38,6 +45,7 @@ class Project(Document):
frappe.db.set_value("Project", self.name, "percent_complete",
int(float(completed) / total * 100))
+
def add_calendar_event(self):
# delete any earlier event for this project
delete_events(self.doctype, self.name)
diff --git a/erpnext/projects/doctype/project/project_list.html b/erpnext/projects/doctype/project/project_list.html
new file mode 100644
index 00000000000..42af477561f
--- /dev/null
+++ b/erpnext/projects/doctype/project/project_list.html
@@ -0,0 +1,38 @@
+
+
+
+ {%= list.get_avatar_and_id(doc) %}
+
+ {%= doc.status %}
+
+
+ {%= doc.priority %}
+
+ {% if(doc.status==="Open" && doc.completion_date
+ && frappe.datetime.get_diff(doc.completion_date) <= 0) { %}
+
+ {%= __("Overdue") %}
+
+ {% } else if(doc.completion_date) { %}
+
+ {%= doc.get_formatted("completion_date") %}
+
+ {% } %}
+
+
+
+ {% var completed = doc.percent_complete, title = __("% Tasks Completed") %}
+ {% include "templates/form_grid/includes/progress.html" %}
+
+
+ {% var completed = doc.percent_milestones_completed,
+ title = __("% Milestones Achieved") %}
+ {% include "templates/form_grid/includes/progress.html" %}
+
+
diff --git a/erpnext/projects/doctype/project/project_list.js b/erpnext/projects/doctype/project/project_list.js
new file mode 100644
index 00000000000..dd0ac609582
--- /dev/null
+++ b/erpnext/projects/doctype/project/project_list.js
@@ -0,0 +1,5 @@
+frappe.listview_settings['Project'] = {
+ add_fields: ["status", "priority", "is_active", "percent_complete",
+ "percent_milestones_completed", "completion_date"],
+ filters:[["status","=", "Open"]]
+};
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index 6b0b237a402..7ca502d91e6 100644
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -62,8 +62,10 @@ def get_events(start, end, filters=None):
data = frappe.db.sql("""select name, exp_start_date, exp_end_date,
subject, status, project from `tabTask`
- where ((exp_start_date between '%(start)s' and '%(end)s') \
- or (exp_end_date between '%(start)s' and '%(end)s'))
+ where ((ifnull(exp_start_date, '0000-00-00')!= '0000-00-00') \
+ and (exp_start_date between '%(start)s' and '%(end)s') \
+ or ((ifnull(exp_start_date, '0000-00-00')!= '0000-00-00') \
+ and exp_end_date between '%(start)s' and '%(end)s'))
%(conditions)s""" % {
"start": start,
"end": end,
diff --git a/erpnext/projects/doctype/task/task_list.html b/erpnext/projects/doctype/task/task_list.html
new file mode 100644
index 00000000000..0d95055b41d
--- /dev/null
+++ b/erpnext/projects/doctype/task/task_list.html
@@ -0,0 +1,34 @@
+
+
+
+ {%= list.get_avatar_and_id(doc) %}
+ {% if(doc.project) { %}
+
+ {%= doc.project %}
+ {% } %}
+
+ {%= doc.status %}
+
+
+ {%= doc.priority %}
+
+ {% if(doc.status==="Open" && doc.exp_end_date
+ && frappe.datetime.get_diff(doc.exp_end_date) <= 0) { %}
+
+ {%= __("Overdue") %}
+
+ {% } else if(doc.exp_end_date) { %}
+
+ {%= doc.get_formatted("exp_end_date") %}
+
+ {% } %}
+
+
+
diff --git a/erpnext/projects/doctype/task/task_list.js b/erpnext/projects/doctype/task/task_list.js
new file mode 100644
index 00000000000..4406085e698
--- /dev/null
+++ b/erpnext/projects/doctype/task/task_list.js
@@ -0,0 +1,4 @@
+frappe.listview_settings['Task'] = {
+ add_fields: ["project", "status", "priority", "exp_end_date"],
+ filters:[["status","=", "Open"]]
+};
diff --git a/erpnext/projects/doctype/time_log/time_log.js b/erpnext/projects/doctype/time_log/time_log.js
index eb5fc0993be..d4d109d6f95 100644
--- a/erpnext/projects/doctype/time_log/time_log.js
+++ b/erpnext/projects/doctype/time_log/time_log.js
@@ -3,12 +3,27 @@
frappe.provide("erpnext.projects");
-erpnext.projects.TimeLog = frappe.ui.form.Controller.extend({
- onload: function() {
- this.frm.set_query("task", erpnext.queries.task);
- }
+frappe.ui.form.on("Time Log", "onload", function(frm) {
+ frm.set_query("task", erpnext.queries.task);
});
-cur_frm.cscript = new erpnext.projects.TimeLog({frm: cur_frm});
+// set to time if hours is updated
+frappe.ui.form.on("Time Log", "hours", function(frm) {
+ if(!frm.doc.from_time) {
+ frm.set_value("from_time", frappe.datetime.now_datetime());
+ }
+ var d = moment(frm.doc.from_time);
+ d.add(frm.doc.hours, "hours");
+ frm._setting_hours = true;
+ frm.set_value("to_time", d.format(moment.defaultDatetimeFormat));
+ frm._setting_hours = false;
+});
-cur_frm.add_fetch('task','project','project');
\ No newline at end of file
+// set hours if to_time is updated
+frappe.ui.form.on("Time Log", "to_time", function(frm) {
+ if(frm._setting_hours) return;
+ frm.set_value("hours", moment(cur_frm.doc.to_time).diff(moment(cur_frm.doc.from_time),
+ "hours"));
+});
+
+cur_frm.add_fetch('task','project','project');
diff --git a/erpnext/projects/doctype/time_log/time_log.json b/erpnext/projects/doctype/time_log/time_log.json
index daeddbaa3b1..157be0cdd48 100644
--- a/erpnext/projects/doctype/time_log/time_log.json
+++ b/erpnext/projects/doctype/time_log/time_log.json
@@ -26,6 +26,14 @@
"read_only": 0,
"reqd": 1
},
+ {
+ "fieldname": "hours",
+ "fieldtype": "Float",
+ "in_list_view": 1,
+ "label": "Hours",
+ "permlevel": 0,
+ "read_only": 0
+ },
{
"fieldname": "to_time",
"fieldtype": "Datetime",
@@ -35,14 +43,6 @@
"read_only": 0,
"reqd": 1
},
- {
- "fieldname": "hours",
- "fieldtype": "Float",
- "in_list_view": 1,
- "label": "Hours",
- "permlevel": 0,
- "read_only": 1
- },
{
"fieldname": "column_break_3",
"fieldtype": "Column Break",
@@ -152,7 +152,7 @@
"icon": "icon-time",
"idx": 1,
"is_submittable": 1,
- "modified": "2014-05-27 03:49:21.143356",
+ "modified": "2014-08-04 05:23:15.740050",
"modified_by": "Administrator",
"module": "Projects",
"name": "Time Log",
diff --git a/erpnext/projects/doctype/time_log/time_log_list.html b/erpnext/projects/doctype/time_log/time_log_list.html
new file mode 100644
index 00000000000..ee0b96f28cf
--- /dev/null
+++ b/erpnext/projects/doctype/time_log/time_log_list.html
@@ -0,0 +1,25 @@
+
+
+
+ {%= list.get_avatar_and_id(doc) %}
+ {% if(doc.billable) { %}
+
+
+
+ {% } %}
+
+ {%= doc.activity_type %}
+
+ ({%= doc.hours + " " + __("hours") %})
+
+ {% if(doc.project) { %}
+
+ {%= doc.project %}
+ {% } %}
+
+
+
diff --git a/erpnext/projects/doctype/time_log/time_log_list.js b/erpnext/projects/doctype/time_log/time_log_list.js
index a40297fcd9c..664117484d0 100644
--- a/erpnext/projects/doctype/time_log/time_log_list.js
+++ b/erpnext/projects/doctype/time_log/time_log_list.js
@@ -3,10 +3,10 @@
// render
frappe.listview_settings['Time Log'] = {
- add_fields: ["`tabTime Log`.`status`", "`tabTime Log`.`billable`", "`tabTime Log`.`activity_type`"],
+ add_fields: ["status", "billable", "activity_type", "task", "project", "hours"],
selectable: true,
onload: function(me) {
- me.appframe.add_button(__("Make Time Log Batch"), function() {
+ me.appframe.add_primary_action(__("Make Time Log Batch"), function() {
var selected = me.get_checked_items() || [];
if(!selected.length) {
diff --git a/erpnext/projects/doctype/time_log_batch/time_log_batch_list.html b/erpnext/projects/doctype/time_log_batch/time_log_batch_list.html
new file mode 100644
index 00000000000..4a34f1cdb85
--- /dev/null
+++ b/erpnext/projects/doctype/time_log_batch/time_log_batch_list.html
@@ -0,0 +1,15 @@
+
+
+
+ {%= list.get_avatar_and_id(doc) %}
+
+ {%= doc.status %}
+
+ ({%= doc.total_hours + " " + __("hours") %})
+
+
+
+
diff --git a/erpnext/projects/doctype/time_log_batch/time_log_batch_list.js b/erpnext/projects/doctype/time_log_batch/time_log_batch_list.js
new file mode 100644
index 00000000000..a0825a2709d
--- /dev/null
+++ b/erpnext/projects/doctype/time_log_batch/time_log_batch_list.js
@@ -0,0 +1,4 @@
+frappe.listview_settings['Time Log Batch'] = {
+ add_fields: ["status", "total_hours", "rate"],
+ filters:[["status","in", "Draft,Submitted"]]
+};
diff --git a/erpnext/selling/doctype/quotation/quotation_list.js b/erpnext/selling/doctype/quotation/quotation_list.js
index bbc264d033f..91b65eeb9fb 100644
--- a/erpnext/selling/doctype/quotation/quotation_list.js
+++ b/erpnext/selling/doctype/quotation/quotation_list.js
@@ -1,4 +1,5 @@
frappe.listview_settings['Quotation'] = {
add_fields: ["customer_name", "quotation_to", "grand_total", "status",
- "company", "currency", "order_type", "lead", "customer"]
+ "company", "currency", "order_type", "lead", "customer"],
+ filters: [["status", "=", "Submitted"]]
};
diff --git a/erpnext/selling/doctype/sales_order/sales_order_list.js b/erpnext/selling/doctype/sales_order/sales_order_list.js
index a801cb93164..3884526e723 100644
--- a/erpnext/selling/doctype/sales_order/sales_order_list.js
+++ b/erpnext/selling/doctype/sales_order/sales_order_list.js
@@ -1,5 +1,5 @@
frappe.listview_settings['Sales Order'] = {
add_fields: ["grand_total", "company", "currency", "customer",
"customer_name", "per_delivered", "per_billed", "delivery_date"],
- filters: [["per_delivered", "<", "100"]]
+ filters: [["per_delivered", "<", 100]]
};
diff --git a/erpnext/stock/doctype/batch/batch_list.html b/erpnext/stock/doctype/batch/batch_list.html
new file mode 100644
index 00000000000..dc29905dcaa
--- /dev/null
+++ b/erpnext/stock/doctype/batch/batch_list.html
@@ -0,0 +1,21 @@
+
+
+
+ {%= list.get_avatar_and_id(doc) %}
+
+ {%= doc.item %}
+ {% if(doc.expiry_date && frappe.datetime.get_diff(doc.expiry_date) <= 0) { %}
+
+ {%= __("Expired") %}: {%= doc.get_formatted("expiry_date") %}
+
+ {% } else if(doc.expiry_date) { %}
+
+ {%= __("Expiry") %}: {%= doc.get_formatted("expiry_date") %}
+
+ {% } %}
+
+
+
diff --git a/erpnext/stock/doctype/batch/batch_list.js b/erpnext/stock/doctype/batch/batch_list.js
new file mode 100644
index 00000000000..daeb69bfa46
--- /dev/null
+++ b/erpnext/stock/doctype/batch/batch_list.js
@@ -0,0 +1,3 @@
+frappe.listview_settings['Batch'] = {
+ add_fields: ["item", "expiry_date"]
+};
diff --git a/erpnext/stock/doctype/material_request/material_request_list.js b/erpnext/stock/doctype/material_request/material_request_list.js
index 2a85dcc8148..989ca60707b 100644
--- a/erpnext/stock/doctype/material_request/material_request_list.js
+++ b/erpnext/stock/doctype/material_request/material_request_list.js
@@ -1,3 +1,4 @@
frappe.listview_settings['Material Request'] = {
- add_fields: ["material_request_type", "status", "per_ordered"]
+ add_fields: ["material_request_type", "status", "per_ordered"],
+ filters: [["per_ordered", "<", 100]]
};
diff --git a/erpnext/stock/doctype/serial_no/serial_no_list.html b/erpnext/stock/doctype/serial_no/serial_no_list.html
new file mode 100644
index 00000000000..d53aab1906a
--- /dev/null
+++ b/erpnext/stock/doctype/serial_no/serial_no_list.html
@@ -0,0 +1,28 @@
+
+
+
+ {%= list.get_avatar_and_id(doc) %}
+
+ {%= doc.item_code %}
+ {% var icon = {
+ "Available": ["icon-ok", "label-success"],
+ "Not Available": ["icon-remove", "label-danger"],
+ "Delivered": ["icon-truck", "label-success"],
+ "Purchase Returned": ["icon-retweet", "label-warning"],
+ "Sales Returned": ["icon-retweet", "label-warning"],
+ }[doc.status]; %}
+
+ {%= doc.status %}
+
+ {% if(doc.warehouse) { %}
+
+ {%= doc.warehouse %}
+
+ {% } %}
+
+
+
diff --git a/erpnext/stock/doctype/serial_no/serial_no_list.js b/erpnext/stock/doctype/serial_no/serial_no_list.js
new file mode 100644
index 00000000000..9a6513895be
--- /dev/null
+++ b/erpnext/stock/doctype/serial_no/serial_no_list.js
@@ -0,0 +1,3 @@
+frappe.listview_settings['Serial No'] = {
+ add_fields: ["status", "item_code", "warehouse"]
+};
diff --git a/erpnext/stock/doctype/warehouse/warehouse.json b/erpnext/stock/doctype/warehouse/warehouse.json
index 4e016e6360b..0a4c244eb1c 100644
--- a/erpnext/stock/doctype/warehouse/warehouse.json
+++ b/erpnext/stock/doctype/warehouse/warehouse.json
@@ -43,6 +43,7 @@
"description": "Account for the warehouse (Perpetual Inventory) will be created under this Account.",
"fieldname": "create_account_under",
"fieldtype": "Link",
+ "in_list_view": 1,
"label": "Parent Account",
"options": "Account",
"permlevel": 0
@@ -150,7 +151,7 @@
],
"icon": "icon-building",
"idx": 1,
- "modified": "2014-05-27 03:49:22.483111",
+ "modified": "2014-08-04 02:55:16.750848",
"modified_by": "Administrator",
"module": "Stock",
"name": "Warehouse",