mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-16 19:49:18 +00:00
Merge remote-tracking branch 'webnotes/4.0.0-wip' into permissions
Conflicts: erpnext/accounts/page/accounts_browser/accounts_browser.css erpnext/controllers/buying_controller.py erpnext/manufacturing/doctype/production_order/production_order.py erpnext/patches/patch_list.py erpnext/selling/doctype/customer/customer.txt erpnext/selling/doctype/sales_order/sales_order.py erpnext/selling/doctype/sales_order/test_sales_order.py erpnext/setup/doctype/features_setup/features_setup.txt erpnext/stock/doctype/stock_entry/test_stock_entry.py erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py startup/query_handlers.py
This commit is contained in:
0
erpnext/projects/__init__.py
Normal file
0
erpnext/projects/__init__.py
Normal file
1
erpnext/projects/doctype/__init__.py
Normal file
1
erpnext/projects/doctype/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from __future__ import unicode_literals
|
||||
1
erpnext/projects/doctype/activity_type/README.md
Normal file
1
erpnext/projects/doctype/activity_type/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Type of Activity (set in Task, Time Log)
|
||||
0
erpnext/projects/doctype/activity_type/__init__.py
Normal file
0
erpnext/projects/doctype/activity_type/__init__.py
Normal file
9
erpnext/projects/doctype/activity_type/activity_type.py
Normal file
9
erpnext/projects/doctype/activity_type/activity_type.py
Normal file
@@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
class DocType:
|
||||
def __init__(self, d, dl):
|
||||
self.doc, self.doclist = d, dl
|
||||
60
erpnext/projects/doctype/activity_type/activity_type.txt
Normal file
60
erpnext/projects/doctype/activity_type/activity_type.txt
Normal file
@@ -0,0 +1,60 @@
|
||||
[
|
||||
{
|
||||
"creation": "2013-03-05 10:14:59",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-12-20 19:23:54",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
{
|
||||
"allow_import": 1,
|
||||
"autoname": "field:activity_type",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Master",
|
||||
"icon": "icon-flag",
|
||||
"in_dialog": 0,
|
||||
"module": "Projects",
|
||||
"name": "__common__"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "activity_type",
|
||||
"fieldtype": "Data",
|
||||
"label": "Activity Type",
|
||||
"name": "__common__",
|
||||
"parent": "Activity Type",
|
||||
"parentfield": "fields",
|
||||
"parenttype": "DocType",
|
||||
"permlevel": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
"doctype": "DocPerm",
|
||||
"email": 1,
|
||||
"name": "__common__",
|
||||
"parent": "Activity Type",
|
||||
"parentfield": "permissions",
|
||||
"parenttype": "DocType",
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocType",
|
||||
"name": "Activity Type"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField"
|
||||
},
|
||||
{
|
||||
"doctype": "DocPerm",
|
||||
"role": "System Manager"
|
||||
},
|
||||
{
|
||||
"doctype": "DocPerm",
|
||||
"role": "Projects User"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,8 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
test_records = [
|
||||
[{"activity_type":"_Test Activity Type"}],
|
||||
[{"activity_type":"_Test Activity Type 1"}],
|
||||
[{"activity_type":"_Test Activity Type 2"}]
|
||||
]
|
||||
1
erpnext/projects/doctype/project/README.md
Normal file
1
erpnext/projects/doctype/project/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Project details. Projects can be internal or external and can have Tasks, Milestones associated to it.
|
||||
1
erpnext/projects/doctype/project/__init__.py
Normal file
1
erpnext/projects/doctype/project/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from __future__ import unicode_literals
|
||||
5
erpnext/projects/doctype/project/help.md
Normal file
5
erpnext/projects/doctype/project/help.md
Normal file
@@ -0,0 +1,5 @@
|
||||
You can use projects to:
|
||||
|
||||
1. Track budgets (Purchase Orders, Invoices).
|
||||
2. Track material consumption.
|
||||
3. Create and assign tasks (and view them on a Gantt Chart).
|
||||
22
erpnext/projects/doctype/project/project.js
Normal file
22
erpnext/projects/doctype/project/project.js
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
// show tasks
|
||||
cur_frm.cscript.refresh = function(doc) {
|
||||
if(!doc.__islocal) {
|
||||
cur_frm.appframe.add_button(wn._("Gantt Chart"), function() {
|
||||
wn.route_options = {"project": doc.name}
|
||||
wn.set_route("Gantt", "Task");
|
||||
}, "icon-tasks");
|
||||
cur_frm.add_custom_button(wn._("Tasks"), function() {
|
||||
wn.route_options = {"project": doc.name}
|
||||
wn.set_route("List", "Task");
|
||||
}, "icon-list");
|
||||
}
|
||||
}
|
||||
|
||||
cur_frm.fields_dict.customer.get_query = function(doc,cdt,cdn) {
|
||||
return{
|
||||
query: "erpnext.controllers.queries.customer_query"
|
||||
}
|
||||
}
|
||||
63
erpnext/projects/doctype/project/project.py
Normal file
63
erpnext/projects/doctype/project/project.py
Normal file
@@ -0,0 +1,63 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
from webnotes.utils import flt, getdate
|
||||
from webnotes import msgprint
|
||||
from erpnext.utilities.transaction_base import delete_events
|
||||
|
||||
class DocType:
|
||||
def __init__(self, doc, doclist=None):
|
||||
self.doc = doc
|
||||
self.doclist = doclist
|
||||
|
||||
def get_gross_profit(self):
|
||||
pft, per_pft =0, 0
|
||||
pft = flt(self.doc.project_value) - flt(self.doc.est_material_cost)
|
||||
#if pft > 0:
|
||||
per_pft = (flt(pft) / flt(self.doc.project_value)) * 100
|
||||
ret = {'gross_margin_value': pft, 'per_gross_margin': per_pft}
|
||||
return ret
|
||||
|
||||
def validate(self):
|
||||
"""validate start date before end date"""
|
||||
if self.doc.project_start_date and self.doc.completion_date:
|
||||
if getdate(self.doc.completion_date) < getdate(self.doc.project_start_date):
|
||||
msgprint("Expected Completion Date can not be less than Project Start Date")
|
||||
raise Exception
|
||||
|
||||
def on_update(self):
|
||||
self.add_calendar_event()
|
||||
|
||||
def update_percent_complete(self):
|
||||
total = webnotes.conn.sql("""select count(*) from tabTask where project=%s""",
|
||||
self.doc.name)[0][0]
|
||||
if total:
|
||||
completed = webnotes.conn.sql("""select count(*) from tabTask where
|
||||
project=%s and status in ('Closed', 'Cancelled')""", self.doc.name)[0][0]
|
||||
webnotes.conn.set_value("Project", self.doc.name, "percent_complete",
|
||||
int(float(completed) / total * 100))
|
||||
|
||||
def add_calendar_event(self):
|
||||
# delete any earlier event for this project
|
||||
delete_events(self.doc.doctype, self.doc.name)
|
||||
|
||||
# add events
|
||||
for milestone in self.doclist.get({"parentfield": "project_milestones"}):
|
||||
if milestone.milestone_date:
|
||||
description = (milestone.milestone or "Milestone") + " for " + self.doc.name
|
||||
webnotes.bean({
|
||||
"doctype": "Event",
|
||||
"owner": self.doc.owner,
|
||||
"subject": description,
|
||||
"description": description,
|
||||
"starts_on": milestone.milestone_date + " 10:00:00",
|
||||
"event_type": "Private",
|
||||
"ref_type": self.doc.doctype,
|
||||
"ref_name": self.doc.name
|
||||
}).insert()
|
||||
|
||||
def on_trash(self):
|
||||
delete_events(self.doc.doctype, self.doc.name)
|
||||
308
erpnext/projects/doctype/project/project.txt
Normal file
308
erpnext/projects/doctype/project/project.txt
Normal file
@@ -0,0 +1,308 @@
|
||||
[
|
||||
{
|
||||
"creation": "2013-03-07 11:55:07",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-12-20 19:24:17",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
{
|
||||
"allow_attach": 1,
|
||||
"allow_import": 1,
|
||||
"autoname": "field:project_name",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Master",
|
||||
"icon": "icon-puzzle-piece",
|
||||
"max_attachments": 4,
|
||||
"module": "Projects",
|
||||
"name": "__common__",
|
||||
"search_fields": "customer, status, priority, is_active"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"name": "__common__",
|
||||
"parent": "Project",
|
||||
"parentfield": "fields",
|
||||
"parenttype": "DocType",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"doctype": "DocPerm",
|
||||
"name": "__common__",
|
||||
"parent": "Project",
|
||||
"parentfield": "permissions",
|
||||
"parenttype": "DocType",
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"submit": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocType",
|
||||
"name": "Project"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "overview",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Overview",
|
||||
"options": "icon-file"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "cb_project_status",
|
||||
"fieldtype": "Column Break",
|
||||
"label": "Status"
|
||||
},
|
||||
{
|
||||
"description": "Project will get saved and will be searchable with project name given",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "project_name",
|
||||
"fieldtype": "Data",
|
||||
"label": "Project Name",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "project_name",
|
||||
"oldfieldtype": "Data",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"default": "Open",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"in_filter": 1,
|
||||
"label": "Status",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "status",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Open\nCompleted\nCancelled",
|
||||
"reqd": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "is_active",
|
||||
"fieldtype": "Select",
|
||||
"label": "Is Active",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "is_active",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Yes\nNo",
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "priority",
|
||||
"fieldtype": "Select",
|
||||
"label": "Priority",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "priority",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Medium\nLow\nHigh",
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "cb_project_dates",
|
||||
"fieldtype": "Column Break",
|
||||
"label": "Dates"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "project_start_date",
|
||||
"fieldtype": "Date",
|
||||
"in_filter": 1,
|
||||
"label": "Project Start Date",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "project_start_date",
|
||||
"oldfieldtype": "Date",
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "completion_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Completion Date",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "completion_date",
|
||||
"oldfieldtype": "Date",
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "act_completion_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Actual Completion Date",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "act_completion_date",
|
||||
"oldfieldtype": "Date",
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "project_type",
|
||||
"fieldtype": "Select",
|
||||
"label": "Project Type",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "project_type",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "Internal\nExternal\nOther",
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "sb_milestones",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Milestones",
|
||||
"oldfieldtype": "Section Break",
|
||||
"options": "icon-flag"
|
||||
},
|
||||
{
|
||||
"description": "Milestones will be added as Events in the Calendar",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "project_milestones",
|
||||
"fieldtype": "Table",
|
||||
"label": "Project Milestones",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "project_milestones",
|
||||
"oldfieldtype": "Table",
|
||||
"options": "Project Milestone",
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "section_break0",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Project Details",
|
||||
"oldfieldtype": "Section Break",
|
||||
"options": "icon-list"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "notes",
|
||||
"fieldtype": "Text Editor",
|
||||
"label": "Notes",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "notes",
|
||||
"oldfieldtype": "Text Editor",
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "percent_complete",
|
||||
"fieldtype": "Percent",
|
||||
"in_list_view": 1,
|
||||
"label": "Percent Complete",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"label": "Company",
|
||||
"options": "Company"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "project_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Project Costing",
|
||||
"oldfieldtype": "Section Break",
|
||||
"options": "icon-money"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "project_value",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Project Value",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "project_value",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"reqd": 0,
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "est_material_cost",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Estimated Material Cost",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "est_material_cost",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "column_break0",
|
||||
"fieldtype": "Column Break",
|
||||
"label": "Margin",
|
||||
"oldfieldtype": "Column Break",
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "gross_margin_value",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Gross Margin Value",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "gross_margin_value",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"reqd": 0,
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "per_gross_margin",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Gross Margin %",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "per_gross_margin",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"reqd": 0,
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "customer_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Customer Details",
|
||||
"oldfieldtype": "Section Break",
|
||||
"options": "icon-user"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "customer",
|
||||
"fieldtype": "Link",
|
||||
"in_filter": 1,
|
||||
"label": "Customer",
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "customer",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Customer",
|
||||
"print_hide": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"doctype": "DocPerm",
|
||||
"email": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"role": "Projects User",
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"doctype": "DocPerm",
|
||||
"permlevel": 1,
|
||||
"role": "All"
|
||||
}
|
||||
]
|
||||
11
erpnext/projects/doctype/project/test_project.py
Normal file
11
erpnext/projects/doctype/project/test_project.py
Normal file
@@ -0,0 +1,11 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
test_records = [[{
|
||||
"project_name": "_Test Project",
|
||||
"status": "Open"
|
||||
}],
|
||||
[{
|
||||
"project_name": "_Test Project 1",
|
||||
"status": "Open"
|
||||
}]]
|
||||
1
erpnext/projects/doctype/project_milestone/README.md
Normal file
1
erpnext/projects/doctype/project_milestone/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Important date in the project lifecycle.
|
||||
1
erpnext/projects/doctype/project_milestone/__init__.py
Normal file
1
erpnext/projects/doctype/project_milestone/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from __future__ import unicode_literals
|
||||
@@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
class DocType:
|
||||
def __init__(self, d, dl):
|
||||
self.doc, self.doclist = d, dl
|
||||
@@ -0,0 +1,56 @@
|
||||
[
|
||||
{
|
||||
"creation": "2013-02-22 01:27:50",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-12-20 19:23:27",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
{
|
||||
"doctype": "DocType",
|
||||
"istable": 1,
|
||||
"module": "Projects",
|
||||
"name": "__common__"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"in_list_view": 1,
|
||||
"name": "__common__",
|
||||
"parent": "Project Milestone",
|
||||
"parentfield": "fields",
|
||||
"parenttype": "DocType",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocType",
|
||||
"name": "Project Milestone"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "milestone_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Milestone Date",
|
||||
"oldfieldname": "milestone_date",
|
||||
"oldfieldtype": "Date"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "milestone",
|
||||
"fieldtype": "Text",
|
||||
"label": "Milestone",
|
||||
"oldfieldname": "milestone",
|
||||
"oldfieldtype": "Text",
|
||||
"print_width": "300px",
|
||||
"width": "300px"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"label": "Status",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "status",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Pending\nCompleted"
|
||||
}
|
||||
]
|
||||
1
erpnext/projects/doctype/task/README.md
Normal file
1
erpnext/projects/doctype/task/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Task to be completed for a Project (optional).
|
||||
1
erpnext/projects/doctype/task/__init__.py
Normal file
1
erpnext/projects/doctype/task/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from __future__ import unicode_literals
|
||||
32
erpnext/projects/doctype/task/task.js
Normal file
32
erpnext/projects/doctype/task/task.js
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
wn.provide("erpnext.projects");
|
||||
|
||||
cur_frm.add_fetch("project", "company", "company");
|
||||
|
||||
erpnext.projects.Task = wn.ui.form.Controller.extend({
|
||||
setup: function() {
|
||||
this.frm.fields_dict.project.get_query = function() {
|
||||
return {
|
||||
query: "projects.doctype.task.task.get_project"
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
project: function() {
|
||||
if(this.frm.doc.project) {
|
||||
return get_server_fields('get_project_details', '','', this.frm.doc, this.frm.doc.doctype,
|
||||
this.frm.doc.name, 1);
|
||||
}
|
||||
},
|
||||
|
||||
validate: function() {
|
||||
this.frm.doc.project && wn.model.remove_from_locals("Project",
|
||||
this.frm.doc.project);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
cur_frm.cscript = new erpnext.projects.Task({frm: cur_frm});
|
||||
|
||||
90
erpnext/projects/doctype/task/task.py
Normal file
90
erpnext/projects/doctype/task/task.py
Normal file
@@ -0,0 +1,90 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes, json
|
||||
|
||||
from webnotes.utils import getdate, today
|
||||
from webnotes.model import db_exists
|
||||
from webnotes.model.bean import copy_doclist
|
||||
from webnotes import msgprint
|
||||
|
||||
|
||||
class DocType:
|
||||
def __init__(self,doc,doclist=[]):
|
||||
self.doc = doc
|
||||
self.doclist = doclist
|
||||
|
||||
def get_project_details(self):
|
||||
cust = webnotes.conn.sql("select customer, customer_name from `tabProject` where name = %s", self.doc.project)
|
||||
if cust:
|
||||
ret = {'customer': cust and cust[0][0] or '', 'customer_name': cust and cust[0][1] or ''}
|
||||
return ret
|
||||
|
||||
def get_customer_details(self):
|
||||
cust = webnotes.conn.sql("select customer_name from `tabCustomer` where name=%s", self.doc.customer)
|
||||
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'")
|
||||
raise Exception
|
||||
|
||||
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()
|
||||
|
||||
def on_update(self):
|
||||
"""update percent complete in project"""
|
||||
if self.doc.project:
|
||||
project = webnotes.bean("Project", self.doc.project)
|
||||
project.run_method("update_percent_complete")
|
||||
|
||||
@webnotes.whitelist()
|
||||
def get_events(start, end, filters=None):
|
||||
from webnotes.widgets.reportview import build_match_conditions
|
||||
if not webnotes.has_permission("Task"):
|
||||
webnotes.msgprint(_("No Permission"), raise_exception=1)
|
||||
|
||||
conditions = build_match_conditions("Task")
|
||||
conditions and (" and " + conditions) or ""
|
||||
|
||||
if filters:
|
||||
filters = json.loads(filters)
|
||||
for key in filters:
|
||||
if filters[key]:
|
||||
conditions += " and " + key + ' = "' + filters[key].replace('"', '\"') + '"'
|
||||
|
||||
data = webnotes.conn.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'))
|
||||
%(conditions)s""" % {
|
||||
"start": start,
|
||||
"end": end,
|
||||
"conditions": conditions
|
||||
}, as_dict=True, update={"allDay": 0})
|
||||
|
||||
return data
|
||||
|
||||
def get_project(doctype, txt, searchfield, start, page_len, filters):
|
||||
from erpnext.controllers.queries import get_match_cond
|
||||
return webnotes.conn.sql(""" select name from `tabProject`
|
||||
where %(key)s like "%(txt)s"
|
||||
%(mcond)s
|
||||
order by name
|
||||
limit %(start)s, %(page_len)s """ % {'key': searchfield,
|
||||
'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype, searchfield),
|
||||
'start': start, 'page_len': page_len})
|
||||
259
erpnext/projects/doctype/task/task.txt
Normal file
259
erpnext/projects/doctype/task/task.txt
Normal file
@@ -0,0 +1,259 @@
|
||||
[
|
||||
{
|
||||
"creation": "2013-01-29 19:25:50",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-12-20 19:24:38",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
{
|
||||
"allow_attach": 1,
|
||||
"allow_import": 1,
|
||||
"autoname": "TASK.#####",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Master",
|
||||
"icon": "icon-check",
|
||||
"max_attachments": 5,
|
||||
"module": "Projects",
|
||||
"name": "__common__"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"name": "__common__",
|
||||
"parent": "Task",
|
||||
"parentfield": "fields",
|
||||
"parenttype": "DocType",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"doctype": "DocPerm",
|
||||
"email": 1,
|
||||
"name": "__common__",
|
||||
"parent": "Task",
|
||||
"parentfield": "permissions",
|
||||
"parenttype": "DocType",
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Projects User",
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocType",
|
||||
"name": "Task"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "task_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Task Details",
|
||||
"oldfieldtype": "Section Break",
|
||||
"print_width": "50%",
|
||||
"search_index": 0,
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "subject",
|
||||
"fieldtype": "Data",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Subject",
|
||||
"oldfieldname": "subject",
|
||||
"oldfieldtype": "Data",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "exp_start_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Expected Start Date",
|
||||
"oldfieldname": "exp_start_date",
|
||||
"oldfieldtype": "Date",
|
||||
"reqd": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "exp_end_date",
|
||||
"fieldtype": "Date",
|
||||
"in_filter": 1,
|
||||
"label": "Expected End Date",
|
||||
"oldfieldname": "exp_end_date",
|
||||
"oldfieldtype": "Date",
|
||||
"reqd": 0,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "column_break0",
|
||||
"fieldtype": "Column Break",
|
||||
"oldfieldtype": "Column Break",
|
||||
"print_width": "50%",
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "project",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Project",
|
||||
"oldfieldname": "project",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Project"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Status",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "status",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Open\nWorking\nPending Review\nClosed\nCancelled"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "priority",
|
||||
"fieldtype": "Select",
|
||||
"in_filter": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Priority",
|
||||
"oldfieldname": "priority",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Low\nMedium\nHigh\nUrgent",
|
||||
"reqd": 0,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "section_break0",
|
||||
"fieldtype": "Section Break",
|
||||
"oldfieldtype": "Section Break",
|
||||
"options": "Simple"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Text Editor",
|
||||
"label": "Details",
|
||||
"oldfieldname": "description",
|
||||
"oldfieldtype": "Text Editor",
|
||||
"print_width": "300px",
|
||||
"reqd": 0,
|
||||
"width": "300px"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "time_and_budget",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Time and Budget",
|
||||
"oldfieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "expected",
|
||||
"fieldtype": "Column Break",
|
||||
"label": "Expected",
|
||||
"oldfieldtype": "Column Break",
|
||||
"print_width": "50%",
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "exp_total_hrs",
|
||||
"fieldtype": "Data",
|
||||
"label": "Total Hours (Expected)",
|
||||
"oldfieldname": "exp_total_hrs",
|
||||
"oldfieldtype": "Data",
|
||||
"reqd": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "allocated_budget",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Allocated Budget",
|
||||
"oldfieldname": "allocated_budget",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "actual",
|
||||
"fieldtype": "Column Break",
|
||||
"label": "Actual",
|
||||
"oldfieldtype": "Column Break",
|
||||
"print_width": "50%",
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "act_start_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Actual Start Date",
|
||||
"oldfieldname": "act_start_date",
|
||||
"oldfieldtype": "Date"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "act_end_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Actual End Date",
|
||||
"oldfieldname": "act_end_date",
|
||||
"oldfieldtype": "Date"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "actual_budget",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Actual Budget",
|
||||
"oldfieldname": "actual_budget",
|
||||
"oldfieldtype": "Currency",
|
||||
"options": "Company:company:default_currency"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "more_details",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "More Details"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.status == \"Closed\" || doc.status == \"Pending Review\"",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "review_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"label": "Review Date",
|
||||
"oldfieldname": "review_date",
|
||||
"oldfieldtype": "Date"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.status == \"Closed\"",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "closing_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"label": "Closing Date",
|
||||
"oldfieldname": "closing_date",
|
||||
"oldfieldtype": "Date"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "column_break_22",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"label": "Company",
|
||||
"options": "Company"
|
||||
},
|
||||
{
|
||||
"doctype": "DocPerm"
|
||||
}
|
||||
]
|
||||
22
erpnext/projects/doctype/task/task_calendar.js
Normal file
22
erpnext/projects/doctype/task/task_calendar.js
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
wn.views.calendar["Task"] = {
|
||||
field_map: {
|
||||
"start": "exp_start_date",
|
||||
"end": "exp_end_date",
|
||||
"id": "name",
|
||||
"title": wn._("subject"),
|
||||
"allDay": "allDay"
|
||||
},
|
||||
gantt: true,
|
||||
filters: [
|
||||
{
|
||||
"fieldtype": "Link",
|
||||
"fieldname": "project",
|
||||
"options": "Project",
|
||||
"label": wn._("Project")
|
||||
}
|
||||
],
|
||||
get_events_method: "erpnext.projects.doctype.task.task.get_events"
|
||||
}
|
||||
10
erpnext/projects/doctype/task/test_task.py
Normal file
10
erpnext/projects/doctype/task/test_task.py
Normal file
@@ -0,0 +1,10 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
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"]
|
||||
1
erpnext/projects/doctype/time_log/README.md
Normal file
1
erpnext/projects/doctype/time_log/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Log of activity done by a user in a particular period.
|
||||
0
erpnext/projects/doctype/time_log/__init__.py
Normal file
0
erpnext/projects/doctype/time_log/__init__.py
Normal file
23
erpnext/projects/doctype/time_log/test_time_log.py
Normal file
23
erpnext/projects/doctype/time_log/test_time_log.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
import webnotes
|
||||
import unittest
|
||||
|
||||
from erpnext.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 = [[{
|
||||
"doctype": "Time Log",
|
||||
"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"]
|
||||
14
erpnext/projects/doctype/time_log/time_log.js
Normal file
14
erpnext/projects/doctype/time_log/time_log.js
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
wn.provide("erpnext.projects");
|
||||
|
||||
erpnext.projects.TimeLog = wn.ui.form.Controller.extend({
|
||||
onload: function() {
|
||||
this.frm.set_query("task", erpnext.queries.task);
|
||||
}
|
||||
});
|
||||
|
||||
cur_frm.cscript = new erpnext.projects.TimeLog({frm: cur_frm});
|
||||
|
||||
cur_frm.add_fetch('task','project','project');
|
||||
86
erpnext/projects/doctype/time_log/time_log.py
Normal file
86
erpnext/projects/doctype/time_log/time_log.py
Normal file
@@ -0,0 +1,86 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes import _
|
||||
from webnotes.utils import cstr
|
||||
|
||||
|
||||
class OverlapError(webnotes.ValidationError): pass
|
||||
|
||||
class DocType:
|
||||
def __init__(self, d, dl):
|
||||
self.doc, self.doclist = d, dl
|
||||
|
||||
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):
|
||||
self.doc.status = {
|
||||
0: "Draft",
|
||||
1: "Submitted",
|
||||
2: "Cancelled"
|
||||
}[self.doc.docstatus or 0]
|
||||
|
||||
if self.doc.time_log_batch:
|
||||
self.doc.status="Batched for Billing"
|
||||
|
||||
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) or
|
||||
(%s between from_time and to_time))
|
||||
and name!=%s
|
||||
and ifnull(task, "")=%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.from_time, self.doc.name or "No Name",
|
||||
cstr(self.doc.task)))
|
||||
|
||||
if existing:
|
||||
webnotes.msgprint(_("This Time Log conflicts with") + ":" + ', '.join(existing),
|
||||
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):
|
||||
from webnotes.widgets.reportview import build_match_conditions
|
||||
if not webnotes.has_permission("Time Log"):
|
||||
webnotes.msgprint(_("No Permission"), raise_exception=1)
|
||||
|
||||
match = build_match_conditions("Time Log")
|
||||
data = webnotes.conn.sql("""select name, from_time, to_time,
|
||||
activity_type, task, project from `tabTime Log`
|
||||
where from_time between '%(start)s' and '%(end)s' or to_time between '%(start)s' and '%(end)s'
|
||||
%(match)s""" % {
|
||||
"start": start,
|
||||
"end": end,
|
||||
"match": match and (" and " + match) or ""
|
||||
}, as_dict=True, update={"allDay": 0})
|
||||
|
||||
for d in data:
|
||||
d.title = d.name + ": " + (d.activity_type or "[Activity Type not set]")
|
||||
if d.task:
|
||||
d.title += " for Task: " + d.task
|
||||
if d.project:
|
||||
d.title += " for Project: " + d.project
|
||||
|
||||
return data
|
||||
214
erpnext/projects/doctype/time_log/time_log.txt
Normal file
214
erpnext/projects/doctype/time_log/time_log.txt
Normal file
@@ -0,0 +1,214 @@
|
||||
[
|
||||
{
|
||||
"creation": "2013-04-03 16:38:41",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-12-20 19:24:39",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
{
|
||||
"allow_attach": 1,
|
||||
"allow_import": 1,
|
||||
"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",
|
||||
"icon": "icon-time",
|
||||
"is_submittable": 1,
|
||||
"module": "Projects",
|
||||
"name": "__common__"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"name": "__common__",
|
||||
"parent": "Time Log",
|
||||
"parentfield": "fields",
|
||||
"parenttype": "DocType"
|
||||
},
|
||||
{
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"doctype": "DocPerm",
|
||||
"email": 1,
|
||||
"name": "__common__",
|
||||
"parent": "Time Log",
|
||||
"parentfield": "permissions",
|
||||
"parenttype": "DocType",
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocType",
|
||||
"name": "Time Log"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Select",
|
||||
"label": "Series",
|
||||
"options": "TL-",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "from_time",
|
||||
"fieldtype": "Datetime",
|
||||
"in_list_view": 1,
|
||||
"label": "From Time",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "to_time",
|
||||
"fieldtype": "Datetime",
|
||||
"in_list_view": 0,
|
||||
"label": "To Time",
|
||||
"permlevel": 0,
|
||||
"read_only": 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,
|
||||
"read_only": 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",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Activity Type",
|
||||
"options": "Activity Type",
|
||||
"permlevel": 0,
|
||||
"read_only": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "task",
|
||||
"fieldtype": "Link",
|
||||
"label": "Task",
|
||||
"options": "Task",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "billable",
|
||||
"fieldtype": "Check",
|
||||
"in_list_view": 1,
|
||||
"label": "Billable",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "section_break_7",
|
||||
"fieldtype": "Section Break",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "note",
|
||||
"fieldtype": "Text Editor",
|
||||
"label": "Note",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "section_break_9",
|
||||
"fieldtype": "Section Break",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "project",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Project",
|
||||
"options": "Project",
|
||||
"permlevel": 0,
|
||||
"read_only": 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": "column_break_16",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Link",
|
||||
"ignore_restrictions": 1,
|
||||
"label": "Amended From",
|
||||
"no_copy": 1,
|
||||
"options": "Time Log",
|
||||
"permlevel": 1,
|
||||
"print_hide": 1,
|
||||
"read_only": 0
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
"doctype": "DocPerm",
|
||||
"match": "owner",
|
||||
"role": "Projects User"
|
||||
},
|
||||
{
|
||||
"doctype": "DocPerm",
|
||||
"role": "Projects Manager"
|
||||
}
|
||||
]
|
||||
13
erpnext/projects/doctype/time_log/time_log_calendar.js
Normal file
13
erpnext/projects/doctype/time_log/time_log_calendar.js
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
wn.views.calendar["Time Log"] = {
|
||||
field_map: {
|
||||
"start": "from_time",
|
||||
"end": "to_time",
|
||||
"id": "name",
|
||||
"title": "title",
|
||||
"allDay": "allDay"
|
||||
},
|
||||
get_events_method: "erpnext.projects.doctype.time_log.time_log.get_events"
|
||||
}
|
||||
48
erpnext/projects/doctype/time_log/time_log_list.js
Normal file
48
erpnext/projects/doctype/time_log/time_log_list.js
Normal file
@@ -0,0 +1,48 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
// 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() {
|
||||
var selected = me.get_checked_items() || [];
|
||||
|
||||
if(!selected.length) {
|
||||
msgprint(wn._("Please select Time Logs."))
|
||||
}
|
||||
|
||||
// select only billable time logs
|
||||
for(var i in selected) {
|
||||
var d = selected[i];
|
||||
if(!d.billable) {
|
||||
msgprint(wn._("Time Log is not billable") + ": " + d.name);
|
||||
return;
|
||||
}
|
||||
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");
|
||||
}
|
||||
};
|
||||
1
erpnext/projects/doctype/time_log_batch/README.md
Normal file
1
erpnext/projects/doctype/time_log_batch/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Group of Time Logs that can be batched for billing.
|
||||
0
erpnext/projects/doctype/time_log_batch/__init__.py
Normal file
0
erpnext/projects/doctype/time_log_batch/__init__.py
Normal file
@@ -0,0 +1,39 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
import webnotes, unittest
|
||||
|
||||
class TimeLogBatchTest(unittest.TestCase):
|
||||
def test_time_log_status(self):
|
||||
from erpnext.projects.doctype.time_log.test_time_log import test_records as time_log_records
|
||||
time_log = webnotes.bean(copy=time_log_records[0])
|
||||
time_log.doc.fields.update({
|
||||
"from_time": "2013-01-02 10:00:00",
|
||||
"to_time": "2013-01-02 11:00:00",
|
||||
"docstatus": 0
|
||||
})
|
||||
time_log.insert()
|
||||
time_log.submit()
|
||||
|
||||
self.assertEquals(webnotes.conn.get_value("Time Log", time_log.doc.name, "status"), "Submitted")
|
||||
tlb = webnotes.bean(copy=test_records[0])
|
||||
tlb.doclist[1].time_log = time_log.doc.name
|
||||
tlb.insert()
|
||||
tlb.submit()
|
||||
|
||||
self.assertEquals(webnotes.conn.get_value("Time Log", time_log.doc.name, "status"), "Batched for Billing")
|
||||
tlb.cancel()
|
||||
self.assertEquals(webnotes.conn.get_value("Time Log", time_log.doc.name, "status"), "Submitted")
|
||||
|
||||
test_records = [[
|
||||
{
|
||||
"doctype": "Time Log Batch",
|
||||
"rate": "500"
|
||||
},
|
||||
{
|
||||
"doctype": "Time Log Batch Detail",
|
||||
"parenttype": "Time Log Batch",
|
||||
"parentfield": "time_log_batch_details",
|
||||
"time_log": "_T-Time Log-00001",
|
||||
}
|
||||
]]
|
||||
39
erpnext/projects/doctype/time_log_batch/time_log_batch.js
Normal file
39
erpnext/projects/doctype/time_log_batch/time_log_batch.js
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
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 {
|
||||
query: "projects.utils.get_time_log_list",
|
||||
filters: {
|
||||
"billable": 1,
|
||||
"status": "Submitted"
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$.extend(cur_frm.cscript, {
|
||||
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(wn._("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"
|
||||
});
|
||||
}
|
||||
});
|
||||
63
erpnext/projects/doctype/time_log_batch/time_log_batch.py
Normal file
63
erpnext/projects/doctype/time_log_batch/time_log_batch.py
Normal file
@@ -0,0 +1,63 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
# For license information, please see license.txt
|
||||
|
||||
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):
|
||||
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()
|
||||
|
||||
|
||||
|
||||
125
erpnext/projects/doctype/time_log_batch/time_log_batch.txt
Normal file
125
erpnext/projects/doctype/time_log_batch/time_log_batch.txt
Normal file
@@ -0,0 +1,125 @@
|
||||
[
|
||||
{
|
||||
"creation": "2013-02-28 17:57:33",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-12-20 19:24:39",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
{
|
||||
"autoname": "naming_series:",
|
||||
"description": "Batch Time Logs for Billing.",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Transaction",
|
||||
"icon": "icon-time",
|
||||
"is_submittable": 1,
|
||||
"module": "Projects",
|
||||
"name": "__common__"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"name": "__common__",
|
||||
"parent": "Time Log Batch",
|
||||
"parentfield": "fields",
|
||||
"parenttype": "DocType",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"doctype": "DocPerm",
|
||||
"email": 1,
|
||||
"name": "__common__",
|
||||
"parent": "Time Log Batch",
|
||||
"parentfield": "permissions",
|
||||
"parenttype": "DocType",
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Projects User",
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocType",
|
||||
"name": "Time Log Batch"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Select",
|
||||
"label": "Series",
|
||||
"options": "TLB-",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"description": "For Sales Invoice",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "rate",
|
||||
"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",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"description": "In Hours",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "total_hours",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Total Hours",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Link",
|
||||
"ignore_restrictions": 1,
|
||||
"label": "Amended From",
|
||||
"no_copy": 1,
|
||||
"options": "Time Log Batch",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocPerm"
|
||||
}
|
||||
]
|
||||
1
erpnext/projects/doctype/time_log_batch_detail/README.md
Normal file
1
erpnext/projects/doctype/time_log_batch_detail/README.md
Normal file
@@ -0,0 +1 @@
|
||||
Time Log detail for parent Time Log Batch.
|
||||
@@ -0,0 +1,11 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
class DocType:
|
||||
def __init__(self, d, dl):
|
||||
self.doc, self.doclist = d, dl
|
||||
@@ -0,0 +1,59 @@
|
||||
[
|
||||
{
|
||||
"creation": "2013-03-05 09:11:06",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-12-20 19:21:53",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
{
|
||||
"doctype": "DocType",
|
||||
"istable": 1,
|
||||
"module": "Projects",
|
||||
"name": "__common__"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"in_list_view": 1,
|
||||
"name": "__common__",
|
||||
"parent": "Time Log Batch Detail",
|
||||
"parentfield": "fields",
|
||||
"parenttype": "DocType",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocType",
|
||||
"name": "Time Log Batch Detail"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "time_log",
|
||||
"fieldtype": "Link",
|
||||
"label": "Time Log",
|
||||
"options": "Time Log",
|
||||
"print_width": "200px",
|
||||
"reqd": 1,
|
||||
"width": "200px"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "created_by",
|
||||
"fieldtype": "Link",
|
||||
"label": "Created By",
|
||||
"options": "Profile",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "activity_type",
|
||||
"fieldtype": "Data",
|
||||
"label": "Activity Type",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "hours",
|
||||
"fieldtype": "Float",
|
||||
"label": "Hours"
|
||||
}
|
||||
]
|
||||
1
erpnext/projects/page/__init__.py
Normal file
1
erpnext/projects/page/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from __future__ import unicode_literals
|
||||
1
erpnext/projects/page/projects_home/__init__.py
Normal file
1
erpnext/projects/page/projects_home/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from __future__ import unicode_literals
|
||||
80
erpnext/projects/page/projects_home/projects_home.js
Normal file
80
erpnext/projects/page/projects_home/projects_home.js
Normal file
@@ -0,0 +1,80 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt"
|
||||
|
||||
wn.module_page["Projects"] = [
|
||||
{
|
||||
title: wn._("Top"),
|
||||
icon: "icon-copy",
|
||||
top: true,
|
||||
items: [
|
||||
{
|
||||
label: wn._("Task"),
|
||||
description: wn._("Project activity / task."),
|
||||
doctype:"Task"
|
||||
},
|
||||
{
|
||||
label: wn._("Project"),
|
||||
description: wn._("Project master."),
|
||||
doctype:"Project"
|
||||
},
|
||||
{
|
||||
label: wn._("Time Log"),
|
||||
description: wn._("Time Log for tasks."),
|
||||
doctype:"Time Log"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
title: wn._("Documents"),
|
||||
icon: "icon-copy",
|
||||
items: [
|
||||
{
|
||||
label: wn._("Time Log Batch"),
|
||||
description: wn._("Batch Time Logs for billing."),
|
||||
doctype:"Time Log Batch"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
title: wn._("Tools"),
|
||||
icon: "icon-wrench",
|
||||
items: [
|
||||
{
|
||||
route: "Gantt/Task",
|
||||
label: wn._("Gantt Chart"),
|
||||
"description":wn._("Gantt chart of all tasks.")
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
title: wn._("Masters"),
|
||||
icon: "icon-book",
|
||||
items: [
|
||||
{
|
||||
label: wn._("Activity Type"),
|
||||
description: wn._("Types of activities for Time Sheets"),
|
||||
doctype:"Activity Type"
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
title: wn._("Reports"),
|
||||
right: true,
|
||||
icon: "icon-list",
|
||||
items: [
|
||||
{
|
||||
"label":wn._("Daily Time Log Summary"),
|
||||
route: "query-report/Daily Time Log Summary",
|
||||
doctype: "Time Log"
|
||||
},
|
||||
{
|
||||
"label":wn._("Project wise Stock Tracking"),
|
||||
route: "query-report/Project wise Stock Tracking",
|
||||
doctype: "Project"
|
||||
},
|
||||
]
|
||||
}]
|
||||
|
||||
pscript['onload_projects-home'] = function(wrapper) {
|
||||
wn.views.moduleview.make(wrapper, "Projects");
|
||||
}
|
||||
22
erpnext/projects/page/projects_home/projects_home.txt
Normal file
22
erpnext/projects/page/projects_home/projects_home.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
[
|
||||
{
|
||||
"creation": "2012-02-21 13:24:22",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-07-11 14:43:49",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
{
|
||||
"doctype": "Page",
|
||||
"icon": "icon-th",
|
||||
"module": "Projects",
|
||||
"name": "__common__",
|
||||
"page_name": "projects-home",
|
||||
"standard": "Yes",
|
||||
"title": "Projects Home"
|
||||
},
|
||||
{
|
||||
"doctype": "Page",
|
||||
"name": "projects-home"
|
||||
}
|
||||
]
|
||||
0
erpnext/projects/report/__init__.py
Normal file
0
erpnext/projects/report/__init__.py
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
// License: GNU General Public License v3. See license.txt
|
||||
|
||||
wn.query_reports["Daily Time Log Summary"] = {
|
||||
"filters": [
|
||||
{
|
||||
"fieldname":"from_date",
|
||||
"label": wn._("From Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": wn.datetime.get_today()
|
||||
},
|
||||
{
|
||||
"fieldname":"to_date",
|
||||
"label": wn._("To Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": wn.datetime.get_today()
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes.utils import flt
|
||||
|
||||
def execute(filters=None):
|
||||
if not filters:
|
||||
filters = {}
|
||||
elif filters.get("to_date"):
|
||||
filters["to_date"] = filters.get("to_date") + "24:00:00"
|
||||
|
||||
columns = ["Time Log:Link/Time Log:120", "Employee::150", "From Datetime::140",
|
||||
"To Datetime::140", "Hours::70", "Activity Type::120", "Task:Link/Task:150",
|
||||
"Task Subject::180", "Project:Link/Project:120", "Status::70"]
|
||||
|
||||
profile_map = get_profile_map()
|
||||
task_map = get_task_map()
|
||||
|
||||
conditions = build_conditions(filters)
|
||||
time_logs = webnotes.conn.sql("""select * from `tabTime Log`
|
||||
where docstatus < 2 %s order by owner asc""" % (conditions, ), filters, as_dict=1)
|
||||
|
||||
if time_logs:
|
||||
profiles = [time_logs[0].owner]
|
||||
|
||||
data = []
|
||||
total_hours = total_employee_hours = count = 0
|
||||
for tl in time_logs:
|
||||
if tl.owner not in profiles:
|
||||
profiles.append(tl.owner)
|
||||
data.append(["", "", "", "Total", total_employee_hours, "", "", "", "", ""])
|
||||
total_employee_hours = 0
|
||||
|
||||
data.append([tl.name, profile_map[tl.owner], tl.from_time, tl.to_time, tl.hours,
|
||||
tl.activity_type, tl.task, task_map.get(tl.task), tl.project, tl.status])
|
||||
|
||||
count += 1
|
||||
total_hours += flt(tl.hours)
|
||||
total_employee_hours += flt(tl.hours)
|
||||
|
||||
if count == len(time_logs):
|
||||
data.append(["", "", "", "Total Hours", total_employee_hours, "", "", "", "", ""])
|
||||
|
||||
if total_hours:
|
||||
data.append(["", "", "", "Grand Total", total_hours, "", "", "", "", ""])
|
||||
|
||||
return columns, data
|
||||
|
||||
def get_profile_map():
|
||||
profiles = webnotes.conn.sql("""select name,
|
||||
concat(first_name, if(last_name, (' ' + last_name), '')) as fullname
|
||||
from tabProfile""", as_dict=1)
|
||||
profile_map = {}
|
||||
for p in profiles:
|
||||
profile_map.setdefault(p.name, []).append(p.fullname)
|
||||
|
||||
return profile_map
|
||||
|
||||
def get_task_map():
|
||||
tasks = webnotes.conn.sql("""select name, subject from tabTask""", as_dict=1)
|
||||
task_map = {}
|
||||
for t in tasks:
|
||||
task_map.setdefault(t.name, []).append(t.subject)
|
||||
|
||||
return task_map
|
||||
|
||||
def build_conditions(filters):
|
||||
conditions = ""
|
||||
if filters.get("from_date"):
|
||||
conditions += " and from_time >= %(from_date)s"
|
||||
if filters.get("to_date"):
|
||||
conditions += " and to_time <= %(to_date)s"
|
||||
|
||||
from webnotes.widgets.reportview import build_match_conditions
|
||||
match_conditions = build_match_conditions("Time Log")
|
||||
if match_conditions:
|
||||
conditions += " and %s" % match_conditions
|
||||
|
||||
return conditions
|
||||
@@ -0,0 +1,21 @@
|
||||
[
|
||||
{
|
||||
"creation": "2013-04-03 11:27:52",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-04-03 11:48:07",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
{
|
||||
"doctype": "Report",
|
||||
"is_standard": "Yes",
|
||||
"name": "__common__",
|
||||
"ref_doctype": "Time Log",
|
||||
"report_name": "Daily Time Log Summary",
|
||||
"report_type": "Script Report"
|
||||
},
|
||||
{
|
||||
"doctype": "Report",
|
||||
"name": "Daily Time Log Summary"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,77 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
import webnotes
|
||||
|
||||
def execute(filters=None):
|
||||
columns = get_columns()
|
||||
proj_details = get_project_details()
|
||||
pr_item_map = get_purchased_items_cost()
|
||||
se_item_map = get_issued_items_cost()
|
||||
dn_item_map = get_delivered_items_cost()
|
||||
|
||||
data = []
|
||||
for project in proj_details:
|
||||
data.append([project.name, pr_item_map.get(project.name, 0),
|
||||
se_item_map.get(project.name, 0), dn_item_map.get(project.name, 0),
|
||||
project.project_name, project.status, project.company,
|
||||
project.customer, project.project_value, project.project_start_date,
|
||||
project.completion_date])
|
||||
|
||||
return columns, data
|
||||
|
||||
def get_columns():
|
||||
return ["Project Id:Link/Project:140", "Cost of Purchased Items:Currency:160",
|
||||
"Cost of Issued Items:Currency:160", "Cost of Delivered Items:Currency:160",
|
||||
"Project Name::120", "Project Status::120", "Company:Link/Company:100",
|
||||
"Customer:Link/Customer:140", "Project Value:Currency:120",
|
||||
"Project Start Date:Date:120", "Completion Date:Date:120"]
|
||||
|
||||
def get_project_details():
|
||||
return webnotes.conn.sql(""" select name, project_name, status, company, customer, project_value,
|
||||
project_start_date, completion_date from tabProject where docstatus < 2""", as_dict=1)
|
||||
|
||||
def get_purchased_items_cost():
|
||||
pr_items = webnotes.conn.sql("""select project_name, sum(amount) as amount
|
||||
from `tabPurchase Receipt Item` where ifnull(project_name, '') != ''
|
||||
and docstatus = 1 group by project_name""", as_dict=1)
|
||||
|
||||
pr_item_map = {}
|
||||
for item in pr_items:
|
||||
pr_item_map.setdefault(item.project_name, item.amount)
|
||||
|
||||
return pr_item_map
|
||||
|
||||
def get_issued_items_cost():
|
||||
se_items = webnotes.conn.sql("""select se.project_name, sum(se_item.amount) as amount
|
||||
from `tabStock Entry` se, `tabStock Entry Detail` se_item
|
||||
where se.name = se_item.parent and se.docstatus = 1 and ifnull(se_item.t_warehouse, '') = ''
|
||||
and ifnull(se.project_name, '') != '' group by se.project_name""", as_dict=1)
|
||||
|
||||
se_item_map = {}
|
||||
for item in se_items:
|
||||
se_item_map.setdefault(item.project_name, item.amount)
|
||||
|
||||
return se_item_map
|
||||
|
||||
def get_delivered_items_cost():
|
||||
dn_items = webnotes.conn.sql("""select dn.project_name, sum(dn_item.amount) as amount
|
||||
from `tabDelivery Note` dn, `tabDelivery Note Item` dn_item
|
||||
where dn.name = dn_item.parent and dn.docstatus = 1 and ifnull(dn.project_name, '') != ''
|
||||
group by dn.project_name""", as_dict=1)
|
||||
|
||||
si_items = webnotes.conn.sql("""select si.project_name, sum(si_item.amount) as amount
|
||||
from `tabSales Invoice` si, `tabSales Invoice Item` si_item
|
||||
where si.name = si_item.parent and si.docstatus = 1 and ifnull(si.update_stock, 0) = 1
|
||||
and ifnull(si.is_pos, 0) = 1 and ifnull(si.project_name, '') != ''
|
||||
group by si.project_name""", as_dict=1)
|
||||
|
||||
|
||||
dn_item_map = {}
|
||||
for item in dn_items:
|
||||
dn_item_map.setdefault(item.project_name, item.amount)
|
||||
|
||||
for item in si_items:
|
||||
dn_item_map.setdefault(item.project_name, item.amount)
|
||||
|
||||
return dn_item_map
|
||||
@@ -0,0 +1,21 @@
|
||||
[
|
||||
{
|
||||
"creation": "2013-06-03 17:37:41",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-06-03 17:37:41",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
{
|
||||
"doctype": "Report",
|
||||
"is_standard": "Yes",
|
||||
"name": "__common__",
|
||||
"ref_doctype": "Project",
|
||||
"report_name": "Project wise Stock Tracking ",
|
||||
"report_type": "Report Builder"
|
||||
},
|
||||
{
|
||||
"doctype": "Report",
|
||||
"name": "Project wise Stock Tracking"
|
||||
}
|
||||
]
|
||||
32
erpnext/projects/utils.py
Normal file
32
erpnext/projects/utils.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
@webnotes.whitelist()
|
||||
def get_time_log_list(doctype, txt, searchfield, start, page_len, filters):
|
||||
return webnotes.conn.get_values("Time Log", filters, ["name", "activity_type", "owner"])
|
||||
|
||||
@webnotes.whitelist()
|
||||
def query_task(doctype, txt, searchfield, start, page_len, filters):
|
||||
from webnotes.widgets.reportview import build_match_conditions
|
||||
|
||||
search_string = "%%%s%%" % txt
|
||||
order_by_string = "%s%%" % txt
|
||||
match_conditions = build_match_conditions("Task")
|
||||
match_conditions = ("and" + match_conditions) if match_conditions else ""
|
||||
|
||||
return webnotes.conn.sql("""select name, subject from `tabTask`
|
||||
where (`%s` like %s or `subject` like %s) %s
|
||||
order by
|
||||
case when `subject` like %s then 0 else 1 end,
|
||||
case when `%s` like %s then 0 else 1 end,
|
||||
`%s`,
|
||||
subject
|
||||
limit %s, %s""" %
|
||||
(searchfield, "%s", "%s", match_conditions, "%s",
|
||||
searchfield, "%s", searchfield, "%s", "%s"),
|
||||
(search_string, search_string, order_by_string, order_by_string, start, page_len))
|
||||
Reference in New Issue
Block a user