diff --git a/modules/sale_complaint/CHANGELOG b/modules/sale_complaint/CHANGELOG index c5838d9861..7ddcf21de1 100644 --- a/modules/sale_complaint/CHANGELOG +++ b/modules/sale_complaint/CHANGELOG @@ -1,3 +1,4 @@ +* Raise a warning when submitting complaint for the same origin Version 7.2.0 - 2024-04-29 -------------------------- diff --git a/modules/sale_complaint/complaint.py b/modules/sale_complaint/complaint.py index 419e1964d3..62c2455fd0 100644 --- a/modules/sale_complaint/complaint.py +++ b/modules/sale_complaint/complaint.py @@ -17,8 +17,11 @@ from trytond.modules.currency.fields import Monetary from trytond.modules.product import price_digits from trytond.pool import Pool from trytond.pyson import Bool, Eval, If +from trytond.tools import grouped_slice from trytond.transaction import Transaction +from .exceptions import ComplaintSimilarWarning + class Type(DeactivableMixin, ModelSQL, ModelView): 'Customer Complaint Type' @@ -332,7 +335,7 @@ class Complaint(Workflow, ModelSQL, ModelView): @Workflow.transition('waiting') @set_employee('submitted_by') def wait(cls, complaints): - pass + cls._check_similar(complaints) @classmethod @ModelView.button @@ -377,6 +380,57 @@ class Complaint(Workflow, ModelSQL, ModelView): action.result = record Action.save(sum(list(actions.values()), [])) + @classmethod + def _check_similar(cls, complaints): + pool = Pool() + Warning = pool.get('res.user.warning') + for sub_complaints in grouped_slice(complaints): + sub_complaints = list(sub_complaints) + domain = list(filter(None, + (c._similar_domain() for c in sub_complaints))) + if not domain: + continue + if cls.search(['OR'] + domain, order=[]): + for complaint in sub_complaints: + domain = complaint._similar_domain() + if not domain: + continue + try: + similar, = cls.search(domain, limit=1) + except ValueError: + continue + warning_key = Warning.format( + 'complaint_similar', [complaint]) + if Warning.check(warning_key): + raise ComplaintSimilarWarning(warning_key, + gettext('sale_complaint.msg_complaint_similar', + similar=similar.rec_name, + complaint=complaint.rec_name)) + + def _similar_domain(self): + pool = Pool() + Sale = pool.get('sale.sale') + SaleLine = pool.get('sale.line') + Invoice = pool.get('account.invoice') + InvoiceLine = pool.get('account.invoice.line') + domain = ['OR', + ('origin', '=', str(self.origin)), + ] + if isinstance(self.origin, Sale): + domain.append(('origin.sale', '=', self.origin.id, 'sale.line')) + elif isinstance(self.origin, SaleLine): + domain.append(('origin', '=', str(self.origin.sale))) + elif isinstance(self.origin, Invoice): + domain.append( + ('origin.invoice', '=', self.origin.id, + 'account.invoice.line')) + elif isinstance(self.origin, InvoiceLine): + domain.append(('origin', '=', str(self.origin.invoice))) + return [ + domain, + ('id', '!=', self.id), + ] + class Action(ModelSQL, ModelView): 'Customer Complaint Action' diff --git a/modules/sale_complaint/exceptions.py b/modules/sale_complaint/exceptions.py new file mode 100644 index 0000000000..eea30e586f --- /dev/null +++ b/modules/sale_complaint/exceptions.py @@ -0,0 +1,8 @@ +# 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.exceptions import UserWarning + + +class ComplaintSimilarWarning(UserWarning): + pass diff --git a/modules/sale_complaint/message.xml b/modules/sale_complaint/message.xml index 11a58a56c1..ae04a0a5d7 100644 --- a/modules/sale_complaint/message.xml +++ b/modules/sale_complaint/message.xml @@ -3,6 +3,9 @@ this repository contains the full copyright notices and license terms. --> + + The complaint "%(complaint)s" is similar to complaint "%(similar)s". + To delete complaint "%(complaint)s" you must reset it to draft state. diff --git a/modules/sale_complaint/tests/scenario_sale_complaint.rst b/modules/sale_complaint/tests/scenario_sale_complaint.rst index dbd8d5ad86..2455088f58 100644 --- a/modules/sale_complaint/tests/scenario_sale_complaint.rst +++ b/modules/sale_complaint/tests/scenario_sale_complaint.rst @@ -162,6 +162,11 @@ Create a complaint to return partially the sale:: >>> complaint.state 'draft' >>> complaint.click('wait') + Traceback (most recent call last): + ... + ComplaintSimilarWarning: ... + >>> config.skip_warning = True + >>> complaint.click('wait') >>> complaint.state 'waiting' >>> complaint.click('approve')