Task added to expense claim
all cost (expense claim and time log) against Task; task updates project cost.
This commit is contained in:
parent
8026137998
commit
50234cb0fe
@ -191,6 +191,14 @@
|
|||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": ""
|
"precision": ""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "task",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Task",
|
||||||
|
"options": "Task",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "email_id",
|
"fieldname": "email_id",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
@ -220,7 +228,7 @@
|
|||||||
"icon": "icon-money",
|
"icon": "icon-money",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"modified": "2015-03-26 04:41:50.473196",
|
"modified": "2015-03-30 05:17:43.963137",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Expense Claim",
|
"name": "Expense Claim",
|
||||||
|
@ -21,17 +21,18 @@ class ExpenseClaim(Document):
|
|||||||
self.validate_sanctioned_amount()
|
self.validate_sanctioned_amount()
|
||||||
self.validate_exp_details()
|
self.validate_exp_details()
|
||||||
self.validate_expense_approver()
|
self.validate_expense_approver()
|
||||||
|
self.validate_task()
|
||||||
set_employee_name(self)
|
set_employee_name(self)
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
if self.approval_status=="Draft":
|
if self.approval_status=="Draft":
|
||||||
frappe.throw(_("""Approval Status must be 'Approved' or 'Rejected'"""))
|
frappe.throw(_("""Approval Status must be 'Approved' or 'Rejected'"""))
|
||||||
if self.project:
|
if self.task:
|
||||||
self.update_project()
|
self.update_task()
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
if self.project:
|
if self.project:
|
||||||
self.update_project()
|
self.update_task()
|
||||||
|
|
||||||
def validate_exp_details(self):
|
def validate_exp_details(self):
|
||||||
if not self.get('expenses'):
|
if not self.get('expenses'):
|
||||||
@ -42,10 +43,14 @@ class ExpenseClaim(Document):
|
|||||||
frappe.throw(_("{0} ({1}) must have role 'Expense Approver'")\
|
frappe.throw(_("{0} ({1}) must have role 'Expense Approver'")\
|
||||||
.format(get_fullname(self.exp_approver), self.exp_approver), InvalidExpenseApproverError)
|
.format(get_fullname(self.exp_approver), self.exp_approver), InvalidExpenseApproverError)
|
||||||
|
|
||||||
def update_project(self):
|
def update_task(self):
|
||||||
expense_amount = frappe.db.sql("""select sum(total_sanctioned_amount) from `tabExpense Claim`
|
expense_amount = frappe.db.sql("""select sum(total_sanctioned_amount) from `tabExpense Claim`
|
||||||
where project = %s and approval_status = "Approved" and docstatus=1""",self.project)
|
where project = %s and task = %s and approval_status = "Approved" and docstatus=1""",(self.project, self.task))
|
||||||
frappe.db.set_value("Project", self.project, "total_expense_claims", expense_amount)
|
frappe.db.set_value("Project", self.project, "total_expense_claim", expense_amount)
|
||||||
|
|
||||||
|
def validate_task(self):
|
||||||
|
if self.project and not self.task:
|
||||||
|
frappe.throw(_("Task is Mandatory if Time Log is against a project"))
|
||||||
|
|
||||||
def validate_sanctioned_amount(self):
|
def validate_sanctioned_amount(self):
|
||||||
if self.total_sanctioned_amount > self.total_claimed_amount:
|
if self.total_sanctioned_amount > self.total_claimed_amount:
|
||||||
|
@ -206,9 +206,9 @@
|
|||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "total_expense_claims",
|
"fieldname": "total_expense_claim",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Total Expense Claims",
|
"label": "Total Expense Claim",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
@ -278,7 +278,7 @@
|
|||||||
"icon": "icon-puzzle-piece",
|
"icon": "icon-puzzle-piece",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"max_attachments": 4,
|
"max_attachments": 4,
|
||||||
"modified": "2015-03-23 06:44:19.538443",
|
"modified": "2015-03-30 08:42:33.940104",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Projects",
|
"module": "Projects",
|
||||||
"name": "Project",
|
"name": "Project",
|
||||||
|
@ -25,6 +25,19 @@ erpnext.projects.Task = frappe.ui.form.Controller.extend({
|
|||||||
this.frm.doc.project && frappe.model.remove_from_locals("Project",
|
this.frm.doc.project && frappe.model.remove_from_locals("Project",
|
||||||
this.frm.doc.project);
|
this.frm.doc.project);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
refresh: function(doc) {
|
||||||
|
if(!doc.__islocal) {
|
||||||
|
cur_frm.add_custom_button(__("Time Logs"), function() {
|
||||||
|
frappe.route_options = {"project": doc.project, "task": doc.name}
|
||||||
|
frappe.set_route("List", "Time Log");
|
||||||
|
}, "icon-list", true);
|
||||||
|
cur_frm.add_custom_button(__("Expense Claims"), function() {
|
||||||
|
frappe.route_options = {"project": doc.project, "task": doc.name}
|
||||||
|
frappe.set_route("List", "Expense Claim");
|
||||||
|
}, "icon-list", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,16 +6,6 @@
|
|||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "Master",
|
"document_type": "Master",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
|
||||||
"fieldname": "task_details",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"label": "",
|
|
||||||
"oldfieldtype": "Section Break",
|
|
||||||
"permlevel": 0,
|
|
||||||
"print_width": "50%",
|
|
||||||
"search_index": 0,
|
|
||||||
"width": "50%"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "subject",
|
"fieldname": "subject",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
@ -110,28 +100,27 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "time_and_budget",
|
"fieldname": "time_and_budget",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Time and Budget",
|
"label": "",
|
||||||
"oldfieldtype": "Section Break",
|
"oldfieldtype": "Section Break",
|
||||||
"permlevel": 0
|
"permlevel": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "expected",
|
"default": "0",
|
||||||
"fieldtype": "Column Break",
|
"description": "in Hours",
|
||||||
"label": "Expected",
|
"fieldname": "expected_time",
|
||||||
"oldfieldtype": "Column Break",
|
"fieldtype": "Float",
|
||||||
"permlevel": 0,
|
"label": "Expected Time",
|
||||||
"print_width": "50%",
|
|
||||||
"width": "50%"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "exp_total_hrs",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"label": "Total Hours (Expected)",
|
|
||||||
"oldfieldname": "exp_total_hrs",
|
"oldfieldname": "exp_total_hrs",
|
||||||
"oldfieldtype": "Data",
|
"oldfieldtype": "Data",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"reqd": 0
|
"reqd": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_12",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": ""
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "allocated_budget",
|
"fieldname": "allocated_budget",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
@ -143,8 +132,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "actual",
|
"fieldname": "actual",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Actual",
|
"label": "",
|
||||||
"oldfieldtype": "Column Break",
|
"oldfieldtype": "Column Break",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_width": "50%",
|
"print_width": "50%",
|
||||||
@ -156,7 +145,14 @@
|
|||||||
"label": "Actual Start Date",
|
"label": "Actual Start Date",
|
||||||
"oldfieldname": "act_start_date",
|
"oldfieldname": "act_start_date",
|
||||||
"oldfieldtype": "Date",
|
"oldfieldtype": "Date",
|
||||||
"permlevel": 0
|
"permlevel": 0,
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_15",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "act_end_date",
|
"fieldname": "act_end_date",
|
||||||
@ -164,16 +160,50 @@
|
|||||||
"label": "Actual End Date",
|
"label": "Actual End Date",
|
||||||
"oldfieldname": "act_end_date",
|
"oldfieldname": "act_end_date",
|
||||||
"oldfieldtype": "Date",
|
"oldfieldtype": "Date",
|
||||||
"permlevel": 0
|
"permlevel": 0,
|
||||||
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "actual_budget",
|
"fieldname": "section_break_17",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"description": "in Hours",
|
||||||
|
"fieldname": "actual_time",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "Actual Time",
|
||||||
|
"options": "",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_20",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "actual_cost",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Actual Budget",
|
"label": "Actual Cost",
|
||||||
"oldfieldname": "actual_budget",
|
"oldfieldname": "actual_budget",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
"permlevel": 0
|
"permlevel": 0,
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "total_expense_claim",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Total Expense Claim",
|
||||||
|
"options": "Company:company:default_currency",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "more_details",
|
"fieldname": "more_details",
|
||||||
@ -217,7 +247,7 @@
|
|||||||
"icon": "icon-check",
|
"icon": "icon-check",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"max_attachments": 5,
|
"max_attachments": 5,
|
||||||
"modified": "2015-02-20 05:09:27.295024",
|
"modified": "2015-03-30 05:50:04.409614",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Projects",
|
"module": "Projects",
|
||||||
"name": "Task",
|
"name": "Task",
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe, json
|
import frappe, json
|
||||||
|
|
||||||
from frappe.utils import getdate, today
|
from frappe.utils import getdate
|
||||||
from frappe import _
|
from frappe import _
|
||||||
|
|
||||||
|
|
||||||
@ -26,28 +26,34 @@ class Task(Document):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
|
self.validate_dates()
|
||||||
|
|
||||||
|
def validate_dates(self):
|
||||||
if self.exp_start_date and self.exp_end_date and getdate(self.exp_start_date) > getdate(self.exp_end_date):
|
if self.exp_start_date and self.exp_end_date and getdate(self.exp_start_date) > getdate(self.exp_end_date):
|
||||||
frappe.throw(_("'Expected Start Date' can not be greater than 'Expected End Date'"))
|
frappe.throw(_("'Expected Start Date' can not be greater than 'Expected End Date'"))
|
||||||
|
|
||||||
if self.act_start_date and self.act_end_date and getdate(self.act_start_date) > getdate(self.act_end_date):
|
if self.act_start_date and self.act_end_date and getdate(self.act_start_date) > getdate(self.act_end_date):
|
||||||
frappe.throw(_("'Actual Start Date' can not be greater than 'Actual End Date'"))
|
frappe.throw(_("'Actual Start Date' can not be greater than 'Actual End Date'"))
|
||||||
|
|
||||||
self.update_status()
|
|
||||||
|
|
||||||
def update_status(self):
|
|
||||||
status = frappe.db.get_value("Task", self.name, "status")
|
|
||||||
if self.status=="Working" and status !="Working" and not self.act_start_date:
|
|
||||||
self.act_start_date = today()
|
|
||||||
|
|
||||||
if self.status=="Closed" and status != "Closed" and not self.act_end_date:
|
|
||||||
self.act_end_date = today()
|
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
|
self.update_percentage()
|
||||||
|
self.update_project()
|
||||||
|
|
||||||
|
def update_percentage(self):
|
||||||
"""update percent complete in project"""
|
"""update percent complete in project"""
|
||||||
if self.project and not self.flags.from_project:
|
if self.project and not self.flags.from_project:
|
||||||
project = frappe.get_doc("Project", self.project)
|
project = frappe.get_doc("Project", self.project)
|
||||||
project.run_method("update_percent_complete")
|
project.run_method("update_percent_complete")
|
||||||
|
|
||||||
|
def update_project(self):
|
||||||
|
total_activity_cost = frappe.db.sql("""select sum(actual_cost) from `tabTask`
|
||||||
|
where project = %s""",self.project)
|
||||||
|
frappe.db.set_value("Project", self.project, "total_activity_cost", total_activity_cost)
|
||||||
|
|
||||||
|
total_expense_claim = frappe.db.sql("""select sum(total_expense_claim) from `tabTask`
|
||||||
|
where project = %s""",self.project)
|
||||||
|
frappe.db.set_value("Project", self.project, "total_expense_claim", total_expense_claim)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_events(start, end, filters=None):
|
def get_events(start, end, filters=None):
|
||||||
from frappe.desk.reportview import build_match_conditions
|
from frappe.desk.reportview import build_match_conditions
|
||||||
|
@ -91,6 +91,25 @@
|
|||||||
"precision": "",
|
"precision": "",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "",
|
||||||
|
"fieldname": "project",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Project",
|
||||||
|
"options": "Project",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "",
|
||||||
|
"fieldname": "task",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Task",
|
||||||
|
"options": "Task",
|
||||||
|
"permlevel": 0,
|
||||||
|
"read_only": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:!doc.for_manufacturing",
|
"depends_on": "eval:!doc.for_manufacturing",
|
||||||
"fieldname": "activity_type",
|
"fieldname": "activity_type",
|
||||||
@ -102,15 +121,6 @@
|
|||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"reqd": 0
|
"reqd": 0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"depends_on": "eval:!doc.for_manufacturing",
|
|
||||||
"fieldname": "task",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Task",
|
|
||||||
"options": "Task",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.for_manufacturing",
|
"depends_on": "eval:doc.for_manufacturing",
|
||||||
"fieldname": "section_break_11",
|
"fieldname": "section_break_11",
|
||||||
@ -188,22 +198,6 @@
|
|||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"read_only": 0
|
"read_only": 0
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "section_break_9",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"depends_on": "",
|
|
||||||
"fieldname": "project",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Project",
|
|
||||||
"options": "Project",
|
|
||||||
"permlevel": 0,
|
|
||||||
"read_only": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"depends_on": "",
|
"depends_on": "",
|
||||||
"fieldname": "section_break_24",
|
"fieldname": "section_break_24",
|
||||||
|
@ -24,15 +24,20 @@ class TimeLog(Document):
|
|||||||
self.check_workstation_timings()
|
self.check_workstation_timings()
|
||||||
self.validate_production_order()
|
self.validate_production_order()
|
||||||
self.validate_manufacturing()
|
self.validate_manufacturing()
|
||||||
|
self.validate_task()
|
||||||
self.validate_cost()
|
self.validate_cost()
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
self.update_production_order()
|
if self.for_manufacturing:
|
||||||
self.update_project()
|
self.update_production_order()
|
||||||
|
if self.task:
|
||||||
|
self.update_task()
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
self.update_production_order()
|
if self.for_manufacturing:
|
||||||
self.update_project()
|
self.update_production_order()
|
||||||
|
if self.task:
|
||||||
|
self.update_task()
|
||||||
|
|
||||||
def before_update_after_submit(self):
|
def before_update_after_submit(self):
|
||||||
self.set_status()
|
self.set_status()
|
||||||
@ -128,7 +133,7 @@ class TimeLog(Document):
|
|||||||
def update_production_order(self):
|
def update_production_order(self):
|
||||||
"""Updates `start_date`, `end_date`, `status` for operation in Production Order."""
|
"""Updates `start_date`, `end_date`, `status` for operation in Production Order."""
|
||||||
|
|
||||||
if self.for_manufacturing and self.production_order:
|
if self.production_order:
|
||||||
if not self.operation_id:
|
if not self.operation_id:
|
||||||
frappe.throw(_("Operation ID not set"))
|
frappe.throw(_("Operation ID not set"))
|
||||||
|
|
||||||
@ -217,10 +222,22 @@ class TimeLog(Document):
|
|||||||
else:
|
else:
|
||||||
self.billing_amount = 0
|
self.billing_amount = 0
|
||||||
|
|
||||||
def update_project(self):
|
def validate_task(self):
|
||||||
activity_cost = frappe.db.sql("""select sum(billing_cost) from `tabTime Log`
|
if self.project and not self.task:
|
||||||
where project = %s and docstatus=1""",self.project)
|
frappe.throw(_("Task is Mandatory if Time Log is against a project"))
|
||||||
frappe.db.set_value("Project", self.project, "total_activity_cost", activity_cost)
|
|
||||||
|
def update_task(self):
|
||||||
|
tl = frappe.db.sql("""select min(from_time) as start_date, max(to_time) as end_date, sum(billing_amount) as cost, sum(hours) as time
|
||||||
|
from `tabTime Log` where project = %s and task = %s and docstatus=1""",(self.project, self.task),as_dict=1)[0]
|
||||||
|
|
||||||
|
task = frappe.get_doc("Task", self.task)
|
||||||
|
if task.status == "Open":
|
||||||
|
task.status = "Working"
|
||||||
|
task.actual_cost= tl.cost
|
||||||
|
task.actual_time= tl.time
|
||||||
|
task.act_start_date= tl.start_date
|
||||||
|
task.act_end_date= tl.end_date
|
||||||
|
task.save()
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_events(start, end, filters=None):
|
def get_events(start, end, filters=None):
|
||||||
|
Loading…
Reference in New Issue
Block a user