[tryton-debian-vcs] tryton-modules-project-invoice branch upstream updated. upstream/3.4.1-1-g38286fe

Mathias Behrle tryton-debian-vcs at alioth.debian.org
Thu Apr 23 16:05:19 UTC 2015


The following commit has been merged in the upstream branch:
https://alioth.debian.org/plugins/scmgit/cgi-bin/gitweb.cgi/?p=tryton/tryton-modules-project-invoice.git;a=commitdiff;h=upstream/3.4.1-1-g38286fe

commit 38286fe21d6fa1a554c45d0220e4ccfb307d6a25
Author: Mathias Behrle <mathiasb at m9s.biz>
Date:   Thu Apr 23 17:00:02 2015 +0200

    Adding upstream version 3.6.0.
    
    Signed-off-by: Mathias Behrle <mathiasb at m9s.biz>

diff --git a/CHANGELOG b/CHANGELOG
index 21b802a..f9c9c47 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,7 @@
-Version 3.4.1 - 2015-02-22
+Version 3.6.0 - 2015-04-20
 * Bug fixes (see mercurial logs for details)
+* Add support for PyPy
+* Use TimeDelta field
 
 Version 3.4.0 - 2014-10-20
 * Bug fixes (see mercurial logs for details)
diff --git a/PKG-INFO b/PKG-INFO
index de3da34..80fa020 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,12 +1,12 @@
 Metadata-Version: 1.1
 Name: trytond_project_invoice
-Version: 3.4.1
+Version: 3.6.0
 Summary: Tryton module to invoice projects
 Home-page: http://www.tryton.org/
 Author: Tryton
 Author-email: issue_tracker at tryton.org
 License: GPL-3
-Download-URL: http://downloads.tryton.org/3.4/
+Download-URL: http://downloads.tryton.org/3.6/
 Description: trytond_project_invoice
         =======================
         
@@ -65,4 +65,6 @@ Classifier: Natural Language :: Slovenian
 Classifier: Natural Language :: Spanish
 Classifier: Operating System :: OS Independent
 Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: Implementation :: CPython
+Classifier: Programming Language :: Python :: Implementation :: PyPy
 Classifier: Topic :: Office/Business
diff --git a/__init__.py b/__init__.py
index 9993976..67b38a4 100644
--- a/__init__.py
+++ b/__init__.py
@@ -1,5 +1,5 @@
-#This file is part of Tryton.  The COPYRIGHT file at the top level of
-#this repository contains the full copyright notices and license terms.
+# 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 trytond.pool import Pool
 from .work import *
diff --git a/locale/ca_ES.po b/locale/ca_ES.po
index 91bced6..a098c75 100644
--- a/locale/ca_ES.po
+++ b/locale/ca_ES.po
@@ -22,9 +22,9 @@ msgctxt "error:timesheet.line:"
 msgid "You can not modify invoiced line."
 msgstr "No podeu modificar una línia facturada."
 
-msgctxt "field:project.work,hours_to_invoice:"
-msgid "Hours to Invoice"
-msgstr "Hores a facturar"
+msgctxt "field:project.work,duration_to_invoice:"
+msgid "Duration to Invoice"
+msgstr "Temps a facturar"
 
 msgctxt "field:project.work,invoice_line:"
 msgid "Invoice Line"
@@ -38,9 +38,9 @@ msgctxt "field:project.work,invoiced_amount:"
 msgid "Invoiced Amount"
 msgstr "Import facturat"
 
-msgctxt "field:project.work,invoiced_hours:"
-msgid "Invoiced Hours"
-msgstr "Hores facturades"
+msgctxt "field:project.work,invoiced_duration:"
+msgid "Invoiced Duration"
+msgstr "Temps facturat"
 
 msgctxt "field:project.work,project_invoice_method:"
 msgid "Invoice Method"
@@ -50,6 +50,10 @@ msgctxt "field:timesheet.line,invoice_line:"
 msgid "Invoice Line"
 msgstr "Línia de factura"
 
+msgctxt "model:ir.action,name:act_timesheet_line_form_invoice"
+msgid "Timesheet Lines"
+msgstr "Línies del full de treball"
+
 msgctxt "model:ir.action,name:open_invoice"
 msgid "Invoices"
 msgstr "Factures"
diff --git a/locale/de_DE.po b/locale/de_DE.po
index 13c8d28..4283736 100644
--- a/locale/de_DE.po
+++ b/locale/de_DE.po
@@ -22,9 +22,9 @@ msgctxt "error:timesheet.line:"
 msgid "You can not modify invoiced line."
 msgstr "Eine abgerechnete Zeile kann nicht geändert werden."
 
-msgctxt "field:project.work,hours_to_invoice:"
-msgid "Hours to Invoice"
-msgstr "Abrechenbare Stunden"
+msgctxt "field:project.work,duration_to_invoice:"
+msgid "Duration to Invoice"
+msgstr "Fakturierbarer Zeitraum"
 
 msgctxt "field:project.work,invoice_line:"
 msgid "Invoice Line"
@@ -38,9 +38,9 @@ msgctxt "field:project.work,invoiced_amount:"
 msgid "Invoiced Amount"
 msgstr "Abgerechneter Betrag"
 
-msgctxt "field:project.work,invoiced_hours:"
-msgid "Invoiced Hours"
-msgstr "Abgerechnete Stunden"
+msgctxt "field:project.work,invoiced_duration:"
+msgid "Invoiced Duration"
+msgstr "Fakturierter Zeitraum"
 
 msgctxt "field:project.work,project_invoice_method:"
 msgid "Invoice Method"
