[IMP] hr_expense: improve expense report by grouping by employee-state-currency
This commit is contained in:
@@ -2,4 +2,5 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import models
|
||||
import report
|
||||
import wizard
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import hr_expense_report
|
||||
@@ -0,0 +1,60 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import time
|
||||
from openerp.osv import osv
|
||||
from openerp.tools.misc import formatLang
|
||||
from openerp.tools.translate import _
|
||||
from openerp.report import report_sxw
|
||||
from openerp.exceptions import UserError
|
||||
|
||||
|
||||
class report_expense(report_sxw.rml_parse):
|
||||
|
||||
def set_context(self, objects, data, ids, report_type=None):
|
||||
res = super(report_expense, self).set_context(objects, data, ids, report_type=report_type)
|
||||
|
||||
hr_expense_obj = self.pool.get('hr.expense')
|
||||
|
||||
context = {'lang': self.pool.get('res.users').browse(self.cr, self.uid, self.uid).lang}
|
||||
state_field = hr_expense_obj.fields_get(self.cr, self.uid, 'state', context=context)['state']['selection']
|
||||
state_dict = {}
|
||||
for state_tuple in state_field:
|
||||
state_dict[state_tuple[0]] = state_tuple[1]
|
||||
|
||||
expenses_info = {}
|
||||
expenses = hr_expense_obj.search(self.cr, self.uid, [('id', 'in', ids)], order="employee_id, currency_id, state, date")
|
||||
for expense in hr_expense_obj.browse(self.cr, self.uid, expenses):
|
||||
key = expense.employee_id.name + '-' + expense.currency_id.name + '-' + expense.state
|
||||
if expenses_info.get(key):
|
||||
expenses_info[key]['lines'] += expense
|
||||
expenses_info[key]['total_amount'] += expense.total_amount
|
||||
else:
|
||||
expenses_info[key] = {
|
||||
'employee_name': expense.employee_id.name,
|
||||
'total_amount': expense.total_amount,
|
||||
'lines': expense,
|
||||
'currency': expense.currency_id,
|
||||
'validator_name': expense.employee_id.parent_id.name,
|
||||
'notes': [],
|
||||
'notes_index': {},
|
||||
'state': state_dict[expense.state],
|
||||
}
|
||||
if expense.description:
|
||||
index = len(expenses_info[key]['notes']) + 1
|
||||
expenses_info[key]['notes'].append({'description': expense.description, 'index':index})
|
||||
expenses_info[key]['notes_index'][expense.id] = index
|
||||
|
||||
# Qweb for-each do not work on dict, so we send a list and we sort it by the name of the employee
|
||||
# that way if we have two sheet for the same employee they will follow in the report
|
||||
self.localcontext.update({
|
||||
'get_expenses': lambda : [v for k,v in sorted(expenses_info.items())],
|
||||
})
|
||||
return res
|
||||
|
||||
|
||||
class report_hr_expense(osv.AbstractModel):
|
||||
_name = 'report.hr_expense.report_expense'
|
||||
_inherit = 'report.abstract_report'
|
||||
_template = 'hr_expense.report_expense'
|
||||
_wrapped_report_class = report_expense
|
||||
@@ -2,7 +2,7 @@
|
||||
<odoo>
|
||||
<template id="report_expense">
|
||||
<t t-call="report.html_container">
|
||||
<t t-foreach="docs" t-as="o">
|
||||
<t t-foreach="get_expenses()" t-as="o">
|
||||
<t t-call="report.external_layout">
|
||||
<div class="page">
|
||||
<h2>HR Expenses</h2>
|
||||
@@ -10,25 +10,26 @@
|
||||
<div class="row mt32 mb32">
|
||||
<div class="col-xs-3">
|
||||
<strong>Employee:</strong>
|
||||
<p t-field="o.employee_id.name"/>
|
||||
<p t-esc="o['employee_name']"/>
|
||||
</div>
|
||||
<div class="col-xs-3">
|
||||
<strong>Date:</strong>
|
||||
<p t-field="o.date"/>
|
||||
<strong>Manager:</strong>
|
||||
<p t-esc="o['validator_name']"/>
|
||||
</div>
|
||||
<div class="col-xs-3">
|
||||
<strong>Description:</strong>
|
||||
<p t-field="o.name"/>
|
||||
<strong>Status:</strong>
|
||||
<p t-esc="o['state']"/>
|
||||
</div>
|
||||
<div class="col-xs-3">
|
||||
<strong>Validated By:</strong>
|
||||
<p t-field="o.employee_id.parent_id.name"/>
|
||||
<strong>Currency:</strong>
|
||||
<p t-field="o['currency'].name"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="table table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Name</th>
|
||||
<th>Unit Price</th>
|
||||
<th class="text-center">Qty</th>
|
||||
@@ -38,35 +39,46 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<span t-field="o.name"/>
|
||||
<span t-field="o.analytic_account_id.name"/>
|
||||
</td>
|
||||
<td>
|
||||
<span t-field="o.unit_amount"/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span t-field="o.quantity"/>
|
||||
</td>
|
||||
<td groups="product.group_uom">
|
||||
<span t-field="o.product_uom_id"/>
|
||||
</td>
|
||||
<td>
|
||||
<t t-foreach="o.tax_ids" t-as="tax">
|
||||
<t t-if="tax.description">
|
||||
<span t-field="tax.description"/>
|
||||
</t>
|
||||
<t t-if="not tax.description">
|
||||
<span t-field="tax.name"/>
|
||||
</t>
|
||||
</t>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-field="o.total_amount"
|
||||
t-field-options='{"widget": "monetary", "display_currency":"o.currency_id"}'/>
|
||||
</td>
|
||||
</tr>
|
||||
<t t-foreach="o['lines']" t-as="line">
|
||||
<tr>
|
||||
<td>
|
||||
<span t-field='line.date'/>
|
||||
<t t-if="line.description">
|
||||
<sup><span t-esc="o['notes_index'][line.id]"/></sup>
|
||||
</t>
|
||||
</td>
|
||||
<td>
|
||||
<span t-field="line.name"/>
|
||||
<t t-if="line.analytic_account_id.name">
|
||||
(<span t-field="line.analytic_account_id.name"/>)
|
||||
</t>
|
||||
</td>
|
||||
<td>
|
||||
<span t-field="line.unit_amount"
|
||||
t-field-options='{"widget": "monetary", "display_currency":"line.currency_id"}'/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span t-field="line.quantity"/>
|
||||
</td>
|
||||
<td groups="product.group_uom">
|
||||
<span t-field="line.product_uom_id"/>
|
||||
</td>
|
||||
<td>
|
||||
<t t-foreach="line.tax_ids" t-as="tax">
|
||||
<t t-if="tax.description">
|
||||
<span t-field="tax.description"/>
|
||||
</t>
|
||||
<t t-if="not tax.description">
|
||||
<span t-field="tax.name"/>
|
||||
</t>
|
||||
</t>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<span t-field="line.total_amount"
|
||||
t-field-options='{"widget": "monetary", "display_currency":"line.currency_id"}'/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -76,15 +88,18 @@
|
||||
<tr class="border-black">
|
||||
<td><strong>Total</strong></td>
|
||||
<td class="text-right">
|
||||
<span t-field="o.total_amount"
|
||||
t-field-options='{"widget": "monetary", "display_currency": "o.currency_id"}'/>
|
||||
<span t-esc="formatLang(o['total_amount'], currency_obj=o['currency'])"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p t-field="o.description"/>
|
||||
<t t-foreach="o['notes']" t-as="note">
|
||||
<span t-esc="note['index']"/>. <span t-esc="note['description']"/>
|
||||
<br/>
|
||||
</t>
|
||||
<br/>
|
||||
<br/>
|
||||
<p>Certified honest and conform,<br/>(Date and signature).<br/><br/></p>
|
||||
<p>This document must be dated and signed for reimbursement.</p>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user