diff --git a/modules/production_work/CHANGELOG b/modules/production_work/CHANGELOG
index a5b65551df..cd7469e52f 100644
--- a/modules/production_work/CHANGELOG
+++ b/modules/production_work/CHANGELOG
@@ -1,3 +1,4 @@
+* Display cost of works
Version 6.8.0 - 2023-05-01
--------------------------
diff --git a/modules/production_work/production.py b/modules/production_work/production.py
index f6e7540935..39b983f2b6 100644
--- a/modules/production_work/production.py
+++ b/modules/production_work/production.py
@@ -1,16 +1,10 @@
# 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.aggregate import Sum
-
from trytond.i18n import gettext
from trytond.model import ModelView, Workflow, fields
from trytond.model.exceptions import AccessError
-from trytond.modules.product import round_price
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Bool, Eval
-from trytond.transaction import Transaction
class Production(metaclass=PoolMeta):
@@ -36,30 +30,10 @@ class Production(metaclass=PoolMeta):
])
def get_cost(self, name):
- pool = Pool()
- Work = pool.get('production.work')
- Cycle = pool.get('production.work.cycle')
- table = self.__table__()
- work = Work.__table__()
- cycle = Cycle.__table__()
- cursor = Transaction().connection.cursor()
-
- cost = super(Production, self).get_cost(name)
-
- cursor.execute(*table.join(work, 'LEFT',
- condition=work.production == table.id
- ).join(cycle, 'LEFT', condition=cycle.work == work.id
- ).select(Sum(cycle.cost),
- where=(cycle.state == 'done')
- & (table.id == self.id)))
- cycle_cost, = cursor.fetchone()
- if cycle_cost is not None:
- # SQLite uses float for SUM
- if not isinstance(cycle_cost, Decimal):
- cycle_cost = Decimal(cycle_cost)
- cost += cycle_cost
-
- return round_price(cost)
+ cost = super().get_cost(name)
+ for work in self.works:
+ cost += work.cost
+ return cost
@classmethod
@ModelView.button
diff --git a/modules/production_work/tests/scenario_production_work.rst b/modules/production_work/tests/scenario_production_work.rst
index a66f44ccaa..e0c7c9043a 100644
--- a/modules/production_work/tests/scenario_production_work.rst
+++ b/modules/production_work/tests/scenario_production_work.rst
@@ -244,6 +244,10 @@ Check production cost::
>>> production.reload()
>>> production.cost
Decimal('17.0000')
+ >>> work1.cost
+ Decimal('10.0000')
+ >>> work2.cost
+ Decimal('5.0000')
Do the production::
diff --git a/modules/production_work/view/work_form.xml b/modules/production_work/view/work_form.xml
index 3fe5289592..95cb718208 100644
--- a/modules/production_work/view/work_form.xml
+++ b/modules/production_work/view/work_form.xml
@@ -17,7 +17,8 @@ this repository contains the full copyright notices and license terms. -->
-
+
+
diff --git a/modules/production_work/view/work_list_sequence.xml b/modules/production_work/view/work_list_sequence.xml
index 95ea7cd5d1..dbcf1201fa 100644
--- a/modules/production_work/view/work_list_sequence.xml
+++ b/modules/production_work/view/work_list_sequence.xml
@@ -5,5 +5,6 @@ this repository contains the full copyright notices and license terms. -->
+
diff --git a/modules/production_work/work.py b/modules/production_work/work.py
index 9ed47b8bfd..8870f310f9 100644
--- a/modules/production_work/work.py
+++ b/modules/production_work/work.py
@@ -2,9 +2,13 @@
# this repository contains the full copyright notices and license terms.
import datetime
import random
+from collections import defaultdict
from decimal import Decimal
from functools import wraps
+from sql.aggregate import Sum
+from sql.conditionals import Coalesce
+
from trytond.i18n import gettext
from trytond.model import (
DeactivableMixin, Index, ModelSQL, ModelView, Workflow, fields,
@@ -13,6 +17,7 @@ from trytond.model.exceptions import AccessError
from trytond.modules.product import price_digits, round_price
from trytond.pool import Pool
from trytond.pyson import Bool, Eval, If, TimeDelta
+from trytond.tools import grouped_slice, reduce_ids
from trytond.transaction import Transaction
from .exceptions import PickerError
@@ -128,6 +133,8 @@ class Work(sequence_ordered(), ModelSQL, ModelView):
filter=[
('state', '=', 'running'),
])
+ cost = fields.Function(fields.Numeric(
+ "Cost", digits=price_digits), 'get_cost')
company = fields.Many2One('company.company', "Company", required=True)
warehouse = fields.Function(fields.Many2One('stock.location', 'Warehouse'),
'on_change_with_warehouse')
@@ -244,6 +251,28 @@ class Work(sequence_ordered(), ModelSQL, ModelView):
('production.rec_name',) + tuple(clause[1:]),
]
+ @classmethod
+ def get_cost(cls, works, name):
+ pool = Pool()
+ Cycle = pool.get('production.work.cycle')
+ cycle = Cycle.__table__()
+ cursor = Transaction().connection.cursor()
+ costs = defaultdict(Decimal)
+
+ for sub_works in grouped_slice(works):
+ red_sql = reduce_ids(cycle.work, [w.id for w in sub_works])
+ cursor.execute(*cycle.select(
+ cycle.work, Sum(Coalesce(cycle.cost, 0)),
+ where=red_sql & (cycle.state == 'done'),
+ group_by=cycle.work))
+ costs.update(cursor)
+
+ for cost in costs:
+ if not isinstance(cost, Decimal):
+ costs[cost] = Decimal(str(costs[cost]))
+ costs[cost] = round_price(costs[cost])
+ return costs
+
@classmethod
def create(cls, values):
works = super(Work, cls).create(values)