[ADD] credit control policy changer.

Add a wizard on Invoice that will add a credit line and deprecate exisiting one on the invoice
This commit is contained in:
Nicolas Bessi
2014-04-08 09:52:42 +02:00
parent 9f9a4303ae
commit 43c6f3f1de
6 changed files with 223 additions and 23 deletions

View File

@@ -69,6 +69,7 @@ On each generated line, you have many choices:
"wizard/credit_control_emailer_view.xml",
"wizard/credit_control_marker_view.xml",
"wizard/credit_control_printer_view.xml",
"wizard/credit_control_policy_changer_view.xml",
"security/ir.model.access.csv"],
'demo_xml': ["credit_control_demo.xml"],
'tests': [],

View File

@@ -116,6 +116,7 @@ class CreditControlLine(orm.Model):
string='Level',
store=True,
readonly=True),
'manually_overriden': fields.boolean('Manually overriden')
}
@@ -141,8 +142,27 @@ class CreditControlLine(orm.Model):
return data
def create_or_update_from_mv_lines(self, cr, uid, ids, lines,
level_id, controlling_date, context=None):
"""Create or update line based on levels"""
level_id, controlling_date,
check_tolerance=True, context=None):
"""Create or update line based on levels
if check_tolerance is true credit line will not be
created if open amount is too small.
eg. we do not want to send a letter for 10 cents
of open amount.
:param lines: move.line id list
:param level_id: credit.control.policy.level id
:param controlling_date: date string of the credit controlling date.
Generally it should be the same
as create date
:param check_tolerance: boolean if True credit line
will not be generated if open amount
is smaller than company defined
tolerance
:returns: list of created credit line ids
"""
currency_obj = self.pool.get('res.currency')
level_obj = self.pool.get('credit.control.policy.level')
ml_obj = self.pool.get('account.move.line')
@@ -164,26 +184,31 @@ class CreditControlLine(orm.Model):
for line in ml_obj.browse(cr, uid, lines, context):
open_amount = line.amount_residual_currency
cur_tolerance = tolerance.get(line.currency_id.id, tolerance_base)
if check_tolerance and open_amount < cur_tolerance:
continue
vals = self._prepare_from_move_line(cr, uid,
line,
level,
controlling_date,
open_amount,
context=context)
line_id = self.create(cr, uid, vals, context=context)
line_ids.append(line_id)
if open_amount > tolerance.get(line.currency_id.id, tolerance_base):
vals = self._prepare_from_move_line(
cr, uid, line, level, controlling_date, open_amount, context=context)
line_id = self.create(cr, uid, vals, context=context)
line_ids.append(line_id)
# when we have lines generated earlier in draft,
# on the same level, it means that we have left
# them, so they are to be considered as ignored
previous_draft_ids = self.search(
cr, uid,
[('move_line_id', '=', line.id),
('level', '=', level.id),
('state', '=', 'draft'),
('id', '!=', line_id)],
context=context)
if previous_draft_ids:
self.write(cr, uid, previous_draft_ids,
{'state': 'ignored'}, context=context)
# when we have lines generated earlier in draft,
# on the same level, it means that we have left
# them, so they are to be considered as ignored
previous_draft_ids = self.search(
cr, uid,
[('move_line_id', '=', line.id),
('level', '=', level.id),
('state', '=', 'draft'),
('id', '!=', line_id)],
context=context)
if previous_draft_ids:
self.write(cr, uid, previous_draft_ids,
{'state': 'ignored'}, context=context)
return line_ids

View File

