From 18969c011f9ec6f02f113e8275d3cadb8c514b5c Mon Sep 17 00:00:00 2001
From: Jordi Ballester Alomar
Date: Tue, 18 Dec 2018 02:05:57 +0100
Subject: [PATCH 01/13] [11.0][add][account_invoice_alternate_payer]
---
account_invoice_alternate_payer/README.rst | 83 ++++
account_invoice_alternate_payer/__init__.py | 1 +
.../__manifest__.py | 16 +
.../i18n/account_invoice_alternate_payer.pot | 58 +++
.../models/__init__.py | 2 +
.../models/account_invoice.py | 66 +++
.../models/account_payment.py | 50 ++
.../readme/CONTRIBUTORS.rst | 2 +
.../readme/DESCRIPTION.rst | 5 +
.../readme/USAGE.rst | 1 +
.../static/description/icon.png | Bin 0 -> 9455 bytes
.../static/description/index.html | 434 ++++++++++++++++++
.../tests/__init__.py | 1 +
.../tests/test_account_invoice.py | 257 +++++++++++
.../views/account_invoice_views.xml | 28 ++
15 files changed, 1004 insertions(+)
create mode 100644 account_invoice_alternate_payer/README.rst
create mode 100644 account_invoice_alternate_payer/__init__.py
create mode 100644 account_invoice_alternate_payer/__manifest__.py
create mode 100644 account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot
create mode 100644 account_invoice_alternate_payer/models/__init__.py
create mode 100644 account_invoice_alternate_payer/models/account_invoice.py
create mode 100644 account_invoice_alternate_payer/models/account_payment.py
create mode 100644 account_invoice_alternate_payer/readme/CONTRIBUTORS.rst
create mode 100644 account_invoice_alternate_payer/readme/DESCRIPTION.rst
create mode 100644 account_invoice_alternate_payer/readme/USAGE.rst
create mode 100644 account_invoice_alternate_payer/static/description/icon.png
create mode 100644 account_invoice_alternate_payer/static/description/index.html
create mode 100644 account_invoice_alternate_payer/tests/__init__.py
create mode 100644 account_invoice_alternate_payer/tests/test_account_invoice.py
create mode 100644 account_invoice_alternate_payer/views/account_invoice_views.xml
diff --git a/account_invoice_alternate_payer/README.rst b/account_invoice_alternate_payer/README.rst
new file mode 100644
index 000000000000..4e67fdaf63bb
--- /dev/null
+++ b/account_invoice_alternate_payer/README.rst
@@ -0,0 +1,83 @@
+===============================
+Account Invoice Alternate Payer
+===============================
+
+.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! This file is generated by oca-gen-addon-readme !!
+ !! changes will be overwritten. !!
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
+ :target: https://odoo-community.org/page/development-status
+ :alt: Beta
+.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
+ :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
+ :alt: License: AGPL-3
+.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Faccount--invoicing-lightgray.png?logo=github
+ :target: https://github.com/OCA/account-invoicing/tree/11.0/account_invoice_alternate_payer
+ :alt: OCA/account-invoicing
+.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
+ :target: https://translation.odoo-community.org/projects/account-invoicing-11-0/account-invoicing-11-0-account_invoice_alternate_payer
+ :alt: Translate me on Weblate
+.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
+ :target: https://runbot.odoo-community.org/runbot/95/11.0
+ :alt: Try me on Runbot
+
+|badge1| |badge2| |badge3| |badge4| |badge5|
+
+This module allows to enter an alternative payer in the
+customer invoice or vendor bill.
+
+This allows, that we pay or expect to get paid by another partner other
+than the main partner.
+
+**Table of contents**
+
+.. contents::
+ :local:
+
+Usage
+=====
+
+Access to the invoice and change the Alternate Payor/Payee of the invoice.
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues `_.
+In case of trouble, please check there if your issue has already been reported.
+If you spotted it first, help us smashing it by providing a detailed and welcomed
+`feedback `_.
+
+Do not contact contributors directly about support or help with technical issues.
+
+Credits
+=======
+
+Authors
+~~~~~~~
+
+* Eficent
+
+Contributors
+~~~~~~~~~~~~
+
+* Eficent Business and IT Consulting Services, S.L. (https://www.eficent.com)
+ * Jordi Ballester Alomar
+
+Maintainers
+~~~~~~~~~~~
+
+This module is maintained by the OCA.
+
+.. image:: https://odoo-community.org/logo.png
+ :alt: Odoo Community Association
+ :target: https://odoo-community.org
+
+OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.
+
+This module is part of the `OCA/account-invoicing `_ project on GitHub.
+
+You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/account_invoice_alternate_payer/__init__.py b/account_invoice_alternate_payer/__init__.py
new file mode 100644
index 000000000000..0650744f6bc6
--- /dev/null
+++ b/account_invoice_alternate_payer/__init__.py
@@ -0,0 +1 @@
+from . import models
diff --git a/account_invoice_alternate_payer/__manifest__.py b/account_invoice_alternate_payer/__manifest__.py
new file mode 100644
index 000000000000..a569c4837f82
--- /dev/null
+++ b/account_invoice_alternate_payer/__manifest__.py
@@ -0,0 +1,16 @@
+# Copyright 2018 Eficent Business and IT Consulting Services, S.L.
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+{
+ 'name': 'Account Invoice Alternate Payer',
+ 'summary': 'Set a alternate payor/payee in invoices',
+ 'version': '11.0.1.0.0',
+ 'license': 'AGPL-3',
+ 'category': 'Accounting',
+ 'author': 'Eficent,Odoo Community Association (OCA)',
+ 'website': 'https://github.com/OCA/account-invoicing/',
+ 'depends': ['account'],
+ 'data': [
+ 'views/account_invoice_views.xml',
+ ],
+}
diff --git a/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot b/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot
new file mode 100644
index 000000000000..34c072a76a47
--- /dev/null
+++ b/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot
@@ -0,0 +1,58 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * account_invoice_alternate_payer
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 11.0\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: account_invoice_alternate_payer
+#: model:ir.ui.view,arch_db:account_invoice_alternate_payer.invoice_supplier_form
+msgid "Alternate Payee"
+msgstr ""
+
+#. module: account_invoice_alternate_payer
+#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_invoice_alternate_payer_id
+msgid "Alternate Payer"
+msgstr ""
+
+#. module: account_invoice_alternate_payer
+#: model:ir.ui.view,arch_db:account_invoice_alternate_payer.invoice_form
+msgid "Alternate Payor"
+msgstr ""
+
+#. module: account_invoice_alternate_payer
+#: code:addons/account_invoice_alternate_payer/models/account_invoice.py:51
+#, python-format
+msgid "Cannot find a chart of accounts for this company, You should configure it. \n"
+"Please go to Account Configuration."
+msgstr ""
+
+#. module: account_invoice_alternate_payer
+#: code:addons/account_invoice_alternate_payer/models/account_invoice.py:56
+#, python-format
+msgid "Go to the configuration panel"
+msgstr ""
+
+#. module: account_invoice_alternate_payer
+#: model:ir.model.fields,help:account_invoice_alternate_payer.field_account_invoice_alternate_payer_id
+msgid "If set, this partner will be the that we expect to pay or to be paid by. If not set, the payor is by default the commercial"
+msgstr ""
+
+#. module: account_invoice_alternate_payer
+#: model:ir.model,name:account_invoice_alternate_payer.model_account_invoice
+msgid "Invoice"
+msgstr ""
+
+#. module: account_invoice_alternate_payer
+#: model:ir.model,name:account_invoice_alternate_payer.model_account_register_payments
+msgid "Register payments on multiple invoices"
+msgstr ""
+
diff --git a/account_invoice_alternate_payer/models/__init__.py b/account_invoice_alternate_payer/models/__init__.py
new file mode 100644
index 000000000000..515ed99ce64c
--- /dev/null
+++ b/account_invoice_alternate_payer/models/__init__.py
@@ -0,0 +1,2 @@
+from . import account_invoice
+from . import account_payment
diff --git a/account_invoice_alternate_payer/models/account_invoice.py b/account_invoice_alternate_payer/models/account_invoice.py
new file mode 100644
index 000000000000..4941b881621b
--- /dev/null
+++ b/account_invoice_alternate_payer/models/account_invoice.py
@@ -0,0 +1,66 @@
+# Copyright 2018 Eficent Business and IT Consulting Services, S.L.
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from odoo import api, fields, models, _
+from odoo.exceptions import RedirectWarning
+
+
+class AccountInvoice(models.Model):
+
+ _inherit = 'account.invoice'
+
+ alternate_payer_id = fields.Many2one(
+ 'res.partner', string='Alternate Payer',
+ readonly=True, states={'draft': [('readonly', False)]},
+ help="If set, this partner will be the that we expect to pay or to "
+ "be paid by. If not set, the payor is by default the "
+ "commercial")
+
+ @api.model
+ def line_get_convert(self, line, part):
+ res = super(AccountInvoice, self).line_get_convert(line, part)
+ if line.get('type', False) == 'dest' and self.alternate_payer_id:
+ res['partner_id'] = self.alternate_payer_id.id
+ return res
+
+ @api.onchange('partner_id', 'company_id', 'alternate_payer_id')
+ def _onchange_partner_id(self):
+ res = super(AccountInvoice, self)._onchange_partner_id()
+ company_id = self.company_id.id
+ domain = {}
+ if self.type in ('in_invoice', 'out_refund') and \
+ self.alternate_payer_id:
+ bank_ids = self.alternate_payer_id.bank_ids.filtered(
+ lambda b: b.company_id.id == company_id or not b.company_id)
+ bank_id = bank_ids[0].id if bank_ids else False
+ self.partner_bank_id = bank_id
+ domain = {'partner_bank_id': [('id', 'in', bank_ids.ids)]}
+ if domain:
+ res['domain'] = domain
+ if self.alternate_payer_id:
+ account_id = False
+ payment_term_id = False
+ p = self.alternate_payer_id if not company_id else \
+ self.alternate_payer_id.with_context(force_company=company_id)
+ type = self.type
+ if p:
+ rec_account = p.property_account_receivable_id
+ pay_account = p.property_account_payable_id
+ if not rec_account and not pay_account:
+ action = self.env.ref('account.action_account_config')
+ msg = _(
+ 'Cannot find a chart of accounts for this company, '
+ 'You should configure it. \nPlease go to Account '
+ 'Configuration.')
+ raise RedirectWarning(msg, action.id,
+ _('Go to the configuration panel'))
+
+ if type in ('out_invoice', 'out_refund'):
+ account_id = rec_account.id
+ payment_term_id = p.property_payment_term_id.id
+ else:
+ account_id = pay_account.id
+ payment_term_id = p.property_supplier_payment_term_id.id
+ self.account_id = account_id
+ self.payment_term_id = payment_term_id
+ return res
diff --git a/account_invoice_alternate_payer/models/account_payment.py b/account_invoice_alternate_payer/models/account_payment.py
new file mode 100644
index 000000000000..5116425345f5
--- /dev/null
+++ b/account_invoice_alternate_payer/models/account_payment.py
@@ -0,0 +1,50 @@
+# Copyright 2018 Eficent Business and IT Consulting Services, S.L.
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from odoo import api, models
+from odoo.addons.account.models.account_payment import \
+ MAP_INVOICE_TYPE_PARTNER_TYPE
+
+
+class AccountRegisterPayments(models.TransientModel):
+ _inherit = "account.register.payments"
+
+ @api.model
+ def default_get(self, fields):
+ rec = super(AccountRegisterPayments, self).default_get(fields)
+ active_ids = self._context.get('active_ids')
+ invoices = self.env['account.invoice'].browse(active_ids)
+
+ # Look if we are mixin multiple alternate_payer or
+ # customer invoices with vendor bills
+ payer = invoices[0].alternate_payer_id or \
+ invoices[0].commercial_partner_id
+ multi = any(inv.alternate_payer_id or inv.commercial_partner_id !=
+ payer for inv in invoices)
+ payer_id = invoices[0].alternate_payer_id.id or \
+ invoices[0].commercial_partner_id.id
+ rec['partner_id'] = False if multi else payer_id
+ rec['multi'] = multi
+ return rec
+
+ @api.multi
+ def _groupby_invoices(self):
+ # We have to re-group because the old groups are not valid anymore
+ super(AccountRegisterPayments, self)._groupby_invoices()
+ results = {}
+ for inv in self.invoice_ids:
+ payer = inv.alternate_payer_id.id or inv.commercial_partner_id.id
+ key = (payer, MAP_INVOICE_TYPE_PARTNER_TYPE[inv.type])
+ if key not in results:
+ results[key] = self.env['account.invoice']
+ results[key] += inv
+ return results
+
+ @api.multi
+ def _prepare_payment_vals(self, invoices):
+ res = super(AccountRegisterPayments, self)._prepare_payment_vals(
+ invoices)
+ payer_id = invoices[0].alternate_payer_id.id or \
+ invoices[0].commercial_partner_id.id
+ res['partner_id'] = payer_id
+ return res
diff --git a/account_invoice_alternate_payer/readme/CONTRIBUTORS.rst b/account_invoice_alternate_payer/readme/CONTRIBUTORS.rst
new file mode 100644
index 000000000000..6466f8907657
--- /dev/null
+++ b/account_invoice_alternate_payer/readme/CONTRIBUTORS.rst
@@ -0,0 +1,2 @@
+* Eficent Business and IT Consulting Services, S.L. (https://www.eficent.com)
+ * Jordi Ballester Alomar
diff --git a/account_invoice_alternate_payer/readme/DESCRIPTION.rst b/account_invoice_alternate_payer/readme/DESCRIPTION.rst
new file mode 100644
index 000000000000..5ac4a0bd5863
--- /dev/null
+++ b/account_invoice_alternate_payer/readme/DESCRIPTION.rst
@@ -0,0 +1,5 @@
+This module allows to enter an alternative payer in the
+customer invoice or vendor bill.
+
+This allows, that we pay or expect to get paid by another partner other
+than the main partner.
diff --git a/account_invoice_alternate_payer/readme/USAGE.rst b/account_invoice_alternate_payer/readme/USAGE.rst
new file mode 100644
index 000000000000..aea8f7fafd17
--- /dev/null
+++ b/account_invoice_alternate_payer/readme/USAGE.rst
@@ -0,0 +1 @@
+Access to the invoice and change the Alternate Payor/Payee of the invoice.
diff --git a/account_invoice_alternate_payer/static/description/icon.png b/account_invoice_alternate_payer/static/description/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d
GIT binary patch
literal 9455
zcmW++2RxMjAAjx~&dlBk9S+%}OXg)AGE&Cb*&}d0jUxM@u(PQx^-s)697TX`ehR4?GS^qbkof1cslKgkU)h65qZ9Oc=ml_0temigYLJfnz{IDzUf>bGs4N!v3=Z3jMq&A#7%rM5eQ#dc?k~!
zVpnB`o+K7|Al`Q_U;eD$B
zfJtP*jH`siUq~{KE)`jP2|#TUEFGRryE2`i0**z#*^6~AI|YzIWy$Cu#CSLW3q=GA
z6`?GZymC;dCPk~rBS%eCb`5OLr;RUZ;D`}um=H)BfVIq%7VhiMr)_#G0N#zrNH|__
zc+blN2UAB0=617@>_u;MPHN;P;N#YoE=)R#i$k_`UAA>WWCcEVMh~L_
zj--gtp&|K1#58Yz*AHCTMziU1Jzt_jG0I@qAOHsk$2}yTmVkBp_eHuY$A9)>P6o~I
z%aQ?!(GqeQ-Y+b0I(m9pwgi(IIZZzsbMv+9w{PFtd_<_(LA~0H(xz{=FhLB@(1&qHA5EJw1>>=%q2f&^X>IQ{!GJ4e9U
z&KlB)z(84HmNgm2hg2C0>WM{E(DdPr+EeU_N@57;PC2&DmGFW_9kP&%?X4}+xWi)(
z;)z%wI5>D4a*5XwD)P--sPkoY(a~WBw;E~AW`Yue4kFa^LM3X`8x|}ZUeMnqr}>kH
zG%WWW>3ml$Yez?i%)2pbKPI7?5o?hydokgQyZsNEr{a|mLdt;X2TX(#B1j35xPnPW
z*bMSSOauW>o;*=kO8ojw91VX!qoOQb)zHJ!odWB}d+*K?#sY_jqPdg{Sm2HdYzdEx
zOGVPhVRTGPtv0o}RfVP;Nd(|CB)I;*t&QO8h
zFfekr30S!-LHmV_Su-W+rEwYXJ^;6&3|L$mMC8*bQptyOo9;>Qb9Q9`ySe3%V$A*9
zeKEe+b0{#KWGp$F+tga)0RtI)nhMa-K@JS}2krK~n8vJ=Ngm?R!9G<~RyuU0d?nz#
z-5EK$o(!F?hmX*2Yt6+coY`6jGbb7tF#6nHA
zuKk=GGJ;ZwON1iAfG$E#Y7MnZVmrY|j0eVI(DN_MNFJmyZ|;w4tf@=CCDZ#5N_0K=
z$;R~bbk?}TpfDjfB&aiQ$VA}s?P}xPERJG{kxk5~R`iRS(SK5d+Xs9swCozZISbnS
zk!)I0>t=A<-^z(cmSFz3=jZ23u13X><0b)P)^1T_))Kr`e!-pb#q&J*Q`p+B6la%C
zuVl&0duN<;uOsB3%T9Fp8t{ED108)`y_~Hnd9AUX7h-H?jVuU|}My+C=TjH(jKz
zqMVr0re3S$H@t{zI95qa)+Crz*5Zj}Ao%4Z><+W(nOZd?gDnfNBC3>M8WE61$So|P
zVvqH0SNtDTcsUdzaMDpT=Ty0pDHHNL@Z0w$Y`XO
z2M-_r1S+GaH%pz#Uy0*w$Vdl=X=rQXEzO}d6J^R6zjM1u&c9vYLvLp?W7w(?np9x1
zE_0JSAJCPB%i7p*Wvg)pn5T`8k3-uR?*NT|J`eS#_#54p>!p(mLDvmc-3o0mX*mp_
zN*AeS<>#^-{S%W<*mz^!X$w_2dHWpcJ6^j64qFBft-o}o_Vx80o0>}Du;>kLts;$8
zC`7q$QI(dKYG`Wa8#wl@V4jVWBRGQ@1dr-hstpQL)Tl+aqVpGpbSfN>5i&QMXfiZ>
zaA?T1VGe?rpQ@;+pkrVdd{klI&jVS@I5_iz!=UMpTsa~mBga?1r}aRBm1WS;TT*s0f0lY=JBl66Upy)-k4J}lh=P^8(SXk~0xW=T9v*B|gzIhN
z>qsO7dFd~mgxAy4V?&)=5ieYq?zi?ZEoj)&2o)RLy=@hbCRcfT5jigwtQGE{L*8<@Yd{zg;CsL5mvzfDY}P-wos_6PfprFVaeqNE%h
zKZhLtcQld;ZD+>=nqN~>GvROfueSzJD&BE*}XfU|H&(FssBqY=hPCt`d
zH?@s2>I(|;fcW&YM6#V#!kUIP8$Nkdh0A(bEVj``-AAyYgwY~jB
zT|I7Bf@%;7aL7Wf4dZ%VqF$eiaC38OV6oy3Z#TER2G+fOCd9Iaoy6aLYbPTN{XRPz
z;U!V|vBf%H!}52L2gH_+j;`bTcQRXB+y9onc^wLm5wi3-Be}U>k_u>2Eg$=k!(l@I
zcCg+flakT2Nej3i0yn+g+}%NYb?ta;R?(g5SnwsQ49U8Wng8d|{B+lyRcEDvR3+`O{zfmrmvFrL6acVP%yG98X
zo&+VBg@px@i)%o?dG(`T;n*$S5*rnyiR#=wW}}GsAcfyQpE|>a{=$Hjg=-*_K;UtD
z#z-)AXwSRY?OPefw^iI+
z)AXz#PfEjlwTes|_{sB?4(O@fg0AJ^g8gP}ex9Ucf*@_^J(s_5jJV}c)s$`Myn|Kd
z$6>}#q^n{4vN@+Os$m7KV+`}c%4)4pv@06af4-x5#wj!KKb%caK{A&Y#Rfs
z-po?Dcb1({W=6FKIUirH&(yg=*6aLCekcKwyfK^JN5{wcA3nhO(o}SK#!CINhI`-I
z1)6&n7O&ZmyFMuNwvEic#IiOAwNkR=u5it{B9n2sAJV5pNhar=j5`*N!Na;c7g!l$
z3aYBqUkqqTJ=Re-;)s!EOeij=7SQZ3Hq}ZRds%IM*PtM$wV
z@;rlc*NRK7i3y5BETSKuumEN`Xu_8GP1Ri=OKQ$@I^ko8>H6)4rjiG5{VBM>B|%`&&s^)jS|-_95&yc=GqjNo{zFkw%%HHhS~e=s
zD#sfS+-?*t|J!+ozP6KvtOl!R)@@-z24}`9{QaVLD^9VCSR2b`b!KC#o;Ki<+wXB6
zx3&O0LOWcg4&rv4QG0)4yb}7BFSEg~=IR5#ZRj8kg}dS7_V&^%#Do==#`u
zpy6{ox?jWuR(;pg+f@mT>#HGWHAJRRDDDv~@(IDw&R>9643kK#HN`!1vBJHnC+RM&yIh8{gG2q
zA%e*U3|N0XSRa~oX-3EAneep)@{h2vvd3Xvy$7og(sayr@95+e6~Xvi1tUqnIxoIH
zVWo*OwYElb#uyW{Imam6f2rGbjR!Y3`#gPqkv57dB6K^wRGxc9B(t|aYDGS=m$&S!NmCtrMMaUg(c
zc2qC=2Z`EEFMW-me5B)24AqF*bV5Dr-M5ig(l-WPS%CgaPzs6p_gnCIvTJ=Y<6!gT
zVt@AfYCzjjsMEGi=rDQHo0yc;HqoRNnNFeWZgcm?f;cp(6CNylj36DoL(?TS7eU#+
z7&mfr#y))+CJOXQKUMZ7QIdS9@#-}7y2K1{8)cCt0~-X0O!O?Qx#E4Og+;A2SjalQ
zs7r?qn0H044=sDN$SRG$arw~n=+T_DNdSrarmu)V6@|?1-ZB#hRn`uilTGPJ@fqEy
zGt(f0B+^JDP&f=r{#Y_wi#AVDf-y!RIXU^0jXsFpf>=Ji*TeqSY!H~AMbJdCGLhC)
zn7Rx+sXw6uYj;WRYrLd^5IZq@6JI1C^YkgnedZEYy<&4(z%Q$5yv#Boo{AH8n$a
zhb4Y3PWdr269&?V%uI$xMcUrMzl=;w<_nm*qr=c3Rl@i5wWB;e-`t7D&c-mcQl7x!
zZWB`UGcw=Y2=}~wzrfLx=uet<;m3~=8I~ZRuzvMQUQdr+yTV|ATf1Uuomr__nDf=X
zZ3WYJtHp_ri(}SQAPjv+Y+0=fH4krOP@S&=zZ-t1jW1o@}z;xk8
z(Nz1co&El^HK^NrhVHa-_;&88vTU>_J33=%{if;BEY*J#1n59=07jrGQ#IP>@u#3A
z;!q+E1Rj3ZJ+!4bq9F8PXJ@yMgZL;>&gYA0%_Kbi8?S=XGM~dnQZQ!yBSgcZhY96H
zrWnU;k)qy`rX&&xlDyA%(a1Hhi5CWkmg(`Gb%m(HKi-7Z!LKGRP_B8@`7&hdDy5n=
z`OIxqxiVfX@OX1p(mQu>0Ai*v_cTMiw4qRt3~NBvr9oBy0)r>w3p~V0SCm=An6@3n)>@z!|o-$HvDK
z|3D2ZMJkLE5loMKl6R^ez@Zz%S$&mbeoqH5`Bb){Ei21q&VP)hWS2tjShfFtGE+$z
zzCR$P#uktu+#!w)cX!lWN1XU%K-r=s{|j?)Akf@q#3b#{6cZCuJ~gCxuMXRmI$nGtnH+-h
z+GEi!*X=AP<|fG`1>MBdTb?28JYc=fGvAi2I<$B(rs$;eoJCyR6_bc~p!XR@O-+sD
z=eH`-ye})I5ic1eL~TDmtfJ|8`0VJ*Yr=hNCd)G1p2MMz4C3^Mj?7;!w|Ly%JqmuW
zlIEW^Ft%z?*|fpXda>Jr^1noFZEwFgVV%|*XhH@acv8rdGxeEX{M$(vG{Zw+x(ei@
zmfXb22}8-?Fi`vo-YVrTH*C?a8%M=Hv9MqVH7H^J$KsD?>!SFZ;ZsvnHr_gn=7acz
z#W?0eCdVhVMWN12VV^$>WlQ?f;P^{(&pYTops|btm6aj>_Uz+hqpGwB)vWp0Cf5y<
zft8-je~nn?W11plq}N)4A{l8I7$!ks_x$PXW-2XaRFswX_BnF{R#6YIwMhAgd5F9X
zGmwdadS6(a^fjHtXg8=l?Rc0Sm%hk6E9!5cLVloEy4eh(=FwgP`)~I^5~pBEWo+F6
zSf2ncyMurJN91#cJTy_u8Y}@%!bq1RkGC~-bV@SXRd4F{R-*V`bS+6;W5vZ(&+I<9$;-V|eNfLa5n-6%
z2(}&uGRF;p92eS*sE*oR$@pexaqr*meB)VhmIg@h{uzkk$9~qh#cHhw#>O%)b@+(|
z^IQgqzuj~Sk(J;swEM-3TrJAPCq9k^^^`q{IItKBRXYe}e0Tdr=Huf7da3$l4PdpwWDop%^}n;dD#K4s#DYA8SHZ
z&1!riV4W4R7R#C))JH1~axJ)RYnM$$lIR%6fIVA@zV{XVyx}C+a-Dt8Y9M)^KU0+H
zR4IUb2CJ{Hg>CuaXtD50jB(_Tcx=Z$^WYu2u5kubqmwp%drJ6
z?Fo40g!Qd<-l=TQxqHEOuPX0;^z7iX?Ke^a%XT<13TA^5`4Xcw6D@Ur&VT&CUe0d}
z1GjOVF1^L@>O)l@?bD~$wzgf(nxX1OGD8fEV?TdJcZc2KoUe|oP1#=$$7ee|xbY)A
zDZq+cuTpc(fFdj^=!;{k03C69lMQ(|>uhRfRu%+!k&YOi-3|1QKB
z
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
Xviia!U7SGha1wx#SCgwmn*{w2TRX*I
literal 0
HcmV?d00001
diff --git a/account_invoice_alternate_payer/static/description/index.html b/account_invoice_alternate_payer/static/description/index.html
new file mode 100644
index 000000000000..0cdab016b9ee
--- /dev/null
+++ b/account_invoice_alternate_payer/static/description/index.html
@@ -0,0 +1,434 @@
+
+
+
+
+
+
+Account Invoice Alternate Payer
+
+
+
+
+
Account Invoice Alternate Payer
+
+
+
+
This module allows to enter an alternative payer in the
+customer invoice or vendor bill.
+
This allows, that we pay or expect to get paid by another partner other
+than the main partner.
+
Table of contents
+
+
+
+
Access to the invoice and change the Alternate Payor/Payee of the invoice.
+
+
+
+
Bugs are tracked on GitHub Issues.
+In case of trouble, please check there if your issue has already been reported.
+If you spotted it first, help us smashing it by providing a detailed and welcomed
+feedback.
+
Do not contact contributors directly about support or help with technical issues.
+
+
+
+
+
+
+
+
This module is maintained by the OCA.
+
+
OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.
+
This module is part of the OCA/account-invoicing project on GitHub.
+
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
+
+
+
+
+
diff --git a/account_invoice_alternate_payer/tests/__init__.py b/account_invoice_alternate_payer/tests/__init__.py
new file mode 100644
index 000000000000..d7555d02125e
--- /dev/null
+++ b/account_invoice_alternate_payer/tests/__init__.py
@@ -0,0 +1 @@
+from . import test_account_invoice
diff --git a/account_invoice_alternate_payer/tests/test_account_invoice.py b/account_invoice_alternate_payer/tests/test_account_invoice.py
new file mode 100644
index 000000000000..439aacefca2d
--- /dev/null
+++ b/account_invoice_alternate_payer/tests/test_account_invoice.py
@@ -0,0 +1,257 @@
+# Copyright 2018 Eficent Business and IT Consulting Services, S.L.
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+from odoo.tests.common import TransactionCase
+from odoo import fields
+
+
+class TestAccountInvoiceAlternateCommercialPartner(TransactionCase):
+
+ def setUp(self):
+ """
+ Setup test instances
+ """
+ super(TestAccountInvoiceAlternateCommercialPartner, self).setUp()
+ self.company = self.env.ref('base.main_company')
+ self.currency_usd_id = self.env.ref("base.USD").id
+ # Instance: account type (receivable)
+ self.type_recv = self.env.ref('account.data_account_type_receivable')
+ # Instance: account type (payable)
+ self.type_payable = self.env.ref('account.data_account_type_payable')
+ # Instance: account type (expense)
+ self.type_expense = self.env.ref('account.data_account_type_expenses')
+ # Instance: account type (revenue)
+ self.type_revenue = self.env.ref('account.data_account_type_revenue')
+ self.register_payments_model = self.env['account.register.payments']
+ # account (receivable)
+ self.account_recv = self.env['account.account'].create({
+ 'name': 'test_account_receivable',
+ 'code': '123',
+ 'user_type_id': self.type_recv.id,
+ 'company_id': self.company.id,
+ 'reconcile': True})
+ # account (payable)
+ self.account_payable = self.env['account.account'].create({
+ 'name': 'test_account_payable',
+ 'code': '321',
+ 'user_type_id': self.type_payable.id,
+ 'company_id': self.company.id,
+ 'reconcile': True})
+ self.account_payable_2 = self.env['account.account'].create({
+ 'name': 'test_account_payable',
+ 'code': '3211',
+ 'user_type_id': self.type_payable.id,
+ 'company_id': self.company.id,
+ 'reconcile': True})
+ self.account_expense = self.env['account.account'].create({
+ 'name': 'test_account_expense',
+ 'code': 'expense',
+ 'user_type_id': self.type_expense.id,
+ 'company_id': self.company.id,
+ 'reconcile': False})
+ self.account_revenue = self.env['account.account'].create({
+ 'name': 'test_account_revenue',
+ 'code': 'revenue',
+ 'user_type_id': self.type_revenue.id,
+ 'company_id': self.company.id,
+ 'reconcile': False})
+ self.customer_commercial = self.env['res.partner'].create({
+ 'name': 'Customer commercial partner',
+ 'property_account_receivable_id': self.account_recv.id,
+ 'is_company': True,
+ })
+ self.customer = self.env['res.partner'].create({
+ 'name': 'Customer',
+ 'property_account_receivable_id': self.account_recv.id,
+ 'company_id': self.company.id,
+ 'parent_id': self.customer_commercial.id,
+ })
+ self.vendor_commercial = self.env['res.partner'].create({
+ 'name': 'Vendor commercial partner',
+ 'property_account_payable_id': self.account_payable.id,
+ 'is_company': True,
+ })
+ self.vendor = self.env['res.partner'].create({
+ 'name': 'Vendor',
+ 'property_account_payable_id': self.account_payable.id,
+ 'company_id': self.company.id,
+ 'parent_id': self.vendor_commercial.id,
+ })
+ self.payor = self.env['res.partner'].create({
+ 'name': 'Payor for customer',
+ 'property_account_receivable_id': self.account_recv.id,
+ 'company_id': self.company.id,
+ })
+ self.payee = self.env['res.partner'].create({
+ 'name': 'Payee for vendor',
+ 'property_account_payable_id': self.account_payable_2.id,
+ 'company_id': self.company.id,
+ })
+ self.payee_bank = self.env['res.partner.bank'].create({
+ 'partner_id': self.payee.id,
+ 'acc_number': 'ES66 2100 0418 4012 3456 7891',
+ 'company_id': self.company.id,
+ })
+ self.purchase_journal = self.env['account.journal'].create(
+ {'name': 'Purchase Journal - TST',
+ 'code': 'PJT',
+ 'type': 'purchase',
+ 'company_id': self.company.id})
+ self.sale_journal = self.env['account.journal'].create(
+ {'name': 'Sale Journal - TST',
+ 'code': 'SJT',
+ 'type': 'sale',
+ 'company_id': self.company.id})
+ self.bank_journal_usd = self.env['account.journal'].create(
+ {'name': 'Bank US TEST', 'type': 'bank', 'code': 'BJT'})
+ self.product = self.env['product.product'].create({
+ 'type': 'service',
+ 'name': 'Sample product'
+ })
+ self.invoice_line = self.env['account.invoice.line'].create({
+ 'name': 'test',
+ 'account_id': self.account_expense.id,
+ 'price_unit': 2000.00,
+ 'quantity': 1,
+ 'product_id': self.product.id})
+ # Instance: invoice
+ self.vendor_invoice = self.env['account.invoice'].create({
+ 'partner_id': self.vendor.id,
+ 'type': 'in_invoice',
+ 'account_id': self.account_payable.id,
+ 'payment_term_id': False,
+ 'journal_id': self.purchase_journal.id,
+ 'company_id': self.company.id,
+ 'currency_id': self.currency_usd_id,
+ 'invoice_line_ids': [(4, self.invoice_line.id)]})
+ invoice_line = self.env['account.invoice.line'].create({
+ 'name': 'test',
+ 'account_id': self.account_revenue.id,
+ 'price_unit': 2000.00,
+ 'quantity': 1,
+ 'product_id': self.product.id})
+ # Instance: invoice
+ self.customer_invoice = self.env['account.invoice'].create({
+ 'partner_id': self.customer.id,
+ 'type': 'out_invoice',
+ 'account_id': self.account_recv.id,
+ 'payment_term_id': False,
+ 'journal_id': self.sale_journal.id,
+ 'company_id': self.company.id,
+ 'currency_id': self.currency_usd_id,
+ 'invoice_line_ids': [(4, invoice_line.id)]})
+
+ def test_01_onchange(self):
+ # Instance: invoice
+ supplier_invoice = self.env['account.invoice'].new({
+ 'partner_id': self.vendor.id,
+ 'type': 'in_invoice',
+ 'account_id': self.account_payable.id,
+ 'payment_term_id': False,
+ 'journal_id': self.purchase_journal.id,
+ 'currency_id': self.currency_usd_id,
+ 'company_id': self.company.id,
+ 'invoice_line_ids': [
+ (0, 0, {'name': 'test',
+ 'account_id': self.account_expense.id,
+ 'price_unit': 2000.00,
+ 'quantity': 1,
+ 'product_id': self.product.id
+ }
+ )
+ ]})
+ supplier_invoice.alternate_payer_id = self.payee
+ supplier_invoice._onchange_partner_id()
+ self.assertEqual(supplier_invoice.partner_bank_id, self.payee_bank)
+ self.assertEqual(supplier_invoice.account_id, self.account_payable_2)
+
+ def test_02_invoice(self):
+ """
+ Test Setting an alternate commercial partner
+ """
+ # Customer invoices
+ self.customer_invoice.alternate_payer_id = self.payor.id
+ self.customer_invoice._onchange_partner_id()
+ self.customer_invoice.action_invoice_open()
+ self.assertEqual(self.customer_invoice.state, 'open')
+ line = self.customer_invoice.move_id.line_ids.filtered(
+ lambda li: li.account_id == self.account_recv)
+ self.assertEqual(line.partner_id, self.payor)
+ ctx = {'active_model': 'account.invoice',
+ 'active_ids': [self.customer_invoice.id]}
+ register_payments = self.register_payments_model.with_context(
+ ctx).create({
+ 'payment_date': fields.Date.today(),
+ 'journal_id': self.bank_journal_usd.id,
+ 'payment_method_id': self.env.ref(
+ 'account.account_payment_method_manual_in').id,
+ })
+ register_payments.create_payments()
+ self.assertEqual(self.customer_invoice.state, 'paid')
+ # Vendor bills
+ self.vendor_invoice.alternate_payer_id = self.payee
+ self.vendor_invoice._onchange_partner_id()
+ self.vendor_invoice.action_invoice_open()
+ self.assertEqual(self.vendor_invoice.state, 'open')
+ line = self.vendor_invoice.move_id.line_ids.filtered(
+ lambda li: li.account_id == self.account_payable_2)
+ self.assertEqual(line.partner_id, self.payee)
+ ctx = {'active_model': 'account.invoice',
+ 'active_ids': [self.vendor_invoice.id]
+ }
+ register_payments = self.register_payments_model.with_context(
+ ctx).create({
+ 'payment_date': fields.Date.today(),
+ 'journal_id': self.bank_journal_usd.id,
+ 'payment_method_id': self.env.ref(
+ 'account.account_payment_method_manual_out').id,
+ })
+ register_payments.create_payments()
+ self.assertEqual(self.vendor_invoice.state, 'paid')
+
+ def test_03_payment_multiple_invoices(self):
+ """
+ Test selecting multiple invoices with different alternate payer
+ """
+ supplier_invoice_1 = self.env['account.invoice'].create({
+ 'partner_id': self.customer.id,
+ 'type': 'in_invoice',
+ 'account_id': self.account_payable.id,
+ 'payment_term_id': False,
+ 'journal_id': self.purchase_journal.id,
+ 'currency_id': self.currency_usd_id,
+ 'company_id': self.company.id,
+ 'invoice_line_ids': [
+ (0, 0, {'name': 'test',
+ 'account_id': self.account_expense.id,
+ 'price_unit': 2000.00,
+ 'quantity': 1,
+ 'product_id': self.product.id
+ }
+ )
+ ]})
+ supplier_invoice_2 = supplier_invoice_1.copy()
+ supplier_invoice_2.alternate_payer_id = self.payee
+ supplier_invoice_3 = supplier_invoice_1.copy()
+ supplier_invoice_1._onchange_partner_id()
+ supplier_invoice_1.action_invoice_open()
+ supplier_invoice_2._onchange_partner_id()
+ supplier_invoice_2.action_invoice_open()
+ supplier_invoice_3._onchange_partner_id()
+ supplier_invoice_3.action_invoice_open()
+ ctx = {'active_model': 'account.invoice',
+ 'active_ids': [supplier_invoice_1.id, supplier_invoice_2.id,
+ supplier_invoice_3.id]}
+ register_payments = self.register_payments_model.with_context(
+ ctx).create({
+ 'payment_date': fields.Date.today(),
+ 'journal_id': self.bank_journal_usd.id,
+ 'payment_method_id': self.env.ref(
+ 'account.account_payment_method_manual_out').id,
+ })
+ res = register_payments.create_payments()
+ # ['domain'][('id', 'in', payments.ids), ('state', '=', 'posted')]
+ self.assertEqual(len(res['domain'][0][2]), 2)
+ self.assertEqual(supplier_invoice_1.state, 'paid')
+ self.assertEqual(supplier_invoice_2.state, 'paid')
+ self.assertEqual(supplier_invoice_3.state, 'paid')
diff --git a/account_invoice_alternate_payer/views/account_invoice_views.xml b/account_invoice_alternate_payer/views/account_invoice_views.xml
new file mode 100644
index 000000000000..572fe2955211
--- /dev/null
+++ b/account_invoice_alternate_payer/views/account_invoice_views.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+ account.invoice.supplier.form
+ account.invoice
+
+
+
+
+
+
+
+
+
+ account.invoice.form
+ account.invoice
+
+
+
+
+
+
+
+
+
+
From 3199dffca6062a3c96e42b454fb4af77db32320e Mon Sep 17 00:00:00 2001
From: Enric Tobella
Date: Wed, 4 Mar 2020 21:24:10 +0100
Subject: [PATCH 02/13] [MIG][12.0] account_invoice_alternate_payer
---
.../__manifest__.py | 2 +-
.../models/account_invoice.py | 23 +++++++++++++++++--
.../tests/test_account_invoice.py | 22 ++++++++++++++++++
3 files changed, 44 insertions(+), 3 deletions(-)
diff --git a/account_invoice_alternate_payer/__manifest__.py b/account_invoice_alternate_payer/__manifest__.py
index a569c4837f82..b74a906eb196 100644
--- a/account_invoice_alternate_payer/__manifest__.py
+++ b/account_invoice_alternate_payer/__manifest__.py
@@ -4,7 +4,7 @@
{
'name': 'Account Invoice Alternate Payer',
'summary': 'Set a alternate payor/payee in invoices',
- 'version': '11.0.1.0.0',
+ 'version': '12.0.1.0.0',
'license': 'AGPL-3',
'category': 'Accounting',
'author': 'Eficent,Odoo Community Association (OCA)',
diff --git a/account_invoice_alternate_payer/models/account_invoice.py b/account_invoice_alternate_payer/models/account_invoice.py
index 4941b881621b..79ec31b5d8c8 100644
--- a/account_invoice_alternate_payer/models/account_invoice.py
+++ b/account_invoice_alternate_payer/models/account_invoice.py
@@ -3,6 +3,7 @@
from odoo import api, fields, models, _
from odoo.exceptions import RedirectWarning
+from odoo.exceptions import ValidationError
class AccountInvoice(models.Model):
@@ -42,7 +43,6 @@ def _onchange_partner_id(self):
payment_term_id = False
p = self.alternate_payer_id if not company_id else \
self.alternate_payer_id.with_context(force_company=company_id)
- type = self.type
if p:
rec_account = p.property_account_receivable_id
pay_account = p.property_account_payable_id
@@ -55,7 +55,7 @@ def _onchange_partner_id(self):
raise RedirectWarning(msg, action.id,
_('Go to the configuration panel'))
- if type in ('out_invoice', 'out_refund'):
+ if self.type in ('out_invoice', 'out_refund'):
account_id = rec_account.id
payment_term_id = p.property_payment_term_id.id
else:
@@ -64,3 +64,22 @@ def _onchange_partner_id(self):
self.account_id = account_id
self.payment_term_id = payment_term_id
return res
+
+ @api.constrains('partner_id', 'partner_bank_id')
+ def validate_partner_bank_id(self):
+ for record in self:
+ if record.partner_bank_id:
+ partner = record.alternate_payer_id or record.partner_id
+ bank_partner = record.partner_bank_id.partner_id
+ if record.type in (
+ 'in_invoice', 'out_refund'
+ ) and bank_partner != partner.commercial_partner_id:
+ raise ValidationError(_(
+ "Commercial partner and vendor account owners must "
+ "be identical."))
+ elif record.type in (
+ 'out_invoice', 'in_refund'
+ ) and record.company_id not in bank_partner.ref_company_ids:
+ raise ValidationError(_(
+ "The account selected for payment does not belong to "
+ "the same company as this invoice."))
diff --git a/account_invoice_alternate_payer/tests/test_account_invoice.py b/account_invoice_alternate_payer/tests/test_account_invoice.py
index 439aacefca2d..e6065043d702 100644
--- a/account_invoice_alternate_payer/tests/test_account_invoice.py
+++ b/account_invoice_alternate_payer/tests/test_account_invoice.py
@@ -3,6 +3,7 @@
from odoo.tests.common import TransactionCase
from odoo import fields
+from odoo.exceptions import ValidationError
class TestAccountInvoiceAlternateCommercialPartner(TransactionCase):
@@ -255,3 +256,24 @@ def test_03_payment_multiple_invoices(self):
self.assertEqual(supplier_invoice_1.state, 'paid')
self.assertEqual(supplier_invoice_2.state, 'paid')
self.assertEqual(supplier_invoice_3.state, 'paid')
+
+ def test_constrains(self):
+ with self.assertRaises(ValidationError):
+ self.env['account.invoice'].create({
+ 'partner_id': self.vendor.id,
+ 'type': 'in_invoice',
+ 'account_id': self.account_payable.id,
+ 'payment_term_id': False,
+ 'journal_id': self.purchase_journal.id,
+ 'currency_id': self.currency_usd_id,
+ 'company_id': self.company.id,
+ 'partner_bank_id': self.payee_bank.id,
+ 'invoice_line_ids': [
+ (0, 0, {'name': 'test',
+ 'account_id': self.account_expense.id,
+ 'price_unit': 2000.00,
+ 'quantity': 1,
+ 'product_id': self.product.id
+ }
+ )
+ ]})
From 63bdbab3eead2e65b54fc8a509cf721afb09d4f4 Mon Sep 17 00:00:00 2001
From: Enric Tobella
Date: Mon, 21 Jun 2021 09:40:15 +0200
Subject: [PATCH 03/13] [IMP] account_invoice_alternate_payer: black, isort,
prettier
---
.../__manifest__.py | 20 +-
.../models/account_invoice.py | 91 ++--
.../models/account_payment.py | 38 +-
.../tests/test_account_invoice.py | 507 ++++++++++--------
.../views/account_invoice_views.xml | 13 +-
5 files changed, 382 insertions(+), 287 deletions(-)
diff --git a/account_invoice_alternate_payer/__manifest__.py b/account_invoice_alternate_payer/__manifest__.py
index b74a906eb196..1b84a8cd309d 100644
--- a/account_invoice_alternate_payer/__manifest__.py
+++ b/account_invoice_alternate_payer/__manifest__.py
@@ -2,15 +2,13 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
{
- 'name': 'Account Invoice Alternate Payer',
- 'summary': 'Set a alternate payor/payee in invoices',
- 'version': '12.0.1.0.0',
- 'license': 'AGPL-3',
- 'category': 'Accounting',
- 'author': 'Eficent,Odoo Community Association (OCA)',
- 'website': 'https://github.com/OCA/account-invoicing/',
- 'depends': ['account'],
- 'data': [
- 'views/account_invoice_views.xml',
- ],
+ "name": "Account Invoice Alternate Payer",
+ "summary": "Set a alternate payor/payee in invoices",
+ "version": "12.0.1.0.0",
+ "license": "AGPL-3",
+ "category": "Accounting",
+ "author": "Eficent,Odoo Community Association (OCA)",
+ "website": "https://github.com/OCA/account-invoicing/",
+ "depends": ["account"],
+ "data": ["views/account_invoice_views.xml",],
}
diff --git a/account_invoice_alternate_payer/models/account_invoice.py b/account_invoice_alternate_payer/models/account_invoice.py
index 79ec31b5d8c8..db614136df64 100644
--- a/account_invoice_alternate_payer/models/account_invoice.py
+++ b/account_invoice_alternate_payer/models/account_invoice.py
@@ -1,61 +1,68 @@
# Copyright 2018 Eficent Business and IT Consulting Services, S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
-from odoo import api, fields, models, _
-from odoo.exceptions import RedirectWarning
-from odoo.exceptions import ValidationError
+from odoo import _, api, fields, models
+from odoo.exceptions import RedirectWarning, ValidationError
class AccountInvoice(models.Model):
- _inherit = 'account.invoice'
+ _inherit = "account.invoice"
alternate_payer_id = fields.Many2one(
- 'res.partner', string='Alternate Payer',
- readonly=True, states={'draft': [('readonly', False)]},
+ "res.partner",
+ string="Alternate Payer",
+ readonly=True,
+ states={"draft": [("readonly", False)]},
help="If set, this partner will be the that we expect to pay or to "
- "be paid by. If not set, the payor is by default the "
- "commercial")
+ "be paid by. If not set, the payor is by default the "
+ "commercial",
+ )
@api.model
def line_get_convert(self, line, part):
res = super(AccountInvoice, self).line_get_convert(line, part)
- if line.get('type', False) == 'dest' and self.alternate_payer_id:
- res['partner_id'] = self.alternate_payer_id.id
+ if line.get("type", False) == "dest" and self.alternate_payer_id:
+ res["partner_id"] = self.alternate_payer_id.id
return res
- @api.onchange('partner_id', 'company_id', 'alternate_payer_id')
+ @api.onchange("partner_id", "company_id", "alternate_payer_id")
def _onchange_partner_id(self):
res = super(AccountInvoice, self)._onchange_partner_id()
company_id = self.company_id.id
domain = {}
- if self.type in ('in_invoice', 'out_refund') and \
- self.alternate_payer_id:
+ if self.type in ("in_invoice", "out_refund") and self.alternate_payer_id:
bank_ids = self.alternate_payer_id.bank_ids.filtered(
- lambda b: b.company_id.id == company_id or not b.company_id)
+ lambda b: b.company_id.id == company_id or not b.company_id
+ )
bank_id = bank_ids[0].id if bank_ids else False
self.partner_bank_id = bank_id
- domain = {'partner_bank_id': [('id', 'in', bank_ids.ids)]}
+ domain = {"partner_bank_id": [("id", "in", bank_ids.ids)]}
if domain:
- res['domain'] = domain
+ res["domain"] = domain
if self.alternate_payer_id:
account_id = False
payment_term_id = False
- p = self.alternate_payer_id if not company_id else \
- self.alternate_payer_id.with_context(force_company=company_id)
+ p = (
+ self.alternate_payer_id
+ if not company_id
+ else self.alternate_payer_id.with_context(force_company=company_id)
+ )
if p:
rec_account = p.property_account_receivable_id
pay_account = p.property_account_payable_id
if not rec_account and not pay_account:
- action = self.env.ref('account.action_account_config')
+ action = self.env.ref("account.action_account_config")
msg = _(
- 'Cannot find a chart of accounts for this company, '
- 'You should configure it. \nPlease go to Account '
- 'Configuration.')
- raise RedirectWarning(msg, action.id,
- _('Go to the configuration panel'))
+ "Cannot find a chart of accounts for this company, "
+ "You should configure it. \nPlease go to Account "
+ "Configuration."
+ )
+ raise RedirectWarning(
+ msg, action.id, _("Go to the configuration panel")
+ )
- if self.type in ('out_invoice', 'out_refund'):
+ if self.type in ("out_invoice", "out_refund"):
account_id = rec_account.id
payment_term_id = p.property_payment_term_id.id
else:
@@ -65,21 +72,29 @@ def _onchange_partner_id(self):
self.payment_term_id = payment_term_id
return res
- @api.constrains('partner_id', 'partner_bank_id')
+ @api.constrains("partner_id", "partner_bank_id")
def validate_partner_bank_id(self):
for record in self:
if record.partner_bank_id:
partner = record.alternate_payer_id or record.partner_id
bank_partner = record.partner_bank_id.partner_id
- if record.type in (
- 'in_invoice', 'out_refund'
- ) and bank_partner != partner.commercial_partner_id:
- raise ValidationError(_(
- "Commercial partner and vendor account owners must "
- "be identical."))
- elif record.type in (
- 'out_invoice', 'in_refund'
- ) and record.company_id not in bank_partner.ref_company_ids:
- raise ValidationError(_(
- "The account selected for payment does not belong to "
- "the same company as this invoice."))
+ if (
+ record.type in ("in_invoice", "out_refund")
+ and bank_partner != partner.commercial_partner_id
+ ):
+ raise ValidationError(
+ _(
+ "Commercial partner and vendor account owners must "
+ "be identical."
+ )
+ )
+ elif (
+ record.type in ("out_invoice", "in_refund")
+ and record.company_id not in bank_partner.ref_company_ids
+ ):
+ raise ValidationError(
+ _(
+ "The account selected for payment does not belong to "
+ "the same company as this invoice."
+ )
+ )
diff --git a/account_invoice_alternate_payer/models/account_payment.py b/account_invoice_alternate_payer/models/account_payment.py
index 5116425345f5..2726ff847b54 100644
--- a/account_invoice_alternate_payer/models/account_payment.py
+++ b/account_invoice_alternate_payer/models/account_payment.py
@@ -2,8 +2,8 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import api, models
-from odoo.addons.account.models.account_payment import \
- MAP_INVOICE_TYPE_PARTNER_TYPE
+
+from odoo.addons.account.models.account_payment import MAP_INVOICE_TYPE_PARTNER_TYPE
class AccountRegisterPayments(models.TransientModel):
@@ -12,19 +12,21 @@ class AccountRegisterPayments(models.TransientModel):
@api.model
def default_get(self, fields):
rec = super(AccountRegisterPayments, self).default_get(fields)
- active_ids = self._context.get('active_ids')
- invoices = self.env['account.invoice'].browse(active_ids)
+ active_ids = self._context.get("active_ids")
+ invoices = self.env["account.invoice"].browse(active_ids)
# Look if we are mixin multiple alternate_payer or
# customer invoices with vendor bills
- payer = invoices[0].alternate_payer_id or \
- invoices[0].commercial_partner_id
- multi = any(inv.alternate_payer_id or inv.commercial_partner_id !=
- payer for inv in invoices)
- payer_id = invoices[0].alternate_payer_id.id or \
- invoices[0].commercial_partner_id.id
- rec['partner_id'] = False if multi else payer_id
- rec['multi'] = multi
+ payer = invoices[0].alternate_payer_id or invoices[0].commercial_partner_id
+ multi = any(
+ inv.alternate_payer_id or inv.commercial_partner_id != payer
+ for inv in invoices
+ )
+ payer_id = (
+ invoices[0].alternate_payer_id.id or invoices[0].commercial_partner_id.id
+ )
+ rec["partner_id"] = False if multi else payer_id
+ rec["multi"] = multi
return rec
@api.multi
@@ -36,15 +38,15 @@ def _groupby_invoices(self):
payer = inv.alternate_payer_id.id or inv.commercial_partner_id.id
key = (payer, MAP_INVOICE_TYPE_PARTNER_TYPE[inv.type])
if key not in results:
- results[key] = self.env['account.invoice']
+ results[key] = self.env["account.invoice"]
results[key] += inv
return results
@api.multi
def _prepare_payment_vals(self, invoices):
- res = super(AccountRegisterPayments, self)._prepare_payment_vals(
- invoices)
- payer_id = invoices[0].alternate_payer_id.id or \
- invoices[0].commercial_partner_id.id
- res['partner_id'] = payer_id
+ res = super(AccountRegisterPayments, self)._prepare_payment_vals(invoices)
+ payer_id = (
+ invoices[0].alternate_payer_id.id or invoices[0].commercial_partner_id.id
+ )
+ res["partner_id"] = payer_id
return res
diff --git a/account_invoice_alternate_payer/tests/test_account_invoice.py b/account_invoice_alternate_payer/tests/test_account_invoice.py
index e6065043d702..6dfa242c4836 100644
--- a/account_invoice_alternate_payer/tests/test_account_invoice.py
+++ b/account_invoice_alternate_payer/tests/test_account_invoice.py
@@ -1,166 +1,219 @@
# Copyright 2018 Eficent Business and IT Consulting Services, S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
-from odoo.tests.common import TransactionCase
from odoo import fields
from odoo.exceptions import ValidationError
+from odoo.tests.common import TransactionCase
class TestAccountInvoiceAlternateCommercialPartner(TransactionCase):
-
def setUp(self):
"""
Setup test instances
"""
super(TestAccountInvoiceAlternateCommercialPartner, self).setUp()
- self.company = self.env.ref('base.main_company')
+ self.company = self.env.ref("base.main_company")
self.currency_usd_id = self.env.ref("base.USD").id
# Instance: account type (receivable)
- self.type_recv = self.env.ref('account.data_account_type_receivable')
+ self.type_recv = self.env.ref("account.data_account_type_receivable")
# Instance: account type (payable)
- self.type_payable = self.env.ref('account.data_account_type_payable')
+ self.type_payable = self.env.ref("account.data_account_type_payable")
# Instance: account type (expense)
- self.type_expense = self.env.ref('account.data_account_type_expenses')
+ self.type_expense = self.env.ref("account.data_account_type_expenses")
# Instance: account type (revenue)
- self.type_revenue = self.env.ref('account.data_account_type_revenue')
- self.register_payments_model = self.env['account.register.payments']
+ self.type_revenue = self.env.ref("account.data_account_type_revenue")
+ self.register_payments_model = self.env["account.register.payments"]
# account (receivable)
- self.account_recv = self.env['account.account'].create({
- 'name': 'test_account_receivable',
- 'code': '123',
- 'user_type_id': self.type_recv.id,
- 'company_id': self.company.id,
- 'reconcile': True})
+ self.account_recv = self.env["account.account"].create(
+ {
+ "name": "test_account_receivable",
+ "code": "123",
+ "user_type_id": self.type_recv.id,
+ "company_id": self.company.id,
+ "reconcile": True,
+ }
+ )
# account (payable)
- self.account_payable = self.env['account.account'].create({
- 'name': 'test_account_payable',
- 'code': '321',
- 'user_type_id': self.type_payable.id,
- 'company_id': self.company.id,
- 'reconcile': True})
- self.account_payable_2 = self.env['account.account'].create({
- 'name': 'test_account_payable',
- 'code': '3211',
- 'user_type_id': self.type_payable.id,
- 'company_id': self.company.id,
- 'reconcile': True})
- self.account_expense = self.env['account.account'].create({
- 'name': 'test_account_expense',
- 'code': 'expense',
- 'user_type_id': self.type_expense.id,
- 'company_id': self.company.id,
- 'reconcile': False})
- self.account_revenue = self.env['account.account'].create({
- 'name': 'test_account_revenue',
- 'code': 'revenue',
- 'user_type_id': self.type_revenue.id,
- 'company_id': self.company.id,
- 'reconcile': False})
- self.customer_commercial = self.env['res.partner'].create({
- 'name': 'Customer commercial partner',
- 'property_account_receivable_id': self.account_recv.id,
- 'is_company': True,
- })
- self.customer = self.env['res.partner'].create({
- 'name': 'Customer',
- 'property_account_receivable_id': self.account_recv.id,
- 'company_id': self.company.id,
- 'parent_id': self.customer_commercial.id,
- })
- self.vendor_commercial = self.env['res.partner'].create({
- 'name': 'Vendor commercial partner',
- 'property_account_payable_id': self.account_payable.id,
- 'is_company': True,
- })
- self.vendor = self.env['res.partner'].create({
- 'name': 'Vendor',
- 'property_account_payable_id': self.account_payable.id,
- 'company_id': self.company.id,
- 'parent_id': self.vendor_commercial.id,
- })
- self.payor = self.env['res.partner'].create({
- 'name': 'Payor for customer',
- 'property_account_receivable_id': self.account_recv.id,
- 'company_id': self.company.id,
- })
- self.payee = self.env['res.partner'].create({
- 'name': 'Payee for vendor',
- 'property_account_payable_id': self.account_payable_2.id,
- 'company_id': self.company.id,
- })
- self.payee_bank = self.env['res.partner.bank'].create({
- 'partner_id': self.payee.id,
- 'acc_number': 'ES66 2100 0418 4012 3456 7891',
- 'company_id': self.company.id,
- })
- self.purchase_journal = self.env['account.journal'].create(
- {'name': 'Purchase Journal - TST',
- 'code': 'PJT',
- 'type': 'purchase',
- 'company_id': self.company.id})
- self.sale_journal = self.env['account.journal'].create(
- {'name': 'Sale Journal - TST',
- 'code': 'SJT',
- 'type': 'sale',
- 'company_id': self.company.id})
- self.bank_journal_usd = self.env['account.journal'].create(
- {'name': 'Bank US TEST', 'type': 'bank', 'code': 'BJT'})
- self.product = self.env['product.product'].create({
- 'type': 'service',
- 'name': 'Sample product'
- })
- self.invoice_line = self.env['account.invoice.line'].create({
- 'name': 'test',
- 'account_id': self.account_expense.id,
- 'price_unit': 2000.00,
- 'quantity': 1,
- 'product_id': self.product.id})
+ self.account_payable = self.env["account.account"].create(
+ {
+ "name": "test_account_payable",
+ "code": "321",
+ "user_type_id": self.type_payable.id,
+ "company_id": self.company.id,
+ "reconcile": True,
+ }
+ )
+ self.account_payable_2 = self.env["account.account"].create(
+ {
+ "name": "test_account_payable",
+ "code": "3211",
+ "user_type_id": self.type_payable.id,
+ "company_id": self.company.id,
+ "reconcile": True,
+ }
+ )
+ self.account_expense = self.env["account.account"].create(
+ {
+ "name": "test_account_expense",
+ "code": "expense",
+ "user_type_id": self.type_expense.id,
+ "company_id": self.company.id,
+ "reconcile": False,
+ }
+ )
+ self.account_revenue = self.env["account.account"].create(
+ {
+ "name": "test_account_revenue",
+ "code": "revenue",
+ "user_type_id": self.type_revenue.id,
+ "company_id": self.company.id,
+ "reconcile": False,
+ }
+ )
+ self.customer_commercial = self.env["res.partner"].create(
+ {
+ "name": "Customer commercial partner",
+ "property_account_receivable_id": self.account_recv.id,
+ "is_company": True,
+ }
+ )
+ self.customer = self.env["res.partner"].create(
+ {
+ "name": "Customer",
+ "property_account_receivable_id": self.account_recv.id,
+ "company_id": self.company.id,
+ "parent_id": self.customer_commercial.id,
+ }
+ )
+ self.vendor_commercial = self.env["res.partner"].create(
+ {
+ "name": "Vendor commercial partner",
+ "property_account_payable_id": self.account_payable.id,
+ "is_company": True,
+ }
+ )
+ self.vendor = self.env["res.partner"].create(
+ {
+ "name": "Vendor",
+ "property_account_payable_id": self.account_payable.id,
+ "company_id": self.company.id,
+ "parent_id": self.vendor_commercial.id,
+ }
+ )
+ self.payor = self.env["res.partner"].create(
+ {
+ "name": "Payor for customer",
+ "property_account_receivable_id": self.account_recv.id,
+ "company_id": self.company.id,
+ }
+ )
+ self.payee = self.env["res.partner"].create(
+ {
+ "name": "Payee for vendor",
+ "property_account_payable_id": self.account_payable_2.id,
+ "company_id": self.company.id,
+ }
+ )
+ self.payee_bank = self.env["res.partner.bank"].create(
+ {
+ "partner_id": self.payee.id,
+ "acc_number": "ES66 2100 0418 4012 3456 7891",
+ "company_id": self.company.id,
+ }
+ )
+ self.purchase_journal = self.env["account.journal"].create(
+ {
+ "name": "Purchase Journal - TST",
+ "code": "PJT",
+ "type": "purchase",
+ "company_id": self.company.id,
+ }
+ )
+ self.sale_journal = self.env["account.journal"].create(
+ {
+ "name": "Sale Journal - TST",
+ "code": "SJT",
+ "type": "sale",
+ "company_id": self.company.id,
+ }
+ )
+ self.bank_journal_usd = self.env["account.journal"].create(
+ {"name": "Bank US TEST", "type": "bank", "code": "BJT"}
+ )
+ self.product = self.env["product.product"].create(
+ {"type": "service", "name": "Sample product"}
+ )
+ self.invoice_line = self.env["account.invoice.line"].create(
+ {
+ "name": "test",
+ "account_id": self.account_expense.id,
+ "price_unit": 2000.00,
+ "quantity": 1,
+ "product_id": self.product.id,
+ }
+ )
# Instance: invoice
- self.vendor_invoice = self.env['account.invoice'].create({
- 'partner_id': self.vendor.id,
- 'type': 'in_invoice',
- 'account_id': self.account_payable.id,
- 'payment_term_id': False,
- 'journal_id': self.purchase_journal.id,
- 'company_id': self.company.id,
- 'currency_id': self.currency_usd_id,
- 'invoice_line_ids': [(4, self.invoice_line.id)]})
- invoice_line = self.env['account.invoice.line'].create({
- 'name': 'test',
- 'account_id': self.account_revenue.id,
- 'price_unit': 2000.00,
- 'quantity': 1,
- 'product_id': self.product.id})
+ self.vendor_invoice = self.env["account.invoice"].create(
+ {
+ "partner_id": self.vendor.id,
+ "type": "in_invoice",
+ "account_id": self.account_payable.id,
+ "payment_term_id": False,
+ "journal_id": self.purchase_journal.id,
+ "company_id": self.company.id,
+ "currency_id": self.currency_usd_id,
+ "invoice_line_ids": [(4, self.invoice_line.id)],
+ }
+ )
+ invoice_line = self.env["account.invoice.line"].create(
+ {
+ "name": "test",
+ "account_id": self.account_revenue.id,
+ "price_unit": 2000.00,
+ "quantity": 1,
+ "product_id": self.product.id,
+ }
+ )
# Instance: invoice
- self.customer_invoice = self.env['account.invoice'].create({
- 'partner_id': self.customer.id,
- 'type': 'out_invoice',
- 'account_id': self.account_recv.id,
- 'payment_term_id': False,
- 'journal_id': self.sale_journal.id,
- 'company_id': self.company.id,
- 'currency_id': self.currency_usd_id,
- 'invoice_line_ids': [(4, invoice_line.id)]})
+ self.customer_invoice = self.env["account.invoice"].create(
+ {
+ "partner_id": self.customer.id,
+ "type": "out_invoice",
+ "account_id": self.account_recv.id,
+ "payment_term_id": False,
+ "journal_id": self.sale_journal.id,
+ "company_id": self.company.id,
+ "currency_id": self.currency_usd_id,
+ "invoice_line_ids": [(4, invoice_line.id)],
+ }
+ )
def test_01_onchange(self):
# Instance: invoice
- supplier_invoice = self.env['account.invoice'].new({
- 'partner_id': self.vendor.id,
- 'type': 'in_invoice',
- 'account_id': self.account_payable.id,
- 'payment_term_id': False,
- 'journal_id': self.purchase_journal.id,
- 'currency_id': self.currency_usd_id,
- 'company_id': self.company.id,
- 'invoice_line_ids': [
- (0, 0, {'name': 'test',
- 'account_id': self.account_expense.id,
- 'price_unit': 2000.00,
- 'quantity': 1,
- 'product_id': self.product.id
- }
- )
- ]})
+ supplier_invoice = self.env["account.invoice"].new(
+ {
+ "partner_id": self.vendor.id,
+ "type": "in_invoice",
+ "account_id": self.account_payable.id,
+ "payment_term_id": False,
+ "journal_id": self.purchase_journal.id,
+ "currency_id": self.currency_usd_id,
+ "company_id": self.company.id,
+ "invoice_line_ids": [
+ (
+ 0,
+ 0,
+ {
+ "name": "test",
+ "account_id": self.account_expense.id,
+ "price_unit": 2000.00,
+ "quantity": 1,
+ "product_id": self.product.id,
+ },
+ )
+ ],
+ }
+ )
supplier_invoice.alternate_payer_id = self.payee
supplier_invoice._onchange_partner_id()
self.assertEqual(supplier_invoice.partner_bank_id, self.payee_bank)
@@ -174,63 +227,79 @@ def test_02_invoice(self):
self.customer_invoice.alternate_payer_id = self.payor.id
self.customer_invoice._onchange_partner_id()
self.customer_invoice.action_invoice_open()
- self.assertEqual(self.customer_invoice.state, 'open')
+ self.assertEqual(self.customer_invoice.state, "open")
line = self.customer_invoice.move_id.line_ids.filtered(
- lambda li: li.account_id == self.account_recv)
+ lambda li: li.account_id == self.account_recv
+ )
self.assertEqual(line.partner_id, self.payor)
- ctx = {'active_model': 'account.invoice',
- 'active_ids': [self.customer_invoice.id]}
- register_payments = self.register_payments_model.with_context(
- ctx).create({
- 'payment_date': fields.Date.today(),
- 'journal_id': self.bank_journal_usd.id,
- 'payment_method_id': self.env.ref(
- 'account.account_payment_method_manual_in').id,
- })
+ ctx = {
+ "active_model": "account.invoice",
+ "active_ids": [self.customer_invoice.id],
+ }
+ register_payments = self.register_payments_model.with_context(ctx).create(
+ {
+ "payment_date": fields.Date.today(),
+ "journal_id": self.bank_journal_usd.id,
+ "payment_method_id": self.env.ref(
+ "account.account_payment_method_manual_in"
+ ).id,
+ }
+ )
register_payments.create_payments()
- self.assertEqual(self.customer_invoice.state, 'paid')
+ self.assertEqual(self.customer_invoice.state, "paid")
# Vendor bills
self.vendor_invoice.alternate_payer_id = self.payee
self.vendor_invoice._onchange_partner_id()
self.vendor_invoice.action_invoice_open()
- self.assertEqual(self.vendor_invoice.state, 'open')
+ self.assertEqual(self.vendor_invoice.state, "open")
line = self.vendor_invoice.move_id.line_ids.filtered(
- lambda li: li.account_id == self.account_payable_2)
+ lambda li: li.account_id == self.account_payable_2
+ )
self.assertEqual(line.partner_id, self.payee)
- ctx = {'active_model': 'account.invoice',
- 'active_ids': [self.vendor_invoice.id]
- }
- register_payments = self.register_payments_model.with_context(
- ctx).create({
- 'payment_date': fields.Date.today(),
- 'journal_id': self.bank_journal_usd.id,
- 'payment_method_id': self.env.ref(
- 'account.account_payment_method_manual_out').id,
- })
+ ctx = {
+ "active_model": "account.invoice",
+ "active_ids": [self.vendor_invoice.id],
+ }
+ register_payments = self.register_payments_model.with_context(ctx).create(
+ {
+ "payment_date": fields.Date.today(),
+ "journal_id": self.bank_journal_usd.id,
+ "payment_method_id": self.env.ref(
+ "account.account_payment_method_manual_out"
+ ).id,
+ }
+ )
register_payments.create_payments()
- self.assertEqual(self.vendor_invoice.state, 'paid')
+ self.assertEqual(self.vendor_invoice.state, "paid")
def test_03_payment_multiple_invoices(self):
"""
Test selecting multiple invoices with different alternate payer
"""
- supplier_invoice_1 = self.env['account.invoice'].create({
- 'partner_id': self.customer.id,
- 'type': 'in_invoice',
- 'account_id': self.account_payable.id,
- 'payment_term_id': False,
- 'journal_id': self.purchase_journal.id,
- 'currency_id': self.currency_usd_id,
- 'company_id': self.company.id,
- 'invoice_line_ids': [
- (0, 0, {'name': 'test',
- 'account_id': self.account_expense.id,
- 'price_unit': 2000.00,
- 'quantity': 1,
- 'product_id': self.product.id
- }
- )
- ]})
+ supplier_invoice_1 = self.env["account.invoice"].create(
+ {
+ "partner_id": self.customer.id,
+ "type": "in_invoice",
+ "account_id": self.account_payable.id,
+ "payment_term_id": False,
+ "journal_id": self.purchase_journal.id,
+ "currency_id": self.currency_usd_id,
+ "company_id": self.company.id,
+ "invoice_line_ids": [
+ (
+ 0,
+ 0,
+ {
+ "name": "test",
+ "account_id": self.account_expense.id,
+ "price_unit": 2000.00,
+ "quantity": 1,
+ "product_id": self.product.id,
+ },
+ )
+ ],
+ }
+ )
supplier_invoice_2 = supplier_invoice_1.copy()
supplier_invoice_2.alternate_payer_id = self.payee
supplier_invoice_3 = supplier_invoice_1.copy()
@@ -240,40 +309,54 @@ def test_03_payment_multiple_invoices(self):
supplier_invoice_2.action_invoice_open()
supplier_invoice_3._onchange_partner_id()
supplier_invoice_3.action_invoice_open()
- ctx = {'active_model': 'account.invoice',
- 'active_ids': [supplier_invoice_1.id, supplier_invoice_2.id,
- supplier_invoice_3.id]}
- register_payments = self.register_payments_model.with_context(
- ctx).create({
- 'payment_date': fields.Date.today(),
- 'journal_id': self.bank_journal_usd.id,
- 'payment_method_id': self.env.ref(
- 'account.account_payment_method_manual_out').id,
- })
+ ctx = {
+ "active_model": "account.invoice",
+ "active_ids": [
+ supplier_invoice_1.id,
+ supplier_invoice_2.id,
+ supplier_invoice_3.id,
+ ],
+ }
+ register_payments = self.register_payments_model.with_context(ctx).create(
+ {
+ "payment_date": fields.Date.today(),
+ "journal_id": self.bank_journal_usd.id,
+ "payment_method_id": self.env.ref(
+ "account.account_payment_method_manual_out"
+ ).id,
+ }
+ )
res = register_payments.create_payments()
# ['domain'][('id', 'in', payments.ids), ('state', '=', 'posted')]
- self.assertEqual(len(res['domain'][0][2]), 2)
- self.assertEqual(supplier_invoice_1.state, 'paid')
- self.assertEqual(supplier_invoice_2.state, 'paid')
- self.assertEqual(supplier_invoice_3.state, 'paid')
+ self.assertEqual(len(res["domain"][0][2]), 2)
+ self.assertEqual(supplier_invoice_1.state, "paid")
+ self.assertEqual(supplier_invoice_2.state, "paid")
+ self.assertEqual(supplier_invoice_3.state, "paid")
def test_constrains(self):
with self.assertRaises(ValidationError):
- self.env['account.invoice'].create({
- 'partner_id': self.vendor.id,
- 'type': 'in_invoice',
- 'account_id': self.account_payable.id,
- 'payment_term_id': False,
- 'journal_id': self.purchase_journal.id,
- 'currency_id': self.currency_usd_id,
- 'company_id': self.company.id,
- 'partner_bank_id': self.payee_bank.id,
- 'invoice_line_ids': [
- (0, 0, {'name': 'test',
- 'account_id': self.account_expense.id,
- 'price_unit': 2000.00,
- 'quantity': 1,
- 'product_id': self.product.id
- }
- )
- ]})
+ self.env["account.invoice"].create(
+ {
+ "partner_id": self.vendor.id,
+ "type": "in_invoice",
+ "account_id": self.account_payable.id,
+ "payment_term_id": False,
+ "journal_id": self.purchase_journal.id,
+ "currency_id": self.currency_usd_id,
+ "company_id": self.company.id,
+ "partner_bank_id": self.payee_bank.id,
+ "invoice_line_ids": [
+ (
+ 0,
+ 0,
+ {
+ "name": "test",
+ "account_id": self.account_expense.id,
+ "price_unit": 2000.00,
+ "quantity": 1,
+ "product_id": self.product.id,
+ },
+ )
+ ],
+ }
+ )
diff --git a/account_invoice_alternate_payer/views/account_invoice_views.xml b/account_invoice_alternate_payer/views/account_invoice_views.xml
index 572fe2955211..5213c0359081 100644
--- a/account_invoice_alternate_payer/views/account_invoice_views.xml
+++ b/account_invoice_alternate_payer/views/account_invoice_views.xml
@@ -1,28 +1,25 @@
-
+
-
account.invoice.supplier.form
account.invoice
-
+
-
+
-
account.invoice.form
account.invoice
-
+
-
+
-
From 08af3e21b748e5b2fcd4c7b2b357dc92b52b9b3a Mon Sep 17 00:00:00 2001
From: Enric Tobella
Date: Mon, 21 Jun 2021 11:15:35 +0200
Subject: [PATCH 04/13] [MIG] account_invoice_alternate_payer: Migration to
13.0
---
account_invoice_alternate_payer/README.rst | 10 +-
.../__manifest__.py | 4 +-
.../i18n/account_invoice_alternate_payer.pot | 40 +-
.../migrations/13.0.1.0.0/post-migration.py | 32 ++
.../models/__init__.py | 2 +-
.../models/account_invoice.py | 100 ----
.../models/account_move.py | 120 ++++
.../models/account_payment.py | 49 +-
.../static/description/index.html | 6 +-
.../tests/test_account_invoice.py | 535 +++++++-----------
.../views/account_invoice_views.xml | 25 -
.../views/account_move_views.xml | 13 +
12 files changed, 431 insertions(+), 505 deletions(-)
create mode 100644 account_invoice_alternate_payer/migrations/13.0.1.0.0/post-migration.py
delete mode 100644 account_invoice_alternate_payer/models/account_invoice.py
create mode 100644 account_invoice_alternate_payer/models/account_move.py
delete mode 100644 account_invoice_alternate_payer/views/account_invoice_views.xml
create mode 100644 account_invoice_alternate_payer/views/account_move_views.xml
diff --git a/account_invoice_alternate_payer/README.rst b/account_invoice_alternate_payer/README.rst
index 4e67fdaf63bb..ec24af360412 100644
--- a/account_invoice_alternate_payer/README.rst
+++ b/account_invoice_alternate_payer/README.rst
@@ -14,13 +14,13 @@ Account Invoice Alternate Payer
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Faccount--invoicing-lightgray.png?logo=github
- :target: https://github.com/OCA/account-invoicing/tree/11.0/account_invoice_alternate_payer
+ :target: https://github.com/OCA/account-invoicing/tree/13.0/account_invoice_alternate_payer
:alt: OCA/account-invoicing
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
- :target: https://translation.odoo-community.org/projects/account-invoicing-11-0/account-invoicing-11-0-account_invoice_alternate_payer
+ :target: https://translation.odoo-community.org/projects/account-invoicing-13-0/account-invoicing-13-0-account_invoice_alternate_payer
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
- :target: https://runbot.odoo-community.org/runbot/95/11.0
+ :target: https://runbot.odoo-community.org/runbot/95/13.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
@@ -47,7 +47,7 @@ Bug Tracker
Bugs are tracked on `GitHub Issues `_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
-`feedback `_.
+`feedback `_.
Do not contact contributors directly about support or help with technical issues.
@@ -78,6 +78,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
-This module is part of the `OCA/account-invoicing `_ project on GitHub.
+This module is part of the `OCA/account-invoicing `_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/account_invoice_alternate_payer/__manifest__.py b/account_invoice_alternate_payer/__manifest__.py
index 1b84a8cd309d..36dd42394367 100644
--- a/account_invoice_alternate_payer/__manifest__.py
+++ b/account_invoice_alternate_payer/__manifest__.py
@@ -4,11 +4,11 @@
{
"name": "Account Invoice Alternate Payer",
"summary": "Set a alternate payor/payee in invoices",
- "version": "12.0.1.0.0",
+ "version": "13.0.1.0.0",
"license": "AGPL-3",
"category": "Accounting",
"author": "Eficent,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/account-invoicing/",
"depends": ["account"],
- "data": ["views/account_invoice_views.xml",],
+ "data": ["views/account_move_views.xml"],
}
diff --git a/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot b/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot
index 34c072a76a47..4cc3eae10200 100644
--- a/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot
+++ b/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot
@@ -1,12 +1,12 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
-# * account_invoice_alternate_payer
+# * account_invoice_alternate_payer
#
msgid ""
msgstr ""
-"Project-Id-Version: Odoo Server 11.0\n"
+"Project-Id-Version: Odoo Server 13.0\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: <>\n"
+"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -14,45 +14,45 @@ msgstr ""
"Plural-Forms: \n"
#. module: account_invoice_alternate_payer
-#: model:ir.ui.view,arch_db:account_invoice_alternate_payer.invoice_supplier_form
+#: model_terms:ir.ui.view,arch_db:account_invoice_alternate_payer.view_move_form
msgid "Alternate Payee"
msgstr ""
#. module: account_invoice_alternate_payer
-#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_invoice_alternate_payer_id
+#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move__alternate_payer_id
msgid "Alternate Payer"
msgstr ""
#. module: account_invoice_alternate_payer
-#: model:ir.ui.view,arch_db:account_invoice_alternate_payer.invoice_form
-msgid "Alternate Payor"
+#: model:ir.model.fields,help:account_invoice_alternate_payer.field_account_move__alternate_payer_id
+msgid ""
+"If set, this will be the partner that we expect to pay or to be paid by. If "
+"not set, the payor is by default the commercial"
msgstr ""
#. module: account_invoice_alternate_payer
-#: code:addons/account_invoice_alternate_payer/models/account_invoice.py:51
-#, python-format
-msgid "Cannot find a chart of accounts for this company, You should configure it. \n"
-"Please go to Account Configuration."
+#: model:ir.model,name:account_invoice_alternate_payer.model_account_move
+msgid "Journal Entries"
msgstr ""
#. module: account_invoice_alternate_payer
-#: code:addons/account_invoice_alternate_payer/models/account_invoice.py:56
+#: code:addons/account_invoice_alternate_payer/models/account_move.py:0
#, python-format
-msgid "Go to the configuration panel"
+msgid "Outstanding credits"
msgstr ""
#. module: account_invoice_alternate_payer
-#: model:ir.model.fields,help:account_invoice_alternate_payer.field_account_invoice_alternate_payer_id
-msgid "If set, this partner will be the that we expect to pay or to be paid by. If not set, the payor is by default the commercial"
+#: code:addons/account_invoice_alternate_payer/models/account_move.py:0
+#, python-format
+msgid "Outstanding debits"
msgstr ""
#. module: account_invoice_alternate_payer
-#: model:ir.model,name:account_invoice_alternate_payer.model_account_invoice
-msgid "Invoice"
+#: model:ir.model,name:account_invoice_alternate_payer.model_account_payment
+msgid "Payments"
msgstr ""
#. module: account_invoice_alternate_payer
-#: model:ir.model,name:account_invoice_alternate_payer.model_account_register_payments
-msgid "Register payments on multiple invoices"
+#: model:ir.model,name:account_invoice_alternate_payer.model_account_payment_register
+msgid "Register Payment"
msgstr ""
-
diff --git a/account_invoice_alternate_payer/migrations/13.0.1.0.0/post-migration.py b/account_invoice_alternate_payer/migrations/13.0.1.0.0/post-migration.py
new file mode 100644
index 000000000000..3cd7f21532be
--- /dev/null
+++ b/account_invoice_alternate_payer/migrations/13.0.1.0.0/post-migration.py
@@ -0,0 +1,32 @@
+from openupgradelib import openupgrade
+
+
+@openupgrade.migrate()
+def migrate(env, version):
+ openupgrade.logged_query(
+ env.cr,
+ """
+ UPDATE account_move am
+ SET alternate_payer_id = ai.alternate_payer_id
+ FROM account_invoice ai
+ WHERE ai.alternate_payer_id IS NOT NULL
+ AND ai.id = am.old_invoice_id
+ """,
+ )
+ openupgrade.logged_query(
+ env.cr,
+ """
+ UPDATE account_move_line aml
+ SET partner_id = am.alternate_payer_id
+ FROM
+ account_move am,
+ account_account as aa,
+ account_account_type as aat
+ WHERE am.alternate_payer_id IS NOT NULL
+ AND am.id = aml.move_id
+ AND am.state = 'draft'
+ AND aat.type in ('receivable', 'payable')
+ AND aa.id = aml.account_id
+ AND aat.id = aa.user_type_id
+ """,
+ )
diff --git a/account_invoice_alternate_payer/models/__init__.py b/account_invoice_alternate_payer/models/__init__.py
index 515ed99ce64c..11623d4e5329 100644
--- a/account_invoice_alternate_payer/models/__init__.py
+++ b/account_invoice_alternate_payer/models/__init__.py
@@ -1,2 +1,2 @@
-from . import account_invoice
+from . import account_move
from . import account_payment
diff --git a/account_invoice_alternate_payer/models/account_invoice.py b/account_invoice_alternate_payer/models/account_invoice.py
deleted file mode 100644
index db614136df64..000000000000
--- a/account_invoice_alternate_payer/models/account_invoice.py
+++ /dev/null
@@ -1,100 +0,0 @@
-# Copyright 2018 Eficent Business and IT Consulting Services, S.L.
-# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
-
-from odoo import _, api, fields, models
-from odoo.exceptions import RedirectWarning, ValidationError
-
-
-class AccountInvoice(models.Model):
-
- _inherit = "account.invoice"
-
- alternate_payer_id = fields.Many2one(
- "res.partner",
- string="Alternate Payer",
- readonly=True,
- states={"draft": [("readonly", False)]},
- help="If set, this partner will be the that we expect to pay or to "
- "be paid by. If not set, the payor is by default the "
- "commercial",
- )
-
- @api.model
- def line_get_convert(self, line, part):
- res = super(AccountInvoice, self).line_get_convert(line, part)
- if line.get("type", False) == "dest" and self.alternate_payer_id:
- res["partner_id"] = self.alternate_payer_id.id
- return res
-
- @api.onchange("partner_id", "company_id", "alternate_payer_id")
- def _onchange_partner_id(self):
- res = super(AccountInvoice, self)._onchange_partner_id()
- company_id = self.company_id.id
- domain = {}
- if self.type in ("in_invoice", "out_refund") and self.alternate_payer_id:
- bank_ids = self.alternate_payer_id.bank_ids.filtered(
- lambda b: b.company_id.id == company_id or not b.company_id
- )
- bank_id = bank_ids[0].id if bank_ids else False
- self.partner_bank_id = bank_id
- domain = {"partner_bank_id": [("id", "in", bank_ids.ids)]}
- if domain:
- res["domain"] = domain
- if self.alternate_payer_id:
- account_id = False
- payment_term_id = False
- p = (
- self.alternate_payer_id
- if not company_id
- else self.alternate_payer_id.with_context(force_company=company_id)
- )
- if p:
- rec_account = p.property_account_receivable_id
- pay_account = p.property_account_payable_id
- if not rec_account and not pay_account:
- action = self.env.ref("account.action_account_config")
- msg = _(
- "Cannot find a chart of accounts for this company, "
- "You should configure it. \nPlease go to Account "
- "Configuration."
- )
- raise RedirectWarning(
- msg, action.id, _("Go to the configuration panel")
- )
-
- if self.type in ("out_invoice", "out_refund"):
- account_id = rec_account.id
- payment_term_id = p.property_payment_term_id.id
- else:
- account_id = pay_account.id
- payment_term_id = p.property_supplier_payment_term_id.id
- self.account_id = account_id
- self.payment_term_id = payment_term_id
- return res
-
- @api.constrains("partner_id", "partner_bank_id")
- def validate_partner_bank_id(self):
- for record in self:
- if record.partner_bank_id:
- partner = record.alternate_payer_id or record.partner_id
- bank_partner = record.partner_bank_id.partner_id
- if (
- record.type in ("in_invoice", "out_refund")
- and bank_partner != partner.commercial_partner_id
- ):
- raise ValidationError(
- _(
- "Commercial partner and vendor account owners must "
- "be identical."
- )
- )
- elif (
- record.type in ("out_invoice", "in_refund")
- and record.company_id not in bank_partner.ref_company_ids
- ):
- raise ValidationError(
- _(
- "The account selected for payment does not belong to "
- "the same company as this invoice."
- )
- )
diff --git a/account_invoice_alternate_payer/models/account_move.py b/account_invoice_alternate_payer/models/account_move.py
new file mode 100644
index 000000000000..b52d8dd2c9f9
--- /dev/null
+++ b/account_invoice_alternate_payer/models/account_move.py
@@ -0,0 +1,120 @@
+# Copyright 2018 Eficent Business and IT Consulting Services, S.L.
+# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
+
+import json
+
+from odoo import _, api, fields, models
+from odoo.tools import float_is_zero
+
+
+class AccountMove(models.Model):
+
+ _inherit = "account.move"
+
+ alternate_payer_id = fields.Many2one(
+ "res.partner",
+ string="Alternate Payer",
+ readonly=True,
+ states={"draft": [("readonly", False)]},
+ help="If set, this will be the partner that we expect to pay or to "
+ "be paid by. If not set, the payor is by default the "
+ "commercial",
+ )
+
+ @api.depends("commercial_partner_id", "alternate_payer_id")
+ def _compute_bank_partner_id(self):
+ super(
+ AccountMove,
+ self.filtered(lambda r: not r.alternate_payer_id or not r.is_outbound()),
+ )._compute_bank_partner_id()
+ for move in self:
+ if move.is_outbound() and move.alternate_payer_id:
+ move.bank_partner_id = move.alternate_payer_id
+
+ @api.onchange("partner_id", "alternate_payer_id")
+ def _onchange_partner_id(self):
+ return super()._onchange_partner_id()
+
+ def _recompute_payment_terms_lines(self):
+ super()._recompute_payment_terms_lines()
+ for invoice in self:
+ if invoice.alternate_payer_id:
+ invoice.line_ids.filtered(
+ lambda r: r.account_id.user_type_id.type
+ in ("receivable", "payable")
+ ).update({"partner_id": invoice.alternate_payer_id.id})
+
+ def _compute_payments_widget_to_reconcile_info(self):
+ super(
+ AccountMove, self.filtered(lambda r: not r.alternate_payer_id)
+ )._compute_payments_widget_to_reconcile_info()
+ for move in self:
+ if not self.alternate_payer_id:
+ continue
+ move.invoice_outstanding_credits_debits_widget = json.dumps(False)
+ move.invoice_has_outstanding = False
+ if (
+ move.state != "posted"
+ or move.invoice_payment_state != "not_paid"
+ or not move.is_invoice(include_receipts=True)
+ ):
+ continue
+ pay_term_line_ids = move.line_ids.filtered(
+ lambda line: line.account_id.user_type_id.type
+ in ("receivable", "payable")
+ )
+
+ domain = [
+ ("account_id", "in", pay_term_line_ids.mapped("account_id").ids),
+ "|",
+ ("move_id.state", "=", "posted"),
+ "&",
+ ("move_id.state", "=", "draft"),
+ ("journal_id.post_at", "=", "bank_rec"),
+ ("partner_id", "=", move.alternate_payer_id.id),
+ ("reconciled", "=", False),
+ "|",
+ ("amount_residual", "!=", 0.0),
+ ("amount_residual_currency", "!=", 0.0),
+ ]
+
+ if move.is_inbound():
+ domain.extend([("credit", ">", 0), ("debit", "=", 0)])
+ type_payment = _("Outstanding credits")
+ else:
+ domain.extend([("credit", "=", 0), ("debit", ">", 0)])
+ type_payment = _("Outstanding debits")
+ info = {"title": "", "outstanding": True, "content": [], "move_id": move.id}
+ lines = self.env["account.move.line"].search(domain)
+ currency_id = move.currency_id
+ if len(lines) != 0:
+ for line in lines:
+ # get the outstanding residual value in invoice currency
+ if line.currency_id and line.currency_id == move.currency_id:
+ amount_to_show = abs(line.amount_residual_currency)
+ else:
+ currency = line.company_id.currency_id
+ amount_to_show = currency._convert(
+ abs(line.amount_residual),
+ move.currency_id,
+ move.company_id,
+ line.date or fields.Date.today(),
+ )
+ if float_is_zero(
+ amount_to_show, precision_rounding=move.currency_id.rounding
+ ):
+ continue
+ info["content"].append(
+ {
+ "journal_name": line.ref or line.move_id.name,
+ "amount": amount_to_show,
+ "currency": currency_id.symbol,
+ "id": line.id,
+ "position": currency_id.position,
+ "digits": [69, move.currency_id.decimal_places],
+ "payment_date": fields.Date.to_string(line.date),
+ }
+ )
+ info["title"] = type_payment
+ move.invoice_outstanding_credits_debits_widget = json.dumps(info)
+ move.invoice_has_outstanding = True
diff --git a/account_invoice_alternate_payer/models/account_payment.py b/account_invoice_alternate_payer/models/account_payment.py
index 2726ff847b54..0be5cdcbde30 100644
--- a/account_invoice_alternate_payer/models/account_payment.py
+++ b/account_invoice_alternate_payer/models/account_payment.py
@@ -3,48 +3,31 @@
from odoo import api, models
-from odoo.addons.account.models.account_payment import MAP_INVOICE_TYPE_PARTNER_TYPE
-
-class AccountRegisterPayments(models.TransientModel):
- _inherit = "account.register.payments"
+class AccountPayment(models.Model):
+ _inherit = "account.payment"
@api.model
- def default_get(self, fields):
- rec = super(AccountRegisterPayments, self).default_get(fields)
+ def default_get(self, default_fields):
+ rec = super().default_get(default_fields)
+ if self.env.context.get("active_model") != "account.move":
+ return rec
active_ids = self._context.get("active_ids")
- invoices = self.env["account.invoice"].browse(active_ids)
-
- # Look if we are mixin multiple alternate_payer or
- # customer invoices with vendor bills
- payer = invoices[0].alternate_payer_id or invoices[0].commercial_partner_id
- multi = any(
- inv.alternate_payer_id or inv.commercial_partner_id != payer
- for inv in invoices
- )
- payer_id = (
- invoices[0].alternate_payer_id.id or invoices[0].commercial_partner_id.id
+ invoices = (
+ self.env["account.move"]
+ .browse(active_ids)
+ .filtered(lambda move: move.is_invoice(include_receipts=True))
)
- rec["partner_id"] = False if multi else payer_id
- rec["multi"] = multi
+ if invoices and invoices[0].alternate_payer_id:
+ rec.update({"partner_id": invoices[0].alternate_payer_id.id})
return rec
- @api.multi
- def _groupby_invoices(self):
- # We have to re-group because the old groups are not valid anymore
- super(AccountRegisterPayments, self)._groupby_invoices()
- results = {}
- for inv in self.invoice_ids:
- payer = inv.alternate_payer_id.id or inv.commercial_partner_id.id
- key = (payer, MAP_INVOICE_TYPE_PARTNER_TYPE[inv.type])
- if key not in results:
- results[key] = self.env["account.invoice"]
- results[key] += inv
- return results
- @api.multi
+class AccountPaymentRegister(models.TransientModel):
+ _inherit = "account.payment.register"
+
def _prepare_payment_vals(self, invoices):
- res = super(AccountRegisterPayments, self)._prepare_payment_vals(invoices)
+ res = super()._prepare_payment_vals(invoices)
payer_id = (
invoices[0].alternate_payer_id.id or invoices[0].commercial_partner_id.id
)
diff --git a/account_invoice_alternate_payer/static/description/index.html b/account_invoice_alternate_payer/static/description/index.html
index 0cdab016b9ee..ffa32435c024 100644
--- a/account_invoice_alternate_payer/static/description/index.html
+++ b/account_invoice_alternate_payer/static/description/index.html
@@ -367,7 +367,7 @@ Account Invoice Alternate Payer
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
-
+
This module allows to enter an alternative payer in the
customer invoice or vendor bill.
This allows, that we pay or expect to get paid by another partner other
@@ -394,7 +394,7 @@
Bugs are tracked on GitHub Issues.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
-feedback.
+feedback.
Do not contact contributors directly about support or help with technical issues.
@@ -425,7 +425,7 @@
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
-
This module is part of the OCA/account-invoicing project on GitHub.
+
This module is part of the OCA/account-invoicing project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/account_invoice_alternate_payer/tests/test_account_invoice.py b/account_invoice_alternate_payer/tests/test_account_invoice.py
index 6dfa242c4836..119db82de8e4 100644
--- a/account_invoice_alternate_payer/tests/test_account_invoice.py
+++ b/account_invoice_alternate_payer/tests/test_account_invoice.py
@@ -1,362 +1,265 @@
# Copyright 2018 Eficent Business and IT Consulting Services, S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
-from odoo import fields
-from odoo.exceptions import ValidationError
-from odoo.tests.common import TransactionCase
+from odoo.tests import Form
+from odoo.addons.account.tests.account_test_savepoint import AccountTestInvoicingCommon
-class TestAccountInvoiceAlternateCommercialPartner(TransactionCase):
- def setUp(self):
- """
- Setup test instances
- """
- super(TestAccountInvoiceAlternateCommercialPartner, self).setUp()
- self.company = self.env.ref("base.main_company")
- self.currency_usd_id = self.env.ref("base.USD").id
- # Instance: account type (receivable)
- self.type_recv = self.env.ref("account.data_account_type_receivable")
- # Instance: account type (payable)
- self.type_payable = self.env.ref("account.data_account_type_payable")
- # Instance: account type (expense)
- self.type_expense = self.env.ref("account.data_account_type_expenses")
- # Instance: account type (revenue)
- self.type_revenue = self.env.ref("account.data_account_type_revenue")
- self.register_payments_model = self.env["account.register.payments"]
- # account (receivable)
- self.account_recv = self.env["account.account"].create(
- {
- "name": "test_account_receivable",
- "code": "123",
- "user_type_id": self.type_recv.id,
- "company_id": self.company.id,
- "reconcile": True,
- }
+
+class TestAccountInvoiceAlternateCommercialPartner(AccountTestInvoicingCommon):
+ @classmethod
+ def setUpClass(cls, chart_template_ref=None):
+ super().setUpClass(chart_template_ref=chart_template_ref)
+ cls.in_invoice = cls.init_invoice("in_invoice")
+ cls.out_invoice = cls.init_invoice("out_invoice")
+ cls.in_invoice_02 = cls.init_invoice("in_invoice")
+ cls.out_invoice_02 = cls.init_invoice("out_invoice")
+ cls.alternate_partner = cls.env["res.partner"].create(
+ {"name": "Alternate Payer"}
)
- # account (payable)
- self.account_payable = self.env["account.account"].create(
- {
- "name": "test_account_payable",
- "code": "321",
- "user_type_id": self.type_payable.id,
- "company_id": self.company.id,
- "reconcile": True,
- }
+ cls.payment_method_manual_out = cls.env.ref(
+ "account.account_payment_method_manual_out"
)
- self.account_payable_2 = self.env["account.account"].create(
- {
- "name": "test_account_payable",
- "code": "3211",
- "user_type_id": self.type_payable.id,
- "company_id": self.company.id,
- "reconcile": True,
- }
+ cls.payment_method_manual_in = cls.env.ref(
+ "account.account_payment_method_manual_in"
)
- self.account_expense = self.env["account.account"].create(
- {
- "name": "test_account_expense",
- "code": "expense",
- "user_type_id": self.type_expense.id,
- "company_id": self.company.id,
- "reconcile": False,
- }
+ cls.bank_journal_euro = cls.env["account.journal"].create(
+ {"name": "Bank", "type": "bank", "code": "BNK67"}
)
- self.account_revenue = self.env["account.account"].create(
+ cls.bank_account = cls.env["account.account"].create(
{
- "name": "test_account_revenue",
- "code": "revenue",
- "user_type_id": self.type_revenue.id,
- "company_id": self.company.id,
- "reconcile": False,
+ "name": "Demo Bank account",
+ "code": "demo_bank_account",
+ "user_type_id": cls.env.ref("account.data_account_type_liquidity").id,
}
)
- self.customer_commercial = self.env["res.partner"].create(
- {
- "name": "Customer commercial partner",
- "property_account_receivable_id": self.account_recv.id,
- "is_company": True,
- }
- )
- self.customer = self.env["res.partner"].create(
- {
- "name": "Customer",
- "property_account_receivable_id": self.account_recv.id,
- "company_id": self.company.id,
- "parent_id": self.customer_commercial.id,
- }
+
+ def test_01_onchange_out_invoice(self):
+ with Form(self.out_invoice) as form:
+ form.alternate_payer_id = self.alternate_partner
+ self.assertEqual(
+ self.out_invoice.line_ids.filtered(
+ lambda r: r.account_id.user_type_id.type in ("receivable", "payable")
+ ).mapped("partner_id"),
+ self.alternate_partner,
)
- self.vendor_commercial = self.env["res.partner"].create(
- {
- "name": "Vendor commercial partner",
- "property_account_payable_id": self.account_payable.id,
- "is_company": True,
- }
+ self.assertEqual(
+ self.out_invoice.line_ids.filtered(
+ lambda r: r.account_id.user_type_id.type
+ not in ("receivable", "payable")
+ ).mapped("partner_id"),
+ self.out_invoice.partner_id,
)
- self.vendor = self.env["res.partner"].create(
- {
- "name": "Vendor",
- "property_account_payable_id": self.account_payable.id,
- "company_id": self.company.id,
- "parent_id": self.vendor_commercial.id,
- }
+ self.assertEqual(
+ self.out_invoice.bank_partner_id, self.out_invoice.company_id.partner_id
)
- self.payor = self.env["res.partner"].create(
- {
- "name": "Payor for customer",
- "property_account_receivable_id": self.account_recv.id,
- "company_id": self.company.id,
- }
- )
- self.payee = self.env["res.partner"].create(
- {
- "name": "Payee for vendor",
- "property_account_payable_id": self.account_payable_2.id,
- "company_id": self.company.id,
- }
+
+ def test_02_onchange_in_invoice(self):
+ with Form(self.in_invoice) as form:
+ form.alternate_payer_id = self.alternate_partner
+ self.assertEqual(
+ self.in_invoice.line_ids.filtered(
+ lambda r: r.account_id.user_type_id.type in ("receivable", "payable")
+ ).mapped("partner_id"),
+ self.alternate_partner,
)
- self.payee_bank = self.env["res.partner.bank"].create(
- {
- "partner_id": self.payee.id,
- "acc_number": "ES66 2100 0418 4012 3456 7891",
- "company_id": self.company.id,
- }
+ self.assertEqual(
+ self.in_invoice.line_ids.filtered(
+ lambda r: r.account_id.user_type_id.type
+ not in ("receivable", "payable")
+ ).mapped("partner_id"),
+ self.out_invoice.partner_id,
)
- self.purchase_journal = self.env["account.journal"].create(
- {
- "name": "Purchase Journal - TST",
- "code": "PJT",
- "type": "purchase",
- "company_id": self.company.id,
- }
+ self.assertEqual(self.in_invoice.bank_partner_id, self.alternate_partner)
+
+ def test_03_payment_out_invoice(self):
+ with Form(self.out_invoice) as form:
+ form.alternate_payer_id = self.alternate_partner
+ self.out_invoice.post()
+ records = self.out_invoice
+ action = (
+ self.env["account.payment"]
+ .with_context(active_model=records._name, active_ids=records.ids)
+ .action_register_payment()
)
- self.sale_journal = self.env["account.journal"].create(
- {
- "name": "Sale Journal - TST",
- "code": "SJT",
- "type": "sale",
- "company_id": self.company.id,
- }
+ payment = (
+ self.env[action["res_model"]]
+ .with_context(action["context"])
+ .create(
+ {
+ "payment_method_id": self.payment_method_manual_out.id,
+ "journal_id": self.bank_journal_euro.id,
+ }
+ )
)
- self.bank_journal_usd = self.env["account.journal"].create(
- {"name": "Bank US TEST", "type": "bank", "code": "BJT"}
+ payment.post()
+ self.assertEqual(payment.partner_id, self.alternate_partner)
+
+ def test_04_payment_in_invoice(self):
+ with Form(self.in_invoice) as form:
+ form.alternate_payer_id = self.alternate_partner
+ self.in_invoice.post()
+ records = self.in_invoice
+ action = (
+ self.env["account.payment"]
+ .with_context(active_model=records._name, active_ids=records.ids)
+ .action_register_payment()
)
- self.product = self.env["product.product"].create(
- {"type": "service", "name": "Sample product"}
+ payment = (
+ self.env[action["res_model"]]
+ .with_context(action["context"])
+ .create(
+ {
+ "payment_method_id": self.payment_method_manual_in.id,
+ "journal_id": self.bank_journal_euro.id,
+ }
+ )
)
- self.invoice_line = self.env["account.invoice.line"].create(
- {
- "name": "test",
- "account_id": self.account_expense.id,
- "price_unit": 2000.00,
- "quantity": 1,
- "product_id": self.product.id,
- }
+ payment.post()
+ self.assertEqual(payment.partner_id, self.alternate_partner)
+
+ def test_05_payment_out_invoices(self):
+ with Form(self.out_invoice) as form:
+ form.alternate_payer_id = self.alternate_partner
+ self.out_invoice.post()
+ with Form(self.out_invoice_02) as form:
+ form.alternate_payer_id = self.alternate_partner
+ self.out_invoice_02.post()
+ records = self.out_invoice | self.out_invoice_02
+ action = (
+ self.env["account.payment"]
+ .with_context(active_model=records._name, active_ids=records.ids)
+ .action_register_payment()
)
- # Instance: invoice
- self.vendor_invoice = self.env["account.invoice"].create(
- {
- "partner_id": self.vendor.id,
- "type": "in_invoice",
- "account_id": self.account_payable.id,
- "payment_term_id": False,
- "journal_id": self.purchase_journal.id,
- "company_id": self.company.id,
- "currency_id": self.currency_usd_id,
- "invoice_line_ids": [(4, self.invoice_line.id)],
- }
+ action = (
+ self.env[action["res_model"]]
+ .with_context(action["context"])
+ .create(
+ {
+ "payment_method_id": self.payment_method_manual_out.id,
+ "journal_id": self.bank_journal_euro.id,
+ }
+ )
+ .create_payments()
)
- invoice_line = self.env["account.invoice.line"].create(
- {
- "name": "test",
- "account_id": self.account_revenue.id,
- "price_unit": 2000.00,
- "quantity": 1,
- "product_id": self.product.id,
- }
+ payments = self.env[action["res_model"]]
+ if action.get("res_ids", False):
+ payments = payments.browse(action["res_id"])
+ else:
+ payments = payments.search(action["domain"])
+ for payment in payments:
+ self.assertEqual(payment.partner_id, self.alternate_partner)
+
+ def test_06_payment_in_invoices(self):
+ with Form(self.in_invoice) as form:
+ form.alternate_payer_id = self.alternate_partner
+ self.in_invoice.post()
+ with Form(self.in_invoice_02) as form:
+ form.alternate_payer_id = self.alternate_partner
+ self.in_invoice_02.post()
+ records = self.in_invoice | self.in_invoice_02
+ action = (
+ self.env["account.payment"]
+ .with_context(active_model=records._name, active_ids=records.ids)
+ .action_register_payment()
)
- # Instance: invoice
- self.customer_invoice = self.env["account.invoice"].create(
- {
- "partner_id": self.customer.id,
- "type": "out_invoice",
- "account_id": self.account_recv.id,
- "payment_term_id": False,
- "journal_id": self.sale_journal.id,
- "company_id": self.company.id,
- "currency_id": self.currency_usd_id,
- "invoice_line_ids": [(4, invoice_line.id)],
- }
+ action = (
+ self.env[action["res_model"]]
+ .with_context(action["context"])
+ .create(
+ {
+ "payment_method_id": self.payment_method_manual_out.id,
+ "journal_id": self.bank_journal_euro.id,
+ }
+ )
+ .create_payments()
)
+ payments = self.env[action["res_model"]]
+ if action.get("res_ids", False):
+ payments = payments.browse(action["res_id"])
+ else:
+ payments = payments.search(action["domain"])
+ for payment in payments:
+ self.assertEqual(payment.partner_id, self.alternate_partner)
- def test_01_onchange(self):
- # Instance: invoice
- supplier_invoice = self.env["account.invoice"].new(
+ def test_07_payment_widget_in_invoices(self):
+ with Form(self.in_invoice) as form:
+ form.alternate_payer_id = self.alternate_partner
+ line = self.in_invoice.line_ids.filtered(
+ lambda r: r.account_id.user_type_id.type in ("receivable", "payable")
+ )
+ payment_move = self.env["account.move"].create(
{
- "partner_id": self.vendor.id,
- "type": "in_invoice",
- "account_id": self.account_payable.id,
- "payment_term_id": False,
- "journal_id": self.purchase_journal.id,
- "currency_id": self.currency_usd_id,
- "company_id": self.company.id,
- "invoice_line_ids": [
+ "journal_id": self.bank_journal_euro.id,
+ "line_ids": [
+ (
+ 0,
+ 0,
+ {
+ "account_id": line.account_id.id,
+ "partner_id": line.partner_id.id,
+ "debit": line.credit,
+ "credit": line.debit,
+ },
+ ),
(
0,
0,
{
- "name": "test",
- "account_id": self.account_expense.id,
- "price_unit": 2000.00,
- "quantity": 1,
- "product_id": self.product.id,
+ "account_id": self.bank_account.id,
+ "debit": line.debit,
+ "credit": line.credit,
},
- )
+ ),
],
}
)
- supplier_invoice.alternate_payer_id = self.payee
- supplier_invoice._onchange_partner_id()
- self.assertEqual(supplier_invoice.partner_bank_id, self.payee_bank)
- self.assertEqual(supplier_invoice.account_id, self.account_payable_2)
+ payment_move.action_post()
+ self.assertFalse(self.in_invoice.invoice_has_outstanding)
+ self.in_invoice.post()
+ self.in_invoice.refresh()
+ self.assertTrue(self.in_invoice.invoice_has_outstanding)
+ self.in_invoice.write({"invoice_payment_state": "paid"})
+ self.in_invoice.refresh()
+ self.assertFalse(self.in_invoice.invoice_has_outstanding)
- def test_02_invoice(self):
- """
- Test Setting an alternate commercial partner
- """
- # Customer invoices
- self.customer_invoice.alternate_payer_id = self.payor.id
- self.customer_invoice._onchange_partner_id()
- self.customer_invoice.action_invoice_open()
- self.assertEqual(self.customer_invoice.state, "open")
- line = self.customer_invoice.move_id.line_ids.filtered(
- lambda li: li.account_id == self.account_recv
+ def test_08_payment_widget_out_invoices(self):
+ with Form(self.out_invoice) as form:
+ form.alternate_payer_id = self.alternate_partner
+ line = self.out_invoice.line_ids.filtered(
+ lambda r: r.account_id.user_type_id.type in ("receivable", "payable")
)
- self.assertEqual(line.partner_id, self.payor)
- ctx = {
- "active_model": "account.invoice",
- "active_ids": [self.customer_invoice.id],
- }
- register_payments = self.register_payments_model.with_context(ctx).create(
+ payment_move = self.env["account.move"].create(
{
- "payment_date": fields.Date.today(),
- "journal_id": self.bank_journal_usd.id,
- "payment_method_id": self.env.ref(
- "account.account_payment_method_manual_in"
- ).id,
- }
- )
- register_payments.create_payments()
- self.assertEqual(self.customer_invoice.state, "paid")
- # Vendor bills
- self.vendor_invoice.alternate_payer_id = self.payee
- self.vendor_invoice._onchange_partner_id()
- self.vendor_invoice.action_invoice_open()
- self.assertEqual(self.vendor_invoice.state, "open")
- line = self.vendor_invoice.move_id.line_ids.filtered(
- lambda li: li.account_id == self.account_payable_2
- )
- self.assertEqual(line.partner_id, self.payee)
- ctx = {
- "active_model": "account.invoice",
- "active_ids": [self.vendor_invoice.id],
- }
- register_payments = self.register_payments_model.with_context(ctx).create(
- {
- "payment_date": fields.Date.today(),
- "journal_id": self.bank_journal_usd.id,
- "payment_method_id": self.env.ref(
- "account.account_payment_method_manual_out"
- ).id,
- }
- )
- register_payments.create_payments()
- self.assertEqual(self.vendor_invoice.state, "paid")
-
- def test_03_payment_multiple_invoices(self):
- """
- Test selecting multiple invoices with different alternate payer
- """
- supplier_invoice_1 = self.env["account.invoice"].create(
- {
- "partner_id": self.customer.id,
- "type": "in_invoice",
- "account_id": self.account_payable.id,
- "payment_term_id": False,
- "journal_id": self.purchase_journal.id,
- "currency_id": self.currency_usd_id,
- "company_id": self.company.id,
- "invoice_line_ids": [
+ "journal_id": self.bank_journal_euro.id,
+ "line_ids": [
+ (
+ 0,
+ 0,
+ {
+ "account_id": line.account_id.id,
+ "partner_id": line.partner_id.id,
+ "debit": line.credit,
+ "credit": line.debit,
+ },
+ ),
(
0,
0,
{
- "name": "test",
- "account_id": self.account_expense.id,
- "price_unit": 2000.00,
- "quantity": 1,
- "product_id": self.product.id,
+ "account_id": self.bank_account.id,
+ "debit": line.debit,
+ "credit": line.credit,
},
- )
+ ),
],
}
)
- supplier_invoice_2 = supplier_invoice_1.copy()
- supplier_invoice_2.alternate_payer_id = self.payee
- supplier_invoice_3 = supplier_invoice_1.copy()
- supplier_invoice_1._onchange_partner_id()
- supplier_invoice_1.action_invoice_open()
- supplier_invoice_2._onchange_partner_id()
- supplier_invoice_2.action_invoice_open()
- supplier_invoice_3._onchange_partner_id()
- supplier_invoice_3.action_invoice_open()
- ctx = {
- "active_model": "account.invoice",
- "active_ids": [
- supplier_invoice_1.id,
- supplier_invoice_2.id,
- supplier_invoice_3.id,
- ],
- }
- register_payments = self.register_payments_model.with_context(ctx).create(
- {
- "payment_date": fields.Date.today(),
- "journal_id": self.bank_journal_usd.id,
- "payment_method_id": self.env.ref(
- "account.account_payment_method_manual_out"
- ).id,
- }
- )
- res = register_payments.create_payments()
- # ['domain'][('id', 'in', payments.ids), ('state', '=', 'posted')]
- self.assertEqual(len(res["domain"][0][2]), 2)
- self.assertEqual(supplier_invoice_1.state, "paid")
- self.assertEqual(supplier_invoice_2.state, "paid")
- self.assertEqual(supplier_invoice_3.state, "paid")
-
- def test_constrains(self):
- with self.assertRaises(ValidationError):
- self.env["account.invoice"].create(
- {
- "partner_id": self.vendor.id,
- "type": "in_invoice",
- "account_id": self.account_payable.id,
- "payment_term_id": False,
- "journal_id": self.purchase_journal.id,
- "currency_id": self.currency_usd_id,
- "company_id": self.company.id,
- "partner_bank_id": self.payee_bank.id,
- "invoice_line_ids": [
- (
- 0,
- 0,
- {
- "name": "test",
- "account_id": self.account_expense.id,
- "price_unit": 2000.00,
- "quantity": 1,
- "product_id": self.product.id,
- },
- )
- ],
- }
- )
+ payment_move.action_post()
+ self.assertFalse(self.out_invoice.invoice_has_outstanding)
+ self.out_invoice.post()
+ self.out_invoice.refresh()
+ self.assertTrue(self.out_invoice.invoice_has_outstanding)
+ self.out_invoice.write({"invoice_payment_state": "paid"})
+ self.out_invoice.refresh()
+ self.assertFalse(self.out_invoice.invoice_has_outstanding)
diff --git a/account_invoice_alternate_payer/views/account_invoice_views.xml b/account_invoice_alternate_payer/views/account_invoice_views.xml
deleted file mode 100644
index 5213c0359081..000000000000
--- a/account_invoice_alternate_payer/views/account_invoice_views.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
- account.invoice.supplier.form
- account.invoice
-
-
-
-
-
-
-
-
- account.invoice.form
- account.invoice
-
-
-
-
-
-
-
-
-
diff --git a/account_invoice_alternate_payer/views/account_move_views.xml b/account_invoice_alternate_payer/views/account_move_views.xml
new file mode 100644
index 000000000000..58c0e0368e83
--- /dev/null
+++ b/account_invoice_alternate_payer/views/account_move_views.xml
@@ -0,0 +1,13 @@
+
+
+
+ account.move.supplier.form
+ account.move
+
+
+
+
+
+
+
+
From cbad9a06c34019338b6826654e26eb57fc395e49 Mon Sep 17 00:00:00 2001
From: Olga Marco
Date: Mon, 24 Jan 2022 13:06:47 +0100
Subject: [PATCH 05/13] [IMP] account_invoice_alternate_payer: black, isort,
prettier
---
account_invoice_alternate_payer/__manifest__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/account_invoice_alternate_payer/__manifest__.py b/account_invoice_alternate_payer/__manifest__.py
index 36dd42394367..baf7edd632f2 100644
--- a/account_invoice_alternate_payer/__manifest__.py
+++ b/account_invoice_alternate_payer/__manifest__.py
@@ -8,7 +8,7 @@
"license": "AGPL-3",
"category": "Accounting",
"author": "Eficent,Odoo Community Association (OCA)",
- "website": "https://github.com/OCA/account-invoicing/",
+ "website": "https://github.com/OCA/account-invoicing",
"depends": ["account"],
"data": ["views/account_move_views.xml"],
}
From fd8fe003159b2c7cf52a2d2d64e51d082ebbe8d1 Mon Sep 17 00:00:00 2001
From: Olga Marco
Date: Mon, 24 Jan 2022 13:09:08 +0100
Subject: [PATCH 06/13] [MIG] account_invoice_alternate_payer: Migration to
14.0
---
.../__manifest__.py | 2 +-
.../models/account_move.py | 9 +-
.../tests/test_account_invoice.py | 87 +++++++------------
.../views/account_move_views.xml | 2 +-
4 files changed, 35 insertions(+), 65 deletions(-)
diff --git a/account_invoice_alternate_payer/__manifest__.py b/account_invoice_alternate_payer/__manifest__.py
index baf7edd632f2..774c768f58d1 100644
--- a/account_invoice_alternate_payer/__manifest__.py
+++ b/account_invoice_alternate_payer/__manifest__.py
@@ -4,7 +4,7 @@
{
"name": "Account Invoice Alternate Payer",
"summary": "Set a alternate payor/payee in invoices",
- "version": "13.0.1.0.0",
+ "version": "14.0.1.0.0",
"license": "AGPL-3",
"category": "Accounting",
"author": "Eficent,Odoo Community Association (OCA)",
diff --git a/account_invoice_alternate_payer/models/account_move.py b/account_invoice_alternate_payer/models/account_move.py
index b52d8dd2c9f9..8cf1c724d534 100644
--- a/account_invoice_alternate_payer/models/account_move.py
+++ b/account_invoice_alternate_payer/models/account_move.py
@@ -31,9 +31,9 @@ def _compute_bank_partner_id(self):
if move.is_outbound() and move.alternate_payer_id:
move.bank_partner_id = move.alternate_payer_id
- @api.onchange("partner_id", "alternate_payer_id")
- def _onchange_partner_id(self):
- return super()._onchange_partner_id()
+ @api.onchange("alternate_payer_id")
+ def _onchange_alternate_payer_id(self):
+ return self._onchange_partner_id()
def _recompute_payment_terms_lines(self):
super()._recompute_payment_terms_lines()
@@ -55,7 +55,7 @@ def _compute_payments_widget_to_reconcile_info(self):
move.invoice_has_outstanding = False
if (
move.state != "posted"
- or move.invoice_payment_state != "not_paid"
+ or move.payment_state != "not_paid"
or not move.is_invoice(include_receipts=True)
):
continue
@@ -70,7 +70,6 @@ def _compute_payments_widget_to_reconcile_info(self):
("move_id.state", "=", "posted"),
"&",
("move_id.state", "=", "draft"),
- ("journal_id.post_at", "=", "bank_rec"),
("partner_id", "=", move.alternate_payer_id.id),
("reconciled", "=", False),
"|",
diff --git a/account_invoice_alternate_payer/tests/test_account_invoice.py b/account_invoice_alternate_payer/tests/test_account_invoice.py
index 119db82de8e4..c2630426d84c 100644
--- a/account_invoice_alternate_payer/tests/test_account_invoice.py
+++ b/account_invoice_alternate_payer/tests/test_account_invoice.py
@@ -1,19 +1,20 @@
# Copyright 2018 Eficent Business and IT Consulting Services, S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
-from odoo.tests import Form
+from odoo.tests import Form, tagged
-from odoo.addons.account.tests.account_test_savepoint import AccountTestInvoicingCommon
+from odoo.addons.account.tests.common import AccountTestInvoicingCommon
+@tagged("post_install", "-at_install")
class TestAccountInvoiceAlternateCommercialPartner(AccountTestInvoicingCommon):
@classmethod
def setUpClass(cls, chart_template_ref=None):
super().setUpClass(chart_template_ref=chart_template_ref)
- cls.in_invoice = cls.init_invoice("in_invoice")
- cls.out_invoice = cls.init_invoice("out_invoice")
- cls.in_invoice_02 = cls.init_invoice("in_invoice")
- cls.out_invoice_02 = cls.init_invoice("out_invoice")
+ cls.in_invoice = cls.init_invoice("in_invoice", products=cls.product_b)
+ cls.out_invoice = cls.init_invoice("out_invoice", products=cls.product_a)
+ cls.in_invoice_02 = cls.init_invoice("in_invoice", products=cls.product_a)
+ cls.out_invoice_02 = cls.init_invoice("out_invoice", products=cls.product_b)
cls.alternate_partner = cls.env["res.partner"].create(
{"name": "Alternate Payer"}
)
@@ -75,16 +76,12 @@ def test_02_onchange_in_invoice(self):
def test_03_payment_out_invoice(self):
with Form(self.out_invoice) as form:
form.alternate_payer_id = self.alternate_partner
- self.out_invoice.post()
+ self.out_invoice._post()
records = self.out_invoice
- action = (
- self.env["account.payment"]
- .with_context(active_model=records._name, active_ids=records.ids)
- .action_register_payment()
- )
+ ctx = {"active_model": records._name, "active_ids": records.ids}
payment = (
- self.env[action["res_model"]]
- .with_context(action["context"])
+ self.env["account.payment"]
+ .with_context(ctx)
.create(
{
"payment_method_id": self.payment_method_manual_out.id,
@@ -92,22 +89,17 @@ def test_03_payment_out_invoice(self):
}
)
)
- payment.post()
self.assertEqual(payment.partner_id, self.alternate_partner)
def test_04_payment_in_invoice(self):
with Form(self.in_invoice) as form:
form.alternate_payer_id = self.alternate_partner
- self.in_invoice.post()
+ self.in_invoice._post()
records = self.in_invoice
- action = (
- self.env["account.payment"]
- .with_context(active_model=records._name, active_ids=records.ids)
- .action_register_payment()
- )
+ ctx = {"active_model": records._name, "active_ids": records.ids}
payment = (
- self.env[action["res_model"]]
- .with_context(action["context"])
+ self.env["account.payment"]
+ .with_context(ctx)
.create(
{
"payment_method_id": self.payment_method_manual_in.id,
@@ -115,70 +107,49 @@ def test_04_payment_in_invoice(self):
}
)
)
- payment.post()
self.assertEqual(payment.partner_id, self.alternate_partner)
def test_05_payment_out_invoices(self):
with Form(self.out_invoice) as form:
form.alternate_payer_id = self.alternate_partner
- self.out_invoice.post()
+ self.out_invoice._post()
with Form(self.out_invoice_02) as form:
form.alternate_payer_id = self.alternate_partner
- self.out_invoice_02.post()
+ self.out_invoice_02._post()
records = self.out_invoice | self.out_invoice_02
- action = (
+ ctx = {"active_model": records._name, "active_ids": records.ids}
+ payments = (
self.env["account.payment"]
- .with_context(active_model=records._name, active_ids=records.ids)
- .action_register_payment()
- )
- action = (
- self.env[action["res_model"]]
- .with_context(action["context"])
+ .with_context(ctx)
.create(
{
"payment_method_id": self.payment_method_manual_out.id,
"journal_id": self.bank_journal_euro.id,
}
)
- .create_payments()
)
- payments = self.env[action["res_model"]]
- if action.get("res_ids", False):
- payments = payments.browse(action["res_id"])
- else:
- payments = payments.search(action["domain"])
for payment in payments:
self.assertEqual(payment.partner_id, self.alternate_partner)
def test_06_payment_in_invoices(self):
with Form(self.in_invoice) as form:
form.alternate_payer_id = self.alternate_partner
- self.in_invoice.post()
+ self.in_invoice._post()
with Form(self.in_invoice_02) as form:
form.alternate_payer_id = self.alternate_partner
- self.in_invoice_02.post()
+ self.in_invoice_02._post()
records = self.in_invoice | self.in_invoice_02
- action = (
+ ctx = {"active_model": records._name, "active_ids": records.ids}
+ payments = (
self.env["account.payment"]
- .with_context(active_model=records._name, active_ids=records.ids)
- .action_register_payment()
- )
- action = (
- self.env[action["res_model"]]
- .with_context(action["context"])
+ .with_context(ctx)
.create(
{
"payment_method_id": self.payment_method_manual_out.id,
"journal_id": self.bank_journal_euro.id,
}
)
- .create_payments()
)
- payments = self.env[action["res_model"]]
- if action.get("res_ids", False):
- payments = payments.browse(action["res_id"])
- else:
- payments = payments.search(action["domain"])
for payment in payments:
self.assertEqual(payment.partner_id, self.alternate_partner)
@@ -216,10 +187,10 @@ def test_07_payment_widget_in_invoices(self):
)
payment_move.action_post()
self.assertFalse(self.in_invoice.invoice_has_outstanding)
- self.in_invoice.post()
+ self.in_invoice._post()
self.in_invoice.refresh()
self.assertTrue(self.in_invoice.invoice_has_outstanding)
- self.in_invoice.write({"invoice_payment_state": "paid"})
+ self.in_invoice.write({"payment_state": "paid"})
self.in_invoice.refresh()
self.assertFalse(self.in_invoice.invoice_has_outstanding)
@@ -257,9 +228,9 @@ def test_08_payment_widget_out_invoices(self):
)
payment_move.action_post()
self.assertFalse(self.out_invoice.invoice_has_outstanding)
- self.out_invoice.post()
+ self.out_invoice._post()
self.out_invoice.refresh()
self.assertTrue(self.out_invoice.invoice_has_outstanding)
- self.out_invoice.write({"invoice_payment_state": "paid"})
+ self.out_invoice.write({"payment_state": "paid"})
self.out_invoice.refresh()
self.assertFalse(self.out_invoice.invoice_has_outstanding)
diff --git a/account_invoice_alternate_payer/views/account_move_views.xml b/account_invoice_alternate_payer/views/account_move_views.xml
index 58c0e0368e83..b0c3eb12ad83 100644
--- a/account_invoice_alternate_payer/views/account_move_views.xml
+++ b/account_invoice_alternate_payer/views/account_move_views.xml
@@ -6,7 +6,7 @@
-
+
From 391263fdba5a654e9f1841ead5cd681de4c39a43 Mon Sep 17 00:00:00 2001
From: oca-ci
Date: Wed, 31 Aug 2022 14:14:33 +0000
Subject: [PATCH 07/13] [UPD] Update account_invoice_alternate_payer.pot
---
.../i18n/account_invoice_alternate_payer.pot | 31 ++++++++++++++++---
1 file changed, 26 insertions(+), 5 deletions(-)
diff --git a/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot b/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot
index 4cc3eae10200..c6f1bd6d1347 100644
--- a/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot
+++ b/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot
@@ -4,7 +4,7 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Odoo Server 13.0\n"
+"Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -14,17 +14,31 @@ msgstr ""
"Plural-Forms: \n"
#. module: account_invoice_alternate_payer
+#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_bank_statement_line__alternate_payer_id
+#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move__alternate_payer_id
+#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment__alternate_payer_id
#: model_terms:ir.ui.view,arch_db:account_invoice_alternate_payer.view_move_form
-msgid "Alternate Payee"
+msgid "Alternate Payer"
msgstr ""
#. module: account_invoice_alternate_payer
-#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move__alternate_payer_id
-msgid "Alternate Payer"
+#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move__display_name
+#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment__display_name
+#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment_register__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: account_invoice_alternate_payer
+#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move__id
+#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment__id
+#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment_register__id
+msgid "ID"
msgstr ""
#. module: account_invoice_alternate_payer
+#: model:ir.model.fields,help:account_invoice_alternate_payer.field_account_bank_statement_line__alternate_payer_id
#: model:ir.model.fields,help:account_invoice_alternate_payer.field_account_move__alternate_payer_id
+#: model:ir.model.fields,help:account_invoice_alternate_payer.field_account_payment__alternate_payer_id
msgid ""
"If set, this will be the partner that we expect to pay or to be paid by. If "
"not set, the payor is by default the commercial"
@@ -32,7 +46,14 @@ msgstr ""
#. module: account_invoice_alternate_payer
#: model:ir.model,name:account_invoice_alternate_payer.model_account_move
-msgid "Journal Entries"
+msgid "Journal Entry"
+msgstr ""
+
+#. module: account_invoice_alternate_payer
+#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move____last_update
+#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment____last_update
+#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment_register____last_update
+msgid "Last Modified on"
msgstr ""
#. module: account_invoice_alternate_payer
From a9d0b46c87aa4b31f61b822c547cc372c67931d8 Mon Sep 17 00:00:00 2001
From: OCA-git-bot
Date: Wed, 31 Aug 2022 14:21:42 +0000
Subject: [PATCH 08/13] [UPD] README.rst
---
account_invoice_alternate_payer/README.rst | 10 +++++-----
.../static/description/index.html | 6 +++---
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/account_invoice_alternate_payer/README.rst b/account_invoice_alternate_payer/README.rst
index ec24af360412..747824489743 100644
--- a/account_invoice_alternate_payer/README.rst
+++ b/account_invoice_alternate_payer/README.rst
@@ -14,13 +14,13 @@ Account Invoice Alternate Payer
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Faccount--invoicing-lightgray.png?logo=github
- :target: https://github.com/OCA/account-invoicing/tree/13.0/account_invoice_alternate_payer
+ :target: https://github.com/OCA/account-invoicing/tree/14.0/account_invoice_alternate_payer
:alt: OCA/account-invoicing
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
- :target: https://translation.odoo-community.org/projects/account-invoicing-13-0/account-invoicing-13-0-account_invoice_alternate_payer
+ :target: https://translation.odoo-community.org/projects/account-invoicing-14-0/account-invoicing-14-0-account_invoice_alternate_payer
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
- :target: https://runbot.odoo-community.org/runbot/95/13.0
+ :target: https://runbot.odoo-community.org/runbot/95/14.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
@@ -47,7 +47,7 @@ Bug Tracker
Bugs are tracked on `GitHub Issues `_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
-`feedback `_.
+`feedback `_.
Do not contact contributors directly about support or help with technical issues.
@@ -78,6 +78,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
-This module is part of the `OCA/account-invoicing `_ project on GitHub.
+This module is part of the `OCA/account-invoicing `_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/account_invoice_alternate_payer/static/description/index.html b/account_invoice_alternate_payer/static/description/index.html
index ffa32435c024..a335c6cd3572 100644
--- a/account_invoice_alternate_payer/static/description/index.html
+++ b/account_invoice_alternate_payer/static/description/index.html
@@ -367,7 +367,7 @@ Account Invoice Alternate Payer
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
-
+
This module allows to enter an alternative payer in the
customer invoice or vendor bill.
This allows, that we pay or expect to get paid by another partner other
@@ -394,7 +394,7 @@
Bugs are tracked on GitHub Issues.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
-feedback.
+feedback.
Do not contact contributors directly about support or help with technical issues.
@@ -425,7 +425,7 @@
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
-
This module is part of the OCA/account-invoicing project on GitHub.
+
This module is part of the OCA/account-invoicing project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
From eb1ec7ebbb56cf93f9d688b07dc3fb42bf42cf38 Mon Sep 17 00:00:00 2001
From: Christopher Ormaza
Date: Wed, 7 Sep 2022 08:43:36 -0500
Subject: [PATCH 09/13] [14.0][FIX] Set rigth partner on alternate invoices
lines
---
.../models/account_move.py | 13 ++++++
.../tests/test_account_invoice.py | 43 +++++++++++++++++++
2 files changed, 56 insertions(+)
diff --git a/account_invoice_alternate_payer/models/account_move.py b/account_invoice_alternate_payer/models/account_move.py
index 8cf1c724d534..898963b65b2f 100644
--- a/account_invoice_alternate_payer/models/account_move.py
+++ b/account_invoice_alternate_payer/models/account_move.py
@@ -117,3 +117,16 @@ def _compute_payments_widget_to_reconcile_info(self):
info["title"] = type_payment
move.invoice_outstanding_credits_debits_widget = json.dumps(info)
move.invoice_has_outstanding = True
+
+
+class AccountMoveLine(models.Model):
+
+ _inherit = "account.move.line"
+
+ def write(self, values):
+ # CHECK ME: this change to commercial partner when find difference between main partner
+ # https://github.com/odoo/odoo/blob/0f90852818a334d66ed8a6781f5abdc022f76ff7/addons/account/models/account_move.py#L2695 # noqa: B950
+ if "partner_id" in values and len(values.keys()) == 1:
+ lines_to_skip = self.filtered(lambda x: x.move_id.alternate_payer_id)
+ return super(AccountMoveLine, self - lines_to_skip).write(values)
+ return super(AccountMoveLine, self).write(values)
diff --git a/account_invoice_alternate_payer/tests/test_account_invoice.py b/account_invoice_alternate_payer/tests/test_account_invoice.py
index c2630426d84c..a90668284c8c 100644
--- a/account_invoice_alternate_payer/tests/test_account_invoice.py
+++ b/account_invoice_alternate_payer/tests/test_account_invoice.py
@@ -55,6 +55,29 @@ def test_01_onchange_out_invoice(self):
self.out_invoice.bank_partner_id, self.out_invoice.company_id.partner_id
)
+ def test_01_1_post_out_invoice(self):
+ with Form(self.out_invoice) as form:
+ form.alternate_payer_id = self.alternate_partner
+ self.out_invoice_posted = form.save()
+ self.out_invoice_posted.action_post()
+ self.assertEqual(
+ self.out_invoice_posted.line_ids.filtered(
+ lambda r: r.account_id.user_type_id.type in ("receivable", "payable")
+ ).mapped("partner_id"),
+ self.alternate_partner,
+ )
+ self.assertEqual(
+ self.out_invoice_posted.line_ids.filtered(
+ lambda r: r.account_id.user_type_id.type
+ not in ("receivable", "payable")
+ ).mapped("partner_id"),
+ self.out_invoice_posted.partner_id,
+ )
+ self.assertEqual(
+ self.out_invoice_posted.bank_partner_id,
+ self.out_invoice_posted.company_id.partner_id,
+ )
+
def test_02_onchange_in_invoice(self):
with Form(self.in_invoice) as form:
form.alternate_payer_id = self.alternate_partner
@@ -73,6 +96,26 @@ def test_02_onchange_in_invoice(self):
)
self.assertEqual(self.in_invoice.bank_partner_id, self.alternate_partner)
+ def test_02_1_post_in_invoice(self):
+ with Form(self.in_invoice) as form:
+ form.alternate_payer_id = self.alternate_partner
+ self.in_invoice_posted = form.save()
+ self.in_invoice_posted.action_post()
+ self.assertEqual(
+ self.in_invoice_posted.line_ids.filtered(
+ lambda r: r.account_id.user_type_id.type in ("receivable", "payable")
+ ).mapped("partner_id"),
+ self.alternate_partner,
+ )
+ self.assertEqual(
+ self.in_invoice_posted.line_ids.filtered(
+ lambda r: r.account_id.user_type_id.type
+ not in ("receivable", "payable")
+ ).mapped("partner_id"),
+ self.out_invoice.partner_id,
+ )
+ self.assertEqual(self.in_invoice_posted.bank_partner_id, self.alternate_partner)
+
def test_03_payment_out_invoice(self):
with Form(self.out_invoice) as form:
form.alternate_payer_id = self.alternate_partner
From 51904b13dc1af12f6de5e4f464b1b3af534e3dbc Mon Sep 17 00:00:00 2001
From: oca-ci
Date: Mon, 2 Jan 2023 16:35:38 +0000
Subject: [PATCH 10/13] [UPD] Update account_invoice_alternate_payer.pot
---
.../i18n/account_invoice_alternate_payer.pot | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot b/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot
index c6f1bd6d1347..fb5c666b026d 100644
--- a/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot
+++ b/account_invoice_alternate_payer/i18n/account_invoice_alternate_payer.pot
@@ -23,6 +23,7 @@ msgstr ""
#. module: account_invoice_alternate_payer
#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move__display_name
+#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move_line__display_name
#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment__display_name
#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment_register__display_name
msgid "Display Name"
@@ -30,6 +31,7 @@ msgstr ""
#. module: account_invoice_alternate_payer
#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move__id
+#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move_line__id
#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment__id
#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment_register__id
msgid "ID"
@@ -49,8 +51,14 @@ msgstr ""
msgid "Journal Entry"
msgstr ""
+#. module: account_invoice_alternate_payer
+#: model:ir.model,name:account_invoice_alternate_payer.model_account_move_line
+msgid "Journal Item"
+msgstr ""
+
#. module: account_invoice_alternate_payer
#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move____last_update
+#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_move_line____last_update
#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment____last_update
#: model:ir.model.fields,field_description:account_invoice_alternate_payer.field_account_payment_register____last_update
msgid "Last Modified on"
From 2b97dc942fa75b5ce60a18e41491a12d65ce371c Mon Sep 17 00:00:00 2001
From: OCA-git-bot
Date: Mon, 2 Jan 2023 16:43:50 +0000
Subject: [PATCH 11/13] account_invoice_alternate_payer 14.0.1.0.1
---
account_invoice_alternate_payer/__manifest__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/account_invoice_alternate_payer/__manifest__.py b/account_invoice_alternate_payer/__manifest__.py
index 774c768f58d1..77d93fabe824 100644
--- a/account_invoice_alternate_payer/__manifest__.py
+++ b/account_invoice_alternate_payer/__manifest__.py
@@ -4,7 +4,7 @@
{
"name": "Account Invoice Alternate Payer",
"summary": "Set a alternate payor/payee in invoices",
- "version": "14.0.1.0.0",
+ "version": "14.0.1.0.1",
"license": "AGPL-3",
"category": "Accounting",
"author": "Eficent,Odoo Community Association (OCA)",
From f4e2c984a8650fda0534ce1fb7374a18af079517 Mon Sep 17 00:00:00 2001
From: Ruchir Shukla
Date: Sat, 4 Mar 2023 20:08:48 +0530
Subject: [PATCH 12/13] [IMP]account_invoice_alternate_payer:black, isort,
prettier
---
.../odoo/addons/account_invoice_alternate_payer | 1 +
setup/account_invoice_alternate_payer/setup.py | 6 ++++++
2 files changed, 7 insertions(+)
create mode 120000 setup/account_invoice_alternate_payer/odoo/addons/account_invoice_alternate_payer
create mode 100644 setup/account_invoice_alternate_payer/setup.py
diff --git a/setup/account_invoice_alternate_payer/odoo/addons/account_invoice_alternate_payer b/setup/account_invoice_alternate_payer/odoo/addons/account_invoice_alternate_payer
new file mode 120000
index 000000000000..8060f345cc40
--- /dev/null
+++ b/setup/account_invoice_alternate_payer/odoo/addons/account_invoice_alternate_payer
@@ -0,0 +1 @@
+../../../../account_invoice_alternate_payer
\ No newline at end of file
diff --git a/setup/account_invoice_alternate_payer/setup.py b/setup/account_invoice_alternate_payer/setup.py
new file mode 100644
index 000000000000..28c57bb64031
--- /dev/null
+++ b/setup/account_invoice_alternate_payer/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+ setup_requires=['setuptools-odoo'],
+ odoo_addon=True,
+)
From 116d46f905b7380357e4c96b71a1527e23ca6516 Mon Sep 17 00:00:00 2001
From: Ruchir Shukla
Date: Sat, 4 Mar 2023 20:13:55 +0530
Subject: [PATCH 13/13] [MIG][15.0]account_invoice_alternate_payer: Migration
to 15.0
---
.../__manifest__.py | 2 +-
.../migrations/13.0.1.0.0/post-migration.py | 32 -------------------
.../models/account_move.py | 9 ++++--
.../tests/test_account_invoice.py | 8 ++---
4 files changed, 11 insertions(+), 40 deletions(-)
delete mode 100644 account_invoice_alternate_payer/migrations/13.0.1.0.0/post-migration.py
diff --git a/account_invoice_alternate_payer/__manifest__.py b/account_invoice_alternate_payer/__manifest__.py
index 77d93fabe824..a3f42c986c4a 100644
--- a/account_invoice_alternate_payer/__manifest__.py
+++ b/account_invoice_alternate_payer/__manifest__.py
@@ -4,7 +4,7 @@
{
"name": "Account Invoice Alternate Payer",
"summary": "Set a alternate payor/payee in invoices",
- "version": "14.0.1.0.1",
+ "version": "15.0.1.0.0",
"license": "AGPL-3",
"category": "Accounting",
"author": "Eficent,Odoo Community Association (OCA)",
diff --git a/account_invoice_alternate_payer/migrations/13.0.1.0.0/post-migration.py b/account_invoice_alternate_payer/migrations/13.0.1.0.0/post-migration.py
deleted file mode 100644
index 3cd7f21532be..000000000000
--- a/account_invoice_alternate_payer/migrations/13.0.1.0.0/post-migration.py
+++ /dev/null
@@ -1,32 +0,0 @@
-from openupgradelib import openupgrade
-
-
-@openupgrade.migrate()
-def migrate(env, version):
- openupgrade.logged_query(
- env.cr,
- """
- UPDATE account_move am
- SET alternate_payer_id = ai.alternate_payer_id
- FROM account_invoice ai
- WHERE ai.alternate_payer_id IS NOT NULL
- AND ai.id = am.old_invoice_id
- """,
- )
- openupgrade.logged_query(
- env.cr,
- """
- UPDATE account_move_line aml
- SET partner_id = am.alternate_payer_id
- FROM
- account_move am,
- account_account as aa,
- account_account_type as aat
- WHERE am.alternate_payer_id IS NOT NULL
- AND am.id = aml.move_id
- AND am.state = 'draft'
- AND aat.type in ('receivable', 'payable')
- AND aa.id = aml.account_id
- AND aat.id = aa.user_type_id
- """,
- )
diff --git a/account_invoice_alternate_payer/models/account_move.py b/account_invoice_alternate_payer/models/account_move.py
index 898963b65b2f..ff055c51b9f1 100644
--- a/account_invoice_alternate_payer/models/account_move.py
+++ b/account_invoice_alternate_payer/models/account_move.py
@@ -23,29 +23,31 @@ class AccountMove(models.Model):
@api.depends("commercial_partner_id", "alternate_payer_id")
def _compute_bank_partner_id(self):
- super(
+ res = super(
AccountMove,
self.filtered(lambda r: not r.alternate_payer_id or not r.is_outbound()),
)._compute_bank_partner_id()
for move in self:
if move.is_outbound() and move.alternate_payer_id:
move.bank_partner_id = move.alternate_payer_id
+ return res
@api.onchange("alternate_payer_id")
def _onchange_alternate_payer_id(self):
return self._onchange_partner_id()
def _recompute_payment_terms_lines(self):
- super()._recompute_payment_terms_lines()
+ res = super()._recompute_payment_terms_lines()
for invoice in self:
if invoice.alternate_payer_id:
invoice.line_ids.filtered(
lambda r: r.account_id.user_type_id.type
in ("receivable", "payable")
).update({"partner_id": invoice.alternate_payer_id.id})
+ return res
def _compute_payments_widget_to_reconcile_info(self):
- super(
+ res = super(
AccountMove, self.filtered(lambda r: not r.alternate_payer_id)
)._compute_payments_widget_to_reconcile_info()
for move in self:
@@ -117,6 +119,7 @@ def _compute_payments_widget_to_reconcile_info(self):
info["title"] = type_payment
move.invoice_outstanding_credits_debits_widget = json.dumps(info)
move.invoice_has_outstanding = True
+ return res
class AccountMoveLine(models.Model):
diff --git a/account_invoice_alternate_payer/tests/test_account_invoice.py b/account_invoice_alternate_payer/tests/test_account_invoice.py
index a90668284c8c..568cbe05a56c 100644
--- a/account_invoice_alternate_payer/tests/test_account_invoice.py
+++ b/account_invoice_alternate_payer/tests/test_account_invoice.py
@@ -124,7 +124,7 @@ def test_03_payment_out_invoice(self):
ctx = {"active_model": records._name, "active_ids": records.ids}
payment = (
self.env["account.payment"]
- .with_context(ctx)
+ .with_context(**ctx)
.create(
{
"payment_method_id": self.payment_method_manual_out.id,
@@ -142,7 +142,7 @@ def test_04_payment_in_invoice(self):
ctx = {"active_model": records._name, "active_ids": records.ids}
payment = (
self.env["account.payment"]
- .with_context(ctx)
+ .with_context(**ctx)
.create(
{
"payment_method_id": self.payment_method_manual_in.id,
@@ -163,7 +163,7 @@ def test_05_payment_out_invoices(self):
ctx = {"active_model": records._name, "active_ids": records.ids}
payments = (
self.env["account.payment"]
- .with_context(ctx)
+ .with_context(**ctx)
.create(
{
"payment_method_id": self.payment_method_manual_out.id,
@@ -185,7 +185,7 @@ def test_06_payment_in_invoices(self):
ctx = {"active_model": records._name, "active_ids": records.ids}
payments = (
self.env["account.payment"]
- .with_context(ctx)
+ .with_context(**ctx)
.create(
{
"payment_method_id": self.payment_method_manual_out.id,