@@ -50,6 +50,10 @@ msgctxt "field:timesheet.line,invoice_line:"
 msgid "Invoice Line"
 msgstr "Rechnungsposition"
 
+msgctxt "model:ir.action,name:act_timesheet_line_form_invoice"
+msgid "Timesheet Lines"
+msgstr "Zeitpositionen"
+
 msgctxt "model:ir.action,name:open_invoice"
 msgid "Invoices"
 msgstr "Rechnungsausgang"
diff --git a/locale/es_AR.po b/locale/es_AR.po
index f138942..ada2fb7 100644
--- a/locale/es_AR.po
+++ b/locale/es_AR.po
@@ -22,9 +22,9 @@ msgctxt "error:timesheet.line:"
 msgid "You can not modify invoiced line."
 msgstr "No puede modificar una línea facturada."
 
-msgctxt "field:project.work,hours_to_invoice:"
-msgid "Hours to Invoice"
-msgstr "Horas a facturar"
+msgctxt "field:project.work,duration_to_invoice:"
+msgid "Duration to Invoice"
+msgstr "Duración a facturar"
 
 msgctxt "field:project.work,invoice_line:"
 msgid "Invoice Line"
@@ -38,9 +38,9 @@ msgctxt "field:project.work,invoiced_amount:"
 msgid "Invoiced Amount"
 msgstr "Importe facturado"
 
-msgctxt "field:project.work,invoiced_hours:"
-msgid "Invoiced Hours"
-msgstr "Horas facturadas"
+msgctxt "field:project.work,invoiced_duration:"
+msgid "Invoiced Duration"
+msgstr "Duración facturada"
 
 msgctxt "field:project.work,project_invoice_method:"
 msgid "Invoice Method"
@@ -50,6 +50,10 @@ msgctxt "field:timesheet.line,invoice_line:"
 msgid "Invoice Line"
 msgstr "Línea de factura"
 
+msgctxt "model:ir.action,name:act_timesheet_line_form_invoice"
+msgid "Timesheet Lines"
+msgstr "Líneas de parte de trabajo"
+
 msgctxt "model:ir.action,name:open_invoice"
 msgid "Invoices"
 msgstr "Facturas"
diff --git a/locale/es_CO.po b/locale/es_CO.po
index 5107864..54959c2 100644
--- a/locale/es_CO.po
+++ b/locale/es_CO.po
@@ -22,9 +22,9 @@ msgctxt "error:timesheet.line:"
 msgid "You can not modify invoiced line."
 msgstr "No puede modificar una línea facurada."
 
-msgctxt "field:project.work,hours_to_invoice:"
-msgid "Hours to Invoice"
-msgstr "Horas a Facturar"
+msgctxt "field:project.work,duration_to_invoice:"
+msgid "Duration to Invoice"
+msgstr "Duración de Factura"
 
 msgctxt "field:project.work,invoice_line:"
 msgid "Invoice Line"
@@ -38,9 +38,9 @@ msgctxt "field:project.work,invoiced_amount:"
 msgid "Invoiced Amount"
 msgstr "Valor Facturado"
 
-msgctxt "field:project.work,invoiced_hours:"
-msgid "Invoiced Hours"
-msgstr "Horas Facturadas"
+msgctxt "field:project.work,invoiced_duration:"
+msgid "Invoiced Duration"
+msgstr ""
 
 msgctxt "field:project.work,project_invoice_method:"
 msgid "Invoice Method"
@@ -50,6 +50,10 @@ msgctxt "field:timesheet.line,invoice_line:"
 msgid "Invoice Line"
 msgstr "Línea de Factura"
 
+msgctxt "model:ir.action,name:act_timesheet_line_form_invoice"
+msgid "Timesheet Lines"
+msgstr "Lineas de Registro de Tiempo"
+
 msgctxt "model:ir.action,name:open_invoice"
 msgid "Invoices"
 msgstr "Facturas"
diff --git a/locale/es_EC.po b/locale/es_EC.po
index 0496be7..045b42f 100644
--- a/locale/es_EC.po
+++ b/locale/es_EC.po
@@ -22,13 +22,13 @@ msgctxt "error:timesheet.line:"
 msgid "You can not modify invoiced line."
 msgstr "No puede modificar una línea facturada."
 
-msgctxt "field:project.work,hours_to_invoice:"
-msgid "Hours to Invoice"
-msgstr "Horas a Facturar"
+msgctxt "field:project.work,duration_to_invoice:"
+msgid "Duration to Invoice"
+msgstr "Duración a facturar"
 
 msgctxt "field:project.work,invoice_line:"
 msgid "Invoice Line"
-msgstr "Línea de Factura"
+msgstr "Línea de factura"
 
 msgctxt "field:project.work,invoice_method:"
 msgid "Invoice Method"
@@ -38,9 +38,9 @@ msgctxt "field:project.work,invoiced_amount:"
 msgid "Invoiced Amount"
 msgstr "Valor Facturado"
 
-msgctxt "field:project.work,invoiced_hours:"
-msgid "Invoiced Hours"
-msgstr "Horas Facturadas"
+msgctxt "field:project.work,invoiced_duration:"
+msgid "Invoiced Duration"
+msgstr "Duración Facturada"
 
 msgctxt "field:project.work,project_invoice_method:"
 msgid "Invoice Method"
@@ -50,6 +50,10 @@ msgctxt "field:timesheet.line,invoice_line:"
 msgid "Invoice Line"
 msgstr "Línea de Factura"
 
+msgctxt "model:ir.action,name:act_timesheet_line_form_invoice"
+msgid "Timesheet Lines"
+msgstr "Líneas de parte de trabajo"
+
 msgctxt "model:ir.action,name:open_invoice"
 msgid "Invoices"
 msgstr "Facturas"
