[IMP] hr*: adaptation due to the new Sale module

Major changes:
- No use of UoS anymore
- No journal since invoicing is managed in Sale
- No invoicing from timesheet

Reason: complete rewrite of the Sale module.

Responsible: fp, dbo, nim
This commit is contained in:
Nicolas Martinelli
2015-08-27 18:10:18 +02:00
parent 868e7c6a6e
commit e021a08b30
22 changed files with 97 additions and 399 deletions
+3 -3
View File
@@ -199,7 +199,7 @@ class hr_expense_expense(osv.osv):
'ref': x.get('ref', False),
'quantity': x.get('quantity',1.00),
'product_id': x.get('product_id', False),
'product_uom_id': x.get('uos_id', False),
'product_uom_id': x.get('uom_id', False),
'analytic_account_id': x.get('account_analytic_id', False),
}
@@ -342,7 +342,7 @@ class hr_expense_expense(osv.osv):
'price':line.total_amount,
'account_id':acc.id,
'product_id':line.product_id.id,
'uos_id':line.uom_id.id,
'uom_id':line.uom_id.id,
'account_analytic_id':line.analytic_account.id,
}
@@ -399,7 +399,7 @@ class hr_expense_line(osv.osv):
'total_amount': fields.function(_amount, string='Total', digits=0),
'unit_amount': fields.float('Unit Price', digits_compute=dp.get_precision('Product Price')),
'unit_quantity': fields.float('Quantities', digits_compute= dp.get_precision('Product Unit of Measure')),
'product_id': fields.many2one('product.product', 'Product', domain=[('hr_expense_ok','=',True)]),
'product_id': fields.many2one('product.product', 'Product', domain=[('hr_expense_ok','=',True)], required=True),
'uom_id': fields.many2one('product.uom', 'Unit of Measure', required=True),
'description': fields.text('Description'),
'analytic_account': fields.many2one('account.analytic.account','Analytic account'),
+12 -11
View File
@@ -26,7 +26,7 @@
<field name="list_price">700.0</field>
<field name="standard_price">700.0</field>
<field name="type">service</field>
<field name="name">Air Ticket</field>
<field name="name">Air Flight</field>
<field name="default_code">AT</field>
<field name="categ_id" ref="hr_expense.cat_expense"/>
<field name="hr_expense_ok" eval="True" />
@@ -50,7 +50,8 @@
<record id="expenses_line0" model="hr.expense.line">
<field name="name">Travel Expenses</field>
<field name="date_value" eval="time.strftime('%Y-08-10')"/>
<field name="analytic_account" ref="analytic.analytic_consultancy"/>
<field name="analytic_account" ref="analytic.analytic_our_super_product"/>
<field name="product_id" ref="hotel_rent"/>
<field name="expense_id" ref="expenses0"/>
<field eval="200.0" name="unit_amount"/>
<field name="uom_id" ref="product.product_uom_unit"/>
@@ -66,7 +67,7 @@
<record id="travel_by_air_sep" model="hr.expense.line">
<field name="name">Travel by Air</field>
<field name="date_value" eval="time.strftime('%Y-09-03')"/>
<field name="analytic_account" ref="analytic.analytic_consultancy"/>
<field name="analytic_account" ref="analytic.analytic_our_super_product"/>
<field name="product_id" ref="air_ticket"/>
<field name="expense_id" ref="sep_expenses"/>
<field eval="700.0" name="unit_amount"/>
@@ -86,14 +87,14 @@
</record>
<record id="car_travel_sep" model="hr.expense.line">
<field name="name">Bruxelles - Paris</field>
<field name="date_value" eval="time.strftime('%Y-09-15')"/>
<field name="analytic_account" ref="analytic.analytic_nebula"/>
<field name="product_id" ref="car_travel"/>
<field name="expense_id" ref="sep_expenses"/>
<field eval="0.30" name="unit_amount"/>
<field name="uom_id" ref="product.product_uom_km"/>
<field eval="622.0" name="unit_quantity"/>
<field name="name">Bruxelles - Paris</field>
<field name="date_value" eval="time.strftime('%Y-09-15')"/>
<field name="analytic_account" ref="analytic.analytic_nebula"/>
<field name="product_id" ref="car_travel"/>
<field name="expense_id" ref="sep_expenses"/>
<field eval="0.30" name="unit_amount"/>
<field name="uom_id" ref="product.product_uom_km"/>
<field eval="622.0" name="unit_quantity"/>
</record>
</data>
+4 -4
View File
@@ -13,7 +13,7 @@
<field name="date_value"/>
<field name="name"/>
<field name="ref"/>
<field domain="[('type','in',['normal','contract']), ('parent_id','!=',False)]" name="analytic_account" groups="analytic.group_analytic_accounting"/>
<field name="analytic_account"/>
<field name="unit_amount"/>
<field name="unit_quantity"/>
<field name="total_amount" sum="Total" widget="monetary"/>
@@ -94,7 +94,7 @@
<field name="product_id" on_change="onchange_product_id(product_id, context)" context="{'default_hr_expense_ok':1}"/>
<field name="name"/>
<field name="ref"/>
<field domain="[('type','in',['normal','contract'])]" name="analytic_account" groups="analytic.group_analytic_accounting"/>
<field name="analytic_account"/>
</group>
<group>
<field name="unit_amount"/>
@@ -113,7 +113,7 @@
<field name="date_value" string="Expense Date"/>
<field name="name" string="Description"/>
<field name="ref"/>
<field domain="[('type','in',['normal','contract'])]" name="analytic_account" groups="analytic.group_analytic_accounting"/>
<field name="analytic_account"/>
<field name="uom_id" on_change="onchange_uom(product_id, uom_id, context)"/>
<field name="unit_amount"/>
<field name="unit_quantity"/>
@@ -130,7 +130,7 @@
</group>
</group>
</page>
<page string="Accounting Info" groups="account.group_account_user" attrs="{'invisible': [('state', 'not in', ['done', 'paid'])]}">
<page string="Accounting Info" groups="account.group_account_user" attrs="{'invisible': [('state', 'not in', ['done', 'paid', 'accepted'])]}">
<group>
<group>
<field name="journal_id" widget="selection" attrs="{'readonly':[('state','=','done')]}" domain="[('type', '=', 'purchase')]" string="Journal"/>
@@ -12,7 +12,6 @@ access_account_journal_user,account.journal.user,account.model_account_journal,b
access_account_journal_employee,account.journal.employee,account.model_account_journal,base.group_user,1,0,0,0
access_account_invoice_user,account.invoice.user,account.model_account_invoice,base.group_hr_user,1,1,1,1
access_account_invoice_line_user,account.invoice.line.user,account.model_account_invoice_line,base.group_hr_user,1,1,1,1
access_account_analytic_journal_user,account.ianalytic.journal.user,analytic.model_account_analytic_journal,base.group_hr_user,1,1,1,1
access_account_invoice_tax_user,account.invoice.tax.user,account.model_account_invoice_tax,base.group_hr_user,1,1,1,1
access_account_move_user,account.move.user,account.model_account_move,base.group_hr_user,1,1,1,1
access_account_move_line_user,account.move.line.user,account.model_account_move_line,base.group_hr_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
12 access_account_journal_employee account.journal.employee account.model_account_journal base.group_user 1 0 0 0
13 access_account_invoice_user account.invoice.user account.model_account_invoice base.group_hr_user 1 1 1 1
14 access_account_invoice_line_user account.invoice.line.user account.model_account_invoice_line base.group_hr_user 1 1 1 1
access_account_analytic_journal_user account.ianalytic.journal.user analytic.model_account_analytic_journal base.group_hr_user 1 1 1 1
15 access_account_invoice_tax_user account.invoice.tax.user account.model_account_invoice_tax base.group_hr_user 1 1 1 1
16 access_account_move_user account.move.user account.model_account_move base.group_hr_user 1 1 1 1
17 access_account_move_line_user account.move.line.user account.model_account_move_line base.group_hr_user 1 1 1 1
+1 -4
View File
@@ -2,10 +2,7 @@
!record {model: hr.expense.expense, id: sep_expenses}:
employee_id: hr.employee_mit
name : 'John Smith'
-
!record {model: product.product, id: car_travel}:
hr_expense_ok: 'True'
-
!record {model: hr.expense.line, id: expense_line}:
product_id: car_travel
product_id: hr_expense.car_travel
name: 'Car Travel Expenses'
+1 -1
View File
@@ -44,7 +44,7 @@
<td>
<span t-field="line.name"/>
<span t-field="line.description"/><br/>
<span t-field="line.analytic_account.complete_name"/>
<span t-field="line.analytic_account.name"/>
</td>
<td style="text-center">
<span t-field="line.ref"/>
-2
View File
@@ -27,11 +27,9 @@ up a management by affair.
'hr_timesheet_view.xml',
'report/hr_timesheet_report_view.xml',
'hr_timesheet_installer.xml',
'hr_timesheet_data.xml',
'hr_dashboard.xml',
],
'demo': [
'hr_timesheet_demo.xml',
'hr_timesheet_demo.yml',
],
'test': [
+4 -138
View File
@@ -1,149 +1,15 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from openerp import models, api, fields, exceptions
from openerp.tools.translate import _
class HrEmployee(models.Model):
_inherit = "hr.employee"
@api.model
def _get_default_analytic_journal(self):
# We need the "or ..." because we need an empty recordset of the right type, 'False' is not enough.
return self.env.ref('hr_timesheet.analytic_journal', raise_if_not_found=False) or self.env['account.analytic.journal']
product_id = fields.Many2one('product.product', 'Product', help="If you want to reinvoice working time of employees, link this employee to a service to determinate the cost price of the job.")
journal_id = fields.Many2one('account.analytic.journal', 'Analytic Journal', default=_get_default_analytic_journal)
uom_id = fields.Many2one('product.uom', related='product_id.uom_id', string='Unit of Measure', store=True, readonly=True)
from openerp import models, fields
class Company(models.Model):
_inherit = 'res.company'
class account_analytic_line(models.Model):
_inherit = 'account.analytic.line'
is_timesheet = fields.Boolean()
@api.model
def _get_employee_product(self, user_id=None):
emp = self.env['hr.employee'].search([('user_id', '=', user_id or self.env.uid)], limit=1)
if emp and emp.product_id.id:
return emp.product_id.id
else:
return None
@api.model
def _get_employee_unit(self, user_id=None):
emp = self.env['hr.employee'].search([('user_id', '=', user_id or self.env.uid)], limit=1)
if emp and emp.product_id.uom_id.id:
return emp.product_id.uom_id.id
else:
return None
@api.model
def _get_general_account(self, user_id=None):
emp = self.env['hr.employee'].search([('user_id', '=', user_id or self.env.uid)], limit=1)
if emp and emp.product_id.categ_id.property_account_expense_categ_id.id:
return emp.product_id.categ_id.property_account_expense_categ_id.id
else:
return None
@api.model
def _get_analytic_journal(self, user_id=None):
emp = self.env['hr.employee'].search([('user_id', '=', user_id or self.env.uid)], limit=1)
if emp and emp.journal_id.id:
return emp.journal_id.id
else:
journal = self.env['account.analytic.journal'].search([('type', '=', 'general')], limit=1)
if journal:
return journal.id
else:
return None
@api.onchange('user_id')
def V8_on_change_user_id(self):
new_values = self.on_change_user_id(self.user_id.id, self.is_timesheet)
if new_values.get("value"):
for key, value in new_values["value"].iteritems():
setattr(self, key, value)
def on_change_user_id(self, cr, uid, ids, user_id, is_timesheet=False, context=None):
if not is_timesheet or not user_id:
return {}
res = {"value": {
'journal_id': self._get_analytic_journal(cr, uid, user_id, context=context),
'product_id': self._get_employee_product(cr, uid, user_id, context=context),
'uom_id': self._get_employee_unit(cr, uid, user_id, context=context),
'general_account_id': self._get_general_account(cr, uid, user_id, context=context)
}
}
return res
def on_change_unit_amount(self, cr, uid, id, prod_id, unit_amount, company_id, unit=False, journal_id=False, context=None):
res = {'value': {}}
if unit_amount:
# find company
company_id = self.pool.get('res.company')._company_default_get(cr, uid, 'account.analytic.line', context=context)
r = super(account_analytic_line, self).on_change_unit_amount(cr, uid, id, prod_id, unit_amount, company_id, unit, journal_id, context=context)
if r:
res.update(r)
# update unit of measurement
if prod_id:
uom = self.pool.get('product.product').browse(cr, uid, prod_id, context=context)
if uom.uom_id:
res['value'].update({'product_uom_id': uom.uom_id.id})
else:
res['value'].update({'product_uom_id': False})
return res
@api.onchange('date')
def on_change_date(self):
if self.is_timesheet and self._origin.date and (self._origin.date != self.date):
raise exceptions.Warning(_('Changing the date will let this entry appear in the timesheet of the new date.'))
@api.model
def create(self, values):
if values.get('is_timesheet'):
if not values.get('product_id'):
values['product_id'] = self._get_employee_product()
if not values.get('product_uom_id'):
values['product_uom_id'] = self._get_employee_unit()
if not values.get('general_account_id'):
values['general_account_id'] = self._get_general_account()
if not values.get('journal_id'):
values['journal_id'] = self._get_analytic_journal()
return super(account_analytic_line, self).create(values)
is_timesheet = fields.Boolean(string="Is a Timesheet")
class account_analytic_account(models.Model):
_inherit = 'account.analytic.account'
use_timesheets = fields.Boolean('Timesheets', help="Check this field if this project manages timesheets", deprecated=True)
invoice_on_timesheets = fields.Boolean('Timesheets', help="Check this field if this project manages timesheets")
@api.onchange('invoice_on_timesheets')
def onchange_invoice_on_timesheets(self):
result = {'value': {}}
if not self.invoice_on_timesheets:
return {'value': {'to_invoice': False}}
try:
to_invoice = self.env['ir.model.data'].xmlid_to_res_id('hr_timesheet_invoice.timesheet_invoice_factor1')
result['value']['to_invoice'] = to_invoice
except ValueError:
pass
return result
@api.onchange('template_id')
def V8_on_change_template(self):
new_values = self.on_change_template(selftemplate_id.id, self.date_start)
if new_values.get("value"):
for key, value in new_values["value"].iteritems():
setattr(self, key, value)
def on_change_template(self, cr, uid, ids, template_id, date_start=False, context=None):
res = super(account_analytic_account, self).on_change_template(cr, uid, ids, template_id, date_start=date_start, context=context)
if template_id and 'value' in res:
template = self.browse(cr, uid, template_id, context=context)
res['value']['invoice_on_timesheets'] = template.invoice_on_timesheets
return res
-13
View File
@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record id="analytic_journal" model="account.analytic.journal">
<field name="code">TS</field>
<field name="name">Timesheet Journal</field>
<field name="type">general</field>
</record>
</data>
</openerp>
-26
View File
@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record id="hr.employee_fp" model="hr.employee">
<field name="product_id" ref="product.product_product_1"/>
<field name="journal_id" ref="analytic_journal"/>
</record>
<record id="hr.employee_qdp" model="hr.employee">
<field name="product_id" ref="product.product_product_1"/>
<field name="journal_id" ref="analytic_journal"/>
</record>
<record id="analytic.analytic_administratif" model="account.analytic.account">
<field name="invoice_on_timesheets">True</field>
</record>
<record id="analytic.analytic_partners" model="account.analytic.account">
<field name="invoice_on_timesheets">True</field>
</record>
<record id="analytic.analytic_consultancy" model="account.analytic.account">
<field name="invoice_on_timesheets">True</field>
</record>
<record id="analytic.analytic_super_product_trainings" model="account.analytic.account">
<field name="invoice_on_timesheets">True</field>
</record>
</data>
</openerp>
+55 -67
View File
@@ -3,70 +3,58 @@
-
!python {model: ir.model.data} : |
import time
expense_account_id = self.pool.get('account.account').search(cr, uid, [('user_type_id', '=', ref('account.data_account_type_expenses'))])
if expense_account_id:
vals = {
'name': 'Requirements analysis and specification',
'user_id': ref('base.user_root'),
'date': time.strftime('%Y-%m-%d'),
'unit_amount': 2.00,
'product_id': ref('product.product_product_1'),
'product_uom_id': ref('product.product_uom_hour'),
'account_id': ref('analytic.analytic_administratif'),
'amount': -60.00,
'general_account_id': expense_account_id[0],
'journal_id': ref('analytic_journal')
}
self._update(cr, uid, 'account.analytic.line', 'hr_timesheet', vals, 'working_hours_requirements')
vals = {
'name': 'Design and specification',
'user_id': ref('base.user_root'),
'date': time.strftime('%Y-%m-%d'),
'unit_amount': 1.00,
'product_id': ref('product.product_product_1'),
'product_uom_id': ref('product.product_uom_hour'),
'account_id': ref('analytic.analytic_administratif'),
'amount': -30.00,
'general_account_id': expense_account_id[0],
'journal_id': ref('analytic_journal')
}
self._update(cr, uid, 'account.analytic.line', 'hr_timesheet', vals, 'working_hours_design')
vals = {
'name': 'Coding and module testing',
'user_id': ref('base.user_root'),
'date': time.strftime('%Y-%m-%d'),
'unit_amount': 3.00,
'product_id': ref('product.product_product_1'),
'product_uom_id': ref('product.product_uom_hour'),
'account_id': ref('analytic.analytic_administratif'),
'amount': -90.00,
'general_account_id': expense_account_id[0],
'journal_id': ref('analytic_journal')
}
self._update(cr, uid, 'account.analytic.line', 'hr_timesheet', vals, 'working_hours_coding')
vals = {
'name': 'Integration and system testing',
'user_id': ref('base.user_root'),
'date': time.strftime('%Y-%m-%d'),
'unit_amount': 1.00,
'product_id': ref('product.product_product_1'),
'product_uom_id': ref('product.product_uom_hour'),
'account_id': ref('analytic.analytic_administratif'),
'amount': -30.00,
'general_account_id': expense_account_id[0],
'journal_id': ref('analytic_journal')
}
self._update(cr, uid, 'account.analytic.line', 'hr_timesheet', vals, 'working_hours_testing')
vals = {
'name': 'Delivery and maintenance',
'user_id': ref('base.user_root'),
'date': time.strftime('%Y-%m-%d'),
'unit_amount': 1.00,
'product_id': ref('product.product_product_1'),
'product_uom_id': ref('product.product_uom_hour'),
'account_id': ref('analytic.analytic_administratif'),
'amount': -30.00,
'general_account_id': expense_account_id[0],
'journal_id': ref('analytic_journal')
}
self._update(cr, uid, 'account.analytic.line', 'hr_timesheet', vals, 'working_hours_maintenance')
vals = {
'name': 'Requirements analysis and specification',
'user_id': ref('base.user_root'),
'date': time.strftime('%Y-%m-%d'),
'unit_amount': 2.00,
'product_id': ref('product.product_product_1'),
'product_uom_id': ref('product.product_uom_hour'),
'account_id': ref('analytic.analytic_administratif'),
'amount': -60.00,
}
self._update(cr, uid, 'account.analytic.line', 'hr_timesheet', vals, 'working_hours_requirements')
vals = {
'name': 'Design and specification',
'user_id': ref('base.user_root'),
'date': time.strftime('%Y-%m-%d'),
'unit_amount': 1.00,
'product_id': ref('product.product_product_1'),
'product_uom_id': ref('product.product_uom_hour'),
'account_id': ref('analytic.analytic_administratif'),
'amount': -30.00,
}
self._update(cr, uid, 'account.analytic.line', 'hr_timesheet', vals, 'working_hours_design')
vals = {
'name': 'Coding and module testing',
'user_id': ref('base.user_root'),
'date': time.strftime('%Y-%m-%d'),
'unit_amount': 3.00,
'product_id': ref('product.product_product_1'),
'product_uom_id': ref('product.product_uom_hour'),
'account_id': ref('analytic.analytic_administratif'),
'amount': -90.00,
}
self._update(cr, uid, 'account.analytic.line', 'hr_timesheet', vals, 'working_hours_coding')
vals = {
'name': 'Integration and system testing',
'user_id': ref('base.user_root'),
'date': time.strftime('%Y-%m-%d'),
'unit_amount': 1.00,
'product_id': ref('product.product_product_1'),
'product_uom_id': ref('product.product_uom_hour'),
'account_id': ref('analytic.analytic_administratif'),
'amount': -30.00,
}
self._update(cr, uid, 'account.analytic.line', 'hr_timesheet', vals, 'working_hours_testing')
vals = {
'name': 'Delivery and maintenance',
'user_id': ref('base.user_root'),
'date': time.strftime('%Y-%m-%d'),
'unit_amount': 1.00,
'product_id': ref('product.product_product_1'),
'product_uom_id': ref('product.product_uom_hour'),
'account_id': ref('analytic.analytic_administratif'),
'amount': -30.00,
}
self._update(cr, uid, 'account.analytic.line', 'hr_timesheet', vals, 'working_hours_maintenance')
+5 -71
View File
@@ -11,13 +11,8 @@
<field name="user_id" required="1" options='{"no_open": True}'
context="{'default_groups_ref': ['base.group_user']}"/>
<field name="name"/>
<field domain="[('type','=','normal'),('invoice_on_timesheets','=',1)]" name="account_id" context="{'default_use_timesheets': 1, 'default_type': 'contract'}" options="{'no_open': True, 'no_create': True}"/>
<field name="unit_amount" string="Duration" on_change="on_change_unit_amount(product_id, unit_amount, False, product_uom_id,journal_id)" sum="Total time" widget="float_time"/>
<field name="product_uom_id" on_change="on_change_unit_amount(product_id, unit_amount, False, product_uom_id,journal_id)" invisible="1"/>
<field name="journal_id" invisible="1"/>
<field name="amount" sum="Total cost" invisible="1"/>
<field name="general_account_id" invisible="1"/>
<field name="product_id" on_change="on_change_unit_amount(product_id, unit_amount, False, product_uom_id,journal_id)" domain="[('type','=','service')]" invisible="1"/>
<field name="account_id" context="{'default_use_timesheets': 1, 'default_type': 'contract'}" options="{'no_open': True, 'no_create': True}"/>
<field name="unit_amount" string="Duration" sum="Total time" widget="float_time"/>
<field name="is_timesheet" invisible="1"/>
</tree>
</field>
@@ -43,18 +38,16 @@
<page string="Information">
<group>
<group string="Product">
<field name="product_id" on_change="on_change_unit_amount(product_id, unit_amount, False, product_uom_id,journal_id)" domain="[('type','=','service')]"/>
<field name="product_id" domain="[('type','=','service')]"/>
<label string="Duration" for="unit_amount"/>
<div>
<field name="unit_amount" class="oe_inline" on_change="on_change_unit_amount(product_id, unit_amount, False, product_uom_id,journal_id)"/>
<field name="unit_amount" class="oe_inline"/>
<field name="product_uom_id" class="oe_inline"/>
</div>
</group>
<group name="accounting" string="Accounting">
<field domain="[('type','=','normal'),('state', '&lt;&gt;', 'close'),('parent_id','!=',False)]" name="account_id" select="1" options="{'no_open': True, 'no_create': True}"/>
<field domain="[('account_type', '=', 'normal')]" name="account_id" select="1" options="{'no_open': True, 'no_create': True}"/>
<field name="amount"/>
<field name="general_account_id"/>
<field name="journal_id"/>
</group>
</group>
</page>
@@ -81,58 +74,12 @@
</field>
</record>
<record model="ir.actions.act_window" id="act_analytic_cost_revenue">
<field name="context">{'search_default_group_date': 1, 'search_default_group_journal': 1}</field>
<field name="domain">[('account_id','child_of', active_id)]</field>
<field name="name">Costs &amp; Revenues</field>
<field name="res_model">account.analytic.line</field>
<field name="src_model">account.analytic.account</field>
<field name="view_mode">tree,form</field>
<field name="view_type">tree</field>
<field name="help" type="html">
<p>
No activity yet on this contract.
</p><p>
In Odoo, contracts and projects are implemented using
analytic account. So, you can track costs and revenues to analyse
your margins easily.
</p><p>
Costs will be created automatically when you register supplier
invoices, expenses or timesheets.
</p><p>
Revenues will be created automatically when you create customer
invoices. Customer invoices can be created based on sale orders
(fixed price invoices), on timesheets (based on the work done) or
on expenses (e.g. reinvoicing of travel costs).
</p>
</field>
</record>
<record id="account_analytic_account_timesheet_form" model="ir.ui.view">
<field name="name">account.analytic.account.invoice.form</field>
<field name="model">account.analytic.account</field>
<field name="inherit_id" ref="analytic.view_account_analytic_account_form"/>
<field name="arch" type="xml">
<xpath expr='//div[@name="project"]' position='inside'>
<field name="invoice_on_timesheets"/>
<label for="invoice_on_timesheets"/>
</xpath>
<div name="button_box" position="inside">
<button class="oe_stat_button" type="action" name="%(act_analytic_cost_revenue)d"
icon="fa-usd" string="Cost/Revenue" widget="statinfo" attrs="{'invisible': [('type','=','template')]}"/>
</div>
</field>
</record>
<record id="act_hr_timesheet_accounts_form" model="ir.actions.act_window">
<field name="name">Timesheet Accounts</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">account.analytic.account</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('invoice_on_timesheets','=', True)]</field>
<field name="context">{'default_invoice_on_timesheets':1}</field>
</record>
<menuitem name="Configuration" id="menu_hr_timesheet_config" sequence="100"
@@ -166,19 +113,6 @@
<menuitem id="menu_hr_working_hours" parent="hr_attendance.menu_hr_time_tracking" action="act_hr_timesheet_line_evry1_all_form"/>
<record id="hr_timesheet_employee_extd_form" model="ir.ui.view">
<field name="name">hr.timesheet.employee.extd_form</field>
<field name="model">hr.employee</field>
<field name="inherit_id" ref="hr.view_employee_form"/>
<field name="arch" type="xml">
<xpath expr="//group[@name='active_group']" position="after">
<group string="Timesheets">
<field name="product_id" domain="[('type','=','service')]"/>
<field name="journal_id"/>
</group>
</xpath>
</field>
</record>
</data>
</openerp>
@@ -11,8 +11,6 @@ class hr_timesheet_report(models.Model):
date = fields.Date('Date', readonly=True)
name = fields.Char('Description', readonly=True)
product_id = fields.Many2one('product.product', 'Product', readonly=True)
journal_id = fields.Many2one('account.analytic.journal', 'Journal', readonly=True)
general_account_id = fields.Many2one('account.account', 'General Account', readonly=True)
user_id = fields.Many2one('res.users', 'User', readonly=True)
account_id = fields.Many2one('account.analytic.account', 'Analytic Account', readonly=True)
company_id = fields.Many2one('res.company', 'Company', readonly=True)
@@ -26,9 +24,7 @@ class hr_timesheet_report(models.Model):
sum(aal.amount) as cost,
sum(aal.unit_amount) as quantity,
aal.account_id as account_id,
aal.journal_id as journal_id,
aal.product_id as product_id,
aal.general_account_id as general_account_id,
aal.user_id as user_id,
aal.company_id as company_id,
aal.currency_id as currency_id
@@ -46,8 +42,6 @@ class hr_timesheet_report(models.Model):
GROUP BY aal.date,
aal.account_id,
aal.product_id,
aal.general_account_id,
aal.journal_id,
aal.user_id,
aal.company_id,
aal.currency_id
@@ -35,9 +35,7 @@
<field name="user_id"/>
<filter string="This Month" name="month" domain="[('date','&lt;=', time.strftime('%Y-%m-%d')),('date','&gt;=',time.strftime('%Y-%m-01'))]" help="month"/>
<group expand="0" string="Extended Filters...">
<field name="general_account_id"/>
<field name="product_id"/>
<field name="journal_id"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="date"/>
</group>
@@ -1,10 +1,8 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_hr_account_analytic_line,account.account.analytic.line,account.model_account_analytic_line,base.group_hr_user,1,1,1,1
access_hr_account_analytic_line_employee,account.account.analytic.line employee,account.model_account_analytic_line,base.group_user,1,1,1,1
access_account_analytic_journal,account.account.analytic.journal,analytic.model_account_analytic_journal,base.group_hr_user,1,1,1,1
access_product_product_user,product.product user,product.model_product_product,base.group_hr_user,1,1,1,1
access_product_template_hr_timesheet,product.template.hr.timesheet,product.model_product_template,base.group_hr_user,1,1,1,1
access_product_uom_hr_timesheet,product.uom.hr.timesheet,product.model_product_uom,base.group_hr_user,1,1,1,1
access_account_analytic_line_user,account.analytic.line.user,model_account_analytic_line,base.group_user,1,1,1,0
access_account_analytic_journal_user,account.account.analytic.journal.user,analytic.model_account_analytic_journal,base.group_user,1,0,0,0
access_hr_timesheet_report,hr.timesheet.report,model_hr_timesheet_report,base.group_hr_manager,1,1,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_hr_account_analytic_line account.account.analytic.line account.model_account_analytic_line base.group_hr_user 1 1 1 1
3 access_hr_account_analytic_line_employee account.account.analytic.line employee account.model_account_analytic_line base.group_user 1 1 1 1
access_account_analytic_journal account.account.analytic.journal analytic.model_account_analytic_journal base.group_hr_user 1 1 1 1
4 access_product_product_user product.product user product.model_product_product base.group_hr_user 1 1 1 1
5 access_product_template_hr_timesheet product.template.hr.timesheet product.model_product_template base.group_hr_user 1 1 1 1
6 access_product_uom_hr_timesheet product.uom.hr.timesheet product.model_product_uom base.group_hr_user 1 1 1 1
7 access_account_analytic_line_user account.analytic.line.user model_account_analytic_line base.group_user 1 1 1 0
access_account_analytic_journal_user account.account.analytic.journal.user analytic.model_account_analytic_journal base.group_user 1 0 0 0
8 access_hr_timesheet_report hr.timesheet.report model_hr_timesheet_report base.group_hr_manager 1 1 0 0
+1 -1
View File
@@ -26,7 +26,7 @@ The validation can be configured in the company:
* Maximal difference between timesheet and attendances
""",
'website': 'https://www.odoo.com/page/employees',
'depends': ['hr_timesheet', 'hr_timesheet_invoice'],
'depends': ['hr_timesheet'],
'data': [
'security/ir.model.access.csv',
'security/hr_timesheet_sheet_security.xml',
@@ -52,8 +52,6 @@ class hr_timesheet_sheet(osv.osv):
if 'employee_id' in vals:
if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id'], context=context).user_id:
raise UserError(_('In order to create a timesheet for this employee, you must link him/her to a user.'))
if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id'], context=context).journal_id:
raise UserError(_('In order to create a timesheet for this employee, you must assign an analytic journal to the employee, like \'Timesheet Journal\'.'))
if vals.get('attendances_ids'):
# If attendances, we sort them by date asc before writing them, to satisfy the alternance constraint
vals['attendances_ids'] = self.sort_attendances(cr, uid, vals['attendances_ids'], context=context)
@@ -68,8 +66,6 @@ class hr_timesheet_sheet(osv.osv):
raise UserError(_('You cannot have 2 timesheets that overlap!\nYou should use the menu \'My Timesheet\' to avoid this problem.'))
if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id'], context=context).product_id:
raise UserError(_('In order to create a timesheet for this employee, you must link the employee to a product.'))
if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id'], context=context).journal_id:
raise UserError(_('In order to create a timesheet for this employee, you must assign an analytic journal to the employee, like \'Timesheet Journal\'.'))
if vals.get('attendances_ids'):
# If attendances, we sort them by date asc before writing them, to satisfy the alternance constraint
# In addition to the date order, deleting attendances are done before inserting attendances
@@ -587,11 +583,10 @@ class hr_timesheet_sheet_sheet_account(osv.osv):
'name': fields.many2one('account.analytic.account', 'Project / Analytic Account', readonly=True),
'sheet_id': fields.many2one('hr_timesheet_sheet.sheet', 'Sheet', readonly=True),
'total': fields.float('Total Time', digits=(16,2), readonly=True),
'invoice_rate': fields.many2one('hr_timesheet_invoice.factor', 'Invoice rate', readonly=True),
}
_depends = {
'account.analytic.line': ['account_id', 'date', 'to_invoice', 'unit_amount', 'user_id'],
'account.analytic.line': ['account_id', 'date', 'unit_amount', 'user_id'],
'hr_timesheet_sheet.sheet': ['date_from', 'date_to', 'user_id'],
}
@@ -601,15 +596,14 @@ class hr_timesheet_sheet_sheet_account(osv.osv):
min(l.id) as id,
l.account_id as name,
s.id as sheet_id,
sum(l.unit_amount) as total,
l.to_invoice as invoice_rate
sum(l.unit_amount) as total
from
account_analytic_line l
LEFT JOIN hr_timesheet_sheet_sheet s
ON (s.date_to >= l.date
AND s.date_from <= l.date
AND s.user_id = l.user_id)
group by l.account_id, s.id, l.to_invoice
group by l.account_id, s.id
)""")
@@ -11,7 +11,6 @@
<field name="sheet_id"/>
<field name="name" groups="analytic.group_analytic_accounting"/>
<field name="total" sum="Total"/>
<field name="invoice_rate"/>
</group>
</form>
</field>
@@ -22,7 +21,6 @@
<field name="arch" type="xml">
<search string="Search Account">
<field name="name" groups="analytic.group_analytic_accounting"/>
<field name="invoice_rate"/>
<field name="sheet_id" />
</search>
</field>
@@ -35,7 +33,6 @@
<field name="sheet_id"/>
<field name="name" groups="analytic.group_analytic_accounting"/>
<field name="total" sum="Total"/>
<field name="invoice_rate"/>
</tree>
</field>
</record>
@@ -130,27 +127,17 @@
<field context="{'employee_id': employee_id, 'user_id':user_id, 'timesheet_date_from': date_from, 'timesheet_date_to': date_to, 'default_is_timesheet' : 1}" name="timesheet_ids" nolabel="1">
<tree editable="bottom" string="Timesheet Activities">
<field name="date"/>
<field domain="[('type','in',['normal', 'contract']), ('state', '!=', 'close'),('invoice_on_timesheets','=',1)]" name="account_id" on_change="on_change_account_id(account_id, user_id, unit_amount, is_timesheet, context)" options="{'no_open': True, 'no_create': True}" context="{'default_use_timesheets': 1}"/>
<field domain="[('use_timesheets','=',1)]" name="account_id" on_change="on_change_account_id(account_id, user_id, unit_amount, is_timesheet, context)" options="{'no_open': True, 'no_create': True}" context="{'default_use_timesheets': 1}"/>
<field name="name"/>
<field name="unit_amount" on_change="on_change_unit_amount(product_id, unit_amount, False, product_uom_id,journal_id)" widget="float_time" string="Hours" sum="Hours"/>
<field name="to_invoice" widget="selection"/>
<field invisible="1" name="journal_id"/>
<field invisible="1" name="product_id" domain="[('type','=','service')]" on_change="on_change_unit_amount(product_id, unit_amount, False, product_uom_id,journal_id)"/>
<field invisible="1" name="product_uom_id" on_change="on_change_unit_amount(product_id, unit_amount, False, product_uom_id,journal_id)"/>
<field invisible="1" name="amount"/>
<field invisible="1" name="general_account_id"/>
<field name="unit_amount" widget="float_time" string="Hours" sum="Hours"/>
<field invisible="1" name="user_id" required="1"/>
<field name="is_timesheet" invisible="1"/>
</tree>
<form string="Timesheet Activities">
<field name="date"/>
<field domain="[('type','=','normal'), ('state', '!=', 'close')]" name="account_id" on_change="on_change_account_id(account_id, user_id, unit_amount, is_timesheet, context)"/>
<field domain="[('use_timesheets','=',1)]" name="account_id"/>
<field name="name"/>
<field name="unit_amount" on_change="on_change_unit_amount(product_id, unit_amount, False, product_uom_id,journal_id)" widget="float_time"/>
<field name="to_invoice"/>
<field name="journal_id"/>
<field name="product_id" domain="[('type','=','service')]" on_change="on_change_unit_amount(product_id, unit_amount, False, product_uom_id,journal_id)"/>
<field name="product_uom_id" on_change="on_change_unit_amount(product_id, unit_amount, False, product_uom_id,journal_id)"/>
<field name="unit_amount" widget="float_time"/>
<field name="amount"/>
<field name="general_account_id"/>
<field name="user_id" required="1"/>
@@ -387,7 +374,7 @@
<record id="hr_timesheet_sheet_employee_extd_form" model="ir.ui.view">
<field name="name">hr.timesheet.sheet.employee.extd_form</field>
<field name="model">hr.employee</field>
<field name="inherit_id" ref="hr_timesheet.hr_timesheet_employee_extd_form"/>
<field name="inherit_id" ref="hr.view_employee_form"/>
<field name="arch" type="xml">
<div name="button_box" position="inside">
<button name="%(act_hr_employee_2_hr_timesheet)d"
@@ -7,7 +7,6 @@ from openerp.osv import fields,osv
class hr_timesheet_report(osv.osv):
_inherit = "hr.timesheet.report"
_columns = {
'to_invoice': fields.many2one('hr_timesheet_invoice.factor', 'Type of Invoicing',readonly=True),
'nbr': fields.integer('# Nbr Timesheet',readonly=True),
'total_diff': fields.float('# Total Diff',readonly=True),
'total_timesheet': fields.float('# Total Timesheet',readonly=True),
@@ -50,7 +49,6 @@ class hr_timesheet_report(osv.osv):
sum(t.total_diff) as total_diff,
sum(t.total_timesheet) as total_timesheet,
sum(t.total_attendance) as total_attendance,
aal.to_invoice,
htss.department_id,
htss.state"""
@@ -63,7 +61,6 @@ class hr_timesheet_report(osv.osv):
htss.date_to,
aal.unit_amount,
aal.amount,
aal.to_invoice,
htss.name,
htss.state,
htss.id,
@@ -6,9 +6,6 @@
<field name="model">hr.timesheet.report</field>
<field name="inherit_id" ref="hr_timesheet.view_hr_timesheet_report_graph"/>
<field name="arch" type="xml">
<field name="user_id" position="after">
<field name="to_invoice" type="row"/>
</field>
<field name="quantity" position="after">
<field name="total_diff" type="measure"/>
<field name="total_timesheet" type="measure"/>
@@ -30,7 +27,7 @@
<field name="model_id">hr.timesheet.report</field>
<field name="domain">[('state','=','done'), ('date','&lt;=', time.strftime('%Y-%m-%d')),('date','&gt;=',time.strftime('%Y-%m-01'))]</field>
<field name="user_id" eval="False"/>
<field name="context">{'group_by': ['company_id', 'to_invoice'], 'col_group_by': ['user_id'], 'measures': ['time','cost']}</field>
<field name="context">{'group_by': ['company_id'], 'col_group_by': ['user_id'], 'measures': ['time','cost']}</field>
</record>
<record id="view_timesheet_report_search" model="ir.ui.view">
@@ -43,15 +40,13 @@
<filter string="Confirmed" domain="[('state','=','confirm')]"/>
<filter string="Done" domain="[('state','=','done')]"/>
</field>
<field name="general_account_id" position="after">
<field name="to_invoice"/>
<field name="product_id" position="before">
<field name="department_id"/>
<field name="date_to"/>
<field name="date_from"/>
</field>
<filter name="group_user_id" position="after">
<filter string="Department" context="{'group_by':'department_id'}"/>
<filter string="Type of Invoicing" context="{'group_by':'to_invoice'}"/>
<filter string="Status" context="{'group_by':'state'}"/>
</filter>
</field>
@@ -111,7 +111,7 @@ var WeeklyTimesheet = form_common.FormWidget.extend(form_common.ReinitializeWidg
var account_names;
var default_get;
return this.render_drop.add(new Model("account.analytic.line").call("default_get", [
['account_id','general_account_id', 'journal_id','date','name','user_id','product_id','product_uom_id','to_invoice','amount','unit_amount', 'is_timesheet'],
['account_id','general_account_id', 'journal_id','date','name','user_id','product_id','product_uom_id','amount','unit_amount', 'is_timesheet'],
new data.CompoundContext({'user_id': self.get('user_id'), 'default_is_timesheet':true})]).then(function(result) {
default_get = result;
// calculating dates
@@ -219,11 +219,6 @@ var WeeklyTimesheet = form_common.FormWidget.extend(form_common.ReinitializeWidg
account.days[day_count].lines[0].unit_amount += num - self.sum_box(account, day_count);
var product = (account.days[day_count].lines[0].product_id instanceof Array) ? account.days[day_count].lines[0].product_id[0] : account.days[day_count].lines[0].product_id;
var journal = (account.days[day_count].lines[0].journal_id instanceof Array) ? account.days[day_count].lines[0].journal_id[0] : account.days[day_count].lines[0].journal_id;
self.defs.push(new Model("account.analytic.line").call("on_change_unit_amount", [[], product, account.days[day_count].lines[0].unit_amount, false, false, journal]).then(function(res) {
account.days[day_count].lines[0]['amount'] = res.value.amount || 0;
self.display_totals();
self.sync();
}));
if(!isNaN($(this).val())){
$(this).val(self.sum_box(account, day_count, true));
}
@@ -256,11 +251,9 @@ var WeeklyTimesheet = form_common.FormWidget.extend(form_common.ReinitializeWidg
domain: [
['type','in',['normal', 'contract']],
['state', '<>', 'close'],
['invoice_on_timesheets','=',1],
['id', 'not in', _.pluck(self.accounts, "account")],
],
context: {
default_invoice_on_timesheets: 1,
default_type: "contract",
},
modifiers: '{"required": true}',
@@ -47,7 +47,6 @@
amount: -90.00
product_id: product.product_product_1
general_account_id: a_expense
journal_id: hr_timesheet.analytic_journal
-
I confirm my Timesheet at end of period by click on "Confirm" button,
if the difference between Timesheet hour and attendance hour is more than 1 hour it will give message.
@@ -76,7 +75,6 @@
amount: -90.00
product_id: product.product_product_1
general_account_id: a_expense
journal_id: hr_timesheet.analytic_journal
-
I set an allowed difference of 1 hour
-