mirror of
https://github.com/OCA/account-financial-tools.git
synced 2025-02-02 12:47:26 +02:00
Move account_credit_control_dunning_fees to root folder
Set account_credit_control_dunning_fees to installable Extract the module description to README.rst Port Dunning fees to the new API, activate the tests for 8.0 Add fees in the report Use the new API instead of mocks for FixedFeesTester It will be easier to write additional tests Remove required on the currency and fallback to company's currency... ... on the policy level if it is empty. Also, it fixes a bug when a credit line had no currency and the level had the company's currency. As False is different than any currency, it entered in res_currency.compute() with a False currency. It must just fallback on the company's currency if the credit line's currency is empty.
This commit is contained in:
committed by
Akim Juillerat
parent
089b4846b4
commit
da48baad91
30
account_credit_control_dunning_fees/README.rst
Normal file
30
account_credit_control_dunning_fees/README.rst
Normal file
@@ -0,0 +1,30 @@
|
||||
Dunning Fees for Credit Control
|
||||
===============================
|
||||
|
||||
This extention of credit control adds the notion of dunning fees
|
||||
on credit control lines.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
For release 0.1 only fixed fees are supported.
|
||||
|
||||
You can specifiy a fixed fees amount, a product and a currency
|
||||
on the credit control level form.
|
||||
|
||||
The amount will be used as fees values the currency will determine
|
||||
the currency of the fee. If the credit control line has not the
|
||||
same currency as the fees currency, fees will be converted to
|
||||
the credit control line currency.
|
||||
|
||||
The product is used to compute taxes in reconciliation process.
|
||||
|
||||
Run
|
||||
---
|
||||
Fees are automatically computed on credit run and saved
|
||||
on the generated credit lines.
|
||||
|
||||
Fees can be manually edited as long credit line is draft
|
||||
|
||||
Credit control Summary report includes a new fees column
|
||||
--------------------------------------------------------
|
||||
Support of fees price list
|
||||
21
account_credit_control_dunning_fees/__init__.py
Normal file
21
account_credit_control_dunning_fees/__init__.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Nicolas Bessi
|
||||
# Copyright 2014 Camptocamp SA
|
||||
#
|
||||
# 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 model
|
||||
@@ -25,44 +25,12 @@
|
||||
'category': 'Accounting',
|
||||
'complexity': 'normal',
|
||||
'depends': ['account_credit_control'],
|
||||
'description': """
|
||||
Dunning Fees for Credit Control
|
||||
===============================
|
||||
|
||||
This extention of credit control adds the notion of dunning fees
|
||||
on credit control lines.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
For release 0.1 only fixed fees are supported.
|
||||
|
||||
You can specifiy a fixed fees amount, a product and a currency
|
||||
on the credit control level form.
|
||||
|
||||
The amount will be used as fees values the currency will determine
|
||||
the currency of the fee. If the credit control line has not the
|
||||
same currency as the fees currency, fees will be converted to
|
||||
the credit control line currency.
|
||||
|
||||
The product is used to compute taxes in reconciliation process.
|
||||
|
||||
Run
|
||||
---
|
||||
Fees are automatically computed on credit run and saved
|
||||
on the generated credit lines.
|
||||
|
||||
Fees can be manually edited as long credit line is draft
|
||||
|
||||
Credit control Summary report includes a new fees column.
|
||||
-------
|
||||
Support of fees price list
|
||||
|
||||
""",
|
||||
'website': 'http://www.camptocamp.com',
|
||||
'data': ['view/policy_view.xml',
|
||||
'view/line_view.xml',
|
||||
'report/report.xml',
|
||||
'security/ir.model.access.csv'],
|
||||
'report/report_credit_control_summary.xml',
|
||||
'security/ir.model.access.csv',
|
||||
],
|
||||
'demo': [],
|
||||
'test': [],
|
||||
'installable': True,
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
# Translation of OpenERP Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * account_credit_control_dunning_fees
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OpenERP Server 7.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2014-05-07 11:44+0000\n"
|
||||
"PO-Revision-Date: 2014-05-07 11:44+0000\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_credit_control_dunning_fees
|
||||
#: code:_description:0
|
||||
#: model:ir.model,name:account_credit_control_dunning_fees.model_credit_control_line
|
||||
#, python-format
|
||||
msgid "A credit control line"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_credit_control_dunning_fees
|
||||
#: code:_description:0
|
||||
#: model:ir.model,name:account_credit_control_dunning_fees.model_credit_control_policy_level
|
||||
#, python-format
|
||||
msgid "A credit control policy level"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_credit_control_dunning_fees
|
||||
#: code:_description:0
|
||||
#: model:ir.model,name:account_credit_control_dunning_fees.model_credit_control_run
|
||||
#, python-format
|
||||
msgid "Credit control line generator"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_credit_control_dunning_fees
|
||||
#: field:credit.control.line,dunning_fees_amount:0
|
||||
#: view:credit.control.policy:0
|
||||
msgid "Fees"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_credit_control_dunning_fees
|
||||
#: field:credit.control.policy.level,dunning_fixed_amount:0
|
||||
msgid "Fees Fixed Amount"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_credit_control_dunning_fees
|
||||
#: field:credit.control.policy.level,dunning_product_id:0
|
||||
msgid "Fees Product"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_credit_control_dunning_fees
|
||||
#: field:credit.control.policy.level,dunning_currency_id:0
|
||||
msgid "Fees currency"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_credit_control_dunning_fees
|
||||
#: selection:credit.control.policy.level,dunning_fees_type:0
|
||||
msgid "Fixed"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_credit_control_dunning_fees
|
||||
#: view:credit.control.policy:0
|
||||
msgid "Mail and reporting"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_credit_control_dunning_fees
|
||||
#: code:_description:0
|
||||
#: model:ir.model,name:account_credit_control_dunning_fees.model_credit_control_dunning_fees_computer
|
||||
#, python-format
|
||||
msgid "credit.control.dunning.fees.computer"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_credit_control_dunning_fees
|
||||
#: field:credit.control.policy.level,dunning_fees_type:0
|
||||
msgid "unknown"
|
||||
msgstr ""
|
||||
|
||||
80
account_credit_control_dunning_fees/i18n/fr.po
Normal file
80
account_credit_control_dunning_fees/i18n/fr.po
Normal file
@@ -0,0 +1,80 @@
|
||||
# Translation of OpenERP Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * account_credit_control_dunning_fees
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OpenERP Server 7.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2014-04-16 07:11+0000\n"
|
||||
"PO-Revision-Date: 2014-04-16 07:11+0000\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_credit_control_dunning_fees
|
||||
#: code:_description:0
|
||||
#: model:ir.model,name:account_credit_control_dunning_fees.model_credit_control_line
|
||||
#, python-format
|
||||
msgid "A credit control line"
|
||||
msgstr "Ligne de relance"
|
||||
|
||||
#. module: account_credit_control_dunning_fees
|
||||
#: code:_description:0
|
||||
#: model:ir.model,name:account_credit_control_dunning_fees.model_credit_control_policy_level
|
||||
#, python-format
|
||||
msgid "A credit control policy level"
|
||||
msgstr "Une politique de relance"
|
||||
|
||||
#. module: account_credit_control_dunning_fees
|
||||
#: code:_description:0
|
||||
#: model:ir.model,name:account_credit_control_dunning_fees.model_credit_control_run
|
||||
#, python-format
|
||||
msgid "Credit control line generator"
|
||||
msgstr "Générateur de relance"
|
||||
|
||||
#. module: account_credit_control_dunning_fees
|
||||
#: field:credit.control.line,dunning_fees_amount:0
|
||||
#: view:credit.control.policy:0
|
||||
msgid "Fees"
|
||||
msgstr "Frais de relance"
|
||||
|
||||
#. module: account_credit_control_dunning_fees
|
||||
#: field:credit.control.policy.level,dunning_fixed_amount:0
|
||||
msgid "Fees Fixed Amount"
|
||||
msgstr "Montant des frais"
|
||||
|
||||
#. module: account_credit_control_dunning_fees
|
||||
#: field:credit.control.policy.level,dunning_product_id:0
|
||||
msgid "Fees Product"
|
||||
msgstr "Article lié"
|
||||
|
||||
#. module: account_credit_control_dunning_fees
|
||||
#: field:credit.control.policy.level,dunning_currency_id:0
|
||||
msgid "Fees currency"
|
||||
msgstr "Devises"
|
||||
|
||||
#. module: account_credit_control_dunning_fees
|
||||
#: selection:credit.control.policy.level,dunning_fees_type:0
|
||||
msgid "Fixed"
|
||||
msgstr "Fixe"
|
||||
|
||||
#. module: account_credit_control_dunning_fees
|
||||
#: view:credit.control.policy:0
|
||||
msgid "Mail and reporting"
|
||||
msgstr "Lettres et e-mails"
|
||||
|
||||
#. module: account_credit_control_dunning_fees
|
||||
#: code:_description:0
|
||||
#: model:ir.model,name:account_credit_control_dunning_fees.model_credit_control_dunning_fees_computer
|
||||
#, python-format
|
||||
msgid "credit.control.dunning.fees.computer"
|
||||
msgstr "credit.control.dunning.fees.computer"
|
||||
|
||||
#. module: account_credit_control_dunning_fees
|
||||
#: field:credit.control.policy.level,dunning_fees_type:0
|
||||
msgid "unknown"
|
||||
msgstr "inconnu"
|
||||
24
account_credit_control_dunning_fees/model/__init__.py
Normal file
24
account_credit_control_dunning_fees/model/__init__.py
Normal file
@@ -0,0 +1,24 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Nicolas Bessi
|
||||
# Copyright 2014 Camptocamp SA
|
||||
#
|
||||
# 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 line
|
||||
from . import policy
|
||||
from . import run
|
||||
from . import dunning
|
||||
@@ -18,16 +18,16 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from openerp.osv import orm
|
||||
from openerp import models, api
|
||||
|
||||
|
||||
class FeesComputer(orm.BaseModel):
|
||||
class FeesComputer(models.BaseModel):
|
||||
"""Model that compute dunnig fees.
|
||||
|
||||
This class does not need any database storage as
|
||||
it contains pure logic.
|
||||
|
||||
It inherits form ``orm.BaseModel`` to benefit of orm facility
|
||||
It inherits form ``models.BaseModel`` to benefit of orm facility
|
||||
|
||||
Similar to AbstractModel but log access and actions
|
||||
"""
|
||||
@@ -38,16 +38,18 @@ class FeesComputer(orm.BaseModel):
|
||||
_register = True
|
||||
_transient = False
|
||||
|
||||
@api.model
|
||||
def _get_compute_fun(self, level_fees_type):
|
||||
"""Retrieve function of class that should compute the fees based on type
|
||||
"""Retrieve function of class that should compute the fees based
|
||||
on type
|
||||
|
||||
:param level_fee_type: type exisiting in model
|
||||
:param level_fee_type: type existing in model
|
||||
`credit.control.policy.level`
|
||||
for field dunning_fees_type
|
||||
|
||||
:returns: a function of class :class:`FeesComputer`
|
||||
with following signature
|
||||
self, cr, uid, credit_line (record), context
|
||||
self, credit_line (record)
|
||||
|
||||
"""
|
||||
if level_fees_type == 'fixed':
|
||||
@@ -56,33 +58,30 @@ class FeesComputer(orm.BaseModel):
|
||||
raise NotImplementedError('fees type %s is not supported' %
|
||||
level_fees_type)
|
||||
|
||||
def _compute_fees(self, cr, uid, credit_line_ids, context=None):
|
||||
"""Compute fees for `credit_line_ids` parameter
|
||||
@api.model
|
||||
def _compute_fees(self, credit_lines):
|
||||
"""Compute fees for `credit_lines` parameter
|
||||
|
||||
Fees amount is written on credit line in field dunning_fees_amount
|
||||
Fees amount is written on credit lines in the field dunning_fees_amount
|
||||
|
||||
:param credit_line_ids: list of `credit.control.line` ids
|
||||
:param credit_lines: recordset of `credit.control.line`
|
||||
|
||||
:returns: `credit_line_ids` list of `credit.control.line` ids
|
||||
:returns: recordset of `credit.control.line`
|
||||
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
if not credit_line_ids:
|
||||
return credit_line_ids
|
||||
c_model = self.pool['credit.control.line']
|
||||
credit_lines = c_model.browse(cr, uid, credit_line_ids,
|
||||
context=context)
|
||||
if not credit_lines:
|
||||
return credit_lines
|
||||
for credit in credit_lines:
|
||||
# if there is no dependence between generated credit lines
|
||||
# this could be threaded
|
||||
self._compute(cr, uid, credit, context=context),
|
||||
return credit_line_ids
|
||||
self._compute(credit)
|
||||
return credit_lines
|
||||
|
||||
def _compute(self, cr, uid, credit_line, context=None):
|
||||
@api.model
|
||||
def _compute(self, credit_line):
|
||||
"""Compute fees for a given credit line
|
||||
|
||||
Fees amount is written on credit line in field dunning_fees_amount
|
||||
Fees amount is written on credit line in then field dunning_fees_amount
|
||||
|
||||
:param credit_line: credit line record
|
||||
|
||||
@@ -90,13 +89,13 @@ class FeesComputer(orm.BaseModel):
|
||||
"""
|
||||
fees_type = credit_line.policy_level_id.dunning_fees_type
|
||||
compute = self._get_compute_fun(fees_type)
|
||||
fees = compute(cr, uid, credit_line, context=context)
|
||||
fees = compute(credit_line)
|
||||
if fees:
|
||||
credit_line.write({'dunning_fees_amount': fees},
|
||||
context=context)
|
||||
credit_line.write({'dunning_fees_amount': fees})
|
||||
return credit_line
|
||||
|
||||
def compute_fixed_fees(self, cr, uid, credit_line, context=None):
|
||||
@api.model
|
||||
def compute_fixed_fees(self, credit_line):
|
||||
"""Compute fees amount for fixed fees.
|
||||
Correspond to the fixed dunning fees type
|
||||
|
||||
@@ -109,16 +108,15 @@ class FeesComputer(orm.BaseModel):
|
||||
:return: fees amount float (in credit line currency)
|
||||
|
||||
"""
|
||||
currency_model = self.pool['res.currency']
|
||||
credit_currency = credit_line.currency_id
|
||||
credit_currency = (credit_line.currency_id or
|
||||
credit_line.company_id.currency_id)
|
||||
level = credit_line.policy_level_id
|
||||
fees_amount = level.dunning_fixed_amount
|
||||
if not fees_amount:
|
||||
return 0.0
|
||||
fees_currency = level.dunning_currency_id
|
||||
fees_currency = (level.dunning_currency_id or
|
||||
level.policy_id.company_id.currency_id)
|
||||
if fees_currency == credit_currency:
|
||||
return fees_amount
|
||||
else:
|
||||
return currency_model.compute(cr, uid, fees_currency.id,
|
||||
credit_currency.id, fees_amount,
|
||||
context=context)
|
||||
return fees_currency.compute(fees_amount, credit_currency)
|
||||
|
||||
29
account_credit_control_dunning_fees/model/line.py
Normal file
29
account_credit_control_dunning_fees/model/line.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Nicolas Bessi
|
||||
# Copyright 2014 Camptocamp SA
|
||||
#
|
||||
# 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
|
||||
|
||||
|
||||
class CreditControlLine(models.Model):
|
||||
"""Add dunning_fees_amount_fees field"""
|
||||
|
||||
_inherit = "credit.control.line"
|
||||
|
||||
dunning_fees_amount = fields.Float(string='Fees')
|
||||
44
account_credit_control_dunning_fees/model/policy.py
Normal file
44
account_credit_control_dunning_fees/model/policy.py
Normal file
@@ -0,0 +1,44 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Nicolas Bessi
|
||||
# Copyright 2014 Camptocamp SA
|
||||
#
|
||||
# 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
|
||||
|
||||
|
||||
class CreditControlPolicy(models.Model):
|
||||
"""ADD dunning fees fields"""
|
||||
|
||||
_inherit = "credit.control.policy.level"
|
||||
|
||||
dunning_product_id = fields.Many2one('product.product',
|
||||
string='Fees Product')
|
||||
|
||||
dunning_fixed_amount = fields.Float(string='Fees Fixed Amount')
|
||||
|
||||
dunning_currency_id = fields.Many2one(
|
||||
'res.currency',
|
||||
string='Fees currency',
|
||||
help="Currency of the dunning fees. If empty, it takes the "
|
||||
"company's currency."
|
||||
)
|
||||
|
||||
# planned type are fixed, percent, compound
|
||||
dunning_fees_type = fields.Selection([('fixed', 'Fixed')],
|
||||
string='Type',
|
||||
default='fixed')
|
||||
@@ -18,22 +18,19 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from openerp.osv import orm
|
||||
from openerp import models, api
|
||||
|
||||
|
||||
class credit_control_run(orm.Model):
|
||||
class CreditControlRun(models.Model):
|
||||
"""Add computation of fees"""
|
||||
|
||||
_inherit = "credit.control.run"
|
||||
|
||||
def _generate_credit_lines(self, cr, uid, run_id, context=None):
|
||||
@api.multi
|
||||
@api.returns('credit.control.line')
|
||||
def _generate_credit_lines(self):
|
||||
"""Override method to add fees computation"""
|
||||
credit_line_ids = super(credit_control_run,
|
||||
self)._generate_credit_lines(
|
||||
cr,
|
||||
uid,
|
||||
run_id,
|
||||
context=context)
|
||||
fees_model = self.pool['credit.control.dunning.fees.computer']
|
||||
fees_model._compute_fees(cr, uid, credit_line_ids, context=context)
|
||||
return credit_line_ids
|
||||
credit_lines = super(CreditControlRun, self)._generate_credit_lines()
|
||||
fees_model = self.env['credit.control.dunning.fees.computer']
|
||||
fees_model._compute_fees(credit_lines)
|
||||
return credit_lines
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
## -*- coding: utf-8 -*-
|
||||
<html>
|
||||
<head>
|
||||
<style type="text/css">
|
||||
${css}
|
||||
body {
|
||||
font-family: helvetica;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.custom_text {
|
||||
font-family: helvetica;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
table {
|
||||
font-family: helvetica;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.header {
|
||||
margin-left: 0px;
|
||||
text-align: left;
|
||||
width: 300px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.basic_table{
|
||||
text-align: center;
|
||||
border: 1px solid lightGrey;
|
||||
border-collapse: collapse;
|
||||
font-family: helvetica;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.basic_table th {
|
||||
border: 1px solid lightGrey;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
.basic_table td {
|
||||
border: 1px solid lightGrey;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.list_table {
|
||||
border-color: black;
|
||||
text-align: center;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.list_table td {
|
||||
border-color: gray;
|
||||
border-top: 1px solid gray;
|
||||
text-align: left;
|
||||
font-size: 12px;
|
||||
padding-right: 3px;
|
||||
padding-left: 3px;
|
||||
padding-top: 3px;
|
||||
padding-bottom:3px;
|
||||
}
|
||||
|
||||
.list_table th {
|
||||
border-bottom: 2px solid black;
|
||||
text-align: left;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
padding-right: 3px
|
||||
padding-left: 3px
|
||||
}
|
||||
|
||||
.list_table thead {
|
||||
display: table-header-group;
|
||||
}
|
||||
|
||||
.address table {
|
||||
font-size: 11px;
|
||||
border-collapse: collapse;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.address .shipping {
|
||||
|
||||
}
|
||||
|
||||
.address .invoice {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.address .recipient {
|
||||
font-size: 13px;
|
||||
margin-right: 120px;
|
||||
margin-left: 350px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
|
||||
table .address_title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.address td.name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
td.amount, th.amount {
|
||||
text-align: right;
|
||||
padding-right:2px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
tr.line .note {
|
||||
border-style: none;
|
||||
font-size: 9px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
tr.line {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
%for comm in objects :
|
||||
<% setLang(comm.get_contact_address().lang) %>
|
||||
<div class="address">
|
||||
<table class="recipient">
|
||||
<%
|
||||
add = comm.get_contact_address()
|
||||
%>
|
||||
%if comm.partner_id.id == add.id:
|
||||
<tr><td class="name">${comm.partner_id.title and comm.partner_id.title.name or ''} ${comm.partner_id.name }</td></tr>
|
||||
<% address_lines = comm.partner_id.contact_address.split("\n") %>
|
||||
|
||||
%else:
|
||||
<tr><td class="name">${comm.partner_id.name or ''}</td></tr>
|
||||
<tr><td>${add.title and add.title.name or ''} ${add.name}</td></tr>
|
||||
<% address_lines = add.contact_address.split("\n")[1:] %>
|
||||
%endif
|
||||
%for part in address_lines:
|
||||
%if part:
|
||||
<tr><td>${part}</td></tr>
|
||||
%endif
|
||||
%endfor
|
||||
</table>
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
</div>
|
||||
<br/>
|
||||
<br/>
|
||||
<br/>
|
||||
<div>
|
||||
|
||||
<h3 style="clear: both; padding-top: 20px;">
|
||||
${_('Reminder')}: ${comm.current_policy_level.name or '' }
|
||||
</h3>
|
||||
|
||||
<p>${_('Dear')},</p>
|
||||
<p class="custom_text" width="95%">${comm.current_policy_level.custom_text.replace('\n', '<br />')}</p>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
<p><b>${_('Summary')}<br/></b></p>
|
||||
<table class="basic_table" style="width: 100%;">
|
||||
<tr>
|
||||
<th width="200">${_('Invoice number')}</th>
|
||||
<th>${_('Invoice date')}</th>
|
||||
<th>${_('Date due')}</th>
|
||||
<th>${_('Invoiced amount')}</th>
|
||||
<th>${_('Open amount')}</th>
|
||||
<th>${_('Fees')}</th>
|
||||
<th>${_('Currency')}</th>
|
||||
|
||||
</tr>
|
||||
%for line in comm.credit_control_line_ids:
|
||||
<tr>
|
||||
%if line.invoice_id:
|
||||
<td width="200">${line.invoice_id.number}
|
||||
%if line.invoice_id.name:
|
||||
<br/>
|
||||
${line.invoice_id.name}
|
||||
%endif
|
||||
</td>
|
||||
%else:
|
||||
<td width="200">${line.move_line_id.name}</td>
|
||||
%endif
|
||||
<td class="date">${line.date_entry}</td>
|
||||
<td class="date">${line.date_due}</td>
|
||||
<td class="amount">${line.amount_due}</td>
|
||||
<td class="amount">${line.balance_due}</td>
|
||||
<td class="amount">${line.dunning_fees_amount}</td>
|
||||
<td class="amount">${line.currency_id.name or comm.company_id.currency_id.name}</td>
|
||||
</tr>
|
||||
%endfor
|
||||
</table>
|
||||
<br/>
|
||||
<br/>
|
||||
<%doc>
|
||||
<!-- uncomment to have info after summary -->
|
||||
<p>${_('If you have any question, do not hesitate to contact us.')}</p>
|
||||
|
||||
<p>${comm.user_id.name} ${comm.user_id.email and '<%s>'%(comm.user_id.email) or ''}<br/>
|
||||
${comm.company_id.name}<br/>
|
||||
% if comm.company_id.street:
|
||||
${comm.company_id.street or ''}<br/>
|
||||
|
||||
% endif
|
||||
|
||||
% if comm.company_id.street2:
|
||||
${comm.company_id.street2}<br/>
|
||||
% endif
|
||||
% if comm.company_id.city or comm.company_id.zip:
|
||||
${comm.company_id.zip or ''} ${comm.company_id.city or ''}<br/>
|
||||
% endif
|
||||
% if comm.company_id.country_id:
|
||||
${comm.company_id.state_id and ('%s, ' % comm.company_id.state_id.name) or ''} ${comm.company_id.country_id.name or ''}<br/>
|
||||
% endif
|
||||
% if comm.company_id.phone:
|
||||
Phone: ${comm.company_id.phone}<br/>
|
||||
% endif
|
||||
% if comm.company_id.website:
|
||||
${comm.company_id.website or ''}<br/>
|
||||
% endif
|
||||
</%doc>
|
||||
|
||||
<p style="page-break-after:always"></p>
|
||||
%endfor
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="report_credit_control_summary_document_fees"
|
||||
inherit_id="account_credit_control.report_credit_control_summary_document">
|
||||
<xpath expr="//table[@id='summary_table']/thead/tr/th[last()]" position="after">
|
||||
<th class="text-right">Fees</th>
|
||||
</xpath>
|
||||
<xpath expr="//span[@t-field='l.balance_due']" position="replace">
|
||||
<span t-field="l.balance_due"/>
|
||||
</xpath>
|
||||
<xpath expr="//table[@id='summary_table']/tbody/tr/td[last()]" position="after">
|
||||
<td class="text-right">
|
||||
<span t-field="l.dunning_fees_amount"
|
||||
t-field-options='{"widget": "monetary",
|
||||
"display_currency": "l.currency_id or l.company_id.currency_id"}'/>
|
||||
</td>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
21
account_credit_control_dunning_fees/tests/__init__.py
Normal file
21
account_credit_control_dunning_fees/tests/__init__.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Author: Nicolas Bessi
|
||||
# Copyright 2014 Camptocamp SA
|
||||
#
|
||||
# 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 test_fees_generation
|
||||
@@ -18,42 +18,41 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from mock import MagicMock
|
||||
import openerp.tests.common as test_common
|
||||
from openerp.tests import common
|
||||
|
||||
|
||||
class FixedFeesTester(test_common.TransactionCase):
|
||||
@common.at_install(True)
|
||||
@common.post_install(True)
|
||||
class FixedFeesTester(common.TransactionCase):
|
||||
|
||||
def setUp(self):
|
||||
"""Initialize credit control level mock to test fees computations"""
|
||||
super(FixedFeesTester, self).setUp()
|
||||
self.currency_model = self.registry('res.currency')
|
||||
self.euro = self.currency_model.search(self.cr, self.uid,
|
||||
[('name', '=', 'EUR')])
|
||||
self.currency_model = self.env['res.currency']
|
||||
self.euro = self.currency_model.search([('name', '=', 'EUR')])
|
||||
self.assertTrue(self.euro)
|
||||
self.euro = self.registry('res.currency').browse(self.cr,
|
||||
self.uid,
|
||||
self.euro[0])
|
||||
|
||||
self.usd = self.currency_model.search(self.cr, self.uid,
|
||||
[('name', '=', 'USD')])
|
||||
self.usd = self.currency_model.search([('name', '=', 'USD')])
|
||||
self.assertTrue(self.usd)
|
||||
self.usd = self.registry('res.currency').browse(self.cr,
|
||||
self.uid,
|
||||
self.usd[0])
|
||||
|
||||
self.euro_level = MagicMock(name='Euro policy level')
|
||||
self.euro_level.dunning_fixed_amount = 5.0
|
||||
self.euro_level.dunning_currency_id = self.euro
|
||||
self.euro_level.dunning_type = 'fixed'
|
||||
self.company = self.browse_ref('base.main_company')
|
||||
self.company.currency_id = self.euro
|
||||
|
||||
self.usd_level = MagicMock(name='USD policy level')
|
||||
self.usd_level.dunning_fixed_amount = 5.0
|
||||
self.usd_level.dunning_currency_id = self.usd
|
||||
self.usd_level.dunning_type = 'fixed'
|
||||
self.dunning_model = self.registry(
|
||||
'credit.control.dunning.fees.computer'
|
||||
)
|
||||
level_obj = self.env['credit.control.policy.level']
|
||||
self.euro_level = level_obj.new({
|
||||
'name': 'Euro Level',
|
||||
'dunning_fixed_amount': 5.0,
|
||||
'dunning_currency_id': self.euro,
|
||||
'dunning_type': 'fixed',
|
||||
})
|
||||
|
||||
self.usd_level = level_obj.new({
|
||||
'name': 'USD Level',
|
||||
'dunning_fixed_amount': 5.0,
|
||||
'dunning_currency_id': self.usd,
|
||||
'dunning_type': 'fixed',
|
||||
})
|
||||
self.dunning_model = self.env['credit.control.dunning.fees.computer']
|
||||
self.line_model = self.env['credit.control.line']
|
||||
|
||||
def test_type_getter(self):
|
||||
"""Test that correct compute function is returned for "fixed" type"""
|
||||
@@ -67,31 +66,63 @@ class FixedFeesTester(test_common.TransactionCase):
|
||||
|
||||
def test_computation_same_currency(self):
|
||||
"""Test that fees are correctly computed with same currency"""
|
||||
credit_line = MagicMock(name='Euro credit line')
|
||||
credit_line.policy_level_id = self.euro_level
|
||||
credit_line.currency_id = self.euro
|
||||
fees = self.dunning_model.compute_fixed_fees(self.cr, self.uid,
|
||||
credit_line,
|
||||
{})
|
||||
credit_line = self.line_model.new({
|
||||
'policy_level_id': self.euro_level,
|
||||
'currency_id': self.euro,
|
||||
'company_id': self.company,
|
||||
})
|
||||
fees = self.dunning_model.compute_fixed_fees(credit_line)
|
||||
self.assertEqual(fees, self.euro_level.dunning_fixed_amount)
|
||||
|
||||
def test_computation_different_currency(self):
|
||||
"""Test that fees are correctly computed with different currency"""
|
||||
credit_line = MagicMock(name='USD credit line')
|
||||
credit_line.policy_level_id = self.euro_level
|
||||
credit_line.currency_id = self.usd
|
||||
fees = self.dunning_model.compute_fixed_fees(self.cr, self.uid,
|
||||
credit_line,
|
||||
{})
|
||||
credit_line = self.line_model.new({
|
||||
'policy_level_id': self.euro_level,
|
||||
'currency_id': self.usd.id,
|
||||
'company_id': self.company,
|
||||
})
|
||||
fees = self.dunning_model.compute_fixed_fees(credit_line)
|
||||
self.assertNotEqual(fees, self.euro_level.dunning_fixed_amount)
|
||||
|
||||
def test_computation_credit_currency_empty(self):
|
||||
"""Test that fees are correctly computed with empty credit currency"""
|
||||
credit_line = self.line_model.new({
|
||||
'policy_level_id': self.euro_level,
|
||||
'currency_id': False,
|
||||
'company_id': self.company,
|
||||
})
|
||||
fees = self.dunning_model.compute_fixed_fees(credit_line)
|
||||
self.assertEqual(fees, self.euro_level.dunning_fixed_amount)
|
||||
|
||||
def test_computation_level_currency_empty(self):
|
||||
"""Test that fees are correctly computed with empty level currency"""
|
||||
credit_line = self.line_model.new({
|
||||
'policy_level_id': self.euro_level,
|
||||
'currency_id': self.euro,
|
||||
'company_id': self.company,
|
||||
})
|
||||
self.euro_level.currency_id = False
|
||||
fees = self.dunning_model.compute_fixed_fees(credit_line)
|
||||
self.assertEqual(fees, self.euro_level.dunning_fixed_amount)
|
||||
|
||||
def test_computation_all_currency_empty(self):
|
||||
"""Test that fees are correctly computed with empty currencies"""
|
||||
credit_line = self.line_model.new({
|
||||
'policy_level_id': self.euro_level,
|
||||
'currency_id': False,
|
||||
'company_id': self.company,
|
||||
})
|
||||
self.euro_level.currency_id = False
|
||||
fees = self.dunning_model.compute_fixed_fees(credit_line)
|
||||
self.assertEqual(fees, self.euro_level.dunning_fixed_amount)
|
||||
|
||||
def test_no_fees(self):
|
||||
"""Test that fees are not generated if no amount defined on level"""
|
||||
credit_line = MagicMock(name='USD credit line')
|
||||
credit_line.policy_level_id = self.euro_level
|
||||
credit_line = self.line_model.new({
|
||||
'policy_level_id': self.euro_level,
|
||||
'currency_id': self.usd,
|
||||
'company_id': self.company,
|
||||
})
|
||||
self.euro_level.dunning_fixed_amount = 0.0
|
||||
credit_line.currency_id = self.usd
|
||||
fees = self.dunning_model.compute_fixed_fees(self.cr, self.uid,
|
||||
credit_line,
|
||||
{})
|
||||
fees = self.dunning_model.compute_fixed_fees(credit_line)
|
||||
self.assertEqual(fees, 0.0)
|
||||
|
||||
30
account_credit_control_dunning_fees/view/line_view.xml
Normal file
30
account_credit_control_dunning_fees/view/line_view.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="add_fees_on_credit_control_line" model="ir.ui.view">
|
||||
<field name="name">add fees on credit control line</field>
|
||||
<field name="model">credit.control.line</field>
|
||||
<field name="inherit_id" ref="account_credit_control.credit_control_line_tree" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="balance_due" position="after">
|
||||
<field name="dunning_fees_amount"
|
||||
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="add_fees_on_credit_control_line_from" model="ir.ui.view">
|
||||
<field name="name">add fees on credit control line form</field>
|
||||
<field name="model">credit.control.line</field>
|
||||
<field name="inherit_id" ref="account_credit_control.credit_control_line_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="balance_due" position="after">
|
||||
<field name="dunning_fees_amount"
|
||||
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
24
account_credit_control_dunning_fees/view/policy_view.xml
Normal file
24
account_credit_control_dunning_fees/view/policy_view.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="add_dunning_fees_on_policy" model="ir.ui.view">
|
||||
<field name="name">add dunning fees on policy</field>
|
||||
<field name="model">credit.control.policy</field>
|
||||
<field name="inherit_id" ref="account_credit_control.credit_control_policy_form" />
|
||||
<field name="arch" type="xml">
|
||||
<page string="Mail and reporting" position="after">
|
||||
<page string="Fees">
|
||||
<group>
|
||||
<group>
|
||||
<field name="dunning_fixed_amount"/>
|
||||
<field name="dunning_product_id"/>
|
||||
<field name="dunning_currency_id"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
</page>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
Reference in New Issue
Block a user