[MIG] account_reconcile_payment_order: Migration to 12.0

* Standard procedure.
* README by fragments.
* Adapt logic to new reconciliation widget model.
* Add tests.
pull/283/head
Pedro M. Baeza 2019-08-22 17:00:47 +02:00
parent 4bab3df5aa
commit 7afc2dea9f
17 changed files with 780 additions and 179 deletions

View File

@ -1,70 +1,124 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
========================
Reconcile payment orders
========================
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! 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--reconcile-lightgray.png?logo=github
:target: https://github.com/OCA/account-reconcile/tree/12.0/account_reconcile_payment_order
:alt: OCA/account-reconcile
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/account-reconcile-12-0/account-reconcile-12-0-account_reconcile_payment_order
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/98/12.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
Payment orders that show up as one big transaction can be difficult for the
accounting to handle if a transfer account is used. In this case, we need to
reconcile this transaction with possibly hundreds of move lines, which can be a
bit tiresome. This module tries to recognize transactions deriving from payment
orders and propose the unreconciled move lines from this payment order.
**Table of contents**
.. contents::
:local:
Installation
============
This module requires the module **account_banking_payment_transfer**, available
This module requires the module **account_payment_order**, available
in https://github.com/OCA/bank-payment.
Configuration
=============
#. Go to *Settings > Users & Companies > Users*.
#. Give to your user the permission "Show Full Accounting Features".
Usage
=====
It should just work. What the module does is to search for a payment order in
state 'sent' (for orders transferred to an intermediate account) or done (for
orders non transferred) that has the same amount as the statement line, and the
same bank account than the statement. If any, all move lines are automatically
proposed for the reconcile.
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/98/8.0
#. Go to *Invoicing > Overview*.
#. Locate the bank kanban card and import or create a new statement on it.
#. When reconciling, it should just work. What the module does is to search for
a finished payment order that has the same amount as the statement line. If
any, generated move lines (bank or AR/AP ones) are automatically proposed
for the reconciliation.
Known issues / Roadmap
======================
* it would be good to check references too, but at least the bank in use here
changes some characters, so this doesn't seem to be a general solution.
* It would be good to check references too, but bank usually change some
characters, so this doesn't seem to be a general solution.
* Take into account different currencies (in payment order or in bank
statement).
* Try to match payment orders resulting entries grouped by due date, instead of
a whole, but this will affect performance for sure.
* When the reconcile models end with more inheritable code, implement this
as a new type of reconciliation in this model.
* Develop real UI tests, instead of mimicking the call to the involved method.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/bank-statement-reconcile/issues>`_.
Bugs are tracked on `GitHub Issues <https://github.com/OCA/account-reconcile/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
`here <https://github.com/OCA/bank-statement-reconcile/issues/new?body=module:%20account_reconcile_payment_order%0Aversion:%208.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
If you spotted it first, help us smashing it by providing a detailed and welcomed
`feedback <https://github.com/OCA/account-reconcile/issues/new?body=module:%20account_reconcile_payment_order%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* Therp BV
* Tecnativa
Contributors
------------
~~~~~~~~~~~~
* Holger Brunn <hbrunn@therp.nl>
* Pedro M. Baeza <pedro.baeza@serviciosbaeza.com>
* Holger Brunn
* `Tecnativa <https://www.tecnativa.com>`__:
Maintainer
----------
* Pedro M. Baeza
Maintainers
~~~~~~~~~~~
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
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.
To contribute to this module, please visit http://odoo-community.org.
.. |maintainer-pedrobaeza| image:: https://github.com/pedrobaeza.png?size=40px
:target: https://github.com/pedrobaeza
:alt: pedrobaeza
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
|maintainer-pedrobaeza|
This module is part of the `OCA/account-reconcile <https://github.com/OCA/account-reconcile/tree/12.0/account_reconcile_payment_order>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View File

@ -1,20 +1,3 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# This module copyright (C) 2015 Therp BV <http://therp.nl>.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
from . import models

View File

@ -0,0 +1,20 @@
# Copyright 2015 Therp BV (<http://therp.nl>).
# Copyright 2019 Tecnativa - Pedro M. Baeza
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
{
"name": "Reconcile payment orders",
"version": "12.0.1.0.0",
"author": "Therp BV,"
"Tecnativa,"
"Odoo Community Association (OCA)",
"license": "AGPL-3",
"website": "https://github.com/OCA/account-reconcile",
"category": "Invoicing Management",
"summary": "Automatically propose all lines generated from payment orders",
"depends": [
'account_payment_order',
],
"installable": True,
"maintainers": ['pedrobaeza'],
}

View File

@ -1,35 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# This module copyright (C) 2015 Therp BV <http://therp.nl>.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
"name": "Reconcile payment orders",
"version": "8.0.1.0.1",
"author": "Therp BV,"
"Serv. Tecnol. Avanzados - Pedro M. Baeza,"
"Odoo Community Association (OCA)",
"license": "AGPL-3",
"category": "Accounting & Finance",
"summary": "Automatically reconcile all lines from payment orders",
"depends": [
'account_banking_payment_transfer',
],
"auto_install": False,
"installable": True,
"application": False,
}

View File

@ -1,20 +1,3 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# This module copyright (C) 2015 Therp BV <http://therp.nl>.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import account_bank_statement_line
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
from . import account_reconciliation_widget

View File

@ -1,78 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# This module copyright (C) 2015 Therp BV (<http://therp.nl>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from decimal import Decimal
from openerp import models, api
from openerp.tools.float_utils import float_repr
class AccountBankStatementLine(models.Model):
_inherit = 'account.bank.statement.line'
@api.model
def get_possible_payment_orders_for_statement_line(self, this):
"""find orders that might be candidates for matching a statement
line"""
digits = self.env['decimal.precision'].precision_get('Account')
self.env.cr.execute(
'''with order_sums as (
select order_id, sum(amount_currency) as amount
from payment_line
join payment_order o on o.id=order_id
where o.state in ('sent', 'done')
group by order_id)
select order_id from order_sums where amount = %s''',
(Decimal(float_repr(abs(this.amount), digits)),))
order_ids = [i for i, in self.env.cr.fetchall()]
# verify that this ids are accessible to the user
domain = [
('id', 'in', order_ids),
]
return self.env['payment.order'].search(domain)
@api.model
def get_reconcile_lines_from_order(self, this, orders, excluded_ids=None):
"""return lines to reconcile our statement line with"""
order = orders[0]
target_currency = (
this.currency_id or this.journal_id.currency or
this.journal_id.company_id.currency_id)
if order.state == 'sent':
move_lines_list = list(set(order._get_transfer_move_lines()))
else:
move_lines = order.line_ids.mapped('move_line_id').filtered(
lambda x: not x.reconcile_id)
move_lines_list = [x for x in move_lines]
return self.env['account.move.line']\
.prepare_move_lines_for_reconciliation_widget(
move_lines_list, target_currency=target_currency,
target_date=this.date)
@api.model
def get_reconciliation_proposition(self, this, excluded_ids=None):
"""See if we find a set payment order that matches our line. If yes,
return all unreconciled lines from there"""
orders = self.get_possible_payment_orders_for_statement_line(this)
if orders:
reconcile_lines = self.get_reconcile_lines_from_order(
this, orders, excluded_ids=None)
if reconcile_lines:
return reconcile_lines
return super(AccountBankStatementLine, self)\
.get_reconciliation_proposition(this, excluded_ids=excluded_ids)

View File

@ -0,0 +1,67 @@
# Copyright 2019 Tecnativa - Pedro M. Baeza
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
from odoo import models, api
class AccountReconciliationWidget(models.AbstractModel):
_inherit = 'account.reconciliation.widget'
@api.model
def _get_possible_payment_orders_for_statement_line(self, st_line):
"""Find orders that might be candidates for matching a statement
line.
"""
return self.env['account.payment.order'].search([
('total_company_currency', '=', st_line.amount),
('state', 'in', ['done', 'uploaded']),
])
@api.model
def _get_reconcile_lines_from_order(self, st_line, order,
excluded_ids=None):
"""Return lines to reconcile our statement line with."""
aml_obj = self.env['account.move.line']
reconciled_lines = aml_obj.search([
('bank_payment_line_id', 'in', order.bank_line_ids.ids)
])
return (
reconciled_lines.mapped('move_id.line_ids') - reconciled_lines -
aml_obj.browse(excluded_ids)
).filtered(lambda x: not x.reconciled)
def _prepare_proposition_from_orders(self, st_line, orders,
excluded_ids=None):
"""Fill with the expected format the reconciliation proposition
for the given statement line and possible payment orders.
"""
target_currency = (
st_line.currency_id or st_line.journal_id.currency_id or
st_line.journal_id.company_id.currency_id
)
for order in orders:
elegible_lines = self._get_reconcile_lines_from_order(
st_line, order, excluded_ids=excluded_ids,
)
if elegible_lines:
return self._prepare_move_lines(
elegible_lines, target_currency=target_currency,
target_date=st_line.date,
)
return []
def get_bank_statement_line_data(self, st_line_ids, excluded_ids=None):
res = super().get_bank_statement_line_data(
st_line_ids, excluded_ids=excluded_ids,
)
st_line_obj = self.env['account.bank.statement.line']
for line_vals in res.get('lines', []):
st_line = st_line_obj.browse(line_vals['st_line']['id'])
orders = self._get_possible_payment_orders_for_statement_line(
st_line)
proposition_vals = self._prepare_proposition_from_orders(
st_line, orders, excluded_ids=excluded_ids,
)
if proposition_vals:
line_vals['reconciliation_proposition'] = proposition_vals
return res

View File

@ -0,0 +1,2 @@
#. Go to *Settings > Users & Companies > Users*.
#. Give to your user the permission "Show Full Accounting Features".

View File

@ -0,0 +1,4 @@
* Holger Brunn
* `Tecnativa <https://www.tecnativa.com>`__:
* Pedro M. Baeza

