changeset 0a4b8d475ed7 in modules/account:default
details: https://hg.tryton.org/modules/account?cmd=changeset&node=0a4b8d475ed7
description:
        Add wizard to delegate move lines to another party

        issue11645
        review429251004
diffstat:

 CHANGELOG                              |    1 +
 __init__.py                            |    2 +
 exceptions.py                          |    4 +
 message.xml                            |    6 +
 move.py                                |  123 ++++++++++++++++++++++++++++++++-
 move.xml                               |   27 +++++++
 tests/scenario_move_line_delegate.rst  |  106 ++++++++++++++++++++++++++++
 view/move_line_delegate_start_form.xml |   12 +++
 8 files changed, 278 insertions(+), 3 deletions(-)

diffs (357 lines):

diff -r 0d42af3244b9 -r 0a4b8d475ed7 CHANGELOG
--- a/CHANGELOG Sun Sep 11 15:15:12 2022 +0200
+++ b/CHANGELOG Sun Sep 11 17:45:41 2022 +0200
@@ -1,3 +1,4 @@
+* Add wizard to delegate move lines to another party
 * Support date range context for account type amount
 * Use context model for chart of accounts and taxes
 
diff -r 0d42af3244b9 -r 0a4b8d475ed7 __init__.py
--- a/__init__.py       Sun Sep 11 15:15:12 2022 +0200
+++ b/__init__.py       Sun Sep 11 17:45:41 2022 +0200
@@ -63,6 +63,7 @@
         move.RescheduleLinesStart,
         move.RescheduleLinesPreview,
         move.RescheduleLinesTerm,
+        move.DelegateLinesStart,
         tax.TaxGroup,
         tax.TaxCodeTemplate,
         tax.TaxCode,
@@ -103,6 +104,7 @@
         move.CancelMoves,
         move.GroupLines,
         move.RescheduleLines,
+        move.DelegateLines,
         move_template.CreateMove,
         tax.OpenTaxCode,
         tax.TestTax,
diff -r 0d42af3244b9 -r 0a4b8d475ed7 exceptions.py
--- a/exceptions.py     Sun Sep 11 15:15:12 2022 +0200
+++ b/exceptions.py     Sun Sep 11 17:45:41 2022 +0200
@@ -99,3 +99,7 @@
 
 class RescheduleLineError(UserError):
     pass
+
+
+class DelegateLineError(UserError):
+    pass
diff -r 0d42af3244b9 -r 0a4b8d475ed7 message.xml
--- a/message.xml       Sun Sep 11 15:15:12 2022 +0200
+++ b/message.xml       Sun Sep 11 17:45:41 2022 +0200
@@ -228,6 +228,12 @@
         <record model="ir.message" id="msg_reschedule_line_wrong_amount">
             <field name="text">To reschedule the lines you must change the 
terms to have a total amount of %(total_amount)s instead of %(amount)s.</field>
         </record>
+        <record model="ir.message" id="msg_delegate_line_same_company">
+            <field name="text">You cannot delegate together lines of different 
companies.</field>
+        </record>
+        <record model="ir.message" id="msg_delegate_line_same_origins">
+            <field name="text">You cannot delegate together lines with 
different origins.</field>
+        </record>
         <record model="ir.message" id="msg_cancel_line_delegated">
             <field name="text">The moves "%(moves)s" contain grouped lines, 
cancelling them will ungroup the lines.</field>
         </record>
