diff --git a/patches/january_2013/update_closed_on.py b/patches/january_2013/update_closed_on.py
new file mode 100644
index 0000000000..138549a1fe
--- /dev/null
+++ b/patches/january_2013/update_closed_on.py
@@ -0,0 +1,32 @@
+import webnotes
+
+def execute():
+ webnotes.reload_doc("core", "doctype", "docfield")
+ webnotes.reload_doc("support", "doctype", "support_ticket")
+
+ # customer issue resolved_by should be Profile
+ if webnotes.conn.sql("""select count(*) from `tabCustomer Issue`
+ where ifnull(resolved_by,"")!="" """)[0][0]:
+ webnotes.make_property_setter({
+ "doctype":"Customer Issue",
+ "fieldname": "resolved_by",
+ "property": "options",
+ "value": "Sales Person"
+ })
+
+ def get_communication_time(support_ticket, sort_order = 'asc'):
+ tmp = webnotes.conn.sql("""select creation from tabCommunication where
+ support_ticket=%s order by creation %s limit 1""" % ("%s", sort_order),
+ support_ticket)
+ return tmp and tmp[0][0] or None
+
+ # update in support ticket
+ webnotes.conn.auto_commit_on_many_writes = True
+ for st in webnotes.conn.sql("""select name, modified, status from
+ `tabSupport Ticket`""", as_dict=1):
+
+ webnotes.conn.sql("""update `tabSupport Ticket` set first_responded_on=%s where
+ name=%s""", (get_communication_time(st.name) or st.modified, st.name))
+ if st.status=="Closed":
+ webnotes.conn.sql("""update `tabSupport Ticket` set resolution_date=%s where
+ name=%s""", (get_communication_time(st.name, 'desc') or st.modified, st.name))
diff --git a/projects/doctype/task/task.py b/projects/doctype/task/task.py
index 83f899586a..79fca9aa9c 100644
--- a/projects/doctype/task/task.py
+++ b/projects/doctype/task/task.py
@@ -17,7 +17,7 @@
from __future__ import unicode_literals
import webnotes
-from webnotes.utils import getdate
+from webnotes.utils import getdate, today
from webnotes.model import db_exists
from webnotes.model.wrapper import copy_doclist
from webnotes import msgprint
@@ -40,7 +40,7 @@ class DocType:
if cust:
ret = {'customer_name': cust and cust[0][0] or ''}
return ret
-
+
def validate(self):
if self.doc.exp_start_date and self.doc.exp_end_date and getdate(self.doc.exp_start_date) > getdate(self.doc.exp_end_date):
msgprint("'Expected Start Date' can not be greater than 'Expected End Date'")
@@ -49,4 +49,14 @@ class DocType:
if self.doc.act_start_date and self.doc.act_end_date and getdate(self.doc.act_start_date) > getdate(self.doc.act_end_date):
msgprint("'Actual Start Date' can not be greater than 'Actual End Date'")
raise Exception
+
+ self.update_status()
+ def update_status(self):
+ status = webnotes.conn.get_value("Task", self.doc.name, "status")
+ if self.doc.status=="Working" and status !="Working" and not self.doc.act_start_date:
+ self.doc.act_start_date = today()
+
+ if self.doc.status=="Closed" and status != "Closed" and not self.doc.act_end_date:
+ self.doc.act_end_date = today()
+
\ No newline at end of file
diff --git a/projects/doctype/task/task.txt b/projects/doctype/task/task.txt
index 9b8c2eb2ca..e95c456418 100644
--- a/projects/doctype/task/task.txt
+++ b/projects/doctype/task/task.txt
@@ -2,9 +2,9 @@
{
"owner": "Administrator",
"docstatus": 0,
- "creation": "2012-10-29 14:30:00",
+ "creation": "2013-01-10 16:34:17",
"modified_by": "Administrator",
- "modified": "2013-01-02 12:40:26"
+ "modified": "2013-01-14 14:03:52"
},
{
"autoname": "TASK.#####",
@@ -28,6 +28,8 @@
"parent": "Task",
"read": 1,
"doctype": "DocPerm",
+ "submit": 0,
+ "report": 1,
"parenttype": "DocType",
"role": "Projects User",
"parentfield": "permissions"
@@ -191,14 +193,6 @@
"fieldname": "act_end_date",
"fieldtype": "Date"
},
- {
- "oldfieldtype": "Data",
- "doctype": "DocField",
- "label": "Total Hours (Actual)",
- "oldfieldname": "act_total_hrs",
- "fieldname": "act_total_hrs",
- "fieldtype": "Data"
- },
{
"oldfieldtype": "Currency",
"doctype": "DocField",
@@ -253,7 +247,6 @@
"amend": 0,
"create": 0,
"doctype": "DocPerm",
- "submit": 0,
"cancel": 0,
"permlevel": 1
}
diff --git a/public/js/utils.js b/public/js/utils.js
index fe79248c59..271dab14d4 100644
--- a/public/js/utils.js
+++ b/public/js/utils.js
@@ -32,6 +32,7 @@ erpnext.utils.Controller = Class.extend({
var defaults = {
posting_date: wn.datetime.get_today(),
+ posting_time: wn.datetime.now_time()
}
$.each(defaults, function(k, v) {
diff --git a/startup/report_data_map.py b/startup/report_data_map.py
index 41d6cb868a..228a8ae2a1 100644
--- a/startup/report_data_map.py
+++ b/startup/report_data_map.py
@@ -219,7 +219,7 @@ data_map = {
# Support
"Support Ticket": {
- "columns": ["name","status","creation","modified"],
+ "columns": ["name","status","creation","resolution_date","first_responded_on"],
"conditions": ["docstatus < 2"],
"order_by": "creation"
}
diff --git a/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
index fae2fcb9f6..3e013b6495 100644
--- a/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
+++ b/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
@@ -100,7 +100,7 @@ class DocType:
def validate_posting_time(self):
""" Validate posting time format"""
- if self.doc.posting_time and len(self.doc.posting_time.split(':')) > 2:
+ if self.doc.posting_time and len(self.doc.posting_time.split(':')) > 3:
msgprint("Wrong format of posting time, can not complete the transaction. If you think \
you entered posting time correctly, please contact ERPNext support team.")
raise Exception
@@ -108,6 +108,4 @@ class DocType:
def scrub_posting_time(self):
if not self.doc.posting_time or self.doc.posting_time == '00:0':
self.doc.posting_time = '00:00'
- if len(self.doc.posting_time.split(':')) > 2:
- self.doc.posting_time = '00:00'
\ No newline at end of file
diff --git a/support/doctype/customer_issue/customer_issue.js b/support/doctype/customer_issue/customer_issue.js
index 835509fd5f..523b240172 100644
--- a/support/doctype/customer_issue/customer_issue.js
+++ b/support/doctype/customer_issue/customer_issue.js
@@ -15,15 +15,17 @@
// along with this program. If not, see
' + signature + '
' return content + + def validate(self): + self.update_status() def on_communication_sent(self, comm): webnotes.conn.set(self.doc, 'status', 'Waiting for Customer') @@ -47,15 +51,23 @@ class DocType(TransactionBase): webnotes.conn.set(self.doc, 'lead', comm.lead) if comm.contact and not self.doc.contact: webnotes.conn.set(self.doc, 'contact', comm.contact) - - def close_ticket(self): - webnotes.conn.set(self.doc,'status','Closed') - update_feed(self) - - def reopen_ticket(self): - webnotes.conn.set(self.doc,'status','Open') - update_feed(self) - + def on_trash(self): webnotes.conn.sql("""update `tabCommunication` set support_ticket=NULL where support_ticket=%s""", (self.doc.name,)) + + def update_status(self): + status = webnotes.conn.get_value("Support Ticket", self.doc.name, "status") + if self.doc.status!="Open" and status =="Open": + self.doc.first_responded_on = now() + if self.doc.status=="Closed" and status !="Closed": + self.doc.resolution_date = now() + if self.doc.status=="Open" and status !="Open": + self.doc.resolution_date = "" + +@webnotes.whitelist() +def set_status(name, status): + st = webnotes.model_wrapper("Support Ticket", name) + st.doc.status = status + st.save() + diff --git a/support/doctype/support_ticket/support_ticket.txt b/support/doctype/support_ticket/support_ticket.txt index b2bdadb735..b475db56b4 100644 --- a/support/doctype/support_ticket/support_ticket.txt +++ b/support/doctype/support_ticket/support_ticket.txt @@ -2,9 +2,9 @@ { "owner": "Administrator", "docstatus": 0, - "creation": "2012-11-02 17:17:05", + "creation": "2013-01-10 16:34:31", "modified_by": "Administrator", - "modified": "2012-11-28 10:45:19" + "modified": "2013-01-14 14:15:37" }, { "autoname": "naming_series:", @@ -25,10 +25,11 @@ "name": "__common__", "parent": "Support Ticket", "amend": 0, - "submit": 0, "doctype": "DocPerm", + "submit": 0, "read": 1, "parenttype": "DocType", + "report": 1, "parentfield": "permissions" }, { @@ -52,7 +53,6 @@ "permlevel": 1, "no_copy": 1, "oldfieldtype": "Select", - "colour": "White:FFF", "doctype": "DocField", "label": "Status", "oldfieldname": "status", @@ -117,7 +117,6 @@ "permlevel": 1 }, { - "colour": "White:FFF", "doctype": "DocField", "label": "Additional Info", "fieldname": "additional_info", @@ -152,12 +151,10 @@ { "print_hide": 1, "oldfieldtype": "Link", - "colour": "White:FFF", "doctype": "DocField", "label": "Customer", "oldfieldname": "customer", "permlevel": 1, - "trigger": "Client", "fieldname": "customer", "fieldtype": "Link", "search_index": 1, @@ -218,31 +215,26 @@ "permlevel": 1 }, { - "depends_on": "eval:!doc.__islocal", + "doctype": "DocField", + "label": "First Responded On", + "fieldname": "first_responded_on", + "fieldtype": "Datetime", + "permlevel": 0 + }, + { "no_copy": 1, - "search_index": 0, - "colour": "White:FFF", + "depends_on": "eval:!doc.__islocal", "doctype": "DocField", "label": "Resolution Date", "oldfieldname": "resolution_date", "fieldname": "resolution_date", - "fieldtype": "Date", + "fieldtype": "Datetime", + "search_index": 0, "oldfieldtype": "Date", "permlevel": 1, "in_filter": 0 }, { - "oldfieldtype": "Time", - "doctype": "DocField", - "label": "Resolution Time", - "oldfieldname": "resolution_time", - "fieldname": "resolution_time", - "fieldtype": "Time", - "depends_on": "eval:!doc.__islocal", - "permlevel": 1 - }, - { - "colour": "White:FFF", "doctype": "DocField", "label": "Content Type", "fieldname": "content_type", diff --git a/support/page/support_analytics/support_analytics.js b/support/page/support_analytics/support_analytics.js index e310df30a3..60384bb0a8 100644 --- a/support/page/support_analytics/support_analytics.js +++ b/support/page/support_analytics/support_analytics.js @@ -53,8 +53,12 @@ erpnext.SupportAnalytics = wn.views.GridReportWithPlot.extend({ checked:true}; var days_to_close = {status:"Days to Close", "id":"days-to-close", checked:false}; + var total_closed = {}; var hours_to_close = {status:"Hours to Close", "id":"hours-to-close", checked:false}; + var hours_to_respond = {status:"Hours to Respond", "id":"hours-to-respond", + checked:false}; + var total_responded = {}; $.each(wn.report_dump.data["Support Ticket"], function(i, d) { @@ -62,25 +66,40 @@ erpnext.SupportAnalytics = wn.views.GridReportWithPlot.extend({ var date = d.creation.split(" ")[0]; var col = me.column_map[date]; if(col) { - // just count - var day_diff = dateutil.get_diff(d.modified, d.creation); - var hour_diff = dateutil.get_hour_diff(d.modified, d.creation); - total_tickets[col.field] = flt(total_tickets[col.field]) + 1; - days_to_close[col.field] = flt(days_to_close[col.field]) + day_diff; - hours_to_close[col.field] = flt(hours_to_close[col.field]) + hour_diff; + if(d.status=="Closed") { + // just count + total_closed[col.field] = flt(total_closed[col.field]) + 1; + + days_to_close[col.field] = flt(days_to_close[col.field]) + + dateutil.get_diff(d.resolution_date, d.creation); + + hours_to_close[col.field] = flt(hours_to_close[col.field]) + + dateutil.get_hour_diff(d.resolution_date, d.creation); + + } + if (d.first_responded_on) { + total_responded[col.field] = flt(total_responded[col.field]) + 1; + + hours_to_respond[col.field] = flt(hours_to_respond[col.field]) + + dateutil.get_hour_diff(d.first_responded_on, d.creation); + } } }); // make averages $.each(this.columns, function(i, col) { if(col.formatter==me.currency_formatter && total_tickets[col.field]) { - days_to_close[col.field] = flt(days_to_close[col.field]) / flt(total_tickets[col.field]); - hours_to_close[col.field] = flt(hours_to_close[col.field]) / flt(total_tickets[col.field]); + days_to_close[col.field] = flt(days_to_close[col.field]) / + flt(total_closed[col.field]); + hours_to_close[col.field] = flt(hours_to_close[col.field]) / + flt(total_closed[col.field]); + hours_to_respond[col.field] = flt(hours_to_respond[col.field]) / + flt(total_responded[col.field]); } }) - this.data = [total_tickets, days_to_close, hours_to_close]; + this.data = [total_tickets, days_to_close, hours_to_close, hours_to_respond]; }, get_plot_points: function(item, col, idx) {