Store cost price on timesheet line
issue4977 review23421002
This commit is contained in:
1 parent
8659660df9
commit
0bf157cc01
8 files changed
+126
-55
No files matched your search
@@ -1,3 +1,5 @@
|
||||
* Store cost price on timesheet line
|
||||
|
||||
Version 3.6.0 - 2015-04-20
|
||||
* Bug fixes (see mercurial logs for details)
|
||||
* Add support for PyPy
|
||||
@@ -8,4 +10,4 @@ Version 3.2.0 - 2014-04-21
|
||||
* Bug fixes (see mercurial logs for details)
|
||||
|
||||
Version 3.0.0 - 2013-10-21
|
||||
* Initial release
|
||||
* Initial release
|
||||
@@ -5,8 +5,10 @@ Prerequisites
|
||||
-------------
|
||||
|
||||
* Python 2.7 or later (http://www.python.org/)
|
||||
* python-sql 0.4 or later (http://pypi.python.org/pypi/python-sql)
|
||||
* trytond (http://www.tryton.org/)
|
||||
* trytond_timesheet (http://www.tryton.org/)
|
||||
* trytond_party (http://www.tryton.org/)
|
||||
* trytond_company (http://www.tryton.org/)
|
||||
|
||||
Installation
|
||||
|
||||
+8
-41
@@ -2,25 +2,26 @@
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from decimal import Decimal
|
||||
from trytond.model import ModelView, ModelSQL, fields, Unique
|
||||
from trytond.pyson import Eval
|
||||
from trytond.cache import Cache
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool, PoolMeta
|
||||
from trytond import backend
|
||||
from trytond.config import config
|
||||
|
||||
__all__ = ['Employee', 'EmployeeCostPrice']
|
||||
__all__ = ['Employee', 'EmployeeCostPrice', 'price_digits']
|
||||
__metaclass__ = PoolMeta
|
||||
|
||||
price_digits = (16, config.getint(
|
||||
'timesheet_cost', 'price_decimal', default=4))
|
||||
|
||||
|
||||
class Employee:
|
||||
__name__ = 'company.employee'
|
||||
cost_price = fields.Function(fields.Numeric('Cost Price',
|
||||
digits=(16, Eval('currency_digits', 2)), depends=['currency_digits'],
|
||||
help="Hourly cost price for this Employee"), 'get_cost_price')
|
||||
digits=price_digits,
|
||||
help="Hourly cost price for this Employee"), 'get_cost_price')
|
||||
cost_prices = fields.One2Many('company.employee_cost_price', 'employee',
|
||||
'Cost Prices', help="List of hourly cost price over time")
|
||||
currency_digits = fields.Function(fields.Integer('Currency Digits'),
|
||||
'on_change_with_currency_digits')
|
||||
_cost_prices_cache = Cache('company_employee.cost_prices')
|
||||
|
||||
def get_cost_price(self, name):
|
||||
@@ -68,21 +69,6 @@ class Employee:
|
||||
break
|
||||
return cost
|
||||
|
||||
@fields.depends('company')
|
||||
def on_change_with_currency_digits(self, name=None):
|
||||
if self.company:
|
||||
return self.company.currency.digits
|
||||
return 2
|
||||
|
||||
@staticmethod
|
||||
def default_currency_digits():
|
||||
Company = Pool().get('company.company')
|
||||
company = Transaction().context.get('company')
|
||||
if company:
|
||||
company = Company(company)
|
||||
return company.currency.digits
|
||||
return 2
|
||||
|
||||
|
||||
class EmployeeCostPrice(ModelSQL, ModelView):
|
||||
'Employee Cost Price'
|
||||
@@ -90,12 +76,8 @@ class EmployeeCostPrice(ModelSQL, ModelView):
|
||||
_rec_name = 'date'
|
||||
date = fields.Date('Date', required=True, select=True)
|
||||
cost_price = fields.Numeric('Cost Price',
|
||||
digits=(16, Eval('currency_digits', 2)),
|
||||
required=True, depends=['currency_digits'],
|
||||
help="Hourly cost price")
|
||||
digits=price_digits, required=True, help="Hourly cost price")
|
||||
employee = fields.Many2One('company.employee', 'Employee')
|
||||
currency_digits = fields.Function(fields.Integer('Currency Digits'),
|
||||
'on_change_with_currency_digits')
|
||||
|
||||
@classmethod
|
||||
def __register__(cls, module_name):
|
||||
@@ -145,18 +127,3 @@ class EmployeeCostPrice(ModelSQL, ModelView):
|
||||
Employee = Pool().get('company.employee')
|
||||
super(EmployeeCostPrice, cls).write(*args)
|
||||
Employee._cost_prices_cache.clear()
|
||||
|
||||
@fields.depends('employee')
|
||||
def on_change_with_currency_digits(self, name=None):
|
||||
if self.employee:
|
||||
return self.employee.company.currency.digits
|
||||
return 2
|
||||
|
||||
@staticmethod
|
||||
def default_currency_digits():
|
||||
Company = Pool().get('company.company')
|
||||
company = Transaction().context.get('company')
|
||||
if company:
|
||||
company = Company(company)
|
||||
return company.currency.digits
|
||||
return 2
|
||||
+33
@@ -20,5 +20,38 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="inherit" ref="company.employee_view_form"/>
|
||||
<field name="name">employee_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.access" id="access_employee_cost_price">
|
||||
<field name="model"
|
||||
search="[('model', '=', 'company.employee_cost_price')]"/>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_delete" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.access" id="access_employee_cost_price_admin">
|
||||
<field name="model"
|
||||
search="[('model', '=', 'company.employee_cost_price')]"/>
|
||||
<field name="group" ref="party.group_party_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
<field name="perm_create" eval="True"/>
|
||||
<field name="perm_delete" eval="True"/>
|
||||
</record>
|
||||
<record model="ir.model.field.access"
|
||||
id="model_field_access_employee_cost_price">
|
||||
<field name="field"
|
||||
search="[('model.model', '=', 'company.employee'), ('name', '=', 'cost_price')]"/>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.field.access"
|
||||
id="model_field_access_employee_cost_price_admin">
|
||||
<field name="field"
|
||||
search="[('model.model', '=', 'company.employee'), ('name', '=', 'cost_price')]"/>
|
||||
<field name="group" ref="party.group_party_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
@@ -41,7 +41,7 @@ if minor_version % 2:
|
||||
'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
|
||||
name[8:], name, version))
|
||||
|
||||
requires = []
|
||||
requires = ['python-sql >= 0.4']
|
||||
for dep in info.get('depends', []):
|
||||
if not re.match(r'(ir|res|webdav)(\W|$)', dep):
|
||||
requires.append(get_require_version('trytond_%s' % dep))
|
||||
|
||||
+55
-12
@@ -1,8 +1,12 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from decimal import Decimal
|
||||
from sql import Null
|
||||
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool, PoolMeta
|
||||
from trytond.model import fields
|
||||
|
||||
from .company import price_digits
|
||||
|
||||
__all__ = ['TimesheetLine']
|
||||
__metaclass__ = PoolMeta
|
||||
@@ -11,17 +15,56 @@ __metaclass__ = PoolMeta
|
||||
class TimesheetLine:
|
||||
__name__ = 'timesheet.line'
|
||||
|
||||
def compute_cost(self):
|
||||
Currency = Pool().get('currency.currency')
|
||||
cost_price = fields.Numeric('Cost Price',
|
||||
digits=price_digits, required=True, readonly=True)
|
||||
|
||||
cost_price = self.employee.compute_cost_price(date=self.date)
|
||||
@classmethod
|
||||
def __register__(cls, module_name):
|
||||
pool = Pool()
|
||||
Employee = pool.get('company.employee')
|
||||
|
||||
line_company = self.employee.company
|
||||
work_company = self.work.company
|
||||
if (line_company != work_company and
|
||||
line_company.currency != work_company.currency):
|
||||
with Transaction().set_context(date=self.date):
|
||||
cost_price = Currency.compute(line_company.currency,
|
||||
cost_price, work_company.currency)
|
||||
cursor = Transaction().cursor
|
||||
table = cls.__table__()
|
||||
|
||||
return Decimal(str(self.hours)) * cost_price
|
||||
super(TimesheetLine, cls).__register__(module_name)
|
||||
|
||||
# Migration from 3.6: add cost_price
|
||||
cursor.execute(*table.select(table.id, table.employee, table.date,
|
||||
where=(table.cost_price == Null)
|
||||
& (table.employee != Null)
|
||||
& (table.date != Null)))
|
||||
for line_id, employee_id, date in cursor.fetchall():
|
||||
employee = Employee(employee_id)
|
||||
cost_price = employee.compute_cost_price(date=date)
|
||||
cursor.execute(*table.update(
|
||||
[table.cost_price],
|
||||
[cost_price],
|
||||
where=table.id == line_id))
|
||||
|
||||
@classmethod
|
||||
def default_cost_price(cls):
|
||||
# Needed at creation as cost_price is required
|
||||
return 0
|
||||
|
||||
@classmethod
|
||||
def create(cls, vlist):
|
||||
lines = super(TimesheetLine, cls).create(vlist)
|
||||
cls.sync_cost(lines)
|
||||
return lines
|
||||
|
||||
@classmethod
|
||||
def write(cls, *args):
|
||||
super(TimesheetLine, cls).write(*args)
|
||||
cls.sync_cost(sum(args[0:None:2], []))
|
||||
|
||||
@classmethod
|
||||
def sync_cost(cls, lines):
|
||||
with Transaction().set_context(_check_access=False):
|
||||
to_write = []
|
||||
lines = cls.browse(lines)
|
||||
for line in lines:
|
||||
cost_price = line.employee.compute_cost_price(date=line.date)
|
||||
if cost_price != line.cost_price:
|
||||
to_write.extend([[line], {'cost_price': cost_price}])
|
||||
if to_write:
|
||||
cls.write(*to_write)
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data>
|
||||
<record model="ir.model.field.access"
|
||||
id="model_field_access_timesheet_cost_price">
|
||||
<field name="field"
|
||||
search="[('model.model', '=', 'timesheet.line'), ('name', '=', 'cost_price')]"/>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
</record>
|
||||
<record model="ir.model.field.access"
|
||||
id="model_field_access_timesheet_cost_price_admin">
|
||||
<field name="field"
|
||||
search="[('model.model', '=', 'timesheet.line'), ('name', '=', 'cost_price')]"/>
|
||||
<field name="group" ref="party.group_party_admin"/>
|
||||
<field name="perm_read" eval="True"/>
|
||||
<field name="perm_write" eval="True"/>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
@@ -3,6 +3,8 @@ version=3.7.0
|
||||
depends:
|
||||
ir
|
||||
company
|
||||
party
|
||||
timesheet
|
||||
xml:
|
||||
company.xml
|
||||
timesheet.xml
|
||||
Reference in new issue
Block a user