diff -r 0d42af3244b9 -r 0a4b8d475ed7 move.py
--- a/move.py   Sun Sep 11 15:15:12 2022 +0200
+++ b/move.py   Sun Sep 11 17:45:41 2022 +0200
@@ -27,9 +27,9 @@
     Button, StateAction, StateTransition, StateView, Wizard)
 
 from .exceptions import (
-    CancelDelegatedWarning, CancelWarning, DeleteDelegatedWarning,
-    GroupLineError, MoveDatesError, PostError, ReconciliationError,
-    RescheduleLineError)
+    CancelDelegatedWarning, CancelWarning, DelegateLineError,
+    DeleteDelegatedWarning, GroupLineError, MoveDatesError, PostError,
+    ReconciliationError, RescheduleLineError)
 
 _MOVE_STATES = {
     'readonly': Eval('state') == 'posted',
@@ -2577,6 +2577,123 @@
     currency = fields.Many2One('currency.currency', "Currency", required=True)
 
 
+class DelegateLines(Wizard):
+    "Delegate Lines"
+    __name__ = 'account.move.line.delegate'
+    start = StateView(
+        'account.move.line.delegate.start',
+        'account.move_line_delegate_start_view_form', [
+            Button("Cancel", 'end', 'tryton-cancel'),
+            Button("Delegate", 'delegate', 'tryton-ok', default=True),
+            ])
+    delegate = StateAction('account.act_move_form_delegate')
+
+    def default_start(self, fields):
+        values = {}
+        if 'journal' in fields:
+            journals = {l.journal for l in self.records}
+            if len(journals) == 1:
+                journal, = journals
+                values['journal'] = journal.id
+        return values
+
+    def do_delegate(self, action):
+        move = self._delegate_lines(self.records, self.start.party)
+        return action, {'res_id': move.id}
+
+    def _delegate_lines(self, lines, party, date=None):
+        move = self.delegate_lines(lines, party, self.start.journal, date)
+        move.description = self.start.description
+        move.save()
+        return move
+
+    @classmethod
+    def delegate_lines(cls, lines, party, journal, date=None):
+        pool = Pool()
+        Line = pool.get('account.move.line')
+
+        move, counterpart, delegated = cls.get_move(
+            lines, party, journal, date=date)
+        move.save()
+        Line.save(counterpart + delegated)
+
+        for line, cline, dline in zip(lines, counterpart, delegated):
+            Line.reconcile([line, cline], delegate_to=dline)
+        return move
+
+    @classmethod
+    def get_move(cls, lines, party, journal, date=None):
+        pool = Pool()
+        Date = pool.get('ir.date')
+        Move = pool.get('account.move')
+        Period = pool.get('account.period')
+
+        try:
+            company, = {l.company for l in lines}
+        except ValueError:
+            raise DelegateLineError(
+                gettext('account.msg_delegate_line_same_company'))
+
+        try:
+            origin, = {l.move.origin for l in lines}
+        except ValueError:
+            raise DelegateLineError(
+                gettext('account.msg_delegate_line_same_origins'))
+
+        if not date:
+            with Transaction().set_context(company=company.id):
+                date = Date.today()
+        period = Period.find(company.id, date=date)
+
+        move = Move()
+        move.company = company
+        move.date = date
+        move.period = period
+        move.journal = journal
+        move.origin = origin
+
+        counterpart = []
+        delegated = []
+        for line in lines:
+            cline = cls.get_move_line(line)
+            cline.move = move
+            cline.debit, cline.credit = line.credit, line.debit
+            if cline.amount_second_currency:
+                cline.amount_second_currency *= -1
+            counterpart.append(cline)
+            dline = cls.get_move_line(line)
+            dline.move = move
+            dline.party = party
+            delegated.append(dline)
+        return move, counterpart, delegated
+
+    @classmethod
+    def get_move_line(cls, line):
+        pool = Pool()
+        Line = pool.get('account.move.line')
+
+        new = Line()
+        new.debit = line.debit
+        new.credit = line.credit
+        new.account = line.account
+        new.origin = line
+        new.description = line.description
+        new.amount_second_currency = line.amount_second_currency
+        new.second_currency = line.second_currency
+        new.party = line.party
+        new.maturity_date = line.maturity_date
+        return new
+
+
+class DelegateLinesStart(ModelView):
+    "Delegate Lines"
+    __name__ = 'account.move.line.delegate.start'
+
+    journal = fields.Many2One('account.journal', "Journal", required=True)
+    party = fields.Many2One('party.party', "Party", required=True)
+    description = fields.Char("Description")
+
+
 class GeneralJournal(Report):
     __name__ = 'account.move.general_journal'
 
diff -r 0d42af3244b9 -r 0a4b8d475ed7 move.xml
--- a/move.xml  Sun Sep 11 15:15:12 2022 +0200
+++ b/move.xml  Sun Sep 11 17:45:41 2022 +0200
@@ -497,6 +497,33 @@
             <field name="act_window" ref="act_move_form_rescheduling"/>
         </record>
 
+        <record model="ir.action.wizard" id="act_delegate_lines_wizard">
+            <field name="name">Delegate Lines</field>
+            <field name="wiz_name">account.move.line.delegate</field>
+            <field name="model">account.move.line</field>
+        </record>
+        <record model="ir.action.keyword" id="act_delegate_lines_keyword1">
+            <field name="keyword">form_action</field>
+            <field name="model">account.move.line,-1</field>
+            <field name="action" ref="act_delegate_lines_wizard"/>
+        </record>
+
+        <record model="ir.ui.view" id="move_line_delegate_start_view_form">
+            <field name="model">account.move.line.delegate.start</field>
+            <field name="type">form</field>
+            <field name="name">move_line_delegate_start_form</field>
+        </record>
+
+        <record model="ir.action.act_window" id="act_move_form_delegate">
+            <field name="name">Delegate Account Move</field>
+            <field name="res_model">account.move</field>
+        </record>
+        <record model="ir.action.act_window.view" 
id="act_move_form_delegate_view1">
+            <field name="sequence" eval="10"/>
+            <field name="view" ref="move_view_form"/>
+            <field name="act_window" ref="act_move_form_delegate"/>
+        </record>
+
         <record model="ir.action.report" id="report_general_journal">
             <field name="name">General Journal</field>
             <field name="model">account.move</field>
diff -r 0d42af3244b9 -r 0a4b8d475ed7 tests/scenario_move_line_delegate.rst
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/scenario_move_line_delegate.rst     Sun Sep 11 17:45:41 2022 +0200
@@ -0,0 +1,106 @@
+=======================
+Delegate Lines Scenario
+=======================
+
+Imports::
+
+    >>> from decimal import Decimal
+
+    >>> from proteus import Model, Wizard
+    >>> from trytond.tests.tools import activate_modules
+    >>> from trytond.modules.currency.tests.tools import get_currency
+    >>> from trytond.modules.company.tests.tools import (
+    ...     create_company, get_company)
+    >>> from trytond.modules.account.tests.tools import (
+    ...     create_fiscalyear, create_chart, get_accounts)
+
+Activate modules::
+
+    >>> config = activate_modules('account')
+
+    >>> Journal = Model.get('account.journal')
+    >>> Move = Model.get('account.move')
+    >>> Party = Model.get('party.party')
+
+Create company::
+
+    >>> usd = get_currency('USD')
+    >>> eur = get_currency('EUR')
+    >>> _ = create_company(currency=usd)
+    >>> company = get_company()
+
+Create fiscal year::
+
+    >>> fiscalyear = create_fiscalyear(company)
+    >>> fiscalyear.click('create_period')
+    >>> period = fiscalyear.periods[0]
+
+Create chart of accounts::
+
+    >>> _ = create_chart(company)
+    >>> accounts = get_accounts(company)
+
+Create parties::
+
+    >>> party1 = Party(name="Party 1")
+    >>> party1.save()
+    >>> party2 = Party(name="Party 2")
+    >>> party2.save()
+
+Create lines to delegate::
+
+    >>> journal, = Journal.find([
+    ...         ('code', '=', 'REV'),
+    ...         ])
+
+    >>> move = Move(journal=journal)
+    >>> move.date = period.start_date
+    >>> line = move.lines.new()
+    >>> line.account = accounts['revenue']
+    >>> line.credit = Decimal('100.00')
+    >>> line = move.lines.new()
+    >>> line.account = accounts['receivable']
+    >>> line.party = party1
+    >>> line.debit = Decimal('80.00')
+    >>> line.second_currency = eur
+    >>> line.amount_second_currency = Decimal('100.00')
+    >>> line.maturity_date = period.end_date
+    >>> line = move.lines.new()
+    >>> line.account = accounts['receivable']
+    >>> line.party = party1
+    >>> line.debit = Decimal('20.00')
+    >>> move.save()
+
+    >>> receivable_lines = [
+    ...     l for l in move.lines if l.account == accounts['receivable']]
+    >>> accounts['receivable'].reload()
+    >>> accounts['receivable'].balance
+    Decimal('100.00')
+    >>> party1.reload()
+    >>> party1.receivable
+    Decimal('100.00')
+    >>> party2.reload()
+    >>> party2.receivable
+    Decimal('0.0')
+
+Delegate lines::
+
+    >>> delegate = Wizard('account.move.line.delegate', receivable_lines)
+    >>> delegate.form.journal == journal
+    True
+    >>> delegate.form.party = party2
+    >>> delegate.form.description = "Delegate lines"
+    >>> delegate.execute('delegate')
+
+    >>> accounts['receivable'].reload()
+    >>> accounts['receivable'].balance
+    Decimal('100.00')
+    >>> party1.reload()
+    >>> party1.receivable
+    Decimal('0.0')
+    >>> party2.reload()
+    >>> party2.receivable
+    Decimal('100.00')
+
+    >>> all(l.reconciliation.delegate_to for l in receivable_lines)
+    True
diff -r 0d42af3244b9 -r 0a4b8d475ed7 view/move_line_delegate_start_form.xml
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/view/move_line_delegate_start_form.xml    Sun Sep 11 17:45:41 2022 +0200
@@ -0,0 +1,12 @@
+<?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. -->
+<form>
+    <label name="party"/>
+    <field name="party"/>
+    <label name="journal"/>
+    <field name="journal"/>
+
+    <label name="description"/>
+    <field name="description" colspan="3"/>
+</form>

Reply via email to