2021-04-19 11:19:28 +00:00
|
|
|
import unittest
|
2021-09-02 11:14:59 +00:00
|
|
|
|
2021-04-19 11:19:28 +00:00
|
|
|
import frappe
|
2021-11-30 08:34:47 +00:00
|
|
|
from frappe.utils import add_days, getdate
|
2021-09-02 11:14:59 +00:00
|
|
|
|
2021-04-19 11:19:28 +00:00
|
|
|
from erpnext.hr.doctype.employee.test_employee import make_employee
|
2021-04-26 10:33:10 +00:00
|
|
|
from erpnext.projects.doctype.timesheet.test_timesheet import (
|
|
|
|
make_salary_structure_for_timesheet,
|
|
|
|
make_timesheet,
|
2021-09-02 11:14:59 +00:00
|
|
|
)
|
2021-04-19 11:19:28 +00:00
|
|
|
from erpnext.projects.doctype.timesheet.timesheet import make_salary_slip, make_sales_invoice
|
|
|
|
from erpnext.projects.report.project_profitability.project_profitability import execute
|
|
|
|
|
2021-09-02 11:14:59 +00:00
|
|
|
|
2021-04-19 11:19:28 +00:00
|
|
|
class TestProjectProfitability(unittest.TestCase):
|
|
|
|
def setUp(self):
|
2021-11-30 08:34:47 +00:00
|
|
|
frappe.db.sql('delete from `tabTimesheet`')
|
2021-04-19 11:19:28 +00:00
|
|
|
emp = make_employee('test_employee_9@salary.com', company='_Test Company')
|
2021-11-30 08:34:47 +00:00
|
|
|
|
2021-04-19 11:19:28 +00:00
|
|
|
if not frappe.db.exists('Salary Component', 'Timesheet Component'):
|
|
|
|
frappe.get_doc({'doctype': 'Salary Component', 'salary_component': 'Timesheet Component'}).insert()
|
2021-11-30 08:34:47 +00:00
|
|
|
|
2021-04-19 11:19:28 +00:00
|
|
|
make_salary_structure_for_timesheet(emp, company='_Test Company')
|
2021-11-30 08:34:47 +00:00
|
|
|
date = getdate()
|
|
|
|
|
|
|
|
self.timesheet = make_timesheet(emp, is_billable=1)
|
2021-04-19 11:19:28 +00:00
|
|
|
self.salary_slip = make_salary_slip(self.timesheet.name)
|
2021-12-28 11:39:46 +00:00
|
|
|
self.salary_slip.start_date = self.timesheet.start_date
|
2021-11-30 08:34:47 +00:00
|
|
|
|
|
|
|
holidays = self.salary_slip.get_holidays_for_employee(date, date)
|
2021-06-20 04:50:35 +00:00
|
|
|
if holidays:
|
|
|
|
frappe.db.set_value('Payroll Settings', None, 'include_holidays_in_total_working_days', 1)
|
|
|
|
|
2021-04-19 11:19:28 +00:00
|
|
|
self.salary_slip.submit()
|
|
|
|
self.sales_invoice = make_sales_invoice(self.timesheet.name, '_Test Item', '_Test Customer')
|
2021-11-30 08:34:47 +00:00
|
|
|
self.sales_invoice.due_date = date
|
2021-04-19 11:19:28 +00:00
|
|
|
self.sales_invoice.submit()
|
|
|
|
|
2021-05-24 12:03:48 +00:00
|
|
|
frappe.db.set_value('HR Settings', None, 'standard_working_hours', 8)
|
2021-06-20 04:50:35 +00:00
|
|
|
frappe.db.set_value('Payroll Settings', None, 'include_holidays_in_total_working_days', 0)
|
2021-04-26 10:33:10 +00:00
|
|
|
|
2021-04-19 11:19:28 +00:00
|
|
|
def test_project_profitability(self):
|
|
|
|
filters = {
|
|
|
|
'company': '_Test Company',
|
2021-12-28 11:39:46 +00:00
|
|
|
'start_date': add_days(self.timesheet.start_date, -3),
|
|
|
|
'end_date': self.timesheet.start_date
|
2021-04-19 11:19:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
report = execute(filters)
|
2021-04-21 07:02:25 +00:00
|
|
|
|
|
|
|
row = report[1][0]
|
|
|
|
timesheet = frappe.get_doc("Timesheet", self.timesheet.name)
|
|
|
|
|
|
|
|
self.assertEqual(self.sales_invoice.customer, row.customer_name)
|
|
|
|
self.assertEqual(timesheet.title, row.employee_name)
|
|
|
|
self.assertEqual(self.sales_invoice.base_grand_total, row.base_grand_total)
|
|
|
|
self.assertEqual(self.salary_slip.base_gross_pay, row.base_gross_pay)
|
|
|
|
self.assertEqual(timesheet.total_billed_hours, row.total_billed_hours)
|
|
|
|
self.assertEqual(self.salary_slip.total_working_days, row.total_working_days)
|
|
|
|
|
|
|
|
standard_working_hours = frappe.db.get_single_value("HR Settings", "standard_working_hours")
|
|
|
|
utilization = timesheet.total_billed_hours/(self.salary_slip.total_working_days * standard_working_hours)
|
|
|
|
self.assertEqual(utilization, row.utilization)
|
2021-04-26 10:33:10 +00:00
|
|
|
|
2021-04-21 07:02:25 +00:00
|
|
|
profit = self.sales_invoice.base_grand_total - self.salary_slip.base_gross_pay * utilization
|
|
|
|
self.assertEqual(profit, row.profit)
|
|
|
|
|
|
|
|
fractional_cost = self.salary_slip.base_gross_pay * utilization
|
|
|
|
self.assertEqual(fractional_cost, row.fractional_cost)
|
2021-04-19 11:19:28 +00:00
|
|
|
|
|
|
|
def tearDown(self):
|
2021-11-30 08:34:47 +00:00
|
|
|
frappe.db.rollback()
|