details:   https://code.tryton.org/tryton/commit/f1bdafb36719
branch:    default
user:      Cédric Krier <[email protected]>
date:      Tue Apr 07 16:58:15 2026 +0200
description:
        Use the EXTRACT function to calculate the cost of the timesheet work
diffstat:

 modules/project_revenue/work.py |  21 +++++++++++----------
 1 files changed, 11 insertions(+), 10 deletions(-)

diffs (55 lines):

diff -r f2642fe60c20 -r f1bdafb36719 modules/project_revenue/work.py
--- a/modules/project_revenue/work.py   Tue Apr 07 16:46:21 2026 +0200
+++ b/modules/project_revenue/work.py   Tue Apr 07 16:58:15 2026 +0200
@@ -1,18 +1,21 @@
 # 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 datetime as dt
 from collections import defaultdict
 from decimal import Decimal
 
 from sql.aggregate import Sum
+from sql.conditionals import Coalesce
+from sql.functions import Extract
 from sql.operators import Concat
 
+from trytond import backend
 from trytond.model import fields
 from trytond.modules.currency.fields import Monetary
 from trytond.modules.product import price_digits, round_price
 from trytond.pool import Pool, PoolMeta
 from trytond.pyson import Bool, Eval, If
+from trytond.tools import sqlite_apply_types
 from trytond.transaction import Transaction
 
 
@@ -98,21 +101,19 @@
         work = Work.__table__()
         line = Line.__table__()
 
+        cost = line.cost_price * Extract('EPOCH', line.duration) / (60 * 60)
         where = fields.SQL_OPERATORS['in'](table.id, map(int, works))
-        cursor.execute(*table.join(work,
+        query = (table.join(work,
                 condition=(
                     Concat(cls.__name__ + ',', table.id) == work.origin)
                 ).join(line, condition=line.work == work.id
-                ).select(table.id, Sum(line.cost_price * line.duration),
+                ).select(table.id, Sum(Coalesce(cost, 0)).as_('cost'),
                 where=where,
                 group_by=[table.id]))
-        for work_id, cost in cursor:
-            # SQLite stores timedelta as float
-            if isinstance(cost, dt.timedelta):
-                cost = cost.total_seconds()
-            # Convert from seconds
-            cost /= 60 * 60
-            yield work_id, Decimal(str(cost))
+        if backend.name == 'sqlite':
+            sqlite_apply_types(query, [None, 'NUMERIC'])
+        cursor.execute(*query)
+        yield from cursor
 
     @classmethod
     def _purchase_cost(cls, works):

Reply via email to