diff --git a/locale/es_ES.po b/locale/es_ES.po
index fa04c28..a38f78d 100644
--- a/locale/es_ES.po
+++ b/locale/es_ES.po
@@ -22,9 +22,9 @@ msgctxt "error:timesheet.line:"
 msgid "You can not modify invoiced line."
 msgstr "No puede modificar una línea facturada."
 
-msgctxt "field:project.work,hours_to_invoice:"
-msgid "Hours to Invoice"
-msgstr "Horas a facturar"
+msgctxt "field:project.work,duration_to_invoice:"
+msgid "Duration to Invoice"
+msgstr "Tiempo a facturar"
 
 msgctxt "field:project.work,invoice_line:"
 msgid "Invoice Line"
@@ -38,9 +38,9 @@ msgctxt "field:project.work,invoiced_amount:"
 msgid "Invoiced Amount"
 msgstr "Importe facturado"
 
-msgctxt "field:project.work,invoiced_hours:"
-msgid "Invoiced Hours"
-msgstr "Horas facturadas"
+msgctxt "field:project.work,invoiced_duration:"
+msgid "Invoiced Duration"
+msgstr "Tiempo facturado"
 
 msgctxt "field:project.work,project_invoice_method:"
 msgid "Invoice Method"
@@ -50,6 +50,10 @@ msgctxt "field:timesheet.line,invoice_line:"
 msgid "Invoice Line"
 msgstr "Línea de factura"
 
+msgctxt "model:ir.action,name:act_timesheet_line_form_invoice"
+msgid "Timesheet Lines"
+msgstr "Líneas de parte de trabajo"
+
 msgctxt "model:ir.action,name:open_invoice"
 msgid "Invoices"
 msgstr "Facturas"
diff --git a/locale/fr_FR.po b/locale/fr_FR.po
index ddbef93..f84995f 100644
--- a/locale/fr_FR.po
+++ b/locale/fr_FR.po
@@ -22,9 +22,9 @@ msgctxt "error:timesheet.line:"
 msgid "You can not modify invoiced line."
 msgstr "Vous ne pouvez pas modifier une ligne facturée."
 
-msgctxt "field:project.work,hours_to_invoice:"
-msgid "Hours to Invoice"
-msgstr "Heures à facturer"
+msgctxt "field:project.work,duration_to_invoice:"
+msgid "Duration to Invoice"
+msgstr "Durée à facturer"
 
 msgctxt "field:project.work,invoice_line:"
 msgid "Invoice Line"
@@ -38,9 +38,9 @@ msgctxt "field:project.work,invoiced_amount:"
 msgid "Invoiced Amount"
 msgstr "Montant facturé"
 
-msgctxt "field:project.work,invoiced_hours:"
-msgid "Invoiced Hours"
-msgstr "Heures facturées"
+msgctxt "field:project.work,invoiced_duration:"
+msgid "Invoiced Duration"
+msgstr "Durée facturée"
 
 msgctxt "field:project.work,project_invoice_method:"
 msgid "Invoice Method"
@@ -50,6 +50,10 @@ msgctxt "field:timesheet.line,invoice_line:"
 msgid "Invoice Line"
 msgstr "Ligne de facture"
 
+msgctxt "model:ir.action,name:act_timesheet_line_form_invoice"
+msgid "Timesheet Lines"
+msgstr "Lignes de feuille de présence"
+
 msgctxt "model:ir.action,name:open_invoice"
 msgid "Invoices"
 msgstr "Factures"
diff --git a/locale/sl_SI.po b/locale/sl_SI.po
index 5bcd25d..ffb5092 100644
--- a/locale/sl_SI.po
+++ b/locale/sl_SI.po
@@ -22,9 +22,9 @@ msgctxt "error:timesheet.line:"
 msgid "You can not modify invoiced line."
 msgstr "Obračunane postavke ni možne popraviti."
 
-msgctxt "field:project.work,hours_to_invoice:"
-msgid "Hours to Invoice"
-msgstr "Ure za obračun"
+msgctxt "field:project.work,duration_to_invoice:"
+msgid "Duration to Invoice"
+msgstr "Čas do zaračunanja"
 
 msgctxt "field:project.work,invoice_line:"
 msgid "Invoice Line"
@@ -38,9 +38,9 @@ msgctxt "field:project.work,invoiced_amount:"
 msgid "Invoiced Amount"
 msgstr "Zaračunan znesek"
 
-msgctxt "field:project.work,invoiced_hours:"
-msgid "Invoiced Hours"
-msgstr "Zaračunane ure"
+msgctxt "field:project.work,invoiced_duration:"
+msgid "Invoiced Duration"
+msgstr "Zaračunan porabljen čas"
 
 msgctxt "field:project.work,project_invoice_method:"
 msgid "Invoice Method"
@@ -50,6 +50,10 @@ msgctxt "field:timesheet.line,invoice_line:"
 msgid "Invoice Line"
 msgstr "Postavka računa"
 
+msgctxt "model:ir.action,name:act_timesheet_line_form_invoice"
+msgid "Timesheet Lines"
+msgstr "Evidenca prisotnosti"
+
 msgctxt "model:ir.action,name:open_invoice"
 msgid "Invoices"
 msgstr "Računi"
diff --git a/setup.py b/setup.py
index cb4c355..bcd7b2b 100644
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
-#This file is part of Tryton.  The COPYRIGHT file at the top level of
-#this repository contains the full copyright notices and license terms.
+# 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 setuptools import setup
 import re