View File

@ -0,0 +1,5 @@
Payment orders that show up as one big transaction can be difficult for the
accounting to handle if a transfer account is used. In this case, we need to
reconcile this transaction with possibly hundreds of move lines, which can be a
bit tiresome. This module tries to recognize transactions deriving from payment
orders and propose the unreconciled move lines from this payment order.

View File

@ -0,0 +1,2 @@
This module requires the module **account_payment_order**, available
in https://github.com/OCA/bank-payment.

View File

@ -0,0 +1,9 @@
* It would be good to check references too, but bank usually change some
characters, so this doesn't seem to be a general solution.
* Take into account different currencies (in payment order or in bank
statement).
* Try to match payment orders resulting entries grouped by due date, instead of
a whole, but this will affect performance for sure.
* When the reconcile models end with more inheritable code, implement this
as a new type of reconciliation in this model.
* Develop real UI tests, instead of mimicking the call to the involved method.

View File

@ -0,0 +1,6 @@
#. Go to *Invoicing > Overview*.
#. Locate the bank kanban card and import or create a new statement on it.
#. When reconciling, it should just work. What the module does is to search for
a finished payment order that has the same amount as the statement line. If
any, generated move lines (bank or AR/AP ones) are automatically proposed
for the reconciliation.

View File

@ -0,0 +1,471 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" />
<title>Reconcile payment orders</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="reconcile-payment-orders">
<h1 class="title">Reconcile payment orders</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/account-reconcile/tree/12.0/account_reconcile_payment_order"><img alt="OCA/account-reconcile" src="https://img.shields.io/badge/github-OCA%2Faccount--reconcile-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/account-reconcile-12-0/account-reconcile-12-0-account_reconcile_payment_order"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/98/12.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>Payment orders that show up as one big transaction can be difficult for the
accounting to handle if a transfer account is used. In this case, we need to
reconcile this transaction with possibly hundreds of move lines, which can be a
bit tiresome. This module tries to recognize transactions deriving from payment
orders and propose the unreconciled move lines from this payment order.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#installation" id="id1">Installation</a></li>
<li><a class="reference internal" href="#configuration" id="id2">Configuration</a></li>
<li><a class="reference internal" href="#usage" id="id3">Usage</a></li>
<li><a class="reference internal" href="#known-issues-roadmap" id="id4">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#bug-tracker" id="id5">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id6">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id7">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id8">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id9">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="installation">
<h1><a class="toc-backref" href="#id1">Installation</a></h1>
<p>This module requires the module <strong>account_payment_order</strong>, available
in <a class="reference external" href="https://github.com/OCA/bank-payment">https://github.com/OCA/bank-payment</a>.</p>
</div>
<div class="section" id="configuration">
<h1><a class="toc-backref" href="#id2">Configuration</a></h1>
<ol class="arabic simple">
<li>Go to <em>Settings &gt; Users &amp; Companies &gt; Users</em>.</li>
<li>Give to your user the permission “Show Full Accounting Features”.</li>
</ol>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#id3">Usage</a></h1>
<ol class="arabic simple">
<li>Go to <em>Invoicing &gt; Overview</em>.</li>
<li>Locate the bank kanban card and import or create a new statement on it.</li>
<li>When reconciling, it should just work. What the module does is to search for
a finished payment order that has the same amount as the statement line. If
any, generated move lines (bank or AR/AP ones) are automatically proposed
for the reconciliation.</li>
</ol>
</div>
<div class="section" id="known-issues-roadmap">
<h1><a class="toc-backref" href="#id4">Known issues / Roadmap</a></h1>
<ul class="simple">
<li>It would be good to check references too, but bank usually change some
characters, so this doesnt seem to be a general solution.</li>
<li>Take into account different currencies (in payment order or in bank
statement).</li>
<li>Try to match payment orders resulting entries grouped by due date, instead of
a whole, but this will affect performance for sure.</li>
<li>When the reconcile models end with more inheritable code, implement this
as a new type of reconciliation in this model.</li>
<li>Develop real UI tests, instead of mimicking the call to the involved method.</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#id5">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/account-reconcile/issues">GitHub Issues</a>.
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
<a class="reference external" href="https://github.com/OCA/account-reconcile/issues/new?body=module:%20account_reconcile_payment_order%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#id6">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#id7">Authors</a></h2>
<ul class="simple">
<li>Therp BV</li>
<li>Tecnativa</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#id8">Contributors</a></h2>
<ul class="simple">
<li>Holger Brunn</li>
<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:<ul>
<li>Pedro M. Baeza</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#id9">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>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.</p>
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
<p><a class="reference external" href="https://github.com/pedrobaeza"><img alt="pedrobaeza" src="https://github.com/pedrobaeza.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/account-reconcile/tree/12.0/account_reconcile_payment_order">OCA/account-reconcile</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,3 @@
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
from . import test_account_reconcile_payment_order

