Add a hook to inherit grouping of the transfer account move line

Use that new hook in SEPA direct debits
Better variable names
This commit is contained in:
Alexis de Lattre
2015-09-24 11:38:50 +02:00
committed by Pedro M. Baeza
parent adedae3bc2
commit 0c2aec9eeb
6 changed files with 185 additions and 107 deletions

View File

@@ -1,4 +1,7 @@
# -*- coding: utf-8 -*-
from . import account_payment
from . import payment_line
from . import bank_payment_line
from . import payment_mode
from . import account_move_reconcile

View File

@@ -4,7 +4,7 @@
# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
# (C) 2011 - 2013 Therp BV (<http://therp.nl>).
# (C) 2014 ACSONE SA (<http://acsone.eu>).
# (C) 2014 Akretion (www.akretion.com)
# (C) 2014-2015 Akretion (www.akretion.com)
#
# All other contributions are (C) by their respective contributors
#
@@ -26,6 +26,7 @@
##############################################################################
from openerp import models, fields, api, _
from openerp.exceptions import Warning as UserError
class PaymentOrder(models.Model):
@@ -165,23 +166,23 @@ class PaymentOrder(models.Model):
return vals
@api.multi
def _prepare_move_line_partner_account(self, line, move, labels):
def _prepare_move_line_partner_account(self, bank_line, move, labels):
# TODO : ALEXIS check don't group if move_line_id.account_id
# is not the same
if self.payment_order_type == 'debit':
account_id = line.partner_id.property_account_receivable.id
account_id = bank_line.partner_id.property_account_receivable.id
else:
account_id = line.partner_id.property_account_payable.id
account_id = bank_line.partner_id.property_account_payable.id
vals = {
'name': _('%s line %s') % (
labels[self.payment_order_type], line.name),
labels[self.payment_order_type], bank_line.name),
'move_id': move.id,
'partner_id': line.partner_id.id,
'partner_id': bank_line.partner_id.id,
'account_id': account_id,
'credit': (self.payment_order_type == 'debit' and
line.amount_currency or 0.0),
bank_line.amount_currency or 0.0),
'debit': (self.payment_order_type == 'payment' and
line.amount_currency or 0.0),
bank_line.amount_currency or 0.0),
}
return vals
@@ -191,20 +192,27 @@ class PaymentOrder(models.Model):
return
@api.multi
def _create_move_line_partner_account(self, line, move, labels):
def _create_move_line_partner_account(self, bank_line, move, labels):
"""This method is designed to be inherited in a custom module"""
# TODO: take multicurrency into account
company_currency = self.env.user.company_id.currency_id
if bank_line.currency != company_currency:
raise UserError(_(
"Cannot generate the transfer move when "
"the currency of the payment (%s) is not the "
"same as the currency of the company. This "
"is not supported for the moment.")
% (bank_line.currency.name, company_currency.name))
aml_obj = self.env['account.move.line']
# create the payment/debit counterpart move line
# on the partner account
partner_ml_vals = self._prepare_move_line_partner_account(
line, move, labels)
bank_line, move, labels)
partner_move_line = aml_obj.create(partner_ml_vals)
# register the payment/debit move line
# on the payment line and call reconciliation on it
line.write({'transit_move_line_id': partner_move_line.id})
bank_line.write({'transit_move_line_id': partner_move_line.id})
@api.multi
def _reconcile_payment_lines(self, bank_payment_lines):
@@ -233,28 +241,25 @@ class PaymentOrder(models.Model):
# key = unique identifier (date or True or line.id)
# value = [pay_line1, pay_line2, ...]
trfmoves = {}
if self.mode.transfer_move_option == 'line':
for line in self.bank_line_ids:
trfmoves[line.id] = [line]
else:
for line in self.bank_line_ids:
if line.date in trfmoves:
trfmoves[line.date].append(line)
else:
trfmoves[line.date] = [line]
for bline in self.bank_line_ids:
hashcode = bline.move_line_transfer_account_hashcode()
if hashcode in trfmoves:
trfmoves[hashcode].append(bline)
else:
trfmoves[hashcode] = [bline]
for identifier, lines in trfmoves.iteritems():
for hashcode, blines in trfmoves.iteritems():
mvals = self._prepare_transfer_move()
move = am_obj.create(mvals)
total_amount = 0
for line in lines:
total_amount += line.amount_currency
self._create_move_line_partner_account(line, move, labels)
for bline in blines:
total_amount += bline.amount_currency
self._create_move_line_partner_account(bline, move, labels)
# create the payment/debit move line on the transfer account
trf_ml_vals = self._prepare_move_line_transfer_account(
total_amount, move, lines, labels)
total_amount, move, blines, labels)
aml_obj.create(trf_ml_vals)
self._reconcile_payment_lines(lines)
self._reconcile_payment_lines(blines)
# consider entry_posted on account_journal
if move.journal_id.entry_posted:

View File