@@ -41,7 +41,7 @@ if minor_version % 2:
         'hg+http://hg.tryton.org/modules/%s#egg=%s-%s' % (
             name[8:], name, version))
 
-requires = ['python-sql']
+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))
@@ -92,6 +92,8 @@ setup(name=name,
         'Natural Language :: Spanish',
         'Operating System :: OS Independent',
         'Programming Language :: Python :: 2.7',
+        'Programming Language :: Python :: Implementation :: CPython',
+        'Programming Language :: Python :: Implementation :: PyPy',
         'Topic :: Office/Business',
         ],
     license='GPL-3',
diff --git a/tests/__init__.py b/tests/__init__.py
index 4f749be..738b8b4 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -1,5 +1,5 @@
-#This file is part of Tryton.  The COPYRIGHT file at the top level of
-#this repository contains the full copyright notices and license terms.
+# 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 .test_project_invoice import suite
 
diff --git a/tests/scenario_project_invoice_effort.rst b/tests/scenario_project_invoice_effort.rst
index 6d1192c..46ccbcf 100644
--- a/tests/scenario_project_invoice_effort.rst
+++ b/tests/scenario_project_invoice_effort.rst
@@ -2,16 +2,18 @@
 Project Invoice Effort Scenario
 ===============================
 
-=============
-General Setup
-=============
-
 Imports::
 
     >>> import datetime
     >>> from dateutil.relativedelta import relativedelta
     >>> from decimal import Decimal
     >>> from proteus import config, Model, Wizard
+    >>> from trytond.modules.company.tests.tools import create_company, \
+    ...     get_company
+    >>> from trytond.modules.account.tests.tools import create_chart, \
+    ...     get_accounts
+    >>> from.trytond.modules.account_invoice.tests.tools import \
+    ...     create_payment_term
     >>> today = datetime.date.today()
 
 Create database::
@@ -25,34 +27,13 @@ Install project_invoice::
     >>> module, = Module.find([
     ...         ('name', '=', 'project_invoice'),
     ...     ])
-    >>> Module.install([module.id], config.context)
+    >>> module.click('install')
     >>> Wizard('ir.module.module.install_upgrade').execute('upgrade')
 
 Create company::
 
-    >>> Currency = Model.get('currency.currency')
-    >>> CurrencyRate = Model.get('currency.currency.rate')
-    >>> Company = Model.get('company.company')
-    >>> Party = Model.get('party.party')
-    >>> company_config = Wizard('company.company.config')
-    >>> company_config.execute('company')
-    >>> company = company_config.form
-    >>> party = Party(name='Dunder Mifflin')
-    >>> party.save()
-    >>> company.party = party
-    >>> currencies = Currency.find([('code', '=', 'USD')])
-    >>> if not currencies:
-    ...     currency = Currency(name='Euro', symbol=u'$', code='USD',
-    ...         rounding=Decimal('0.01'), mon_grouping='[3, 3, 0]',
-    ...         mon_decimal_point='.')
-    ...     currency.save()
-    ...     CurrencyRate(date=today + relativedelta(month=1, day=1),
-    ...         rate=Decimal('1.0'), currency=currency).save()
-    ... else:
-    ...     currency, = currencies
-    >>> company.currency = currency
-    >>> company_config.execute('add')
-    >>> company, = Company.find()
+    >>> _ = create_company()
+    >>> company = get_company()
 
 Reload the context::
 
@@ -85,37 +66,13 @@ Create project invoice user::
 
 Create chart of accounts::
 
-    >>> AccountTemplate = Model.get('account.account.template')
-    >>> Account = Model.get('account.account')
-    >>> account_template, = AccountTemplate.find([('parent', '=', None)])
-    >>> create_chart = Wizard('account.create_chart')
-    >>> create_chart.execute('account')
-    >>> create_chart.form.account_template = account_template
-    >>> create_chart.form.company = company
-    >>> create_chart.execute('create_account')
-    >>> receivable, = Account.find([
-    ...         ('kind', '=', 'receivable'),
-    ...         ('company', '=', company.id),
-    ...         ])
-    >>> payable, = Account.find([
-    ...         ('kind', '=', 'payable'),
-    ...         ('company', '=', company.id),
-    ...         ])
-    >>> revenue, = Account.find([
-    ...         ('kind', '=', 'revenue'),
-    ...         ('company', '=', company.id),
-    ...         ])
-    >>> create_chart.form.account_receivable = receivable
-    >>> create_chart.form.account_payable = payable
-    >>> create_chart.execute('create_properties')
+    >>> _ = create_chart(company)
+    >>> accounts = get_accounts(company)
+    >>> revenue = accounts['revenue']
 
 Create payment term::
 
-    >>> PaymentTerm = Model.get('account.invoice.payment_term')
-    >>> PaymentTermLine = Model.get('account.invoice.payment_term.line')
-    >>> payment_term = PaymentTerm(name='Term')
-    >>> payment_term_line = PaymentTermLine(type='remainder', days=40)
-    >>> payment_term.lines.append(payment_term_line)
+    >>> payment_term = create_payment_term()
     >>> payment_term.save()
 
 Create customer::
@@ -167,7 +124,7 @@ Create a Project::
     >>> project.party = customer
     >>> project.project_invoice_method = 'effort'
     >>> project.product = product
-    >>> project.effort = 1
+    >>> project.effort_duration = datetime.timedelta(hours=1)
     >>> task = ProjectWork()
     >>> work = TimesheetWork()
     >>> work.name = 'Task 1'
@@ -175,18 +132,18 @@ Create a Project::
     >>> task.work = work
     >>> task.type = 'task'
     >>> task.product = product