@@ -319,8 +319,10 @@ class CreditControlPolicyLevel(Model):
" FROM credit_control_line\n"
" WHERE move_line_id = mv_line.id\n"
# lines from a previous level with a draft or ignored state
# or manually overriden
# have to be generated again for the previous level
" AND state not in ('draft', 'ignored'))")
" AND NOT manually_overriden\n"
" AND state NOT IN ('draft', 'ignored'))")
sql += " AND"
sql += self._get_sql_date_boundary_for_computation_mode(cr, uid, level,
controlling_date, context)
@@ -346,11 +348,14 @@ class CreditControlPolicyLevel(Model):
" WHERE cr_line.id = (SELECT credit_control_line.id FROM credit_control_line\n"
" WHERE credit_control_line.move_line_id = mv_line.id\n"
" AND state != 'ignored'"
" AND NOT manually_overriden"
" ORDER BY credit_control_line.level desc limit 1)\n"
" AND cr_line.level = %(previous_level)s\n"
# lines from a previous level with a draft or ignored state
# or manually overriden
# have to be generated again for the previous level
" AND cr_line.state not in ('draft', 'ignored')\n"
" AND NOT manually_overriden\n"
" AND cr_line.state NOT IN ('draft', 'ignored')\n"
" AND mv_line.id in %(line_ids)s\n")
sql += " AND "
sql += self._get_sql_date_boundary_for_computation_mode(cr, uid, level,

View File

@@ -22,3 +22,4 @@ from . import credit_control_emailer
from . import credit_control_marker
from . import credit_control_printer
from . import credit_control_communication
from . import credit_control_policy_changer

View File

@@ -0,0 +1,106 @@
# -*- 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 itertools import chain
from openerp.osv import orm, fields
class credit_control_policy_changer(orm.TransientModel):
"""Wizard that is run from invoices and allows to set manually a policy
Policy are actually apply to related move lines availabe
in selection widget
"""
_name = "credit.control.policy.changer"
_columns = {
'new_policy_id': fields.many2one('credit.control.policy',
'New Policy to Apply',
required=True),
'new_policy_level_id': fields.many2one('credit.control.policy.level',
'New level to apply',
required=True),
'move_line_ids': fields.many2many('account.move.line',
rel='credit_changer_ml_rel',
string='Move line to change'),
}
def _get_default_lines(self, cr, uid, context=None):
if context is None:
context = {}
active_ids = context.get('active_ids')
selected_line_ids = []
inv_model = self.pool['account.invoice']
move_line_model = self.pool['account.move.line']
if not active_ids:
return False
# raise ValueError('No active_ids passed in context')
for invoice in inv_model.browse(cr, uid, active_ids, context=context):
domain = [('account_id', '=', invoice.account_id.id),
('move_id', '=', invoice.move_id.id),
('reconcile_id', '=', False)]
move_ids = move_line_model.search(cr, uid, domain, context=context)
selected_line_ids.extend(move_ids)
return selected_line_ids
_defaults = {'move_line_ids': _get_default_lines}
def _mark_as_overriden(self, cr, uid, move_lines, context=None):
credit_model = self.pool['credit.control.line']
domain = [('id', 'in', [x.id for x in move_lines])]
credits_ids = credit_model.search(cr, uid, domain, context=context)
credit_model.write(cr, uid,
credits_ids,
{'manually_overriden': True},
context)
return credits_ids
def set_new_policy(self, cr, uid, wizard_id, context=None):
assert len(wizard_id) == 1, "Only one id expected"
wizard_id = wizard_id[0]
credit_line_model = self.pool['credit.control.line']
ir_model = self.pool['ir.model.data']
ui_act_model = self.pool['ir.actions.act_window']
wizard = self.browse(cr, uid, wizard_id, context=context)
controlling_date = fields.date.today()
self._mark_as_overriden(cr,
uid,
wizard.move_line_ids,
context=context)
# As disscused with business expert
# draft line should be passed to ignored
# if same level as the new one
# As it is a manual action
# We also ignore rounding tolerance
generated_ids = credit_line_model.create_or_update_from_mv_lines(
cr, uid, [],
[x.id for x in wizard.move_line_ids],
wizard.new_policy_level_id.id,
controlling_date,
check_tolerance=False,
context=None
)
view_id = ir_model.get_object_reference(cr, uid,
"account_credit_control",
"credit_control_line_action")
assert view_id, 'No view found'
action = ui_act_model.read(cr, uid, view_id[1], context=context)
action['domain'] = [('id', 'in', generated_ids)]
return action

View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="credit_control_policy_changer_form" model="ir.ui.view">
<field name="name">credit control policy form</field>
<field name="model">credit.control.policy.changer</field>
<field name="arch" type="xml">
<form version="7.0" string="Set current credit level">
<separator string="Change the overdue level of current invoice" colspan="4"/>
<label string="This wizard will let you set the overdue policy and level for selected invoices"/>
<newline/>
<group>
<group>
<field name="new_policy_id"/>
<field name="new_policy_level_id"
domain="[('policy_id', '=', new_policy_id)]"/>
</group>
<group></group>
</group>
<notebook colspan="4">
<page string="Move lines to affect">
<field name="move_line_ids"/>
</page>
</notebook>
<footer>
<button class="oe_highlight"
name="set_new_policy"
string="Set new policy"
type="object"/>
or
<button class="oe_link"
special="cancel"
string="Cancel"/>
</footer>
</form>
</field>
</record>
<!-- for button -->
<record id="action_wizard_credit_policy_changer" model="ir.actions.act_window">
<field name="name">Change current credit policy</field>
<field name="res_model">credit.control.policy.changer</field>
<field name="src_model">account.invoice</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="view_id" ref="credit_control_policy_changer_form"/>
<field name="target">new</field>
<field name="help">Allows to manually change credit level</field>
</record>
<!-- for menu -->
<act_window name="Change current credit policy"
res_model="credit.control.policy.changer"
src_model="account.invoice"
view_mode="form"
target="new"
key2="client_action_multi"
id="action_wizard_credit_policy_changer_menu_action"/>
</data>
</openerp>