View File

@ -0,0 +1,104 @@
# Copyright 2019 Tecnativa - Pedro M. Baeza
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
from odoo.addons.account_payment_order.tests.test_payment_order_inbound \
import TestPaymentOrderInboundBase
class TestAccountReconcilePaymentOrder(TestPaymentOrderInboundBase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.widget_obj = cls.env['account.reconciliation.widget']
cls.bank_journal = cls.env['account.journal'].search(
[('type', '=', 'bank')], limit=1)
# Create second invoice for being sure it handles the payment order
cls.invoice2 = cls._create_customer_invoice(cls)
cls.partner2 = cls.env['res.partner'].create({
'name': 'Test partner 2',
})
cls.invoice2.partner_id = cls.partner2.id
cls.invoice2.action_invoice_open()
# Add to payment order using the wizard
cls.env['account.invoice.payment.line.multi'].with_context(
active_model='account.invoice',
active_ids=cls.invoice2.ids,
).create({}).run()
# Prepare statement
cls.statement = cls.env['account.bank.statement'].create({
'name': 'Test statement',
'date': '2019-01-01',
'journal_id': cls.bank_journal.id,
'line_ids': [
(0, 0, {
'date': '2019-01-01',
'name': 'Test line',
'amount': 200,
}),
],
})
def test_reconcile_payment_order_bank(self):
self.assertEqual(len(self.inbound_order.payment_line_ids), 2)
self.inbound_mode.write({
'offsetting_account': 'bank_account',
'move_option': 'line',
})
# Prepare payment order
self.inbound_order.draft2open()
self.inbound_order.open2generated()
self.inbound_order.generated2uploaded()
# Check widget result
res = self.widget_obj.get_bank_statement_line_data(
self.statement.line_ids.ids,
)
self.assertEqual(len(res['lines'][0]['reconciliation_proposition']), 2)
def test_reconcile_payment_order_transfer_account(self):
self.assertEqual(len(self.inbound_order.payment_line_ids), 2)
receivable_account = self.env['account.account'].create({
'name': 'Extra receivable account',
'code': 'TEST_ERA',
'reconcile': True,
'user_type_id': (
self.env.ref('account.data_account_type_receivable').id),
})
self.inbound_mode.write({
'offsetting_account': 'transfer_account',
'transfer_account_id': receivable_account.id,
'transfer_journal_id': self.bank_journal.id,
'move_option': 'line',
})
self.assertEqual(len(self.inbound_order.payment_line_ids), 2)
# Prepare payment order
self.inbound_order.draft2open()
self.inbound_order.open2generated()
self.inbound_order.generated2uploaded()
# Check widget result
res = self.widget_obj.get_bank_statement_line_data(
self.statement.line_ids.ids,
)
proposition = res['lines'][0]['reconciliation_proposition']
self.assertEqual(len(proposition), 2)
# Reconcile that entries and check again
st_line_vals = res['lines'][0]['st_line']
self.widget_obj.process_move_lines(
data=[{
'type': '',
'mv_line_ids': [
proposition[0]['id'],
proposition[1]['id'],
],
'new_mv_line_dicts': [{
'name': st_line_vals['name'],
'credit': st_line_vals['amount'],
'debit': 0,
'account_id': st_line_vals['account_id'][0],
'journal_id': st_line_vals['journal_id'],
}],
}],
)
res2 = self.widget_obj.get_bank_statement_line_data(
self.statement.line_ids.ids,
)
self.assertNotEqual(res, res2)

View File

@ -1 +1,2 @@
account-financial-tools
bank-payment