-    >>> task.effort = 5
+    >>> task.effort_duration = datetime.timedelta(hours=5)
     >>> project.children.append(task)
     >>> project.save()
     >>> task, = project.children
 
-Check project hours::
+Check project duration::
 
     >>> project.reload()
-    >>> project.invoiced_hours
-    0.0
-    >>> project.hours_to_invoice
-    0.0
+    >>> project.invoiced_duration
+    datetime.timedelta(0)
+    >>> project.duration_to_invoice
+    datetime.timedelta(0)
     >>> project.invoiced_amount
     Decimal('0')
 
@@ -195,25 +152,24 @@ Do 1 task::
     >>> task.state = 'done'
     >>> task.save()
 
-Check project hours::
+Check project duration::
 
     >>> project.reload()
-    >>> project.invoiced_hours
-    0.0
-    >>> project.hours_to_invoice
-    5.0
+    >>> project.invoiced_duration
+    datetime.timedelta(0)
+    >>> project.duration_to_invoice
+    datetime.timedelta(0, 18000)
     >>> project.invoiced_amount
     Decimal('0')
 
 Invoice project::
 
     >>> config.user = project_invoice_user.id
-    >>> ProjectWork.invoice([project.id], config.context)
-    >>> project.reload()
-    >>> project.invoiced_hours
-    5.0
-    >>> project.hours_to_invoice
-    0.0
+    >>> project.click('invoice')
+    >>> project.invoiced_duration
+    datetime.timedelta(0, 18000)
+    >>> project.duration_to_invoice
+    datetime.timedelta(0)
     >>> project.invoiced_amount
     Decimal('100.00')
 
@@ -223,24 +179,23 @@ Do project::
     >>> project.state = 'done'
     >>> project.save()
 
-Check project hours::
+Check project duration::
 
     >>> project.reload()
-    >>> project.invoiced_hours
-    5.0
-    >>> project.hours_to_invoice
-    1.0
+    >>> project.invoiced_duration
+    datetime.timedelta(0, 18000)
+    >>> project.duration_to_invoice
+    datetime.timedelta(0, 3600)
     >>> project.invoiced_amount
     Decimal('100.00')
 
 Invoice again project::
 
     >>> config.user = project_invoice_user.id
-    >>> ProjectWork.invoice([project.id], config.context)
-    >>> project.reload()
-    >>> project.invoiced_hours
-    6.0
-    >>> project.hours_to_invoice
-    0.0
+    >>> project.click('invoice')
+    >>> project.invoiced_duration
+    datetime.timedelta(0, 21600)
+    >>> project.duration_to_invoice
+    datetime.timedelta(0)
     >>> project.invoiced_amount
     Decimal('120.00')
diff --git a/tests/scenario_project_invoice_timesheet.rst b/tests/scenario_project_invoice_timesheet.rst
index 0163f69..351963f 100644
--- a/tests/scenario_project_invoice_timesheet.rst
+++ b/tests/scenario_project_invoice_timesheet.rst
@@ -2,16 +2,18 @@
 Project Invoice Timesheet Scenario
 ==================================
 
-=============
-General Setup
-=============
-
 Imports::
 
     >>> import datetime
     >>> from dateutil.relativedelta import relativedelta
     >>> from decimal import Decimal
     >>> from proteus import config, Model, Wizard
+    >>> from trytond.modules.company.tests.tools import create_company, \
+    ...     get_company
+    >>> from trytond.modules.account.tests.tools import create_chart, \
+    ...     get_accounts
+    >>> from.trytond.modules.account_invoice.tests.tools import \
+    ...     create_payment_term
     >>> today = datetime.date.today()
 
 Create database::
@@ -25,34 +27,13 @@ Install project_invoice::
     >>> module, = Module.find([
     ...         ('name', '=', 'project_invoice'),
     ...     ])
-    >>> Module.install([module.id], config.context)
+    >>> module.click('install')
     >>> Wizard('ir.module.module.install_upgrade').execute('upgrade')
 
 Create company::
 
-    >>> Currency = Model.get('currency.currency')
-    >>> CurrencyRate = Model.get('currency.currency.rate')
-    >>> Company = Model.get('company.company')
-    >>> Party = Model.get('party.party')
-    >>> company_config = Wizard('company.company.config')
-    >>> company_config.execute('company')
-    >>> company = company_config.form
-    >>> party = Party(name='Dunder Mifflin')
-    >>> party.save()
-    >>> company.party = party
-    >>> currencies = Currency.find([('code', '=', 'USD')])
-    >>> if not currencies:
-    ...     currency = Currency(name='Euro', symbol=u'$', code='USD',
-    ...         rounding=Decimal('0.01'), mon_grouping='[3, 3, 0]',
-    ...         mon_decimal_point='.')
-    ...     currency.save()
-    ...     CurrencyRate(date=today + relativedelta(month=1, day=1),
-    ...         rate=Decimal('1.0'), currency=currency).save()
-    ... else:
-    ...     currency, = currencies
-    >>> company.currency = currency
-    >>> company_config.execute('add')
-    >>> company, = Company.find()
+    >>> _ = create_company()
+    >>> company = get_company()
 
 Reload the context::
 
@@ -85,37 +66,13 @@ Create project invoice user::
 
 Create chart of accounts::
 
