Rename Time Sheet doctype
This commit is contained in:
parent
21f443e37c
commit
e94d18b4cd
@ -238,7 +238,7 @@ class SalesInvoice(SellingController):
|
|||||||
def update_time_sheet(self, sales_invoice):
|
def update_time_sheet(self, sales_invoice):
|
||||||
for d in self.timesheets:
|
for d in self.timesheets:
|
||||||
if d.time_sheet:
|
if d.time_sheet:
|
||||||
timesheet = frappe.get_doc("Time Sheet", d.time_sheet)
|
timesheet = frappe.get_doc("Timesheet", d.time_sheet)
|
||||||
timesheet.sales_invoice = sales_invoice
|
timesheet.sales_invoice = sales_invoice
|
||||||
timesheet.flags.ignore_validate_update_after_submit = True
|
timesheet.flags.ignore_validate_update_after_submit = True
|
||||||
timesheet.set_status()
|
timesheet.set_status()
|
||||||
@ -247,9 +247,9 @@ class SalesInvoice(SellingController):
|
|||||||
def validate_time_sheets_are_submitted(self):
|
def validate_time_sheets_are_submitted(self):
|
||||||
for data in self.timesheets:
|
for data in self.timesheets:
|
||||||
if data.time_sheet:
|
if data.time_sheet:
|
||||||
status = frappe.db.get_value("Time Sheet", data.time_sheet, "status")
|
status = frappe.db.get_value("Timesheet", data.time_sheet, "status")
|
||||||
if status not in ['Submitted', 'Payslip']:
|
if status not in ['Submitted', 'Payslip']:
|
||||||
frappe.throw(_("Time Sheet {0} is already completed or cancelled").format(data.time_sheet))
|
frappe.throw(_("Timesheet {0} is already completed or cancelled").format(data.time_sheet))
|
||||||
|
|
||||||
def set_pos_fields(self, for_validate=False):
|
def set_pos_fields(self, for_validate=False):
|
||||||
"""Set retail related fields from POS Profiles"""
|
"""Set retail related fields from POS Profiles"""
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
"label": "Time Sheet",
|
"label": "Time Sheet",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Time Sheet",
|
"options": "Timesheet",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
@ -71,7 +71,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-06-15 23:56:06.131202",
|
"modified": "2016-07-06 18:35:46.072695",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Sales Invoice Timesheet",
|
"name": "Sales Invoice Timesheet",
|
||||||
|
@ -31,13 +31,13 @@ def get_data():
|
|||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"type": "doctype",
|
"type": "doctype",
|
||||||
"name": "Time Sheet",
|
"name": "Timesheet",
|
||||||
"description": _("Time Sheet for tasks."),
|
"description": _("Timesheet for tasks."),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "doctype",
|
"type": "doctype",
|
||||||
"name": "Activity Type",
|
"name": "Activity Type",
|
||||||
"description": _("Types of activities for Time Sheets"),
|
"description": _("Types of activities for Time Logs"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "doctype",
|
"type": "doctype",
|
||||||
@ -53,8 +53,8 @@ def get_data():
|
|||||||
{
|
{
|
||||||
"type": "report",
|
"type": "report",
|
||||||
"is_query_report": True,
|
"is_query_report": True,
|
||||||
"name": "Daily Time Sheet Summary",
|
"name": "Daily Timesheet Summary",
|
||||||
"doctype": "Time Sheet"
|
"doctype": "Timesheet"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "report",
|
"type": "report",
|
||||||
|
@ -9,7 +9,7 @@ links = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
'label': _('Payroll'),
|
'label': _('Payroll'),
|
||||||
'items': ['Salary Structure', 'Salary Slip', 'Time Sheet']
|
'items': ['Salary Structure', 'Salary Slip', 'Timesheet']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'label': _('Expense'),
|
'label': _('Expense'),
|
||||||
|
@ -64,7 +64,7 @@ class SalarySlip(TransactionBase):
|
|||||||
if self.salary_slip_based_on_timesheet and not self.get('timesheets'):
|
if self.salary_slip_based_on_timesheet and not self.get('timesheets'):
|
||||||
self.set("timesheets", [])
|
self.set("timesheets", [])
|
||||||
|
|
||||||
timesheets = frappe.db.sql(""" select * from `tabTime Sheet` where employee = %(employee)s and (status = 'Submitted' or
|
timesheets = frappe.db.sql(""" select * from `tabTimesheet` where employee = %(employee)s and (status = 'Submitted' or
|
||||||
status = 'Billed')""", {'employee': self.employee}, as_dict=1)
|
status = 'Billed')""", {'employee': self.employee}, as_dict=1)
|
||||||
|
|
||||||
for data in timesheets:
|
for data in timesheets:
|
||||||
@ -220,16 +220,16 @@ class SalarySlip(TransactionBase):
|
|||||||
frappe.throw(_("Salary Slip of employee {0} already created for this period").format(self.employee))
|
frappe.throw(_("Salary Slip of employee {0} already created for this period").format(self.employee))
|
||||||
else:
|
else:
|
||||||
for data in self.timesheets:
|
for data in self.timesheets:
|
||||||
if frappe.db.get_value('Time Sheet', data.time_sheet, 'status') == 'Payrolled':
|
if frappe.db.get_value('Timesheet', data.time_sheet, 'status') == 'Payrolled':
|
||||||
frappe.throw(_("Salary Slip of employee {0} already created for time sheet {1}").format(self.employee, data.time_sheet))
|
frappe.throw(_("Salary Slip of employee {0} already created for time sheet {1}").format(self.employee, data.time_sheet))
|
||||||
|
|
||||||
def calculate_earning_total(self):
|
def calculate_earning_total(self):
|
||||||
self.gross_pay = flt(self.arrear_amount) + flt(self.leave_encashment_amount)
|
self.gross_pay = flt(self.arrear_amount) + flt(self.leave_encashment_amount)
|
||||||
for d in self.get("earnings"):
|
for d in self.get("earnings"):
|
||||||
if cint(d.depends_on_lwp) == 1:
|
if cint(d.depends_on_lwp) == 1 and not self.salary_slip_based_on_timesheet:
|
||||||
d.amount = rounded((flt(d.default_amount) * flt(self.payment_days)
|
d.amount = rounded((flt(d.default_amount) * flt(self.payment_days)
|
||||||
/ cint(self.total_days_in_month)), self.precision("amount", "earnings"))
|
/ cint(self.total_days_in_month)), self.precision("amount", "earnings"))
|
||||||
elif not self.payment_days:
|
elif not self.payment_days and not self.salary_slip_based_on_timesheet:
|
||||||
d.amount = 0
|
d.amount = 0
|
||||||
elif not d.amount:
|
elif not d.amount:
|
||||||
d.amount = d.default_amount
|
d.amount = d.default_amount
|
||||||
@ -238,10 +238,10 @@ class SalarySlip(TransactionBase):
|
|||||||
def calculate_ded_total(self):
|
def calculate_ded_total(self):
|
||||||
self.total_deduction = 0
|
self.total_deduction = 0
|
||||||
for d in self.get('deductions'):
|
for d in self.get('deductions'):
|
||||||
if cint(d.depends_on_lwp) == 1:
|
if cint(d.depends_on_lwp) == 1 and not self.salary_slip_based_on_timesheet:
|
||||||
d.amount = rounded((flt(d.amount) * flt(self.payment_days)
|
d.amount = rounded((flt(d.amount) * flt(self.payment_days)
|
||||||
/ cint(self.total_days_in_month)), self.precision("amount", "deductions"))
|
/ cint(self.total_days_in_month)), self.precision("amount", "deductions"))
|
||||||
elif not self.payment_days:
|
elif not self.payment_days and not self.salary_slip_based_on_timesheet:
|
||||||
d.amount = 0
|
d.amount = 0
|
||||||
elif not d.amount:
|
elif not d.amount:
|
||||||
d.amount = d.default_amount
|
d.amount = d.default_amount
|
||||||
@ -277,7 +277,7 @@ class SalarySlip(TransactionBase):
|
|||||||
def update_status(self, salary_slip=None):
|
def update_status(self, salary_slip=None):
|
||||||
for data in self.timesheets:
|
for data in self.timesheets:
|
||||||
if data.time_sheet:
|
if data.time_sheet:
|
||||||
timesheet = frappe.get_doc('Time Sheet', data.time_sheet)
|
timesheet = frappe.get_doc('Timesheet', data.time_sheet)
|
||||||
timesheet.salary_slip = salary_slip
|
timesheet.salary_slip = salary_slip
|
||||||
timesheet.flags.ignore_validate_update_after_submit = True
|
timesheet.flags.ignore_validate_update_after_submit = True
|
||||||
timesheet.set_status()
|
timesheet.set_status()
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
"label": "Time Sheet",
|
"label": "Time Sheet",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Time Sheet",
|
"options": "Timesheet",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"precision": "",
|
"precision": "",
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
@ -71,7 +71,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-06-15 17:59:57.876373",
|
"modified": "2016-07-06 18:35:46.156411",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Salary Slip Timesheet",
|
"name": "Salary Slip Timesheet",
|
||||||
|
@ -41,7 +41,7 @@ frappe.ui.form.on("Production Order", {
|
|||||||
if(frm.doc.docstatus == 1){
|
if(frm.doc.docstatus == 1){
|
||||||
frm.add_custom_button(__('Make Timesheet'), function(){
|
frm.add_custom_button(__('Make Timesheet'), function(){
|
||||||
frappe.model.open_mapped_doc({
|
frappe.model.open_mapped_doc({
|
||||||
method: "erpnext.manufacturing.doctype.production_order.production_order.make_timesheet",
|
method: "erpnext.manufacturing.doctype.production_order.production_order.make_new_timesheet",
|
||||||
frm: cur_frm
|
frm: cur_frm
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -125,9 +125,9 @@ erpnext.production_order = {
|
|||||||
|
|
||||||
// opertions
|
// opertions
|
||||||
if ((doc.operations || []).length) {
|
if ((doc.operations || []).length) {
|
||||||
frm.add_custom_button(__('Time Sheet'), function() {
|
frm.add_custom_button(__('Timesheet'), function() {
|
||||||
frappe.route_options = {"production_order": frm.doc.name};
|
frappe.route_options = {"production_order": frm.doc.name};
|
||||||
frappe.set_route("List", "Time Sheet");
|
frappe.set_route("List", "Timesheet");
|
||||||
}, __("View"));
|
}, __("View"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ from erpnext.manufacturing.doctype.bom.bom import validate_bom_no
|
|||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from erpnext.stock.doctype.item.item import validate_end_of_life
|
from erpnext.stock.doctype.item.item import validate_end_of_life
|
||||||
from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHolidayError, NotInWorkingHoursError
|
from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHolidayError, NotInWorkingHoursError
|
||||||
from erpnext.projects.doctype.time_sheet.time_sheet import OverlapError
|
from erpnext.projects.doctype.timesheet.timesheet import OverlapError
|
||||||
from erpnext.stock.doctype.stock_entry.stock_entry import get_additional_costs
|
from erpnext.stock.doctype.stock_entry.stock_entry import get_additional_costs
|
||||||
from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations
|
from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations
|
||||||
from erpnext.stock.stock_balance import get_planned_qty, update_bin_qty
|
from erpnext.stock.stock_balance import get_planned_qty, update_bin_qty
|
||||||
@ -162,10 +162,6 @@ class ProductionOrder(Document):
|
|||||||
self.set_required_items()
|
self.set_required_items()
|
||||||
self.make_time_logs()
|
self.make_time_logs()
|
||||||
|
|
||||||
def before_cancel(self):
|
|
||||||
for data in self.operations:
|
|
||||||
data.time_sheet = None
|
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
if not self.wip_warehouse:
|
if not self.wip_warehouse:
|
||||||
frappe.throw(_("Work-in-Progress Warehouse is required before Submit"))
|
frappe.throw(_("Work-in-Progress Warehouse is required before Submit"))
|
||||||
@ -181,7 +177,7 @@ class ProductionOrder(Document):
|
|||||||
|
|
||||||
frappe.db.set(self,'status', 'Cancelled')
|
frappe.db.set(self,'status', 'Cancelled')
|
||||||
self.clear_required_items()
|
self.clear_required_items()
|
||||||
self.delete_time_sheet()
|
self.delete_timesheet()
|
||||||
self.update_completed_qty_in_material_request()
|
self.update_completed_qty_in_material_request()
|
||||||
self.update_planned_qty()
|
self.update_planned_qty()
|
||||||
|
|
||||||
@ -248,10 +244,10 @@ class ProductionOrder(Document):
|
|||||||
if not self.operations:
|
if not self.operations:
|
||||||
return
|
return
|
||||||
|
|
||||||
time_sheets = []
|
timesheets = []
|
||||||
plan_days = frappe.db.get_single_value("Manufacturing Settings", "capacity_planning_for_days") or 30
|
plan_days = frappe.db.get_single_value("Manufacturing Settings", "capacity_planning_for_days") or 30
|
||||||
|
|
||||||
time_sheet = make_time_sheet(self.name)
|
timesheet = make_timesheet(self.name)
|
||||||
workstation_list = []
|
workstation_list = []
|
||||||
last_workstation_idx = {}
|
last_workstation_idx = {}
|
||||||
|
|
||||||
@ -261,18 +257,18 @@ class ProductionOrder(Document):
|
|||||||
self.set_start_end_time_for_workstation(d, workstation_list, last_workstation_idx.get(d.workstation))
|
self.set_start_end_time_for_workstation(d, workstation_list, last_workstation_idx.get(d.workstation))
|
||||||
|
|
||||||
args = self.get_operations_data(d)
|
args = self.get_operations_data(d)
|
||||||
add_timesheet_detail(time_sheet, args)
|
add_timesheet_detail(timesheet, args)
|
||||||
original_start_time = d.planned_start_time
|
original_start_time = d.planned_start_time
|
||||||
|
|
||||||
# validate operating hours if workstation [not mandatory] is specified
|
# validate operating hours if workstation [not mandatory] is specified
|
||||||
self.check_operation_fits_in_working_hours(d)
|
self.check_operation_fits_in_working_hours(d)
|
||||||
try:
|
try:
|
||||||
time_sheet.validate_time_logs()
|
timesheet.validate_time_logs()
|
||||||
except OverlapError:
|
except OverlapError:
|
||||||
if frappe.message_log: frappe.message_log.pop()
|
if frappe.message_log: frappe.message_log.pop()
|
||||||
time_sheet.move_to_next_non_overlapping_slot(d.idx)
|
timesheet.move_to_next_non_overlapping_slot(d.idx)
|
||||||
|
|
||||||
from_time, to_time = self.get_start_end_time(time_sheet, d.name)
|
from_time, to_time = self.get_start_end_time(timesheet, d.name)
|
||||||
|
|
||||||
if date_diff(from_time, original_start_time) > plan_days:
|
if date_diff(from_time, original_start_time) > plan_days:
|
||||||
frappe.throw(_("Unable to find Time Slot in the next {0} days for Operation {1}").format(plan_days, d.operation))
|
frappe.throw(_("Unable to find Time Slot in the next {0} days for Operation {1}").format(plan_days, d.operation))
|
||||||
@ -282,17 +278,17 @@ class ProductionOrder(Document):
|
|||||||
d.planned_end_time = to_time
|
d.planned_end_time = to_time
|
||||||
d.db_update()
|
d.db_update()
|
||||||
|
|
||||||
if time_sheet and open_new:
|
if timesheet and open_new:
|
||||||
return time_sheet
|
return timesheet
|
||||||
|
|
||||||
if time_sheet:
|
if timesheet:
|
||||||
time_sheet.save()
|
timesheet.save()
|
||||||
time_sheets.append(time_sheet.name)
|
timesheets.append(timesheet.name)
|
||||||
|
|
||||||
self.planned_end_date = self.operations[-1].planned_end_time
|
self.planned_end_date = self.operations[-1].planned_end_time
|
||||||
if time_sheets:
|
if timesheets:
|
||||||
frappe.local.message_log = []
|
frappe.local.message_log = []
|
||||||
frappe.msgprint(_("Time Sheet created:") + "\n" + "\n".join(time_sheets))
|
frappe.msgprint(_("Timesheet created:") + "\n" + "\n".join(timesheets))
|
||||||
|
|
||||||
def get_operations_data(self, data):
|
def get_operations_data(self, data):
|
||||||
return {
|
return {
|
||||||
@ -322,8 +318,8 @@ class ProductionOrder(Document):
|
|||||||
if data.planned_start_time == data.planned_end_time:
|
if data.planned_start_time == data.planned_end_time:
|
||||||
frappe.throw(_("Capacity Planning Error"))
|
frappe.throw(_("Capacity Planning Error"))
|
||||||
|
|
||||||
def get_start_end_time(self, time_sheet, operation_id):
|
def get_start_end_time(self, timesheet, operation_id):
|
||||||
for data in time_sheet.time_logs:
|
for data in timesheet.time_logs:
|
||||||
if data.operation_id == operation_id:
|
if data.operation_id == operation_id:
|
||||||
return data.from_time, data.to_time
|
return data.from_time, data.to_time
|
||||||
|
|
||||||
@ -354,9 +350,9 @@ class ProductionOrder(Document):
|
|||||||
self.actual_start_date = None
|
self.actual_start_date = None
|
||||||
self.actual_end_date = None
|
self.actual_end_date = None
|
||||||
|
|
||||||
def delete_time_sheet(self):
|
def delete_timesheet(self):
|
||||||
for time_sheet in frappe.get_all("Time Sheet", ["name"], {"production_order": self.name}):
|
for timesheet in frappe.get_all("Timesheet", ["name"], {"production_order": self.name}):
|
||||||
frappe.delete_doc("Time Sheet", time_sheet.name)
|
frappe.delete_doc("Timesheet", timesheet.name)
|
||||||
|
|
||||||
def validate_production_item(self):
|
def validate_production_item(self):
|
||||||
if frappe.db.get_value("Item", self.production_item, "has_variants"):
|
if frappe.db.get_value("Item", self.production_item, "has_variants"):
|
||||||
@ -508,22 +504,22 @@ def get_events(start, end, filters=None):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_time_sheet(production_order):
|
def make_timesheet(production_order):
|
||||||
time_sheet = frappe.new_doc("Time Sheet")
|
timesheet = frappe.new_doc("Timesheet")
|
||||||
time_sheet.employee = ""
|
timesheet.employee = ""
|
||||||
time_sheet.production_order = production_order
|
timesheet.production_order = production_order
|
||||||
return time_sheet
|
return timesheet
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def add_timesheet_detail(time_sheet, args):
|
def add_timesheet_detail(timesheet, args):
|
||||||
if isinstance(time_sheet, unicode):
|
if isinstance(timesheet, unicode):
|
||||||
time_sheet = frappe.get_doc('Time Sheet', time_sheet)
|
timesheet = frappe.get_doc('Timesheet', timesheet)
|
||||||
|
|
||||||
if isinstance(args, unicode):
|
if isinstance(args, unicode):
|
||||||
args = json.loads(args)
|
args = json.loads(args)
|
||||||
|
|
||||||
time_sheet.append('time_logs', args)
|
timesheet.append('time_logs', args)
|
||||||
return time_sheet
|
return timesheet
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_default_warehouse():
|
def get_default_warehouse():
|
||||||
@ -534,8 +530,11 @@ def get_default_warehouse():
|
|||||||
return {"wip_warehouse": wip_warehouse, "fg_warehouse": fg_warehouse}
|
return {"wip_warehouse": wip_warehouse, "fg_warehouse": fg_warehouse}
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_timesheet(source_name, target_doc=None):
|
def make_new_timesheet(source_name, target_doc=None):
|
||||||
po = frappe.get_doc('Production Order', source_name)
|
po = frappe.get_doc('Production Order', source_name)
|
||||||
ts = po.make_time_logs(open_new=True)
|
ts = po.make_time_logs(open_new=True)
|
||||||
|
|
||||||
|
if not ts.get('time_logs'):
|
||||||
|
frappe.throw(_("Already completed"))
|
||||||
|
|
||||||
return ts
|
return ts
|
||||||
|
@ -83,8 +83,8 @@ class TestProductionOrder(unittest.TestCase):
|
|||||||
d = prod_order.operations[0]
|
d = prod_order.operations[0]
|
||||||
d.completed_qty = flt(d.completed_qty)
|
d.completed_qty = flt(d.completed_qty)
|
||||||
|
|
||||||
name = frappe.db.get_value('Time Sheet', {'production_order': prod_order.name}, 'name')
|
name = frappe.db.get_value('Timesheet', {'production_order': prod_order.name}, 'name')
|
||||||
time_sheet_doc = frappe.get_doc('Time Sheet', name)
|
time_sheet_doc = frappe.get_doc('Timesheet', name)
|
||||||
time_sheet_doc.submit()
|
time_sheet_doc.submit()
|
||||||
|
|
||||||
|
|
||||||
|
@ -288,3 +288,4 @@ erpnext.patches.v7_0.update_prevdoc_values_for_supplier_quotation_item
|
|||||||
erpnext.patches.v7_0.rename_advance_table_fields
|
erpnext.patches.v7_0.rename_advance_table_fields
|
||||||
erpnext.patches.v7_0.rename_salary_components
|
erpnext.patches.v7_0.rename_salary_components
|
||||||
erpnext.patches.v7_0.rename_prevdoc_fields
|
erpnext.patches.v7_0.rename_prevdoc_fields
|
||||||
|
erpnext.patches.v7_0.rename_time_sheet_doctype
|
||||||
|
@ -5,7 +5,7 @@ from erpnext.manufacturing.doctype.production_order.production_order import add_
|
|||||||
def execute():
|
def execute():
|
||||||
for tlb in frappe.get_all('Time Log Batch', fields=["*"],
|
for tlb in frappe.get_all('Time Log Batch', fields=["*"],
|
||||||
filters = [["docstatus", "<", "2"]]):
|
filters = [["docstatus", "<", "2"]]):
|
||||||
time_sheet = frappe.new_doc('Time Sheet')
|
time_sheet = frappe.new_doc('Timesheet')
|
||||||
time_sheet.employee= ""
|
time_sheet.employee= ""
|
||||||
time_sheet.company = frappe.db.get_single_value('Global Defaults', 'default_company')
|
time_sheet.company = frappe.db.get_single_value('Global Defaults', 'default_company')
|
||||||
time_sheet.sales_invoice = tlb.sales_invoice
|
time_sheet.sales_invoice = tlb.sales_invoice
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
for time_sheet in frappe.db.sql(""" select sales_invoice, name, total_billing_amount from `tabTime Sheet`
|
for time_sheet in frappe.db.sql(""" select sales_invoice, name, total_billing_amount from `tabTimesheet`
|
||||||
where sales_invoice is not null and docstatus < 2""", as_dict=True):
|
where sales_invoice is not null and docstatus < 2""", as_dict=True):
|
||||||
si_doc = frappe.get_doc('Sales Invoice', time_sheet.sales_invoice)
|
si_doc = frappe.get_doc('Sales Invoice', time_sheet.sales_invoice)
|
||||||
ts = si_doc.append('timesheets',{})
|
ts = si_doc.append('timesheets',{})
|
||||||
|
13
erpnext/patches/v7_0/rename_time_sheet_doctype.py
Normal file
13
erpnext/patches/v7_0/rename_time_sheet_doctype.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
if frappe.db.table_exists("Time Sheet"):
|
||||||
|
frappe.rename_doc("DocType", "Time Sheet", "Timesheet")
|
||||||
|
frappe.rename_doc("DocType", "Time Sheet Detail", "Timesheet Detail")
|
||||||
|
|
||||||
|
for doctype in ['Time Sheet', 'Time Sheet Detail']:
|
||||||
|
frappe.delete_doc('DocType', doctype)
|
||||||
|
|
||||||
|
report = "Daily Time Sheet Summary"
|
||||||
|
if frappe.db.exists("Report", report):
|
||||||
|
frappe.delete_doc('Report', report)
|
@ -7,9 +7,9 @@ import frappe
|
|||||||
from frappe.custom.doctype.property_setter.property_setter import make_property_setter
|
from frappe.custom.doctype.property_setter.property_setter import make_property_setter
|
||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
frappe.reload_doc('projects', 'doctype','time_sheet')
|
frappe.reload_doc('projects', 'doctype', 'timesheet')
|
||||||
frappe.reload_doc('projects', 'doctype', 'time_sheet_detail')
|
frappe.reload_doc('projects', 'doctype', 'timesheet_detail')
|
||||||
frappe.reload_doc('accounts', 'doctype', 'sales_invoice_timesheet')
|
frappe.reload_doc('accounts', 'doctype', 'sales_invoice_timesheet')
|
||||||
|
|
||||||
make_property_setter('Time Sheet', "naming_series", "options", 'TS-', "Text")
|
make_property_setter('Timesheet', "naming_series", "options", 'TS-', "Text")
|
||||||
make_property_setter('Time Sheet', "naming_series", "default", 'TS-', "Text")
|
make_property_setter('Timesheet', "naming_series", "default", 'TS-', "Text")
|
@ -19,7 +19,7 @@ class Project(Document):
|
|||||||
self.load_tasks()
|
self.load_tasks()
|
||||||
|
|
||||||
self.set_onload('activity_summary', frappe.db.sql('''select activity_type, sum(hours) as total_hours
|
self.set_onload('activity_summary', frappe.db.sql('''select activity_type, sum(hours) as total_hours
|
||||||
from `tabTime Sheet Detail` where project=%s group by activity_type order by total_hours desc''', self.name, as_dict=True))
|
from `tabTimesheet Detail` where project=%s group by activity_type order by total_hours desc''', self.name, as_dict=True))
|
||||||
|
|
||||||
def __setup__(self):
|
def __setup__(self):
|
||||||
self.onload()
|
self.onload()
|
||||||
@ -105,7 +105,7 @@ class Project(Document):
|
|||||||
min(from_time) as start_date,
|
min(from_time) as start_date,
|
||||||
max(to_time) as end_date,
|
max(to_time) as end_date,
|
||||||
sum(hours) as time
|
sum(hours) as time
|
||||||
from `tabTime Sheet Detail` where project = %s and docstatus = 1""", self.name, as_dict=1)[0]
|
from `tabTimesheet Detail` where project = %s and docstatus = 1""", self.name, as_dict=1)[0]
|
||||||
|
|
||||||
from_expense_claim = frappe.db.sql("""select
|
from_expense_claim = frappe.db.sql("""select
|
||||||
sum(total_sanctioned_amount) as total_sanctioned_amount
|
sum(total_sanctioned_amount) as total_sanctioned_amount
|
||||||
@ -154,7 +154,7 @@ class Project(Document):
|
|||||||
def get_timeline_data(doctype, name):
|
def get_timeline_data(doctype, name):
|
||||||
'''Return timeline for attendance'''
|
'''Return timeline for attendance'''
|
||||||
return dict(frappe.db.sql('''select unix_timestamp(from_time), count(*)
|
return dict(frappe.db.sql('''select unix_timestamp(from_time), count(*)
|
||||||
from `tabTime Sheet Detail` where project=%s
|
from `tabTimesheet Detail` where project=%s
|
||||||
and from_time > date_sub(curdate(), interval 1 year)
|
and from_time > date_sub(curdate(), interval 1 year)
|
||||||
and docstatus < 2
|
and docstatus < 2
|
||||||
group by date(from_time)''', name))
|
group by date(from_time)''', name))
|
||||||
|
@ -5,7 +5,7 @@ links = {
|
|||||||
'transactions': [
|
'transactions': [
|
||||||
{
|
{
|
||||||
'label': _('Project'),
|
'label': _('Project'),
|
||||||
'items': ['Task', 'Time Sheet', 'Expense Claim', 'Issue']
|
'items': ['Task', 'Timesheet', 'Expense Claim', 'Issue']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'label': _('Material'),
|
'label': _('Material'),
|
||||||
|
@ -58,7 +58,7 @@ class Task(Document):
|
|||||||
def update_time_and_costing(self):
|
def update_time_and_costing(self):
|
||||||
tl = frappe.db.sql("""select min(from_time) as start_date, max(to_time) as end_date,
|
tl = frappe.db.sql("""select min(from_time) as start_date, max(to_time) as end_date,
|
||||||
sum(billing_amount) as total_billing_amount, sum(costing_amount) as total_costing_amount,
|
sum(billing_amount) as total_billing_amount, sum(costing_amount) as total_costing_amount,
|
||||||
sum(hours) as time from `tabTime Sheet Detail` where task = %s and docstatus=1"""
|
sum(hours) as time from `tabTimesheet Detail` where task = %s and docstatus=1"""
|
||||||
,self.name, as_dict=1)[0]
|
,self.name, as_dict=1)[0]
|
||||||
if self.status == "Open":
|
if self.status == "Open":
|
||||||
self.status = "Working"
|
self.status = "Working"
|
||||||
|
@ -7,40 +7,40 @@ import frappe
|
|||||||
import unittest
|
import unittest
|
||||||
import datetime
|
import datetime
|
||||||
from frappe.utils import now_datetime, nowdate
|
from frappe.utils import now_datetime, nowdate
|
||||||
from erpnext.projects.doctype.time_sheet.time_sheet import OverlapError
|
from erpnext.projects.doctype.timesheet.timesheet import OverlapError
|
||||||
from erpnext.projects.doctype.time_sheet.time_sheet import make_salary_slip, make_sales_invoice
|
from erpnext.projects.doctype.timesheet.timesheet import make_salary_slip, make_sales_invoice
|
||||||
|
|
||||||
class TestTimeSheet(unittest.TestCase):
|
class TestTimesheet(unittest.TestCase):
|
||||||
def test_time_sheet_billing_amount(self):
|
def test_timesheet_billing_amount(self):
|
||||||
salary_structure = make_salary_structure("_T-Employee-0001")
|
salary_structure = make_salary_structure("_T-Employee-0001")
|
||||||
time_sheet = make_time_sheet("_T-Employee-0001", True)
|
timesheet = make_timesheet("_T-Employee-0001", True)
|
||||||
|
|
||||||
self.assertEquals(time_sheet.total_hours, 2)
|
self.assertEquals(timesheet.total_hours, 2)
|
||||||
self.assertEquals(time_sheet.time_logs[0].billing_rate, 50)
|
self.assertEquals(timesheet.time_logs[0].billing_rate, 50)
|
||||||
self.assertEquals(time_sheet.time_logs[0].billing_amount, 100)
|
self.assertEquals(timesheet.time_logs[0].billing_amount, 100)
|
||||||
|
|
||||||
def test_salary_slip_from_timesheet(self):
|
def test_salary_slip_from_timesheet(self):
|
||||||
salary_structure = make_salary_structure("_T-Employee-0001")
|
salary_structure = make_salary_structure("_T-Employee-0001")
|
||||||
time_sheet = make_time_sheet("_T-Employee-0001", simulate = True)
|
timesheet = make_timesheet("_T-Employee-0001", simulate = True)
|
||||||
salary_slip = make_salary_slip(time_sheet.name)
|
salary_slip = make_salary_slip(timesheet.name)
|
||||||
salary_slip.submit()
|
salary_slip.submit()
|
||||||
|
|
||||||
self.assertEquals(salary_slip.total_working_hours, 2)
|
self.assertEquals(salary_slip.total_working_hours, 2)
|
||||||
self.assertEquals(salary_slip.hour_rate, 50)
|
self.assertEquals(salary_slip.hour_rate, 50)
|
||||||
self.assertEquals(salary_slip.net_pay, 150)
|
self.assertEquals(salary_slip.net_pay, 150)
|
||||||
self.assertEquals(salary_slip.timesheets[0].time_sheet, time_sheet.name)
|
self.assertEquals(salary_slip.timesheets[0].time_sheet, timesheet.name)
|
||||||
self.assertEquals(salary_slip.timesheets[0].working_hours, 2)
|
self.assertEquals(salary_slip.timesheets[0].working_hours, 2)
|
||||||
|
|
||||||
time_sheet = frappe.get_doc('Time Sheet', time_sheet.name)
|
timesheet = frappe.get_doc('Timesheet', timesheet.name)
|
||||||
self.assertEquals(time_sheet.status, 'Payslip')
|
self.assertEquals(timesheet.status, 'Payslip')
|
||||||
salary_slip.cancel()
|
salary_slip.cancel()
|
||||||
|
|
||||||
time_sheet = frappe.get_doc('Time Sheet', time_sheet.name)
|
timesheet = frappe.get_doc('Timesheet', timesheet.name)
|
||||||
self.assertEquals(time_sheet.status, 'Submitted')
|
self.assertEquals(timesheet.status, 'Submitted')
|
||||||
|
|
||||||
def test_sales_invoice_from_timesheet(self):
|
def test_sales_invoice_from_timesheet(self):
|
||||||
time_sheet = make_time_sheet("_T-Employee-0001", simulate = True, billable = 1)
|
timesheet = make_timesheet("_T-Employee-0001", simulate = True, billable = 1)
|
||||||
sales_invoice = make_sales_invoice(time_sheet.name)
|
sales_invoice = make_sales_invoice(timesheet.name)
|
||||||
sales_invoice.customer = "_Test Customer"
|
sales_invoice.customer = "_Test Customer"
|
||||||
sales_invoice.due_date = nowdate()
|
sales_invoice.due_date = nowdate()
|
||||||
|
|
||||||
@ -51,9 +51,9 @@ class TestTimeSheet(unittest.TestCase):
|
|||||||
|
|
||||||
sales_invoice.submit()
|
sales_invoice.submit()
|
||||||
|
|
||||||
time_sheet = frappe.get_doc('Time Sheet', time_sheet.name)
|
timesheet = frappe.get_doc('Timesheet', timesheet.name)
|
||||||
self.assertEquals(sales_invoice.total_billing_amount, 100)
|
self.assertEquals(sales_invoice.total_billing_amount, 100)
|
||||||
self.assertEquals(time_sheet.status, 'Billed')
|
self.assertEquals(timesheet.status, 'Billed')
|
||||||
|
|
||||||
def make_salary_structure(employee):
|
def make_salary_structure(employee):
|
||||||
name = frappe.db.get_value('Salary Structure', {'employee': employee, 'salary_slip_based_on_timesheet': 1}, 'name')
|
name = frappe.db.get_value('Salary Structure', {'employee': employee, 'salary_slip_based_on_timesheet': 1}, 'name')
|
||||||
@ -86,32 +86,32 @@ def make_salary_structure(employee):
|
|||||||
|
|
||||||
return salary_structure
|
return salary_structure
|
||||||
|
|
||||||
def make_time_sheet(employee, simulate=False, billable = 0):
|
def make_timesheet(employee, simulate=False, billable = 0):
|
||||||
update_activity_type("_Test Activity Type")
|
update_activity_type("_Test Activity Type")
|
||||||
time_sheet = frappe.new_doc("Time Sheet")
|
timesheet = frappe.new_doc("Timesheet")
|
||||||
time_sheet.employee = employee
|
timesheet.employee = employee
|
||||||
time_sheet_detail = time_sheet.append('time_logs', {})
|
timesheet_detail = timesheet.append('time_logs', {})
|
||||||
time_sheet_detail.billable = billable
|
timesheet_detail.billable = billable
|
||||||
time_sheet_detail.activity_type = "_Test Activity Type"
|
timesheet_detail.activity_type = "_Test Activity Type"
|
||||||
time_sheet_detail.from_time = now_datetime()
|
timesheet_detail.from_time = now_datetime()
|
||||||
time_sheet_detail.hours = 2
|
timesheet_detail.hours = 2
|
||||||
time_sheet_detail.to_time = time_sheet_detail.from_time + datetime.timedelta(hours= time_sheet_detail.hours)
|
timesheet_detail.to_time = timesheet_detail.from_time + datetime.timedelta(hours= timesheet_detail.hours)
|
||||||
|
|
||||||
for data in time_sheet.get('time_logs'):
|
for data in timesheet.get('time_logs'):
|
||||||
if simulate:
|
if simulate:
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
time_sheet.save()
|
timesheet.save()
|
||||||
break
|
break
|
||||||
except OverlapError:
|
except OverlapError:
|
||||||
data.from_time = data.from_time + datetime.timedelta(minutes=10)
|
data.from_time = data.from_time + datetime.timedelta(minutes=10)
|
||||||
data.to_time = data.from_time + datetime.timedelta(hours= data.hours)
|
data.to_time = data.from_time + datetime.timedelta(hours= data.hours)
|
||||||
else:
|
else:
|
||||||
time_sheet.save()
|
timesheet.save()
|
||||||
|
|
||||||
time_sheet.submit()
|
timesheet.submit()
|
||||||
|
|
||||||
return time_sheet
|
return timesheet
|
||||||
|
|
||||||
def update_activity_type(activity_type):
|
def update_activity_type(activity_type):
|
||||||
activity_type = frappe.get_doc('Activity Type',activity_type)
|
activity_type = frappe.get_doc('Activity Type',activity_type)
|
@ -1,7 +1,7 @@
|
|||||||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
// License: GNU General Public License v3. See license.txt
|
// License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
frappe.ui.form.on("Time Sheet", {
|
frappe.ui.form.on("Timesheet", {
|
||||||
setup: function(frm) {
|
setup: function(frm) {
|
||||||
frm.get_field('time_logs').grid.editable_fields = [
|
frm.get_field('time_logs').grid.editable_fields = [
|
||||||
{fieldname: 'activity_type', columns: 2},
|
{fieldname: 'activity_type', columns: 2},
|
||||||
@ -12,7 +12,7 @@ frappe.ui.form.on("Time Sheet", {
|
|||||||
|
|
||||||
frm.fields_dict.employee.get_query = function() {
|
frm.fields_dict.employee.get_query = function() {
|
||||||
return {
|
return {
|
||||||
query:"erpnext.projects.doctype.time_sheet.time_sheet.get_employee_list"
|
query:"erpnext.projects.doctype.timesheet.timesheet.get_employee_list"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,20 +50,20 @@ frappe.ui.form.on("Time Sheet", {
|
|||||||
|
|
||||||
make_invoice: function(frm) {
|
make_invoice: function(frm) {
|
||||||
frappe.model.open_mapped_doc({
|
frappe.model.open_mapped_doc({
|
||||||
method: "erpnext.projects.doctype.time_sheet.time_sheet.make_sales_invoice",
|
method: "erpnext.projects.doctype.timesheet.timesheet.make_sales_invoice",
|
||||||
frm: frm
|
frm: frm
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
make_salary_slip: function(frm) {
|
make_salary_slip: function(frm) {
|
||||||
frappe.model.open_mapped_doc({
|
frappe.model.open_mapped_doc({
|
||||||
method: "erpnext.projects.doctype.time_sheet.time_sheet.make_salary_slip",
|
method: "erpnext.projects.doctype.timesheet.timesheet.make_salary_slip",
|
||||||
frm: frm
|
frm: frm
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
frappe.ui.form.on("Time Sheet Detail", {
|
frappe.ui.form.on("Timesheet Detail", {
|
||||||
time_logs_remove: function(frm) {
|
time_logs_remove: function(frm) {
|
||||||
calculate_time_and_amount(frm);
|
calculate_time_and_amount(frm);
|
||||||
},
|
},
|
||||||
@ -107,7 +107,7 @@ frappe.ui.form.on("Time Sheet Detail", {
|
|||||||
child = locals[cdt][cdn];
|
child = locals[cdt][cdn];
|
||||||
if(frm.doc.employee || frm.doc.production_order){
|
if(frm.doc.employee || frm.doc.production_order){
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.projects.doctype.time_sheet.time_sheet.get_activity_cost",
|
method: "erpnext.projects.doctype.timesheet.timesheet.get_activity_cost",
|
||||||
args: {
|
args: {
|
||||||
employee: frm.doc.employee,
|
employee: frm.doc.employee,
|
||||||
activity_type: child.activity_type
|
activity_type: child.activity_type
|
@ -436,7 +436,7 @@
|
|||||||
"label": "Time Sheets",
|
"label": "Time Sheets",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 0,
|
"no_copy": 0,
|
||||||
"options": "Time Sheet Detail",
|
"options": "Timesheet Detail",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 0,
|
"print_hide": 0,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
@ -563,7 +563,7 @@
|
|||||||
"label": "Amended From",
|
"label": "Amended From",
|
||||||
"length": 0,
|
"length": 0,
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "Time Sheet",
|
"options": "Timesheet",
|
||||||
"permlevel": 0,
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_hide_if_no_value": 0,
|
"print_hide_if_no_value": 0,
|
||||||
@ -586,10 +586,10 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-06-29 15:16:31.668367",
|
"modified": "2016-07-06 18:36:21.103681",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Projects",
|
"module": "Projects",
|
||||||
"name": "Time Sheet",
|
"name": "Timesheet",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
@ -1,6 +1,5 @@
|
|||||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
# -*- coding: utf-8 -*-
|
||||||
# License: GNU General Public License v3. See license.txt
|
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
|
||||||
# For license information, please see license.txt
|
# For license information, please see license.txt
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
@ -15,8 +14,7 @@ from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings
|
|||||||
class OverlapError(frappe.ValidationError): pass
|
class OverlapError(frappe.ValidationError): pass
|
||||||
class OverProductionLoggedError(frappe.ValidationError): pass
|
class OverProductionLoggedError(frappe.ValidationError): pass
|
||||||
|
|
||||||
class TimeSheet(Document):
|
class Timesheet(Document):
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.set_status()
|
self.set_status()
|
||||||
self.total_hours = 0.0
|
self.total_hours = 0.0
|
||||||
@ -117,7 +115,7 @@ class TimeSheet(Document):
|
|||||||
"""Returns 'Actual Operating Time'. """
|
"""Returns 'Actual Operating Time'. """
|
||||||
return frappe.db.sql("""select
|
return frappe.db.sql("""select
|
||||||
sum(tsd.hours*60) as mins, sum(tsd.completed_qty) as completed_qty, min(tsd.from_time) as from_time,
|
sum(tsd.hours*60) as mins, sum(tsd.completed_qty) as completed_qty, min(tsd.from_time) as from_time,
|
||||||
max(tsd.to_time) as to_time from `tabTime Sheet Detail` as tsd, `tabTime Sheet` as ts where
|
max(tsd.to_time) as to_time from `tabTimesheet Detail` as tsd, `tabTimesheet` as ts where
|
||||||
ts.production_order = %s and tsd.operation_id = %s and ts.docstatus=1 and ts.name = tsd.parent""",
|
ts.production_order = %s and tsd.operation_id = %s and ts.docstatus=1 and ts.name = tsd.parent""",
|
||||||
(self.production_order, operation_id), as_dict=1)[0]
|
(self.production_order, operation_id), as_dict=1)[0]
|
||||||
|
|
||||||
@ -159,7 +157,7 @@ class TimeSheet(Document):
|
|||||||
return
|
return
|
||||||
|
|
||||||
existing = frappe.db.sql("""select ts.name as name, tsd.from_time as from_time, tsd.to_time as to_time from
|
existing = frappe.db.sql("""select ts.name as name, tsd.from_time as from_time, tsd.to_time as to_time from
|
||||||
`tabTime Sheet Detail` tsd, `tabTime Sheet` ts where tsd.`{0}`=%(val)s and tsd.parent = ts.name and
|
`tabTimesheet Detail` tsd, `tabTimesheet` ts where tsd.`{0}`=%(val)s and tsd.parent = ts.name and
|
||||||
(
|
(
|
||||||
(%(from_time)s > tsd.from_time and %(from_time)s < tsd.to_time) or
|
(%(from_time)s > tsd.from_time and %(from_time)s < tsd.to_time) or
|
||||||
(%(to_time)s > tsd.from_time and %(to_time)s < tsd.to_time) or
|
(%(to_time)s > tsd.from_time and %(to_time)s < tsd.to_time) or
|
||||||
@ -198,7 +196,7 @@ class TimeSheet(Document):
|
|||||||
|
|
||||||
def get_last_working_slot(self, time_sheet, workstation):
|
def get_last_working_slot(self, time_sheet, workstation):
|
||||||
return frappe.db.sql(""" select max(from_time) as from_time, max(to_time) as to_time
|
return frappe.db.sql(""" select max(from_time) as from_time, max(to_time) as to_time
|
||||||
from `tabTime Sheet Detail` where workstation = %(workstation)s""",
|
from `tabTimesheet Detail` where workstation = %(workstation)s""",
|
||||||
{'workstation': workstation}, as_dict=True)[0]
|
{'workstation': workstation}, as_dict=True)[0]
|
||||||
|
|
||||||
def update_cost(self):
|
def update_cost(self):
|
||||||
@ -216,8 +214,8 @@ class TimeSheet(Document):
|
|||||||
def make_sales_invoice(source_name, target=None):
|
def make_sales_invoice(source_name, target=None):
|
||||||
target = frappe.new_doc("Sales Invoice")
|
target = frappe.new_doc("Sales Invoice")
|
||||||
|
|
||||||
target.append("timesheets", get_mapped_doc("Time Sheet", source_name, {
|
target.append("timesheets", get_mapped_doc("Timesheet", source_name, {
|
||||||
"Time Sheet": {
|
"Timesheet": {
|
||||||
"doctype": "Sales Invoice Timesheet",
|
"doctype": "Sales Invoice Timesheet",
|
||||||
"field_map": {
|
"field_map": {
|
||||||
"total_billing_amount": "billing_amount",
|
"total_billing_amount": "billing_amount",
|
||||||
@ -235,8 +233,8 @@ def make_salary_slip(source_name, target_doc=None):
|
|||||||
target = frappe.new_doc("Salary Slip")
|
target = frappe.new_doc("Salary Slip")
|
||||||
set_missing_values(source_name, target)
|
set_missing_values(source_name, target)
|
||||||
|
|
||||||
target.append("timesheets", get_mapped_doc("Time Sheet", source_name, {
|
target.append("timesheets", get_mapped_doc("Timesheet", source_name, {
|
||||||
"Time Sheet": {
|
"Timesheet": {
|
||||||
"doctype": "Salary Slip Timesheet",
|
"doctype": "Salary Slip Timesheet",
|
||||||
"field_map": {
|
"field_map": {
|
||||||
"total_hours": "working_hours",
|
"total_hours": "working_hours",
|
||||||
@ -250,7 +248,7 @@ def make_salary_slip(source_name, target_doc=None):
|
|||||||
return target
|
return target
|
||||||
|
|
||||||
def set_missing_values(time_sheet, target):
|
def set_missing_values(time_sheet, target):
|
||||||
doc = frappe.get_doc('Time Sheet', time_sheet)
|
doc = frappe.get_doc('Timesheet', time_sheet)
|
||||||
target.employee = doc.employee
|
target.employee = doc.employee
|
||||||
target.employee_name = doc.employee_name
|
target.employee_name = doc.employee_name
|
||||||
target.salary_slip_based_on_timesheet = 1
|
target.salary_slip_based_on_timesheet = 1
|
@ -1,4 +1,4 @@
|
|||||||
frappe.listview_settings['Time Sheet'] = {
|
frappe.listview_settings['Timesheet'] = {
|
||||||
add_fields: ["status", "total_hours"],
|
add_fields: ["status", "total_hours"],
|
||||||
get_indicator: function(doc) {
|
get_indicator: function(doc) {
|
||||||
if (doc.status== "Billed") {
|
if (doc.status== "Billed") {
|
@ -531,10 +531,10 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-07-06 13:40:41.419370",
|
"modified": "2016-07-06 18:35:24.106546",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Projects",
|
"module": "Projects",
|
||||||
"name": "Time Sheet Detail",
|
"name": "Timesheet Detail",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
@ -6,5 +6,5 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
class TimeSheetDetail(Document):
|
class TimesheetDetail(Document):
|
||||||
pass
|
pass
|
@ -12,7 +12,7 @@ def execute(filters=None):
|
|||||||
filters["from_time"] = "00:00:00"
|
filters["from_time"] = "00:00:00"
|
||||||
filters["to_time"] = "24:00:00"
|
filters["to_time"] = "24:00:00"
|
||||||
|
|
||||||
columns = [_("Time Sheet") + ":Link/Time Sheet:120", _("Employee") + "::150", _("From Datetime") + "::140",
|
columns = [_("Timesheet") + ":Link/Timesheet:120", _("Employee") + "::150", _("From Datetime") + "::140",
|
||||||
_("To Datetime") + "::140", _("Hours") + "::70", _("Activity Type") + "::120", _("Task") + ":Link/Task:150",
|
_("To Datetime") + "::140", _("Hours") + "::70", _("Activity Type") + "::120", _("Task") + ":Link/Task:150",
|
||||||
_("Project") + ":Link/Project:120", _("Status") + "::70"]
|
_("Project") + ":Link/Project:120", _("Status") + "::70"]
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ def execute(filters=None):
|
|||||||
|
|
||||||
def get_data(conditions, filters):
|
def get_data(conditions, filters):
|
||||||
time_sheet = frappe.db.sql(""" select ts.name, ts.employee, tsd.from_time, tsd.to_time, tsd.hours,
|
time_sheet = frappe.db.sql(""" select ts.name, ts.employee, tsd.from_time, tsd.to_time, tsd.hours,
|
||||||
tsd.activity_type, tsd.task, tsd.project, ts.status from `tabTime Sheet Detail` tsd,
|
tsd.activity_type, tsd.task, tsd.project, ts.status from `tabTimesheet Detail` tsd,
|
||||||
`tabTime Sheet` ts where ts.name = tsd.parent and %s order by ts.name"""%(conditions), filters, as_list=1)
|
`tabTimesheet` ts where ts.name = tsd.parent and %s order by ts.name"""%(conditions), filters, as_list=1)
|
||||||
|
|
||||||
return time_sheet
|
return time_sheet
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
frappe.query_reports["Daily Timesheet Summary"] = {
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"fieldname":"from_date",
|
||||||
|
"label": __("From Date"),
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"default": frappe.datetime.get_today()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"to_date",
|
||||||
|
"label": __("To Date"),
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"default": frappe.datetime.get_today()
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"add_total_row": 0,
|
||||||
|
"apply_user_permissions": 1,
|
||||||
|
"creation": "2016-07-06 19:31:25.534583",
|
||||||
|
"disabled": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Report",
|
||||||
|
"idx": 0,
|
||||||
|
"is_standard": "Yes",
|
||||||
|
"modified": "2016-07-06 19:31:25.534583",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Projects",
|
||||||
|
"name": "Daily Timesheet Summary",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"ref_doctype": "Timesheet",
|
||||||
|
"report_name": "Daily Timesheet Summary",
|
||||||
|
"report_type": "Script Report"
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
|
||||||
|
def execute(filters=None):
|
||||||
|
if not filters:
|
||||||
|
filters = {}
|
||||||
|
elif filters.get("from_date") or filters.get("to_date"):
|
||||||
|
filters["from_time"] = "00:00:00"
|
||||||
|
filters["to_time"] = "24:00:00"
|
||||||
|
|
||||||
|
columns = [_("Timesheet") + ":Link/Timesheet:120", _("Employee") + "::150", _("From Datetime") + "::140",
|
||||||
|
_("To Datetime") + "::140", _("Hours") + "::70", _("Activity Type") + "::120", _("Task") + ":Link/Task:150",
|
||||||
|
_("Project") + ":Link/Project:120", _("Status") + "::70"]
|
||||||
|
|
||||||
|
conditions = "ts.docstatus = 1"
|
||||||
|
if filters.get("from_date"):
|
||||||
|
conditions += " and tsd.from_time >= timestamp(%(from_date)s, %(from_time)s)"
|
||||||
|
if filters.get("to_date"):
|
||||||
|
conditions += " and tsd.to_time <= timestamp(%(to_date)s, %(to_time)s)"
|
||||||
|
|
||||||
|
data = get_data(conditions, filters)
|
||||||
|
|
||||||
|
return columns, data
|
||||||
|
|
||||||
|
def get_data(conditions, filters):
|
||||||
|
time_sheet = frappe.db.sql(""" select ts.name, ts.employee, tsd.from_time, tsd.to_time, tsd.hours,
|
||||||
|
tsd.activity_type, tsd.task, tsd.project, ts.status from `tabTimesheet Detail` tsd,
|
||||||
|
`tabTimesheet` ts where ts.name = tsd.parent and %s order by ts.name"""%(conditions), filters, as_list=1)
|
||||||
|
|
||||||
|
return time_sheet
|
@ -73,7 +73,7 @@ def delete_bins(company_name):
|
|||||||
def delete_time_sheets(company_name):
|
def delete_time_sheets(company_name):
|
||||||
# Delete Time Logs as it is linked to Production Order / Project / Task, which are linked to company
|
# Delete Time Logs as it is linked to Production Order / Project / Task, which are linked to company
|
||||||
frappe.db.sql("""
|
frappe.db.sql("""
|
||||||
delete from `tabTime Sheet`
|
delete from `tabTimesheet`
|
||||||
where
|
where
|
||||||
company=%(company)s
|
company=%(company)s
|
||||||
""", {"company": company_name})
|
""", {"company": company_name})
|
||||||
|
@ -45,7 +45,7 @@ def get_domains():
|
|||||||
},
|
},
|
||||||
|
|
||||||
'Services': {
|
'Services': {
|
||||||
'desktop_icons': ['Project', 'Time Sheet', 'Customer', 'Sales Order', 'Sales Invoice', 'Lead', 'Opportunity',
|
'desktop_icons': ['Project', 'Timesheet', 'Customer', 'Sales Order', 'Sales Invoice', 'Lead', 'Opportunity',
|
||||||
'Expense Claim', 'Employee', 'HR', 'ToDo'],
|
'Expense Claim', 'Employee', 'HR', 'ToDo'],
|
||||||
'remove_roles': ['Manufacturing User', 'Manufacturing Manager'],
|
'remove_roles': ['Manufacturing User', 'Manufacturing Manager'],
|
||||||
'properties': [
|
'properties': [
|
||||||
|
@ -43,6 +43,6 @@ def get_notification_config():
|
|||||||
"Purchase Receipt": {"docstatus": 0},
|
"Purchase Receipt": {"docstatus": 0},
|
||||||
"Production Order": { "status": ("in", ("Draft", "Not Started", "In Process")) },
|
"Production Order": { "status": ("in", ("Draft", "Not Started", "In Process")) },
|
||||||
"BOM": {"docstatus": 0},
|
"BOM": {"docstatus": 0},
|
||||||
"Time Sheet": {"status": "Draft"}
|
"Timesheet": {"status": "Draft"}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user