From a6927e05ba840e6f9f51eed601e978b9bca15921 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 7 Sep 2016 14:39:17 +0530 Subject: [PATCH] set project wise timesheet data --- .../doctype/sales_invoice/sales_invoice.js | 17 ++++++++--- .../doctype/sales_invoice/sales_invoice.py | 21 +++++++++++++ .../projects/doctype/timesheet/timesheet.json | 28 ++++++++++++++++- .../projects/doctype/timesheet/timesheet.py | 30 +++++++++++++++++++ 4 files changed, 91 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 4886deaa71..47ebc3da78 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -462,12 +462,21 @@ cur_frm.set_query("asset", "items", function(doc, cdt, cdn) { frappe.ui.form.on('Sales Invoice', { setup: function(frm){ frm.fields_dict["timesheets"].grid.get_field("time_sheet").get_query = function(doc, cdt, cdn){ - return { - filters: [ - ["Timesheet", "status", "in", ["Submitted", "Payslip"]] - ] + return{ + query: "erpnext.projects.doctype.timesheet.timesheet.get_timesheet", + filters: {'project': doc.project} } } + }, + + project: function(frm){ + frm.call({ + method: "add_timesheet_data", + doc: frm.doc, + callback: function(r, rt) { + refresh_field(['timesheets']) + } + }) } }) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index ec72be1bad..34296eabe8 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -14,6 +14,7 @@ from erpnext.accounts.doctype.sales_invoice.pos import update_multi_mode_option from erpnext.controllers.selling_controller import SellingController from erpnext.accounts.utils import get_account_currency from erpnext.stock.doctype.delivery_note.delivery_note import update_billed_amount_based_on_so +from erpnext.projects.doctype.timesheet.timesheet import get_projectwise_timesheet_data from erpnext.accounts.doctype.asset.depreciation \ import get_disposal_account_and_cost_center, get_gl_entries_on_asset_disposal @@ -221,11 +222,19 @@ class SalesInvoice(SellingController): for d in self.timesheets: if d.time_sheet: timesheet = frappe.get_doc("Timesheet", d.time_sheet) + self.update_time_sheet_detail(timesheet, d) timesheet.sales_invoice = sales_invoice timesheet.flags.ignore_validate_update_after_submit = True timesheet.set_status() timesheet.save() + def update_time_sheet_detail(self, timesheet, args): + for data in timesheet.time_logs: + if (self.project and self.project == data.project) or \ + (not self.project and (data.billing_amount - data.billed_amount) > 0): + data.billed_amount = args.billing_amount + if self.project: return + def on_update(self): self.set_paid_amount() @@ -464,6 +473,18 @@ class SalesInvoice(SellingController): self.total_billing_amount = total_billing_amount + def add_timesheet_data(self): + self.set('timesheets', []) + if self.project: + for data in get_projectwise_timesheet_data(self.project): + self.append('timesheets', { + 'time_sheet': data.parent, + 'billing_hours': data.billing_hours, + 'billing_amount': data.billing_amt + }) + + self.calculate_billing_amount_from_timesheet() + def get_warehouse(self): user_pos_profile = frappe.db.sql("""select name, warehouse from `tabPOS Profile` where ifnull(user,'') = %s and company = %s""", (frappe.session['user'], self.company)) diff --git a/erpnext/projects/doctype/timesheet/timesheet.json b/erpnext/projects/doctype/timesheet/timesheet.json index 781fa03e1f..1c174c81f8 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.json +++ b/erpnext/projects/doctype/timesheet/timesheet.json @@ -570,6 +570,32 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 1, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "total_billed_amount", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Total Billed Amount", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -739,7 +765,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2016-09-07 02:54:20.930768", + "modified": "2016-09-07 06:48:27.316087", "modified_by": "Administrator", "module": "Projects", "name": "Timesheet", diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py index 63cb8981d0..68a8f4d555 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.py +++ b/erpnext/projects/doctype/timesheet/timesheet.py @@ -31,6 +31,7 @@ class Timesheet(Document): self.total_billing_hours = 0.0 self.total_billing_amount = 0.0 self.total_costing_amount = 0.0 + self.total_billed_amount = 0.0 for d in self.get("time_logs"): self.update_billing_hours(d) @@ -40,6 +41,7 @@ class Timesheet(Document): if d.billable: self.total_billing_amount += flt(d.billing_amount) self.total_costing_amount += flt(d.costing_amount) + self.total_billed_amount += flt(d.billed_amount) def update_billing_hours(self, args): if cint(args.billing_hours) == 0: @@ -245,6 +247,34 @@ class Timesheet(Document): data.billing_amount = data.billing_rate * hours data.costing_amount = data.costing_rate * hours +@frappe.whitelist() +def get_projectwise_timesheet_data(project, parent=None): + cond = '' + if parent: + cond = "and parent = %(parent)s" + + return frappe.db.sql("""select parent, billing_hours, (billing_amount - billed_amount) as billing_amt + from `tabTimesheet Detail` where docstatus=1 and project = %(project)s {0} + having billing_amt > 0""".format(cond), {'project': project, 'parent': parent}, as_dict=1) + +@frappe.whitelist() +def get_timesheet(doctype, txt, searchfield, start, page_len, filters): + if not filters: filters = {} + + condition = "" + if filters.get("project"): + condition = "and tsd.project = %(project)s" + + return frappe.db.sql("""select distinct tsd.parent from `tabTimesheet Detail` tsd, + `tabTimesheet` ts where ts.status in ('Submitted', 'Payslip') and + (tsd.billing_amount - tsd.billed_amount) > 0 and + tsd.docstatus = 1 and tsd.parent LIKE %(txt)s {condition} + order by tsd.parent limit %(start)s, %(page_len)s""" + .format(condition=condition), { + "txt": "%%%s%%" % frappe.db.escape(txt), + "start": start, "page_len": page_len, 'project': filters.get("project") + }) + @frappe.whitelist() def make_sales_invoice(source_name, target=None): target = frappe.new_doc("Sales Invoice")