-    >>> AccountTemplate = Model.get('account.account.template')
-    >>> Account = Model.get('account.account')
-    >>> account_template, = AccountTemplate.find([('parent', '=', None)])
-    >>> create_chart = Wizard('account.create_chart')
-    >>> create_chart.execute('account')
-    >>> create_chart.form.account_template = account_template
-    >>> create_chart.form.company = company
-    >>> create_chart.execute('create_account')
-    >>> receivable, = Account.find([
-    ...         ('kind', '=', 'receivable'),
-    ...         ('company', '=', company.id),
-    ...         ])
-    >>> payable, = Account.find([
-    ...         ('kind', '=', 'payable'),
-    ...         ('company', '=', company.id),
-    ...         ])
-    >>> revenue, = Account.find([
-    ...         ('kind', '=', 'revenue'),
-    ...         ('company', '=', company.id),
-    ...         ])
-    >>> create_chart.form.account_receivable = receivable
-    >>> create_chart.form.account_payable = payable
-    >>> create_chart.execute('create_properties')
+    >>> _ = create_chart(company)
+    >>> accounts = get_accounts(company)
+    >>> revenue = accounts['revenue']
 
 Create payment term::
 
-    >>> PaymentTerm = Model.get('account.invoice.payment_term')
-    >>> PaymentTermLine = Model.get('account.invoice.payment_term.line')
-    >>> payment_term = PaymentTerm(name='Term')
-    >>> payment_term_line = PaymentTermLine(type='remainder', days=40)
-    >>> payment_term.lines.append(payment_term_line)
+    >>> payment_term = create_payment_term()
     >>> payment_term.save()
 
 Create customer::
@@ -183,34 +140,33 @@ Create timesheets::
     >>> TimesheetLine = Model.get('timesheet.line')
     >>> line = TimesheetLine()
     >>> line.employee = employee
-    >>> line.hours = 3
+    >>> line.duration = datetime.timedelta(hours=3)
     >>> line.work = task.work
     >>> line.save()
     >>> line = TimesheetLine()
     >>> line.employee = employee
-    >>> line.hours = 2
+    >>> line.duration = datetime.timedelta(hours=2)
     >>> line.work = project.work
     >>> line.save()
 
-Check project hours::
+Check project duration::
 
     >>> project.reload()
-    >>> project.invoiced_hours
-    0.0
-    >>> project.hours_to_invoice
-    5.0
+    >>> project.invoiced_duration
+    datetime.timedelta(0)
+    >>> project.duration_to_invoice
+    datetime.timedelta(0, 18000)
     >>> project.invoiced_amount
     Decimal('0')
 
 Invoice project::
 
     >>> config.user = project_invoice_user.id
-    >>> ProjectWork.invoice([project.id], config.context)
-    >>> project.reload()
-    >>> project.invoiced_hours
-    5.0
-    >>> project.hours_to_invoice
-    0.0
+    >>> project.click('invoice')
+    >>> project.invoiced_duration
+    datetime.timedelta(0, 18000)
+    >>> project.duration_to_invoice
+    datetime.timedelta(0)
     >>> project.invoiced_amount
     Decimal('100.000000000000')
 
@@ -220,28 +176,27 @@ Create more timesheets::
     >>> TimesheetLine = Model.get('timesheet.line')
     >>> line = TimesheetLine()
     >>> line.employee = employee
-    >>> line.hours = 4
+    >>> line.duration = datetime.timedelta(hours=4)
     >>> line.work = task.work
     >>> line.save()
 
-Check project hours::
+Check project duration::
 
     >>> project.reload()
-    >>> project.invoiced_hours
-    5.0
-    >>> project.hours_to_invoice
-    4.0
+    >>> project.invoiced_duration
+    datetime.timedelta(0, 18000)
+    >>> project.duration_to_invoice
+    datetime.timedelta(0, 14400)
     >>> project.invoiced_amount
     Decimal('100.000000000000')
 
 Invoice again project::
 
     >>> config.user = project_invoice_user.id
-    >>> ProjectWork.invoice([project.id], config.context)
-    >>> project.reload()
-    >>> project.invoiced_hours
-    9.0
-    >>> project.hours_to_invoice
-    0.0
+    >>> project.click('invoice')
+    >>> project.invoiced_duration
+    datetime.timedelta(0, 32400)
+    >>> project.duration_to_invoice
+    datetime.timedelta(0)
     >>> project.invoiced_amount
     Decimal('180.000000000000')
diff --git a/tests/test_project_invoice.py b/tests/test_project_invoice.py
index 22ee69a..7f7f2a6 100644
--- a/tests/test_project_invoice.py
+++ b/tests/test_project_invoice.py
@@ -1,25 +1,15 @@
-#This file is part of Tryton.  The COPYRIGHT file at the top level of
-#this repository contains the full copyright notices and license terms.
+# This file is part of Tryton.  The COPYRIGHT file at the top level of
+# this repository contains the full copyright notices and license terms.
 import unittest
 import doctest
 import trytond.tests.test_tryton
-from trytond.tests.test_tryton import test_view, test_depends
+from trytond.tests.test_tryton import ModuleTestCase
 from trytond.tests.test_tryton import doctest_setup, doctest_teardown
 
 
-class ProjectInvoiceTestCase(unittest.TestCase):
+class ProjectInvoiceTestCase(ModuleTestCase):
     'Test Project Invoice module'
-
-    def setUp(self):
-        trytond.tests.test_tryton.install_module('project_invoice')
-
-    def test0005views(self):
-        'Test views'
-        test_view('project_invoice')
-
-    def test0006depends(self):
-        'Test depends'
-        test_depends()
+    module = 'project_invoice'
 
 
 def suite():
