[IMP] sale_timesheet: split non billable type for timesheet

Timesheet logged on project created from a SO line are
not exactly the same as the non billable ones.

To ease the reporting, we split the non billable type
of timesheet: when timesheeting directly on a project
(whatever the product config), the billable type will
be 'no task found'.
The Overview is adapt to display the 2 'non billable'
categories.
This commit is contained in:
Jérome Maes
2017-09-13 08:41:31 +02:00
parent 40beeed12d
commit fda8d77c69
4 changed files with 32 additions and 12 deletions
+2 -1
View File
@@ -24,7 +24,7 @@ class SaleTimesheetController(http.Controller):
'domain': domain,
}
hour_rounding = request.env.ref('product.product_uom_hour').rounding
billable_types = ['non_billable', 'billable_time', 'billable_fixed']
billable_types = ['non_billable', 'non_billable_project', 'billable_time', 'billable_fixed']
# -- Dashboard (per billable type)
dashboard_values = {
@@ -69,6 +69,7 @@ class SaleTimesheetController(http.Controller):
repartition_employee.setdefault(employee_id, dict(
employee_id=data['employee_id'][0],
employee_name=data['employee_id'][1],
non_billable_project=0.0,
non_billable=0.0,
billable_time=0.0,
billable_fixed=0.0,
+4 -3
View File
@@ -11,7 +11,8 @@ class AccountAnalyticLine(models.Model):
timesheet_invoice_type = fields.Selection([
('billable_time', 'Billable Time'),
('billable_fixed', 'Billable Fixed'),
('non_billable', 'Non Billable')], string="Billable Type", readonly=True, copy=False)
('non_billable', 'Non Billable'),
('non_billable_project', 'No task found')], string="Billable Type", readonly=True, copy=False)
timesheet_invoice_id = fields.Many2one('account.invoice', string="Invoice", readonly=True, copy=False, help="Invoice created from the timesheet")
timesheet_revenue = fields.Monetary("Revenue", default=0.0, readonly=True, currency_field='company_currency_id', copy=False)
@@ -83,14 +84,14 @@ class AccountAnalyticLine(models.Model):
timesheet_uom = self.env.user.company_id.project_time_mode_id
# default values
billable_type = 'non_billable'
billable_type = 'non_billable_project' if not timesheet.task_id else 'non_billable'
unit_amount = timesheet.unit_amount
so_line = timesheet.so_line
revenue = 0.0
billable_type = 'non_billable'
# set the revenue and billable type according to the product and the SO line
if so_line.product_id.type == 'service' and so_line.product_id.service_type == 'timesheet':
if timesheet.task_id and so_line.product_id.type == 'service' and so_line.product_id.service_type == 'timesheet':
# find the analytic account to convert revenue into its currency
analytic_account = timesheet.account_id
# convert the unit of mesure into hours
@@ -35,6 +35,10 @@
background-color: #5bc0de;
color: white;
}
.o_progress_non_billable_project {
background-color: @brand-primary;
color: white;
}
.o_progress_non_billable {
background-color: gray;
color: white;
@@ -19,21 +19,21 @@
<table class="table">
<tbody>
<tr>
<th rowspan="4">
<th rowspan="5">
<a type="action" t-att-domain="json.dumps(domain)" context="{'pivot_row_groupby': ['date:month'],'pivot_column_groupby': ['timesheet_invoice_type'], 'pivot_measures': ['unit_amount']}">Hours</a>
</th>
<td class="o_timesheet_plan_dashboard_cell">
<t t-esc="dashboard['hours']['billable_time']"/> h
</td>
<td>Time and material</td>
<th rowspan="4">
<th rowspan="5">
<a type="action" t-att-domain="json.dumps(domain)" context="{'pivot_row_groupby': ['date:month', 'employee_id'], 'pivot_column_groupby': ['timesheet_invoice_type'],'pivot_measures': ['unit_amount']}">Rates</a>
</th>
<td class="o_timesheet_plan_dashboard_cell">
<t t-esc="dashboard['rates']['billable_time']"/> %
</td>
<td>Time and material</td>
<th rowspan="4">
<th rowspan="5">
<a type="action" t-att-domain="json.dumps(domain)" context="{'pivot_row_groupby': ['timesheet_invoice_id'], 'pivot_column_groupby': ['date:month'],'pivot_measures': ['amount', 'timesheet_revenue']}">Profitability</a>
</th>
<td class="o_timesheet_plan_dashboard_cell">
@@ -61,13 +61,13 @@
</tr>
<tr>
<td class="o_timesheet_plan_dashboard_cell">
<t t-esc="dashboard['hours']['non_billable']"/> h
<t t-esc="float_to_time(dashboard['hours']['non_billable_project'])"/>
</td>
<td>Non Billable</td>
<td>No task found</td>
<td class="o_timesheet_plan_dashboard_cell">
<t t-esc="dashboard['rates']['non_billable']"/> %
<t t-esc="dashboard['rates']['non_billable_project']"/> %
</td>
<td>Non Billable</td>
<td>No task found</td>
<td class="o_timesheet_plan_dashboard_cell">
<t t-if="currency.position == 'before'" t-esc="currency.symbol"/>
<t t-esc="dashboard['money_amount']['cost']"/>
@@ -75,6 +75,18 @@
</td>
<td>Cost</td>
</tr>
<tr>
<td class="o_timesheet_plan_dashboard_cell">
<t t-esc="float_to_time(dashboard['hours']['non_billable'])"/>
</td>
<td>Non Billable</td>
<td class="o_timesheet_plan_dashboard_cell">
<t t-esc="dashboard['rates']['non_billable']"/> %
</td>
<td>Non Billable</td>
<td class="o_timesheet_plan_dashboard_cell"></td>
<td></td>
</tr>
<tr>
<td class="o_timesheet_plan_dashboard_total">
<t t-esc="dashboard['hours']['total']"/> h
@@ -104,6 +116,7 @@
<div class="pull-right o_timesheet_plan_badge">
<span class="badge o_progress_billable_fixed">Billable fixed</span>
<span class="badge o_progress_billable_time">Billable time</span>
<span class="badge o_progress_non_billable_project">No task found</span>
<span class="badge o_progress_non_billable">Non billable</span>
</div>
<table class="table ">
@@ -123,8 +136,9 @@
<div t-if="repartition_employee[employee_id]['billable_fixed']" class="progress-bar o_progress_billable_fixed" t-att-style="'width: ' + str(repartition_employee[employee_id]['billable_fixed'] / repartition_employee[employee_id]['total'] * 100) + '%'" t-att-title="str(repartition_employee[employee_id]['billable_fixed']) + ' hours'">
</div>
<div t-if="repartition_employee[employee_id]['billable_time']" class="progress-bar o_progress_billable_time" t-att-style="'width: ' + str(repartition_employee[employee_id]['billable_time'] / repartition_employee[employee_id]['total'] * 100) + '%'" t-att-title="str(repartition_employee[employee_id]['billable_time']) + ' hours'">
</div><div t-if="repartition_employee[employee_id]['non_billable_project']" class="progress-bar o_progress_non_billable_project" t-att-style="'width: ' + str(repartition_employee[employee_id]['non_billable_project'] / repartition_employee[employee_id]['total'] * 100) + '%'" t-att-title="float_to_time(repartition_employee[employee_id]['non_billable_project'])">
</div>
<div t-if="repartition_employee[employee_id]['non_billable']" class="progress-bar o_progress_non_billable" t-att-style="'width: ' + str(repartition_employee[employee_id]['non_billable'] / repartition_employee[employee_id]['total'] * 100) + '%'" t-att-title="str(repartition_employee[employee_id]['non_billable']) + ' hours'">
<div t-if="repartition_employee[employee_id]['non_billable']" class="progress-bar o_progress_non_billable" t-att-style="'width: ' + str(repartition_employee[employee_id]['non_billable'] / repartition_employee[employee_id]['total'] * 100) + '%'" t-att-title="float_to_time(repartition_employee[employee_id]['non_billable'])">
</div>
</div>
</td>