completed Time Log / Time Log Batch
This commit is contained in:
parent
b21eb9ac09
commit
fee642d547
@ -75,6 +75,7 @@ class DocType(SellingController):
|
||||
self.set_aging_date()
|
||||
self.set_against_income_account()
|
||||
self.validate_c_form()
|
||||
self.validate_time_logs_are_submitted()
|
||||
self.validate_recurring_invoice()
|
||||
|
||||
def on_submit(self):
|
||||
@ -104,7 +105,7 @@ class DocType(SellingController):
|
||||
self.update_against_document_in_jv()
|
||||
|
||||
self.update_c_form()
|
||||
|
||||
self.update_time_log_batch(self.doc.name)
|
||||
self.convert_to_recurring()
|
||||
|
||||
|
||||
@ -122,12 +123,28 @@ class DocType(SellingController):
|
||||
self.check_next_docstatus()
|
||||
sales_com_obj.update_prevdoc_detail(0, self)
|
||||
|
||||
self.update_time_log_batch(None)
|
||||
self.make_gl_entries(is_cancel=1)
|
||||
|
||||
def on_update_after_submit(self):
|
||||
self.validate_recurring_invoice()
|
||||
self.convert_to_recurring()
|
||||
|
||||
def update_time_log_batch(self, sales_invoice):
|
||||
for d in self.doclist.get({"doctype":"Sales Invoice Item"}):
|
||||
if d.time_log_batch:
|
||||
tlb = webnotes.bean("Time Log Batch", d.time_log_batch)
|
||||
tlb.doc.sales_invoice = sales_invoice
|
||||
tlb.update_after_submit()
|
||||
|
||||
def validate_time_logs_are_submitted(self):
|
||||
for d in self.doclist.get({"doctype":"Sales Invoice Item"}):
|
||||
if d.time_log_batch:
|
||||
status = webnotes.conn.get_value("Time Log Batch", d.time_log_batch, "status")
|
||||
if status!="Submitted":
|
||||
webnotes.msgprint(_("Time Log Batch status must be 'Submitted'") + ":" + d.time_log_batch,
|
||||
raise_exception=True)
|
||||
|
||||
def set_pos_fields(self):
|
||||
"""Set retail related fields from pos settings"""
|
||||
pos = webnotes.conn.sql("select * from `tabPOS Setting` where ifnull(user,'') = '%s' and company = '%s'" % (session['user'], self.doc.company), as_dict=1)
|
||||
|
16
accounts/doctype/sales_invoice/sales_invoice_map.js
Normal file
16
accounts/doctype/sales_invoice/sales_invoice_map.js
Normal file
@ -0,0 +1,16 @@
|
||||
wn.model.map_info["Sales Invoice"] = {
|
||||
"Time Log Batch": {
|
||||
table_map: {
|
||||
"Sales Invoice Item": "Time Log Batch",
|
||||
},
|
||||
field_map: {
|
||||
"Sales Invoice Item": {
|
||||
"basic_rate": "rate",
|
||||
"time_log_batch": "name",
|
||||
"qty": "total_hours",
|
||||
"stock_uom": "=Hour",
|
||||
"description": "=via Time Logs"
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
@ -28,6 +28,31 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
jv.cancel()
|
||||
self.assertEquals(webnotes.conn.get_value("Sales Invoice", w.doc.name, "outstanding_amount"),
|
||||
561.8)
|
||||
|
||||
def test_time_log_batch(self):
|
||||
tlb = webnotes.bean("Time Log Batch", "_T-Time Log Batch-00001")
|
||||
tlb.submit()
|
||||
|
||||
w = webnotes.bean(webnotes.copy_doclist(test_records[0]))
|
||||
w.doclist[1].time_log_batch = "_T-Time Log Batch-00001"
|
||||
w.insert()
|
||||
w.submit()
|
||||
|
||||
self.assertEquals(webnotes.conn.get_value("Time Log Batch", "_T-Time Log Batch-00001", "status"),
|
||||
"Billed")
|
||||
|
||||
self.assertEquals(webnotes.conn.get_value("Time Log", "_T-Time Log-00001", "status"),
|
||||
"Billed")
|
||||
|
||||
w.cancel()
|
||||
|
||||
self.assertEquals(webnotes.conn.get_value("Time Log Batch", "_T-Time Log Batch-00001", "status"),
|
||||
"Submitted")
|
||||
|
||||
self.assertEquals(webnotes.conn.get_value("Time Log", "_T-Time Log-00001", "status"),
|
||||
"Batched for Billing")
|
||||
|
||||
|
||||
|
||||
test_dependencies = ["Journal Voucher"]
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
[
|
||||
{
|
||||
"creation": "2013-01-10 16:34:09",
|
||||
"creation": "2013-01-29 19:25:49",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-01-29 16:27:51",
|
||||
"modified": "2013-03-01 13:41:51",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@ -320,6 +320,13 @@
|
||||
"read_only": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "time_log_batch",
|
||||
"fieldtype": "Link",
|
||||
"label": "Time Log Batch",
|
||||
"options": "Time Log Batch"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "item_tax_rate",
|
||||
|
@ -22,6 +22,7 @@ from webnotes.utils import cint, cstr, date_diff, flt, formatdate, getdate, get_
|
||||
from webnotes import msgprint
|
||||
|
||||
class LeaveDayBlockedError(Exception): pass
|
||||
class OverlapError(Exception): pass
|
||||
|
||||
from webnotes.model.controller import DocListController
|
||||
class DocType(DocListController):
|
||||
@ -129,17 +130,22 @@ class DocType(DocListController):
|
||||
(self.doc.leave_type,), raise_exception=1)
|
||||
|
||||
def validate_leave_overlap(self):
|
||||
if not self.doc.name:
|
||||
self.doc.name = "New Leave Application"
|
||||
|
||||
for d in webnotes.conn.sql("""select name, leave_type, posting_date,
|
||||
from_date, to_date
|
||||
from `tabLeave Application`
|
||||
where
|
||||
(from_date <= %(to_date)s and to_date >= %(from_date)s)
|
||||
and employee = %(employee)s
|
||||
employee = %(employee)s
|
||||
and docstatus < 2
|
||||
and status in ("Open", "Approved")
|
||||
and (from_date between %(from_date)s and %(to_date)s
|
||||
or to_date between %(from_date)s and %(to_date)s
|
||||
or %(from_date)s between from_date and to_date)
|
||||
and name != %(name)s""", self.doc.fields, as_dict = 1):
|
||||
|
||||
msgprint("Employee : %s has already applied for %s between %s and %s on %s. Please refer Leave Application : <a href=\"#Form/Leave Application/%s\">%s</a>" % (self.doc.employee, cstr(d['leave_type']), formatdate(d['from_date']), formatdate(d['to_date']), formatdate(d['posting_date']), d['name'], d['name']), raise_exception = 1)
|
||||
msgprint("Employee : %s has already applied for %s between %s and %s on %s. Please refer Leave Application : <a href=\"#Form/Leave Application/%s\">%s</a>" % (self.doc.employee, cstr(d['leave_type']), formatdate(d['from_date']), formatdate(d['to_date']), formatdate(d['posting_date']), d['name'], d['name']), raise_exception = OverlapError)
|
||||
|
||||
def validate_max_days(self):
|
||||
max_days = webnotes.conn.sql("select max_days_allowed from `tabLeave Type` where name = '%s'" %(self.doc.leave_type))
|
||||
|
@ -1,7 +1,7 @@
|
||||
import webnotes
|
||||
import unittest
|
||||
|
||||
from hr.doctype.leave_application.leave_application import LeaveDayBlockedError
|
||||
from hr.doctype.leave_application.leave_application import LeaveDayBlockedError, OverlapError
|
||||
|
||||
class TestLeaveApplication(unittest.TestCase):
|
||||
def get_application(self, doclist):
|
||||
@ -23,13 +23,22 @@ class TestLeaveApplication(unittest.TestCase):
|
||||
|
||||
from webnotes.profile import add_role
|
||||
add_role("test1@example.com", "HR User")
|
||||
|
||||
# clear other applications
|
||||
webnotes.conn.sql("delete from `tabLeave Application`")
|
||||
|
||||
application = self.get_application(test_records[1])
|
||||
self.assertTrue(application.insert())
|
||||
|
||||
def test_overlap(self):
|
||||
application = self.get_application(test_records[1])
|
||||
self.assertRaises(OverlapError, application.insert)
|
||||
|
||||
def test_global_block_list(self):
|
||||
|
||||
application = self.get_application(test_records[3])
|
||||
application.doc.leave_approver = "test@example.com"
|
||||
|
||||
webnotes.conn.set_value("Leave Block List", "_Test Leave Block List",
|
||||
"applies_to_all_departments", 1)
|
||||
webnotes.conn.set_value("Employee", "_T-Employee-0002", "department",
|
||||
|
@ -200,4 +200,5 @@ patch_list = [
|
||||
'execute:webnotes.reload_doc("accounts", "Print Format", "Sales Invoice Modern") # 2013-02-26',
|
||||
'execute:webnotes.reload_doc("accounts", "Print Format", "Sales Invoice Spartan") # 2013-02-26',
|
||||
"execute:(not webnotes.conn.exists('Role', 'Projects Manager')) and webnotes.doc({'doctype':'Role', 'role_name':'Projects Manager'}).insert()",
|
||||
"execute:(not webnotes.conn.exists('UOM', 'Hour')) and webnotes.doc({'uom_name': 'Unit', 'doctype': 'UOM', 'name': 'Hour'}).insert()",
|
||||
]
|
5
projects/doctype/activity_type/test_activity_type.py
Normal file
5
projects/doctype/activity_type/test_activity_type.py
Normal file
@ -0,0 +1,5 @@
|
||||
test_records = [
|
||||
[{"activity_type":"_Test Activity Type"}],
|
||||
[{"activity_type":"_Test Activity Type 1"}],
|
||||
[{"activity_type":"_Test Activity Type 2"}]
|
||||
]
|
8
projects/doctype/project/test_project.py
Normal file
8
projects/doctype/project/test_project.py
Normal file
@ -0,0 +1,8 @@
|
||||
test_records = [[{
|
||||
"project_name": "_Test Project",
|
||||
"status": "Open"
|
||||
}],
|
||||
[{
|
||||
"project_name": "_Test Project 1",
|
||||
"status": "Open"
|
||||
}]]
|
7
projects/doctype/task/test_task.py
Normal file
7
projects/doctype/task/test_task.py
Normal file
@ -0,0 +1,7 @@
|
||||
test_records = [
|
||||
[{"subject": "_Test Task", "project":"_Test Project", "status":"Open"}],
|
||||
[{"subject": "_Test Task 1", "status":"Open"}],
|
||||
[{"subject": "_Test Task 2", "status":"Open"}]
|
||||
]
|
||||
|
||||
test_ignore = ["Customer"]
|
19
projects/doctype/time_log/test_time_log.py
Normal file
19
projects/doctype/time_log/test_time_log.py
Normal file
@ -0,0 +1,19 @@
|
||||
import webnotes
|
||||
import unittest
|
||||
|
||||
from projects.doctype.time_log.time_log import OverlapError
|
||||
|
||||
class TestTimeLog(unittest.TestCase):
|
||||
def test_duplication(self):
|
||||
ts = webnotes.bean(webnotes.copy_doclist(test_records[0]))
|
||||
self.assertRaises(OverlapError, ts.insert)
|
||||
|
||||
test_records = [[{
|
||||
"from_time": "2013-01-01 10:00:00",
|
||||
"to_time": "2013-01-01 11:00:00",
|
||||
"activity_type": "_Test Activity Type",
|
||||
"note": "_Test Note",
|
||||
"docstatus": 1
|
||||
}]]
|
||||
|
||||
test_ignore = ["Sales Invoice", "Time Log Batch"]
|
5
projects/doctype/time_log/time_log.js
Normal file
5
projects/doctype/time_log/time_log.js
Normal file
@ -0,0 +1,5 @@
|
||||
$.extend(cur_frm.cscript, {
|
||||
refresh: function(doc) {
|
||||
|
||||
}
|
||||
});
|
@ -6,6 +6,8 @@ from webnotes import _
|
||||
|
||||
from webnotes.widgets.reportview import build_match_conditions
|
||||
|
||||
class OverlapError(webnotes.ValidationError): pass
|
||||
|
||||
class DocType:
|
||||
def __init__(self, d, dl):
|
||||
self.doc, self.doclist = d, dl
|
||||
@ -13,28 +15,46 @@ class DocType:
|
||||
def validate(self):
|
||||
self.set_status()
|
||||
self.validate_overlap()
|
||||
self.calculate_total_hours()
|
||||
|
||||
def calculate_total_hours(self):
|
||||
from webnotes.utils import time_diff_in_hours
|
||||
self.doc.hours = time_diff_in_hours(self.doc.to_time, self.doc.from_time)
|
||||
|
||||
def set_status(self):
|
||||
if self.doc.docstatus==0:
|
||||
self.doc.status = "Draft"
|
||||
elif self.doc.docstatus==1:
|
||||
self.doc.status = "Submitted"
|
||||
elif self.doc.docstatus==2:
|
||||
self.doc.status = "Cancelled"
|
||||
self.doc.status = {
|
||||
"0": "Draft",
|
||||
"1": "Submitted",
|
||||
"2": "Cancelled"
|
||||
}[str(self.doc.docstatus or 0)]
|
||||
|
||||
if self.doc.time_log_batch:
|
||||
self.doc.status="Batched for Billing"
|
||||
|
||||
# billed will be set directly
|
||||
|
||||
def validate_overlap(self):
|
||||
if self.doc.sales_invoice:
|
||||
self.doc.status="Billed"
|
||||
|
||||
def validate_overlap(self):
|
||||
existing = webnotes.conn.sql_list("""select name from `tabTime Log` where owner=%s and
|
||||
((from_time between %s and %s) or (to_time between %s and %s)) and name!=%s""",
|
||||
(
|
||||
(from_time between %s and %s) or
|
||||
(to_time between %s and %s) or
|
||||
(%s between from_time and to_time))
|
||||
and name!=%s
|
||||
and docstatus < 2""",
|
||||
(self.doc.owner, self.doc.from_time, self.doc.to_time, self.doc.from_time,
|
||||
self.doc.to_time, self.doc.name))
|
||||
self.doc.to_time, self.doc.from_time, self.doc.name or "No Name"))
|
||||
|
||||
if existing:
|
||||
webnotes.msgprint(_("This Time Log conflicts with") + ":" + ', '.join(existing),
|
||||
raise_exception=True)
|
||||
raise_exception=OverlapError)
|
||||
|
||||
def before_cancel(self):
|
||||
self.set_status()
|
||||
|
||||
def before_update_after_submit(self):
|
||||
self.set_status()
|
||||
|
||||
|
||||
@webnotes.whitelist()
|
||||
def get_events(start, end):
|
||||
match = build_match_conditions("Time Log")
|
||||
|
@ -2,13 +2,13 @@
|
||||
{
|
||||
"creation": "2013-02-26 14:58:28",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-02-28 18:41:40",
|
||||
"modified": "2013-03-01 17:48:09",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
{
|
||||
"allow_attach": 1,
|
||||
"autoname": "TL-.######",
|
||||
"autoname": "naming_series:",
|
||||
"description": "Log of Activities performed by users against Tasks that can be used for tracking time, billing.",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Master",
|
||||
@ -40,14 +40,12 @@
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "status",
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Status",
|
||||
"options": "Draft\nSubmitted\nBatched for Billing\nBilled\nCancelled",
|
||||
"label": "Naming Series",
|
||||
"options": "TL-",
|
||||
"permlevel": 0,
|
||||
"read_only": 1,
|
||||
"reqd": 0
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
@ -67,12 +65,31 @@
|
||||
"permlevel": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "hours",
|
||||
"fieldtype": "Float",
|
||||
"label": "Hours",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Status",
|
||||
"options": "Draft\nSubmitted\nBatched for Billing\nBilled\nCancelled",
|
||||
"permlevel": 0,
|
||||
"read_only": 1,
|
||||
"reqd": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "activity_type",
|
||||
@ -127,6 +144,26 @@
|
||||
"options": "Project",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"description": "Will be updated when batched.",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "time_log_batch",
|
||||
"fieldtype": "Link",
|
||||
"label": "Time Log Batch",
|
||||
"options": "Time Log Batch",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"description": "Will be updated when billed.",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "sales_invoice",
|
||||
"fieldtype": "Link",
|
||||
"label": "Sales Invoice",
|
||||
"options": "Sales Invoice",
|
||||
"permlevel": 0,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "file_list",
|
||||
@ -143,7 +180,7 @@
|
||||
"fieldtype": "Link",
|
||||
"label": "Amended From",
|
||||
"no_copy": 1,
|
||||
"options": "Sales Invoice",
|
||||
"options": "Time Log",
|
||||
"permlevel": 1,
|
||||
"print_hide": 1
|
||||
},
|
||||
|
@ -1,5 +1,6 @@
|
||||
// render
|
||||
wn.listview_settings['Time Log'] = {
|
||||
add_fields: ["`tabTime Log`.`status`", "`tabTime Log`.`billable`", "`tabTime Log`.`activity_type`"],
|
||||
selectable: true,
|
||||
onload: function(me) {
|
||||
me.appframe.add_button(wn._("Make Time Log Batch"), function() {
|
||||
@ -16,12 +17,28 @@ wn.listview_settings['Time Log'] = {
|
||||
msgprint(wn._("Time Log is not billable") + ": " + d.name);
|
||||
return;
|
||||
}
|
||||
if(d.sales_invoice) {
|
||||
msgprint(wn._("Time Log has been Invoiced") + ": " + d.name);
|
||||
if(d.status!="Submitted") {
|
||||
msgprint(wn._("Time Log Status must be Submitted."));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// make batch
|
||||
wn.model.with_doctype("Time Log Batch", function() {
|
||||
var tlb = wn.model.get_new_doc("Time Log Batch");
|
||||
$.each(selected, function(i, d) {
|
||||
var detail = wn.model.get_new_doc("Time Log Batch Detail");
|
||||
$.extend(detail, {
|
||||
"parenttype": "Time Log Batch",
|
||||
"parentfield": "time_log_batch_details",
|
||||
"parent": tlb.name,
|
||||
"time_log": d.name,
|
||||
"activity_type": d.activity_type,
|
||||
"created_by": d.owner,
|
||||
"idx": i+1
|
||||
});
|
||||
})
|
||||
wn.set_route("Form", "Time Log Batch", tlb.name);
|
||||
})
|
||||
|
||||
}, "icon-file-alt");
|
||||
}
|
||||
|
20
projects/doctype/time_log_batch/test_time_log_batch.py
Normal file
20
projects/doctype/time_log_batch/test_time_log_batch.py
Normal file
@ -0,0 +1,20 @@
|
||||
import webnotes, unittest
|
||||
|
||||
class TimeLogBatchTest(unittest.TestCase):
|
||||
def test_time_log_status(self):
|
||||
self.assertEquals(webnotes.conn.get_value("Time Log", "_T-Time Log-00001", "status"), "Submitted")
|
||||
tlb = webnotes.bean("Time Log Batch", "_T-Time Log Batch-00001")
|
||||
tlb.submit()
|
||||
self.assertEquals(webnotes.conn.get_value("Time Log", "_T-Time Log-00001", "status"), "Batched for Billing")
|
||||
tlb.cancel()
|
||||
self.assertEquals(webnotes.conn.get_value("Time Log", "_T-Time Log-00001", "status"), "Submitted")
|
||||
|
||||
test_records = [[
|
||||
{"rate": "500"},
|
||||
{
|
||||
"doctype": "Time Log Batch Detail",
|
||||
"parenttype": "Time Log Batch",
|
||||
"parentfield": "time_log_batch_details",
|
||||
"time_log": "_T-Time Log-00001",
|
||||
}
|
||||
]]
|
@ -1,5 +1,6 @@
|
||||
cur_frm.add_fetch("time_log", "activity_type", "activity_type");
|
||||
cur_frm.add_fetch("time_log", "owner", "created_by");
|
||||
cur_frm.add_fetch("time_log", "hours", "hours");
|
||||
|
||||
cur_frm.set_query("time_log", "time_log_batch_details", function(doc) {
|
||||
return {
|
||||
@ -12,7 +13,24 @@ cur_frm.set_query("time_log", "time_log_batch_details", function(doc) {
|
||||
});
|
||||
|
||||
$.extend(cur_frm.cscript, {
|
||||
refresh: function() {
|
||||
refresh: function(doc) {
|
||||
cur_frm.set_intro({
|
||||
"Draft": wn._("Select Time Logs and Submit to create a new Sales Invoice."),
|
||||
"Submitted": wn._("Click on 'Make Sales Invoice' button to create a new Sales Invoice."),
|
||||
"Billed": wn._("This Time Log Batch has been billed."),
|
||||
"Cancelled": wn._("This Time Log Batch has been cancelled.")
|
||||
}[doc.status]);
|
||||
|
||||
if(doc.status=="Submitted") {
|
||||
cur_frm.add_custom_button("Make Sales Invoice", function() { cur_frm.cscript.make_invoice() },
|
||||
"icon-file-alt");
|
||||
}
|
||||
},
|
||||
make_invoice: function() {
|
||||
var doc = cur_frm.doc;
|
||||
wn.model.map({
|
||||
source: wn.model.get_doclist(doc.doctype, doc.name),
|
||||
target: "Sales Invoice"
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
@ -2,10 +2,59 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes import _
|
||||
|
||||
class DocType:
|
||||
def __init__(self, d, dl):
|
||||
self.doc, self.doclist = d, dl
|
||||
|
||||
def validate(self):
|
||||
self.set_status()
|
||||
self.doc.total_hours = 0.0
|
||||
for d in self.doclist.get({"doctype":"Time Log Batch Detail"}):
|
||||
tl = webnotes.doc("Time Log", d.time_log)
|
||||
self.update_time_log_values(d, tl)
|
||||
self.validate_time_log_is_submitted(tl)
|
||||
self.doc.total_hours += float(tl.hours or 0.0)
|
||||
|
||||
def update_time_log_values(self, d, tl):
|
||||
d.fields.update({
|
||||
"hours": tl.hours,
|
||||
"activity_type": tl.activity_type,
|
||||
"created_by": tl.owner
|
||||
})
|
||||
|
||||
def validate_time_log_is_submitted(self, tl):
|
||||
if tl.status != "Submitted":
|
||||
webnotes.msgprint(_("Time Log must have status 'Submitted'") + \
|
||||
" :" + tl.name + " (" + _(tl.status) + ")", raise_exception=True)
|
||||
|
||||
def set_status(self):
|
||||
self.doc.status = {
|
||||
"0": "Draft",
|
||||
"1": "Submitted",
|
||||
"2": "Cancelled"
|
||||
}[str(self.doc.docstatus or 0)]
|
||||
|
||||
if self.doc.sales_invoice:
|
||||
self.doc.status = "Billed"
|
||||
|
||||
def on_submit(self):
|
||||
# update time logs as batched
|
||||
self.update_status(self.doc.name)
|
||||
|
||||
def before_cancel(self):
|
||||
self.update_status(None)
|
||||
|
||||
def before_update_after_submit(self):
|
||||
self.update_status(self.doc.name)
|
||||
|
||||
def update_status(self, time_log_batch):
|
||||
self.set_status()
|
||||
for d in self.doclist.get({"doctype":"Time Log Batch Detail"}):
|
||||
tl = webnotes.bean("Time Log", d.time_log)
|
||||
tl.doc.time_log_batch = time_log_batch
|
||||
tl.doc.sales_invoice = self.doc.sales_invoice
|
||||
tl.update_after_submit()
|
||||
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-02-28 17:57:33",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-02-28 18:36:28",
|
||||
"modified": "2013-03-01 17:54:57",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@ -24,6 +24,7 @@
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"doctype": "DocPerm",
|
||||
@ -57,19 +58,51 @@
|
||||
"fieldtype": "Currency",
|
||||
"label": "Rate"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"default": "Draft",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Status",
|
||||
"options": "Draft\nSubmitted\nBilled\nCancelled",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"description": "Will be updated after Sales Invoice is Submitted.",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "sales_invoice",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Sales Invoice",
|
||||
"options": "Sales Invoice",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "section_break_5",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "time_log_batch_details",
|
||||
"fieldtype": "Table",
|
||||
"label": "Time Log Batch Details",
|
||||
"options": "Time Log Batch Detail"
|
||||
"options": "Time Log Batch Detail",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"description": "In Hours",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "total_time",
|
||||
"fieldname": "total_hours",
|
||||
"fieldtype": "Float",
|
||||
"label": "Total Time",
|
||||
"in_list_view": 1,
|
||||
"label": "Total Hours",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-02-28 17:56:12",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-02-28 17:56:12",
|
||||
"modified": "2013-03-01 15:20:17",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@ -47,5 +47,11 @@
|
||||
"fieldtype": "Data",
|
||||
"label": "Activity Type",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "hours",
|
||||
"fieldtype": "Float",
|
||||
"label": "Hours"
|
||||
}
|
||||
]
|
@ -56,7 +56,18 @@ wn.module_page["Projects"] = [
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
{
|
||||
title: wn._("Reports"),
|
||||
right: true,
|
||||
icon: "icon-list",
|
||||
items: [
|
||||
{
|
||||
"label":wn._("Time Log Summary"),
|
||||
route: "Report2/Time Log/Time Log Summary",
|
||||
doctype: "Time Log"
|
||||
},
|
||||
]
|
||||
}]
|
||||
|
||||
pscript['onload_projects-home'] = function(wrapper) {
|
||||
wn.views.moduleview.make(wrapper, "Projects");
|
||||
|
0
projects/report/__init__.py
Normal file
0
projects/report/__init__.py
Normal file
0
projects/report/time_log_summary/__init__.py
Normal file
0
projects/report/time_log_summary/__init__.py
Normal file
22
projects/report/time_log_summary/time_log_summary.txt
Normal file
22
projects/report/time_log_summary/time_log_summary.txt
Normal file
@ -0,0 +1,22 @@
|
||||
[
|
||||
{
|
||||
"creation": "2013-03-01 17:36:35",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-03-01 18:17:13",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
{
|
||||
"doctype": "Report",
|
||||
"is_standard": "Yes",
|
||||
"json": "{\"filters\":[],\"columns\":[[\"name\",\"Time Log\"],[\"status\",\"Time Log\"],[\"from_time\",\"Time Log\"],[\"hours\",\"Time Log\"],[\"activity_type\",\"Time Log\"],[\"owner\",\"Time Log\"],[\"billable\",\"Time Log\"],[\"time_log_batch\",\"Time Log\"],[\"sales_invoice\",\"Time Log\"]],\"sort_by\":\"Time Log.name\",\"sort_order\":\"desc\",\"sort_by_next\":\"\",\"sort_order_next\":\"desc\"}",
|
||||
"name": "__common__",
|
||||
"ref_doctype": "Time Log",
|
||||
"report_name": "Time Log Summary",
|
||||
"report_type": "Report Builder"
|
||||
},
|
||||
{
|
||||
"doctype": "Report",
|
||||
"name": "Time Log Summary"
|
||||
}
|
||||
]
|
@ -162,6 +162,7 @@ def import_defaults():
|
||||
|
||||
# UOM
|
||||
{'uom_name': 'Unit', 'doctype': 'UOM', 'name': 'Unit'},
|
||||
{'uom_name': 'Unit', 'doctype': 'UOM', 'name': 'Hour'},
|
||||
{'uom_name': 'Box', 'doctype': 'UOM', 'name': 'Box'},
|
||||
{'uom_name': 'Ft', 'doctype': 'UOM', 'name': 'Ft'},
|
||||
{'uom_name': 'Kg', 'doctype': 'UOM', 'name': 'Kg'},
|
||||
|
@ -19,5 +19,4 @@ observer_map = {
|
||||
"*:on_submit": "home.update_feed",
|
||||
"Stock Entry:on_submit": "stock.doctype.material_request.material_request.update_completed_qty",
|
||||
"Stock Entry:on_cancel": "stock.doctype.material_request.material_request.update_completed_qty",
|
||||
# "*:on_update": "webnotes.widgets.moduleview.update_count"
|
||||
}
|
@ -27,4 +27,6 @@ queries = {
|
||||
"Production Order": {"docstatus":0},
|
||||
"BOM": {"docstatus":0},
|
||||
"Timesheet": {"docstatus":0},
|
||||
"Time Log": {"status":"Draft"},
|
||||
"Time Log Batch": {"status":"Draft"},
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user