diff --git a/timesheet.py b/timesheet.py
index c14998f..bbf6cc3 100644
--- a/timesheet.py
+++ b/timesheet.py
@@ -1,5 +1,5 @@
-#This file is part of Tryton.  The COPYRIGHT file at the top level of
-#this repository contains the full copyright notices and license terms.
+# 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 trytond.model import fields
 from trytond.pool import PoolMeta
 
diff --git a/timesheet.xml b/timesheet.xml
index c773caf..16436b4 100644
--- a/timesheet.xml
+++ b/timesheet.xml
@@ -14,4 +14,23 @@ this repository contains the full copyright notices and license terms. -->
             <field name="group" ref="group_project_invoice"/>
         </record>
     </data>
+
+    <record model="ir.action.act_window" id="act_timesheet_line_form_invoice">
+        <field name="name">Timesheet Lines</field>
+        <field name="res_model">timesheet.line</field>
+        <field name="domain"
+            eval="[('invoice_line.invoice', 'in', Eval('active_ids'))]"
+            pyson="1"/>
+    </record>
+    <record model="ir.action.keyword"
+        id="act_timesheet_line_form_invoice_keyword1">
+        <field name="keyword">form_relate</field>
+        <field name="model">account.invoice,-1</field>
+        <field name="action" ref="act_timesheet_line_form_invoice"/>
+    </record>
+    <record model="ir.action-res.group"
+        id="act_timesheet_line_form_invoice-group_timesheet_admin">
+        <field name="action" ref="act_timesheet_line_form_invoice"/>
+        <field name="group" ref="timesheet.group_timesheet_admin"/>
+    </record>
 </tryton>
diff --git a/tryton.cfg b/tryton.cfg
index a93d565..0c36ed3 100644
--- a/tryton.cfg
+++ b/tryton.cfg
@@ -1,5 +1,5 @@
 [tryton]
-version=3.4.1
+version=3.6.0
 depends:
     ir
     project
diff --git a/trytond_project_invoice.egg-info/PKG-INFO b/trytond_project_invoice.egg-info/PKG-INFO
index 67c7953..bb84062 100644
--- a/trytond_project_invoice.egg-info/PKG-INFO
+++ b/trytond_project_invoice.egg-info/PKG-INFO
@@ -1,12 +1,12 @@
 Metadata-Version: 1.1
 Name: trytond-project-invoice
-Version: 3.4.1
+Version: 3.6.0
 Summary: Tryton module to invoice projects
 Home-page: http://www.tryton.org/
 Author: Tryton
 Author-email: issue_tracker at tryton.org
 License: GPL-3
-Download-URL: http://downloads.tryton.org/3.4/
+Download-URL: http://downloads.tryton.org/3.6/
 Description: trytond_project_invoice
         =======================
         
@@ -65,4 +65,6 @@ Classifier: Natural Language :: Slovenian
 Classifier: Natural Language :: Spanish
 Classifier: Operating System :: OS Independent
 Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: Implementation :: CPython
+Classifier: Programming Language :: Python :: Implementation :: PyPy
 Classifier: Topic :: Office/Business
diff --git a/trytond_project_invoice.egg-info/requires.txt b/trytond_project_invoice.egg-info/requires.txt
index 1698eac..ef1f62c 100644
--- a/trytond_project_invoice.egg-info/requires.txt
+++ b/trytond_project_invoice.egg-info/requires.txt
@@ -1,8 +1,8 @@
-python-sql
-trytond_project >= 3.4, < 3.5
-trytond_project_revenue >= 3.4, < 3.5
-trytond_timesheet >= 3.4, < 3.5
-trytond_account >= 3.4, < 3.5
-trytond_account_invoice >= 3.4, < 3.5
-trytond_product >= 3.4, < 3.5
-trytond >= 3.4, < 3.5
\ No newline at end of file
+python-sql >= 0.4
+trytond_project >= 3.6, < 3.7
+trytond_project_revenue >= 3.6, < 3.7
+trytond_timesheet >= 3.6, < 3.7
+trytond_account >= 3.6, < 3.7
+trytond_account_invoice >= 3.6, < 3.7
+trytond_product >= 3.6, < 3.7
+trytond >= 3.6, < 3.7
\ No newline at end of file
diff --git a/view/work_form.xml b/view/work_form.xml
index 57b8b2d..58a479f 100644
--- a/view/work_form.xml
+++ b/view/work_form.xml
@@ -11,14 +11,12 @@ this repository contains the full copyright notices and license terms. -->
     <xpath expr="/form/notebook/page[@id='general']/separator[@name='comment']"
         position="before">
         <newline/>
-        <label name="invoiced_hours"/>
-        <field name="invoiced_hours" widget="float_time"
-            float_time="company_work_time"/>
+        <label name="invoiced_duration"/>
+        <field name="invoiced_duration"/>
         <label name="invoiced_amount"/>
         <field name="invoiced_amount"/>
-        <label name="hours_to_invoice"/>
-        <field name="hours_to_invoice" widget="float_time"
-            float_time="company_work_time"/>
+        <label name="duration_to_invoice"/>
+        <field name="duration_to_invoice"/>
     </xpath>
     <xpath expr="/form/notebook/page[@id='general']/group/group[@id='buttons']"
         position="inside">
diff --git a/work.py b/work.py
index 7f44401..8734e22 100644
--- a/work.py
+++ b/work.py
@@ -1,7 +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.
+# 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 __future__ import division
+
 from itertools import groupby
 from decimal import Decimal
+import datetime
+
+from sql import Null
 from sql.aggregate import Sum
 
 from trytond.model import ModelView, fields