@@ -0,0 +1,97 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
# (C) 2011 - 2013 Therp BV (<http://therp.nl>).
# (C) 2015 Akretion (http://www.akretion.com).
#
# 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 openerp import models, fields, api
class BankPaymentLine(models.Model):
_inherit = 'bank.payment.line'
transit_move_line_id = fields.Many2one(
'account.move.line', string='Transfer move line', readonly=True,
help="Move line through which the payment/debit order "
"pays the invoice")
transfer_move_line_id = fields.Many2one(
'account.move.line', compute='_get_transfer_move_line',
string='Transfer move line counterpart',
help="Counterpart move line on the transfer account")
@api.multi
def move_line_transfer_account_hashcode(self):
"""
This method is inherited in the module
account_banking_sepa_direct_debit
"""
self.ensure_one()
if self.order_id.mode.transfer_move_option == 'date':
hashcode = self.date
else:
hashcode = unicode(self.id)
return hashcode
@api.multi
def _get_transfer_move_line(self):
for bank_line in self:
if bank_line.transit_move_line_id:
order_type = bank_line.order_id.payment_order_type
trf_lines = bank_line.transit_move_line_id.move_id.line_id
for move_line in trf_lines:
if order_type == 'debit' and move_line.debit > 0:
bank_line.transfer_move_line_id = move_line
elif order_type == 'payment' and move_line.credit > 0:
bank_line.transfer_move_line_id = move_line
@api.one
def debit_reconcile(self):
"""
Reconcile a debit order's payment line with the the move line
that it is based on. Called from payment_order.action_sent().
As the amount is derived directly from the counterpart move line,
we do not expect a write off. Take partial reconciliations into
account though.
:param payment_line_id: the single id of the canceled payment line
"""
transit_move_line = self.transit_move_line_id
# if (not transit_move_line or not torec_move_line):
# raise exceptions.Warning(
# _('Can not reconcile: no move line for line %s') % self.name
# )
# if torec_move_line.reconcile_id:
# raise exceptions.Warning(
# _('Move line %s has already been reconciled') %
# torec_move_line.name
# )
# if (transit_move_line.reconcile_id or
# transit_move_line.reconcile_partial_id):
# raise exceptions.Warning(
# _('Move line %s has already been reconciled') %
# transit_move_line.name
# )
lines_to_rec = transit_move_line
for payment_line in self.payment_line_ids:
lines_to_rec += payment_line.move_line_id
lines_to_rec.reconcile_partial(type='auto')

View File

@@ -22,8 +22,8 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import models, fields, workflow, api, exceptions
from openerp.tools.translate import _
from openerp import models, fields, api
class PaymentLine(models.Model):
@@ -38,63 +38,14 @@ class PaymentLine(models.Model):
msg = fields.Char('Message', required=False, readonly=True, default='')
date_done = fields.Date('Date Confirmed', select=True, readonly=True)
class BankPaymentLine(models.Model):
_inherit = 'bank.payment.line'
transit_move_line_id = fields.Many2one(
'account.move.line', string='Transfer move line', readonly=True,
help="Move line through which the payment/debit order "
"pays the invoice")
transfer_move_line_id = fields.Many2one(
'account.move.line', compute='_get_transfer_move_line',
string='Transfer move line counterpart',
help="Counterpart move line on the transfer account")
@api.multi
def _get_transfer_move_line(self):
for bank_line in self:
if bank_line.transit_move_line_id:
order_type = bank_line.order_id.payment_order_type
trf_lines = bank_line.transit_move_line_id.move_id.line_id
for move_line in trf_lines:
if order_type == 'debit' and move_line.debit > 0:
bank_line.transfer_move_line_id = move_line
elif order_type == 'payment' and move_line.credit > 0:
bank_line.transfer_move_line_id = move_line
@api.one
def debit_reconcile(self):
def payment_line_hashcode(self):
"""
Reconcile a debit order's payment line with the the move line
that it is based on. Called from payment_order.action_sent().
As the amount is derived directly from the counterpart move line,
we do not expect a write off. Take partial reconciliations into
account though.
:param payment_line_id: the single id of the canceled payment line
Don't group the payment lines that are attached to the same supplier
but to move lines with different accounts (very unlikely),
for easier generation/comprehension of the transfer move
"""
transit_move_line = self.transit_move_line_id
# if (not transit_move_line or not torec_move_line):
# raise exceptions.UserError(
# _('Can not reconcile: no move line for line %s') % self.name
# )
# if torec_move_line.reconcile_id:
# raise exceptions.UserError(
# _('Move line %s has already been reconciled') %
# torec_move_line.name
# )
# if (transit_move_line.reconcile_id or
# transit_move_line.reconcile_partial_id):
# raise exceptions.UserError(
# _('Move line %s has already been reconciled') %
# transit_move_line.name
# )
lines_to_rec = transit_move_line
for payment_line in self.payment_line_ids:
lines_to_rec += payment_line.move_line_id
lines_to_rec.reconcile_partial(type='auto')
res = super(PaymentLine, self).payment_line_hashcode()
res += '-' + unicode(
self.move_line_id and self.move_line_id.account_id or False)
return res

View File

@@ -1,24 +1,5 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# SEPA Direct Debit module for OpenERP
# Copyright (C) 2013 Akretion (http://www.akretion.com)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
#
# 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/>.
#
##############################################################################
# -*- coding: utf-8 -*-
from . import res_company
from . import account_banking_mandate
from . import bank_payment_line

View File

@@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# SEPA Direct Debit module for Odoo
# Copyright (C) 2015 Akretion (http://www.akretion.com)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
#
# 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 openerp import models, api
class BankPaymentLine(models.Model):
_inherit = 'bank.payment.line'
@api.multi
def move_line_transfer_account_hashcode(self):
"""
From my experience, even when you ask several direct debits
at the same date with enough delay, you will have several credits
on your bank statement: one for each mandate types.
So we split the transfer move lines by mandate type, so easier
reconciliation of the bank statement.
"""
hashcode = super(BankPaymentLine, self).\
move_line_transfer_account_hashcode()
hashcode += self.mandate_id.type
return hashcode