@@ -28,21 +33,21 @@ class Work:
     project_invoice_method = fields.Selection(INVOICE_METHODS,
         'Invoice Method',
         states={
-            'readonly': Bool(Eval('invoiced_hours')),
+            'readonly': Bool(Eval('invoiced_duration')),
             'required': Eval('type') == 'project',
             'invisible': Eval('type') != 'project',
             },
-        depends=['invoiced_hours', 'type'])
+        depends=['invoiced_duration', 'type'])
     invoice_method = fields.Function(fields.Selection(INVOICE_METHODS,
             'Invoice Method'), 'get_invoice_method')
-    invoiced_hours = fields.Function(fields.Float('Invoiced Hours',
-            digits=(16, 2),
+    invoiced_duration = fields.Function(fields.TimeDelta('Invoiced Duration',
+            'company_work_time',
             states={
                 'invisible': Eval('invoice_method') == 'manual',
                 },
             depends=['invoice_method']), 'get_invoice_values')
-    hours_to_invoice = fields.Function(fields.Float('Hours to Invoice',
-            digits=(16, 2),
+    duration_to_invoice = fields.Function(fields.TimeDelta(
+            'Duration to Invoice', 'company_work_time',
             states={
                 'invisible': Eval('invoice_method') == 'manual',
                 },
@@ -65,7 +70,7 @@ class Work:
                     'invisible': ((Eval('type') != 'project')
                         | (Eval('project_invoice_method', 'manual')
                             == 'manual')),
-                    'readonly': ~Eval('hours_to_invoice'),
+                    'readonly': ~Eval('duration_to_invoice'),
                     },
                 })
         cls._error_messages.update({
@@ -94,39 +99,45 @@ class Work:
         else:
             return 'manual'
 
+    @property
+    def effort_hours(self):
+        if not self.effort_duration:
+            return 0
+        return self.effort_duration.total_seconds() / 60 / 60
+
     @staticmethod
-    def default_invoiced_hours():
-        return 0.
+    def default_invoiced_duration():
+        return datetime.timedelta()
 
     @staticmethod
-    def _get_invoiced_hours_manual(works):
+    def _get_invoiced_duration_manual(works):
         return {}
 
     @staticmethod
-    def _get_invoiced_hours_effort(works):
-        return dict((w.id, w.effort) for w in works
+    def _get_invoiced_duration_effort(works):
+        return dict((w.id, w.effort_duration) for w in works
             if w.invoice_line)
 
     @classmethod
-    def _get_invoiced_hours_timesheet(cls, works):
-        return cls._get_hours_timesheet(works, True)
+    def _get_invoiced_duration_timesheet(cls, works):
+        return cls._get_duration_timesheet(works, True)
 
     @staticmethod
-    def default_hours_to_invoice():
-        return 0.
+    def default_duration_to_invoice():
+        return datetime.timedelta()
 
     @staticmethod
-    def _get_hours_to_invoice_manual(works):
+    def _get_duration_to_invoice_manual(works):
         return {}
 
     @staticmethod
-    def _get_hours_to_invoice_effort(works):
-        return dict((w.id, w.effort) for w in works
+    def _get_duration_to_invoice_effort(works):
+        return dict((w.id, w.effort_duration) for w in works
             if w.state == 'done' and not w.invoice_line)
 
     @classmethod
-    def _get_hours_to_invoice_timesheet(cls, works):
-        return cls._get_hours_timesheet(works, False)
+    def _get_duration_to_invoice_timesheet(cls, works):
+        return cls._get_duration_timesheet(works, False)
 
     @staticmethod
     def default_invoiced_amount():
@@ -178,27 +189,30 @@ class Work:
         return amounts
 
     @staticmethod
-    def _get_hours_timesheet(works, invoiced):
+    def _get_duration_timesheet(works, invoiced):
         pool = Pool()
         TimesheetLine = pool.get('timesheet.line')
         cursor = Transaction().cursor
         line = TimesheetLine.__table__()
 
-        hours = {}
+        durations = {}
         twork2work = dict((w.work.id, w.id) for w in works)
         ids = twork2work.keys()
         for sub_ids in grouped_slice(ids):
             red_sql = reduce_ids(line.work, sub_ids)
             if invoiced:
-                where = line.invoice_line != None
+                where = line.invoice_line != Null
             else:
-                where = line.invoice_line == None
-            cursor.execute(*line.select(line.work, Sum(line.hours),
+                where = line.invoice_line == Null
+            cursor.execute(*line.select(line.work, Sum(line.duration),
                     where=red_sql & where,
                     group_by=line.work))
-            hours.update(dict((twork2work[w], h)
-                    for w, h in cursor.fetchall()))
-        return hours
+            for twork_id, duration in cursor.fetchall():
+                # SQLite uses float for SUM
+                if not isinstance(duration, datetime.timedelta):
+                    duration = datetime.timedelta(seconds=duration)
+                durations[twork2work[twork_id]] = duration
+        return durations
 
     @classmethod
     def get_invoice_values(cls, works, name):
@@ -326,14 +340,16 @@ class Work:
         return []
 
     def _get_lines_to_invoice_effort(self):
-        if not self.invoice_line and self.effort and self.state == 'done':
+        if (not self.invoice_line
+                and self.effort_hours
+                and self.state == 'done'):
             if not self.product:
                 self.raise_user_error('missing_product', (self.rec_name,))
             elif self.list_price is None:
                 self.raise_user_error('missing_list_price', (self.rec_name,))
             return [{
                     'product': self.product,
-                    'quantity': self.effort,
+                    'quantity': self.effort_hours,
                     'unit_price': self.list_price,
                     'origin': self,
                     'description': self.work.name,
-- 
tryton-modules-project-invoice



More information about the tryton-debian-vcs mailing list