mirror of
https://github.com/OCA/account-financial-tools.git
synced 2025-02-02 12:47:26 +02:00
[FIX+IMP] account_credit_control
* scenarios: We fix year of scenario on 2013 to have reproducable setup, and ensure test maintnability. The credit control scenarios are based on base_finance setup scenario provided in the project OpenERP Scenarios. This setup provide a financial setup for 2012 2013. We also fix some value as precision computation has been improved in OpenERP. * bug 1287072 Level calculation error if previous credit line is ignored * unifing wizard views to respect UI guide lines * credit control policy changer. Add a wizard on Invoice that will add a credit line and deprecate exisiting one on the invoice * test to ensure that wizard run on customer invoice * Scenario that test coherence of credit run after manually altering an invoice level * multicurrency in communication * ...
This commit is contained in:
committed by
Pedro M. Baeza
parent
9f1e86178c
commit
42a4171121
@@ -19,7 +19,7 @@
|
||||
#
|
||||
##############################################################################
|
||||
{'name': 'Account Credit Control',
|
||||
'version': '0.1',
|
||||
'version': '0.2.0',
|
||||
'author': 'Camptocamp',
|
||||
'maintainer': 'Camptocamp',
|
||||
'category': 'Finance',
|
||||
@@ -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': [],
|
||||
|
||||
@@ -27,11 +27,11 @@ class AccountAccount(orm.Model):
|
||||
_inherit = "account.account"
|
||||
|
||||
_columns = {
|
||||
'credit_control_line_ids':
|
||||
fields.one2many('credit.control.line',
|
||||
'account_id',
|
||||
string='Credit Lines',
|
||||
readonly=True),
|
||||
'credit_control_line_ids': fields.one2many(
|
||||
'credit.control.line',
|
||||
'account_id',
|
||||
string='Credit Lines',
|
||||
readonly=True),
|
||||
}
|
||||
|
||||
def copy_data(self, cr, uid, id, default=None, context=None):
|
||||
@@ -42,34 +42,3 @@ class AccountAccount(orm.Model):
|
||||
default['credit_control_line_ids'] = False
|
||||
return super(AccountAccount, self).copy_data(
|
||||
cr, uid, id, default=default, context=context)
|
||||
|
||||
|
||||
class AccountInvoice(orm.Model):
|
||||
"""Add a link to a credit control policy on account.account"""
|
||||
|
||||
_inherit = "account.invoice"
|
||||
_columns = {
|
||||
'credit_policy_id':
|
||||
fields.many2one('credit.control.policy',
|
||||
'Credit Control Policy',
|
||||
help=("The Credit Control Policy used for this "
|
||||
"invoice. If nothing is defined, it will "
|
||||
"use the account setting or the partner "
|
||||
"setting.")
|
||||
),
|
||||
'credit_control_line_ids':
|
||||
fields.one2many('credit.control.line',
|
||||
'invoice_id',
|
||||
string='Credit Lines',
|
||||
readonly=True),
|
||||
}
|
||||
|
||||
def copy_data(self, cr, uid, id, default=None, context=None):
|
||||
if default is None:
|
||||
default = {}
|
||||
else:
|
||||
default = default.copy()
|
||||
default = default.copy()
|
||||
default['credit_control_line_ids'] = False
|
||||
return super(AccountInvoice, self).copy_data(
|
||||
cr, uid, id, default=default, context=context)
|
||||
|
||||
@@ -31,7 +31,7 @@ class ResCompany(orm.Model):
|
||||
'credit_policy_id': fields.many2one('credit.control.policy',
|
||||
'Credit Control Policy',
|
||||
help=("The Credit Control Policy used on partners"
|
||||
" by default. This setting can be overriden"
|
||||
" by default. This setting can be overridden"
|
||||
" on partners or invoices.")),
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,21 @@
|
||||
<field name="do_nothing" eval="1"/>
|
||||
</record>
|
||||
|
||||
<!-- no follow policy -->
|
||||
<record model="credit.control.policy.level"
|
||||
id="no_follow_1">
|
||||
<field name="name">No follow</field>
|
||||
<field name="level" eval="1"/>
|
||||
<field name="computation_mode">net_days</field>
|
||||
<field name="delay_days" eval="0"/>
|
||||
<field name="email_template_id" ref="email_template_credit_control_base"/>
|
||||
<field name="policy_id" ref="credit_control_no_follow"/>
|
||||
<field name="channel">email</field>
|
||||
<field name="custom_text">Manual no follow</field>
|
||||
|
||||
<field name="custom_mail_text">Manual no follow</field>
|
||||
</record>
|
||||
|
||||
<!-- policy 1 -->
|
||||
<record model="credit.control.policy"
|
||||
id="credit_control_3_time">
|
||||
|
||||
@@ -984,10 +984,10 @@ msgstr "60 days last reminder"
|
||||
#: help:res.company,credit_policy_id:0
|
||||
msgid ""
|
||||
"The Credit Control Policy used on partners by default. This setting can be "
|
||||
"overriden on partners or invoices."
|
||||
"overridden on partners or invoices."
|
||||
msgstr ""
|
||||
"The Credit Control Policy used on partners by default. This setting can be "
|
||||
"overriden on partners or invoices."
|
||||
"overridden on partners or invoices."
|
||||
|
||||
#. module: account_credit_control
|
||||
#: field:credit.control.line,policy_level_id:0
|
||||
|
||||
@@ -984,10 +984,10 @@ msgstr "60 days last reminder"
|
||||
#: help:res.company,credit_policy_id:0
|
||||
msgid ""
|
||||
"The Credit Control Policy used on partners by default. This setting can be "
|
||||
"overriden on partners or invoices."
|
||||
"overridden on partners or invoices."
|
||||
msgstr ""
|
||||
"The Credit Control Policy used on partners by default. This setting can be "
|
||||
"overriden on partners or invoices."
|
||||
"overridden on partners or invoices."
|
||||
|
||||
#. module: account_credit_control
|
||||
#: field:credit.control.line,policy_level_id:0
|
||||
@@ -1042,4 +1042,4 @@ msgstr "Currency"
|
||||
#. module: account_credit_control
|
||||
#: report:addons/account_credit_control/report/credit_control_summary.html.mako:211
|
||||
msgid "If you have any question, do not hesitate to contact us."
|
||||
msgstr "If you have any question, do not hesitate to contact us."
|
||||
msgstr "If you have any question, do not hesitate to contact us."
|
||||
|
||||
@@ -982,10 +982,10 @@ msgstr "60 days last reminder"
|
||||
#: help:res.company,credit_policy_id:0
|
||||
msgid ""
|
||||
"The Credit Control Policy used on partners by default. This setting can be "
|
||||
"overriden on partners or invoices."
|
||||
"overridden on partners or invoices."
|
||||
msgstr ""
|
||||
"The Credit Control Policy used on partners by default. This setting can be "
|
||||
"overriden on partners or invoices."
|
||||
"overridden on partners or invoices."
|
||||
|
||||
#. module: account_credit_control
|
||||
#: field:credit.control.line,policy_level_id:0
|
||||
@@ -1040,4 +1040,4 @@ msgstr "Currency"
|
||||
#. module: account_credit_control
|
||||
#: report:addons/account_credit_control/report/credit_control_summary.html.mako:211
|
||||
msgid "If you have any question, do not hesitate to contact us."
|
||||
msgstr "If you have any question, do not hesitate to contact us."
|
||||
msgstr "If you have any question, do not hesitate to contact us."
|
||||
|
||||
@@ -965,7 +965,7 @@ msgstr "Dernier rappel à 60 jours"
|
||||
#: help:res.company,credit_policy_id:0
|
||||
msgid ""
|
||||
"The Credit Control Policy used on partners by default. This setting can be "
|
||||
"overriden on partners or invoices."
|
||||
"overridden on partners or invoices."
|
||||
msgstr ""
|
||||
"Politique de relance par défaut du client. (Ce paramétrage peut être "
|
||||
"défini plus spécifiquement au niveau de la facture)."
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from openerp.osv import orm
|
||||
from openerp.osv import orm, fields
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
@@ -26,7 +26,36 @@ class AccountInvoice(orm.Model):
|
||||
"""Check on cancelling of an invoice"""
|
||||
_inherit = 'account.invoice'
|
||||
|
||||
_columns = {
|
||||
'credit_policy_id':
|
||||
fields.many2one('credit.control.policy',
|
||||
'Credit Control Policy',
|
||||
help=("The Credit Control Policy used for this "
|
||||
"invoice. If nothing is defined, it will "
|
||||
"use the account setting or the partner "
|
||||
"setting."),
|
||||
readonly=True,
|
||||
),
|
||||
'credit_control_line_ids':
|
||||
fields.one2many('credit.control.line',
|
||||
'invoice_id',
|
||||
string='Credit Lines',
|
||||
readonly=True),
|
||||
}
|
||||
|
||||
def copy_data(self, cr, uid, id, default=None, context=None):
|
||||
"""Ensure that credit lines and policy are not copied"""
|
||||
if default is None:
|
||||
default = {}
|
||||
else:
|
||||
default = default.copy()
|
||||
default['credit_control_line_ids'] = False
|
||||
default['credit_policy_id'] = False
|
||||
return super(AccountInvoice, self).copy_data(
|
||||
cr, uid, id, default=default, context=context)
|
||||
|
||||
def action_cancel(self, cr, uid, ids, context=None):
|
||||
"""Prevent to cancel invoice related to credit line"""
|
||||
# We will search if this invoice is linked with credit
|
||||
cc_line_obj = self.pool.get('credit.control.line')
|
||||
for invoice_id in ids:
|
||||
|
||||
@@ -38,9 +38,11 @@ class CreditControlLine(orm.Model):
|
||||
_name = "credit.control.line"
|
||||
_description = "A credit control line"
|
||||
_rec_name = "id"
|
||||
|
||||
_order = "date DESC"
|
||||
_columns = {
|
||||
'date': fields.date('Controlling date', required=True),
|
||||
'date': fields.date('Controlling date',
|
||||
required=True,
|
||||
select=True),
|
||||
# maturity date of related move line we do not use a related field in order to
|
||||
# allow manual changes
|
||||
'date_due': fields.date('Due date',
|
||||
@@ -116,6 +118,7 @@ class CreditControlLine(orm.Model):
|
||||
string='Level',
|
||||
store=True,
|
||||
readonly=True),
|
||||
'manually_overridden': fields.boolean('Manually overridden')
|
||||
}
|
||||
|
||||
|
||||
@@ -141,8 +144,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 +186,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),
|
||||
('policy_level_id', '=', 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
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<field name="date_due"/>
|
||||
<field name="date_sent"/>
|
||||
<field name="level"/>
|
||||
<field name="manually_overridden"/>
|
||||
<field name="state"/>
|
||||
<field name="channel"/>
|
||||
<field name="invoice_id"/>
|
||||
@@ -32,7 +33,7 @@
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Control Credit Lines">
|
||||
<group>
|
||||
<group string="Filters">
|
||||
<filter name="filter_draft" icon="terp-mail-message-new"
|
||||
string="Draft" domain="[('state', '=', 'draft')]"
|
||||
help="Draft lines have to be triaged."/>
|
||||
@@ -48,6 +49,9 @@
|
||||
<filter name="filter_error" icon="terp-gtk-stop" string="Error"
|
||||
domain="[('state', 'in', ('error', 'email_error'))]"
|
||||
help="An error has occured during the sending of the email."/>
|
||||
<filter name="filter_manual" icon="terp-gtk-stop" string="Manual change"
|
||||
domain="[('manually_overridden', '=', True)]"
|
||||
help="The line was deprecated by a manual change of policy on invoice."/>
|
||||
<separator orientation="vertical"/>
|
||||
|
||||
<field name="date"/>
|
||||
@@ -89,6 +93,8 @@
|
||||
<separator orientation="vertical"/>
|
||||
<filter domain='[]' context="{'group_by': 'channel'}"
|
||||
icon="terp-document-new" string="Channel"/>
|
||||
<filter domain='[]' context="{'group_by': 'manually_overridden'}"
|
||||
icon="terp-document-new" string="Manual change"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
@@ -103,6 +109,7 @@
|
||||
<field name="date"/>
|
||||
<field name="date_due"/>
|
||||
<field name="level"/>
|
||||
<field name="manually_overridden"/>
|
||||
<field name="state"/>
|
||||
<field name="channel"/>
|
||||
<field name="invoice_id"/>
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#
|
||||
##############################################################################
|
||||
from openerp.osv import orm, fields
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class ResPartner(orm.Model):
|
||||
@@ -28,21 +29,47 @@ class ResPartner(orm.Model):
|
||||
_inherit = "res.partner"
|
||||
|
||||
_columns = {
|
||||
'credit_policy_id':
|
||||
fields.many2one('credit.control.policy',
|
||||
'Credit Control Policy',
|
||||
help=("The Credit Control Policy used for this "
|
||||
"partner. This setting can be forced on the "
|
||||
"invoice. If nothing is defined, it will use "
|
||||
"the company setting.")),
|
||||
'credit_control_line_ids':
|
||||
fields.one2many('credit.control.line',
|
||||
'invoice_id',
|
||||
string='Credit Control Lines',
|
||||
readonly=True)
|
||||
'credit_policy_id': fields.many2one(
|
||||
'credit.control.policy',
|
||||
'Credit Control Policy',
|
||||
domain="[('account_ids', 'in', property_account_receivable)]",
|
||||
help=("The Credit Control Policy used for this "
|
||||
"partner. This setting can be forced on the "
|
||||
"invoice. If nothing is defined, it will use "
|
||||
"the company setting.")
|
||||
),
|
||||
'credit_control_line_ids': fields.one2many(
|
||||
'credit.control.line',
|
||||
'invoice_id',
|
||||
string='Credit Control Lines',
|
||||
readonly=True
|
||||
)
|
||||
}
|
||||
|
||||
def _check_credit_policy(self, cr, uid, part_ids, context=None):
|
||||
"""Ensure that policy on partner are limited to the account policy"""
|
||||
if isinstance(part_ids, (int, long)):
|
||||
part_ids = [part_ids]
|
||||
policy_obj = self.pool['credit.control.policy']
|
||||
for partner in self.browse(cr, uid, part_ids, context):
|
||||
if not partner.property_account_receivable or \
|
||||
not partner.credit_policy_id:
|
||||
return True
|
||||
account = partner.property_account_receivable
|
||||
policy_obj.check_policy_against_account(
|
||||
cr, uid,
|
||||
account.id,
|
||||
partner.credit_policy_id.id,
|
||||
context=context
|
||||
)
|
||||
return True
|
||||
|
||||
_constraints = [(_check_credit_policy,
|
||||
'The policy must be related to the receivable account',
|
||||
['credit_policy_id'])]
|
||||
|
||||
def copy_data(self, cr, uid, id, default=None, context=None):
|
||||
"""Remove credit lines when copying partner"""
|
||||
if default is None:
|
||||
default = {}
|
||||
else:
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
from openerp.osv.orm import Model, fields
|
||||
from openerp.osv import orm, fields
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class CreditControlPolicy(Model):
|
||||
class CreditControlPolicy(orm.Model):
|
||||
"""Define a policy of reminder"""
|
||||
|
||||
_name = "credit.control.policy"
|
||||
@@ -42,12 +42,12 @@ class CreditControlPolicy(Model):
|
||||
'account_ids': fields.many2many('account.account',
|
||||
string='Accounts',
|
||||
required=True,
|
||||
domain="[('reconcile', '=', True)]",
|
||||
domain="[('type', '=', 'receivable')]",
|
||||
help="This policy will be active only"
|
||||
" for the selected accounts"),
|
||||
'active': fields.boolean('Active'),
|
||||
}
|
||||
|
||||
|
||||
_defaults = {
|
||||
'active': True,
|
||||
}
|
||||
@@ -103,7 +103,10 @@ class CreditControlPolicy(Model):
|
||||
my_obj = self.pool.get(model)
|
||||
move_l_obj = self.pool.get('account.move.line')
|
||||
|
||||
default_domain = self._move_lines_domain(cr, uid, policy, controlling_date, context=context)
|
||||
default_domain = self._move_lines_domain(cr, uid,
|
||||
policy,
|
||||
controlling_date,
|
||||
context=context)
|
||||
to_add_ids = set()
|
||||
to_remove_ids = set()
|
||||
|
||||
@@ -198,15 +201,34 @@ class CreditControlPolicy(Model):
|
||||
if isinstance(policy_id, list):
|
||||
policy_id = policy_id[0]
|
||||
cr.execute("SELECT move_line_id FROM credit_control_line"
|
||||
" WHERE policy_id != %s and move_line_id in %s",
|
||||
" WHERE policy_id != %s and move_line_id in %s"
|
||||
" AND manually_overridden IS false",
|
||||
(policy_id, tuple(lines)))
|
||||
res = cr.fetchall()
|
||||
if res:
|
||||
different_lines.update([x[0] for x in res])
|
||||
return different_lines
|
||||
|
||||
def check_policy_against_account(self, cr, uid, account_id, policy_id,
|
||||
context=None):
|
||||
"""Ensure that the policy corresponds to account relation"""
|
||||
policy = self.browse(cr, uid, policy_id, context=context)
|
||||
account = self.pool['account.account'].browse(cr, uid, account_id,
|
||||
context=context)
|
||||
policies_id = self.search(cr, uid, [],
|
||||
context=context)
|
||||
policies = self.browse(cr, uid, policies_id, context=context)
|
||||
allowed = [x for x in policies
|
||||
if account in x.account_ids or x.do_nothing]
|
||||
if policy not in allowed:
|
||||
allowed_names = u"\n".join(x.name for x in allowed)
|
||||
raise orm.except_orm(
|
||||
_('You can only use a policy set on account %s') % account.name,
|
||||
_("Please choose one of the following policies:\n %s") % allowed_names)
|
||||
return True
|
||||
|
||||
class CreditControlPolicyLevel(Model):
|
||||
|
||||
class CreditControlPolicyLevel(orm.Model):
|
||||
"""Define a policy level. A level allows to determine if
|
||||
a move line is due and the level of overdue of the line"""
|
||||
|
||||
@@ -319,15 +341,17 @@ 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 overridden
|
||||
# have to be generated again for the previous level
|
||||
" AND state not in ('draft', 'ignored'))")
|
||||
" AND NOT manually_overridden\n"
|
||||
" AND state NOT IN ('draft', 'ignored'))"
|
||||
" AND (mv_line.debit IS NOT NULL AND mv_line.debit != 0.0)\n")
|
||||
sql += " AND"
|
||||
sql += self._get_sql_date_boundary_for_computation_mode(cr, uid, level,
|
||||
controlling_date, context)
|
||||
data_dict = {'controlling_date': controlling_date,
|
||||
'line_ids': tuple(lines),
|
||||
'delay': level.delay_days}
|
||||
|
||||
cr.execute(sql, data_dict)
|
||||
res = cr.fetchall()
|
||||
if res:
|
||||
@@ -346,11 +370,16 @@ class CreditControlPolicyLevel(Model):
|
||||
" ON (mv_line.id = cr_line.move_line_id)\n"
|
||||
" 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_overridden"
|
||||
" ORDER BY credit_control_line.level desc limit 1)\n"
|
||||
" AND cr_line.level = %(previous_level)s\n"
|
||||
" AND (mv_line.debit IS NOT NULL AND mv_line.debit != 0.0)\n"
|
||||
# lines from a previous level with a draft or ignored state
|
||||
# or manually overridden
|
||||
# have to be generated again for the previous level
|
||||
" AND cr_line.state not in ('draft', 'ignored')\n"
|
||||
" AND NOT manually_overridden\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,
|
||||
|
||||
@@ -81,14 +81,24 @@ class CreditControlRun(orm.Model):
|
||||
|
||||
def _check_run_date(self, cr, uid, ids, controlling_date, context=None):
|
||||
"""Ensure that there is no credit line in the future using controlling_date"""
|
||||
line_obj = self.pool.get('credit.control.line')
|
||||
run_obj = self.pool['credit.control.run']
|
||||
runs = run_obj.search(cr, uid, [('date', '>', controlling_date)],
|
||||
order='date DESC', limit=1, context=context)
|
||||
if runs:
|
||||
run = run_obj.browse(cr, uid, runs[0], context=context)
|
||||
raise orm.except_orm(_('Error'),
|
||||
_('A run has already been executed more '
|
||||
'recently than %s') % (run.date))
|
||||
|
||||
line_obj = self.pool['credit.control.line']
|
||||
lines = line_obj.search(cr, uid, [('date', '>', controlling_date)],
|
||||
order='date DESC', limit=1, context=context)
|
||||
if lines:
|
||||
line = line_obj.browse(cr, uid, lines[0], context=context)
|
||||
raise orm.except_orm(_('Error'),
|
||||
_('A run has already been executed more '
|
||||
'recently than %s') % (line.date))
|
||||
_('A credit control line more '
|
||||
'recent than %s exists at %s') %
|
||||
(controlling_date, line.date))
|
||||
return True
|
||||
|
||||
def _generate_credit_lines(self, cr, uid, run_id, context=None):
|
||||
@@ -110,10 +120,10 @@ class CreditControlRun(orm.Model):
|
||||
_('Please select a policy'))
|
||||
|
||||
report = ''
|
||||
generated_ids = []
|
||||
for policy in policies:
|
||||
if policy.do_nothing:
|
||||
continue
|
||||
|
||||
lines = policy._get_move_lines_to_process(run.date, context=context)
|
||||
manual_lines = policy._lines_different_policy(lines, context=context)
|
||||
lines.difference_update(manual_lines)
|
||||
@@ -125,7 +135,7 @@ class CreditControlRun(orm.Model):
|
||||
level_lines = level.get_level_lines(run.date, lines, context=context)
|
||||
policy_generated_ids += cr_line_obj.create_or_update_from_mv_lines(
|
||||
cr, uid, [], list(level_lines), level.id, run.date, context=context)
|
||||
|
||||
generated_ids.extend(policy_generated_ids)
|
||||
if policy_generated_ids:
|
||||
report += _("Policy \"%s\" has generated %d Credit Control Lines.\n") % \
|
||||
(policy.name, len(policy_generated_ids))
|
||||
@@ -138,6 +148,7 @@ class CreditControlRun(orm.Model):
|
||||
'report': report,
|
||||
'manual_ids': [(6, 0, manually_managed_lines)]}
|
||||
run.write(vals, context=context)
|
||||
return generated_ids
|
||||
|
||||
def generate_credit_lines(self, cr, uid, run_id, context=None):
|
||||
"""Generate credit control lines
|
||||
@@ -147,7 +158,7 @@ class CreditControlRun(orm.Model):
|
||||
"""
|
||||
try:
|
||||
cr.execute('SELECT id FROM credit_control_run'
|
||||
' LIMIT 1 FOR UPDATE NOWAIT')
|
||||
' LIMIT 1 FOR UPDATE NOWAIT')
|
||||
except Exception as exc:
|
||||
# in case of exception openerp will do a rollback for us and free the lock
|
||||
raise orm.except_orm(_('Error'),
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Credit control run">
|
||||
<field name="date"/>
|
||||
<field name="date"
|
||||
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
|
||||
<newline/>
|
||||
<notebook colspan="4">
|
||||
<page string="Policies">
|
||||
|
||||
@@ -10,12 +10,7 @@
|
||||
|
||||
Feature: General parameters in order to test the credit control module
|
||||
|
||||
@deactivate_journal_control
|
||||
Scenario: Journal setup to vaoid unfixed voucher bug
|
||||
Given I execute the SQL commands
|
||||
"""
|
||||
UPDATE account_journal SET allow_date = false;
|
||||
"""
|
||||
|
||||
@account_credit_control_setup_install_modules
|
||||
Scenario: MODULES INSTALLATION
|
||||
|
||||
@@ -26,6 +21,14 @@ Feature: General parameters in order to test the credit control module
|
||||
|
||||
Then my modules should have been installed and models reloaded
|
||||
|
||||
|
||||
@deactivate_journal_control
|
||||
Scenario: Journal setup to avoid unfixed voucher bug
|
||||
Given I execute the SQL commands
|
||||
"""
|
||||
UPDATE account_journal SET allow_date = false;
|
||||
"""
|
||||
|
||||
@email_params_mailtrap
|
||||
Scenario: E-MAIL PARAMS WITH EMAIL EATER (http://mailtrap.railsware.com/)
|
||||
Given I need a "ir.mail_server" with name: mailstrap_testings
|
||||
|
||||
@@ -19,7 +19,7 @@ Feature: Invoices creation
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_1 |
|
||||
| date_invoice | %Y-01-15 |
|
||||
| date_invoice | 2013-01-15 |
|
||||
| partner_id | by oid: scen.partner_1 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
@@ -55,7 +55,7 @@ Feature: Invoices creation
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_2 |
|
||||
| date_invoice | %Y-02-15 |
|
||||
| date_invoice | 2013-02-15 |
|
||||
| partner_id | by oid: scen.partner_1 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
@@ -82,7 +82,7 @@ Feature: Invoices creation
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_3 |
|
||||
| date_invoice | %Y-03-15 |
|
||||
| date_invoice | 2013-03-15 |
|
||||
| partner_id | by oid: scen.partner_1 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
@@ -111,7 +111,7 @@ Feature: Invoices creation
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_4 |
|
||||
| date_invoice | %Y-01-18 |
|
||||
| date_invoice | 2013-01-18 |
|
||||
| partner_id | by oid: scen.customer_2 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
@@ -139,7 +139,7 @@ Feature: Invoices creation
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_5 |
|
||||
| date_invoice | %Y-02-15 |
|
||||
| date_invoice | 2013-02-15 |
|
||||
| partner_id | by oid: scen.customer_2 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
@@ -166,7 +166,7 @@ Feature: Invoices creation
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_6 |
|
||||
| date_invoice | %Y-03-15 |
|
||||
| date_invoice | 2013-03-15 |
|
||||
| partner_id | by oid: scen.customer_2 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
@@ -195,7 +195,7 @@ Feature: Invoices creation
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_7 |
|
||||
| date_invoice | %Y-01-18 |
|
||||
| date_invoice | 2013-01-18 |
|
||||
| partner_id | by oid: scen.customer_3 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
@@ -223,7 +223,7 @@ Feature: Invoices creation
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_8 |
|
||||
| date_invoice | %Y-02-15 |
|
||||
| date_invoice | 2013-02-15 |
|
||||
| partner_id | by oid: scen.customer_3 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
@@ -250,7 +250,7 @@ Feature: Invoices creation
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_9 |
|
||||
| date_invoice | %Y-03-15 |
|
||||
| date_invoice | 2013-03-15 |
|
||||
| partner_id | by oid: scen.customer_3 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
@@ -279,7 +279,7 @@ Feature: Invoices creation
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_10 |
|
||||
| date_invoice | %Y-01-18 |
|
||||
| date_invoice | 2013-01-18 |
|
||||
| partner_id | by oid: scen.customer_4 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
@@ -307,7 +307,7 @@ Feature: Invoices creation
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_11 |
|
||||
| date_invoice | %Y-02-15 |
|
||||
| date_invoice | 2013-02-15 |
|
||||
| partner_id | by oid: scen.customer_4 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
@@ -334,7 +334,7 @@ Feature: Invoices creation
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_12 |
|
||||
| date_invoice | %Y-03-15 |
|
||||
| date_invoice | 2013-03-15 |
|
||||
| partner_id | by oid: scen.customer_4 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
@@ -363,7 +363,7 @@ Feature: Invoices creation
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_13 |
|
||||
| date_invoice | %Y-01-18 |
|
||||
| date_invoice | 2013-01-18 |
|
||||
| partner_id | by oid: scen.customer_5 |
|
||||
| account_id | by name: Debtors USD |
|
||||
| journal_id | by name: Sales |
|
||||
@@ -391,7 +391,7 @@ Feature: Invoices creation
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_14 |
|
||||
| date_invoice | %Y-02-15 |
|
||||
| date_invoice | 2013-02-15 |
|
||||
| partner_id | by oid: scen.customer_5 |
|
||||
| account_id | by name: Debtors USD |
|
||||
| journal_id | by name: Sales |
|
||||
@@ -418,7 +418,7 @@ Feature: Invoices creation
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_15 |
|
||||
| date_invoice | %Y-03-15 |
|
||||
| date_invoice | 2013-03-15 |
|
||||
| partner_id | by oid: scen.customer_5 |
|
||||
| account_id | by name: Debtors USD |
|
||||
| journal_id | by name: Sales |
|
||||
@@ -444,7 +444,7 @@ Feature: Invoices creation
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_16 |
|
||||
| date_invoice | %Y-03-15 |
|
||||
| date_invoice | 2013-03-15 |
|
||||
| partner_id | by oid: scen.customer_4 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
@@ -469,7 +469,7 @@ Feature: Invoices creation
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_17 |
|
||||
| date_invoice | %Y-03-15 |
|
||||
| date_invoice | 2013-03-15 |
|
||||
| partner_id | by oid: scen.customer_partial_pay |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
@@ -494,7 +494,7 @@ Feature: Invoices creation
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_18 |
|
||||
| date_invoice | %Y-03-15 |
|
||||
| date_invoice | 2013-03-15 |
|
||||
| partner_id | by oid: scen.customer_multiple_payterm |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
@@ -519,7 +519,7 @@ Feature: Invoices creation
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_19 |
|
||||
| date_invoice | %Y-03-15 |
|
||||
| date_invoice | 2013-03-15 |
|
||||
| partner_id | by oid: scen.customer_multiple_payterm2 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
@@ -543,7 +543,7 @@ Feature: Invoices creation
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_20_test_tolerance |
|
||||
| date_invoice | %Y-03-23 |
|
||||
| date_invoice | 2013-03-23 |
|
||||
| partner_id | by oid: scen.customer_6 |
|
||||
| account_id | by name: Debtors |
|
||||
| journal_id | by name: Sales |
|
||||
@@ -568,7 +568,7 @@ Feature: Invoices creation
|
||||
And having:
|
||||
| name | value |
|
||||
| name | SI_21_test_receivable_account_excluded |
|
||||
| date_invoice | %Y-03-25 |
|
||||
| date_invoice | 2013-03-25 |
|
||||
| partner_id | by oid: scen.customer_6 |
|
||||
| account_id | by name: Debtors GBP |
|
||||
| journal_id | by name: Sales |
|
||||
|
||||
@@ -20,10 +20,10 @@ Feature: Ensure that mail credit line generation first pass is correct
|
||||
Scenario: Create run
|
||||
Given I need a "credit.control.run" with oid: credit_control.run1
|
||||
And having:
|
||||
| name | value |
|
||||
| date | %Y-01-31 |
|
||||
| name | value |
|
||||
| date | 2013-01-31 |
|
||||
When I launch the credit run
|
||||
Then my credit run should be in state "done"
|
||||
And the generated credit lines should have the following values:
|
||||
| balance | date due | account | policy | date | partner | channel | level | move line | policy level | state | amount due | currency |
|
||||
| 300 | %Y-01-18 | Debtors | 3 time policy | %Y-01-31 | customer_4 | email | 1 | SI_10 | 10 days net | draft | 300 | |
|
||||
| balance | date due | account | policy | date | partner | channel | level | move line | policy level | state | amount due | currency |
|
||||
| 300 | 2013-01-18 | Debtors | 3 time policy | 2013-01-31 | customer_4 | email | 1 | SI_10 | 10 days net | draft | 300 | |
|
||||
|
||||
@@ -23,11 +23,11 @@ Feature: Ensure that mail credit line generation first pass is correct
|
||||
Given I need a "credit.control.run" with oid: credit_control.run2
|
||||
And having:
|
||||
| name | value |
|
||||
| date | %Y-02-28 |
|
||||
| date | 2013-02-28 |
|
||||
When I launch the credit run
|
||||
Then my credit run should be in state "done"
|
||||
And the generated credit lines should have the following values:
|
||||
| balance | date due | account | policy | date | partner | channel | level | move line | policy level | state | amount due | currency |
|
||||
| 360 | %Y-02-15 | Debtors | 3 time policy | %Y-02-28 | customer_4 | email | 1 | SI_11 | 10 days net | draft | 360 | USD |
|
||||
| 1000 | %Y-02-17 | Debtors USD | 3 time policy | %Y-02-28 | customer_5_usd | email | 1 | SI_13 | 10 days net | draft | 1000 | USD |
|
||||
| 300 | %Y-01-18 | Debtors | 3 time policy | %Y-02-28 | customer_4 | email | 2 | SI_10 | 30 days end of month | draft | 300 | |
|
||||
| 360 | 2013-02-15 | Debtors | 3 time policy | 2013-02-28 | customer_4 | email | 1 | SI_11 | 10 days net | draft | 360 | USD |
|
||||
| 1000 | 2013-02-17 | Debtors USD | 3 time policy | 2013-02-28 | customer_5_usd | email | 1 | SI_13 | 10 days net | draft | 1000 | USD |
|
||||
| 300 | 2013-01-18 | Debtors | 3 time policy | 2013-02-28 | customer_4 | email | 2 | SI_10 | 30 days end of month | draft | 300 | |
|
||||
|
||||
@@ -24,8 +24,9 @@ Feature: Ensure that email credit line generation first pass is correct
|
||||
And having:
|
||||
| name | value |
|
||||
| name | Bk.St.si_19_part1 |
|
||||
| date | %Y-03-31 |
|
||||
| date | 2013-03-31 |
|
||||
| journal_id | by oid: scen.eur_journal |
|
||||
| period_id | by name: 03/2013 |
|
||||
|
||||
And I import invoice "SI_19" using import invoice button
|
||||
And I should have a "account.bank.statement.line" with name: "SI_19" and amount: "450"
|
||||
@@ -45,18 +46,18 @@ Feature: Ensure that email credit line generation first pass is correct
|
||||
Given I need a "credit.control.run" with oid: credit_control.run3
|
||||
And having:
|
||||
| name | value |
|
||||
| date | %Y-03-31 |
|
||||
| date | 2013-03-31 |
|
||||
When I launch the credit run
|
||||
Then my credit run should be in state "done"
|
||||
And the generated credit lines should have the following values:
|
||||
| balance | date due | account | policy | date | partner | channel | level | move line | policy level | state | amount due | currency |
|
||||
| 1000 | %Y-02-28 | Debtors | 2 time policy | %Y-03-31 | customer_2 | email | 1 | SI_4 | 30 days end of month | draft | 1000 | |
|
||||
| 1000 | %Y-02-17 | Debtors | 2 time policy | %Y-03-31 | customer_3 | email | 1 | SI_7 | 30 days end of month | draft | 1000 | |
|
||||
| 700 | %Y-02-28 | Debtors | 3 time policy | %Y-03-31 | customer_4 | email | 1 | SI_10 | 10 days net | draft | 700 | |
|
||||
| 450 | %Y-03-15 | Debtors | 3 time policy | %Y-03-31 | customer_4 | email | 1 | SI_12 | 10 days net | draft | 450 | |
|
||||
| 1200 | %Y-03-17 | Debtors USD | 3 time policy | %Y-03-31 | customer_5_usd | email | 1 | SI_14 | 10 days net | draft | 1200 | USD |
|
||||
| 360 | %Y-02-15 | Debtors | 3 time policy | %Y-03-31 | customer_4 | email | 2 | SI_11 | 30 days end of month | draft | 360 | USD |
|
||||
| 1000 | %Y-02-17 | Debtors USD | 3 time policy | %Y-03-31 | customer_5_usd | email | 2 | SI_13 | 30 days end of month | draft | 1000 | USD |
|
||||
| 300 | %Y-01-18 | Debtors | 3 time policy | %Y-03-31 | customer_4 | letter | 3 | SI_10 | 10 days last reminder | draft | 300 | |
|
||||
| 450 | %Y-03-15 | Debtors | 3 time policy | %Y-03-31 | Donald Duck | email | 1 | SI_18 | 10 days net | draft | 450 | |
|
||||
| 150 | %Y-03-15 | Debtors | 3 time policy | %Y-03-31 | Gus Goose | email | 1 | SI_19 | 10 days net | draft | 450 | |
|
||||
| balance | date due | account | policy | date | partner | channel | level | move line | policy level | state | amount due | currency |
|
||||
| 1000 | 2013-02-28 | Debtors | 2 time policy | 2013-03-31 | customer_2 | email | 1 | SI_4 | 30 days end of month | draft | 1000 | |
|
||||
| 1000 | 2013-02-17 | Debtors | 2 time policy | 2013-03-31 | customer_3 | email | 1 | SI_7 | 30 days end of month | draft | 1000 | |
|
||||
| 700 | 2013-02-28 | Debtors | 3 time policy | 2013-03-31 | customer_4 | email | 1 | SI_10 | 10 days net | draft | 700 | |
|
||||
| 449.99 | 2013-03-15 | Debtors | 3 time policy | 2013-03-31 | customer_4 | email | 1 | SI_12 | 10 days net | draft | 449.99 | USD |
|
||||
| 1200 | 2013-03-17 | Debtors USD | 3 time policy | 2013-03-31 | customer_5_usd | email | 1 | SI_14 | 10 days net | draft | 1200 | USD |
|
||||
| 360 | 2013-02-15 | Debtors | 3 time policy | 2013-03-31 | customer_4 | email | 2 | SI_11 | 30 days end of month | draft | 360 | USD |
|
||||
| 1000 | 2013-02-17 | Debtors USD | 3 time policy | 2013-03-31 | customer_5_usd | email | 2 | SI_13 | 30 days end of month | draft | 1000 | USD |
|
||||
| 300 | 2013-01-18 | Debtors | 3 time policy | 2013-03-31 | customer_4 | letter | 3 | SI_10 | 10 days last reminder | draft | 300 | |
|
||||
| 450 | 2013-03-15 | Debtors | 3 time policy | 2013-03-31 | Donald Duck | email | 1 | SI_18 | 10 days net | draft | 450 | |
|
||||
| 150 | 2013-03-15 | Debtors | 3 time policy | 2013-03-31 | Gus Goose | email | 1 | SI_19 | 10 days net | draft | 450 | |
|
||||
|
||||
@@ -23,22 +23,22 @@ Feature: Ensure that email credit line generation first pass is correct
|
||||
Given I need a "credit.control.run" with oid: credit_control.run4
|
||||
And having:
|
||||
| name | value |
|
||||
| date | %Y-04-30 |
|
||||
| date | 2013-04-30 |
|
||||
|
||||
When I launch the credit run
|
||||
Then my credit run should be in state "done"
|
||||
And the generated credit lines should have the following values:
|
||||
| balance | date due | account | policy | date | partner | channel | level | move line | policy level | state | amount due | currency |
|
||||
| 360 | %Y-02-15 | Debtors | 3 time policy | %Y-04-30 | customer_4 | letter | 3 | SI_11 | 10 days last reminder | draft | 360 | USD |
|
||||
| 1200 | %Y-03-31 | Debtors | 2 time policy | %Y-04-30 | customer_2 | email | 1 | SI_5 | 30 days end of month | draft | 1200 | USD |
|
||||
| 1200 | %Y-03-17 | Debtors | 2 time policy | %Y-04-30 | customer_3 | email | 1 | SI_8 | 30 days end of month | draft | 1200 | USD |
|
||||
| 700 | %Y-02-28 | Debtors | 3 time policy | %Y-04-30 | customer_4 | email | 2 | SI_10 | 30 days end of month | draft | 700 | |
|
||||
| 840 | %Y-03-31 | Debtors | 3 time policy | %Y-04-30 | customer_4 | email | 1 | SI_11 | 10 days net | draft | 840 | USD |
|
||||
| 450 | %Y-03-15 | Debtors | 3 time policy | %Y-04-30 | customer_4 | email | 2 | SI_12 | 30 days end of month | draft | 450 | USD |
|
||||
| 1500 | %Y-04-14 | Debtors USD | 3 time policy | %Y-04-30 | customer_5_usd | email | 1 | SI_15 | 10 days net | draft | 1500 | USD |
|
||||
| 1200 | %Y-03-17 | Debtors USD | 3 time policy | %Y-04-30 | customer_5_usd | email | 2 | SI_14 | 30 days end of month | draft | 1200 | USD |
|
||||
| 1500 | %Y-04-14 | Debtors USD | 3 time policy | %Y-04-30 | customer_5_usd | email | 1 | SI_15 | 10 days net | draft | 1500 | USD |
|
||||
| 1500 | %Y-04-14 | Debtors | 3 time policy | %Y-04-30 | customer_4 | email | 1 | SI_16 | 10 days net | draft | 1500 | |
|
||||
| 1500 | %Y-04-14 | Debtors | 3 time policy | %Y-04-30 | Scrooge McDuck | email | 1 | SI_17 | 10 days net | draft | 1500 | |
|
||||
| 450 | %Y-03-15 | Debtors | 3 time policy | %Y-04-30 | Donald Duck | email | 2 | SI_18 | 30 days end of month | draft | 450 | |
|
||||
| 150 | %Y-03-15 | Debtors | 3 time policy | %Y-04-30 | Gus Goose | email | 2 | SI_19 | 30 days end of month | draft | 450 | |
|
||||
| balance | date due | account | policy | date | partner | channel | level | move line | policy level | state | amount due | currency |
|
||||
| 360 | 2013-02-15 | Debtors | 3 time policy | 2013-04-30 | customer_4 | letter | 3 | SI_11 | 10 days last reminder | draft | 360 | USD |
|
||||
| 1200 | 2013-03-31 | Debtors | 2 time policy | 2013-04-30 | customer_2 | email | 1 | SI_5 | 30 days end of month | draft | 1200 | USD |
|
||||
| 1200 | 2013-03-17 | Debtors | 2 time policy | 2013-04-30 | customer_3 | email | 1 | SI_8 | 30 days end of month | draft | 1200 | USD |
|
||||
| 700 | 2013-02-28 | Debtors | 3 time policy | 2013-04-30 | customer_4 | email | 2 | SI_10 | 30 days end of month | draft | 700 | |
|
||||
| 840 | 2013-03-31 | Debtors | 3 time policy | 2013-04-30 | customer_4 | email | 1 | SI_11 | 10 days net | draft | 840 | USD |
|
||||
| 449.99 | 2013-03-15 | Debtors | 3 time policy | 2013-04-30 | customer_4 | email | 2 | SI_12 | 30 days end of month | draft | 449.99 | USD |
|
||||
| 1500 | 2013-04-14 | Debtors USD | 3 time policy | 2013-04-30 | customer_5_usd | email | 1 | SI_15 | 10 days net | draft | 1500 | USD |
|
||||
| 1200 | 2013-03-17 | Debtors USD | 3 time policy | 2013-04-30 | customer_5_usd | email | 2 | SI_14 | 30 days end of month | draft | 1200 | USD |
|
||||
| 1500 | 2013-04-14 | Debtors USD | 3 time policy | 2013-04-30 | customer_5_usd | email | 1 | SI_15 | 10 days net | draft | 1500 | USD |
|
||||
| 1500 | 2013-04-14 | Debtors | 3 time policy | 2013-04-30 | customer_4 | email | 1 | SI_16 | 10 days net | draft | 1500 | |
|
||||
| 1500 | 2013-04-14 | Debtors | 3 time policy | 2013-04-30 | Scrooge McDuck | email | 1 | SI_17 | 10 days net | draft | 1500 | |
|
||||
| 450 | 2013-03-15 | Debtors | 3 time policy | 2013-04-30 | Donald Duck | email | 2 | SI_18 | 30 days end of month | draft | 450 | |
|
||||
| 150 | 2013-03-15 | Debtors | 3 time policy | 2013-04-30 | Gus Goose | email | 2 | SI_19 | 30 days end of month | draft | 450 | |
|
||||
|
||||
@@ -24,8 +24,10 @@ Feature: Ensure that email credit line generation first pass is correct
|
||||
And having:
|
||||
| name | value |
|
||||
| name | Bk.St.si_16 |
|
||||
| date | %Y-05-30 |
|
||||
| date | 2013-05-30 |
|
||||
| journal_id | by oid: scen.eur_journal |
|
||||
| period_id | by name: 05/2013 |
|
||||
|
||||
And I import invoice "SI_16" using import invoice button
|
||||
And I set bank statement end-balance
|
||||
When I confirm bank statement
|
||||
@@ -37,8 +39,10 @@ Feature: Ensure that email credit line generation first pass is correct
|
||||
And having:
|
||||
| name | value |
|
||||
| name | Bk.St.si_17 |
|
||||
| date | %Y-05-30 |
|
||||
| date | 2013-05-30 |
|
||||
| journal_id | by oid: scen.eur_journal |
|
||||
| period_id | by name: 05/2013 |
|
||||
|
||||
And I import invoice "SI_17" using import invoice button
|
||||
And I should have a "account.bank.statement.line" with name: "SI_17" and amount: "1500"
|
||||
And I set the voucher paid amount to "1000"
|
||||
@@ -55,8 +59,10 @@ Feature: Ensure that email credit line generation first pass is correct
|
||||
And having:
|
||||
| name | value |
|
||||
| name | Bk.St.si_18_part1 |
|
||||
| date | %Y-05-30 |
|
||||
| date | 2013-05-30 |
|
||||
| journal_id | by oid: scen.eur_journal |
|
||||
| period_id | by name: 05/2013 |
|
||||
|
||||
And I import invoice "SI_18" using import invoice button
|
||||
And I should have a "account.bank.statement.line" with name: "SI_18" and amount: "450"
|
||||
And I set the voucher paid amount to "450"
|
||||
@@ -76,22 +82,22 @@ Feature: Ensure that email credit line generation first pass is correct
|
||||
Given I need a "credit.control.run" with oid: credit_control.run5
|
||||
And having:
|
||||
| name | value |
|
||||
| date | %Y-05-31 |
|
||||
| date | 2013-05-31 |
|
||||
When I launch the credit run
|
||||
Then my credit run should be in state "done"
|
||||
And the generated credit lines should have the following values:
|
||||
| balance | date due | account | policy | date | partner | channel | level | move line | policy level | state | amount due | currency |
|
||||
| 1500 | %Y-04-30 | Debtors | 2 time policy | %Y-05-31 | customer_2 | email | 1 | SI_6 | 30 days end of month | draft | 1500 | USD |
|
||||
| 1000 | %Y-02-28 | Debtors | 2 time policy | %Y-05-31 | customer_2 | letter | 2 | SI_4 | 60 days last reminder | draft | 1000 | |
|
||||
| 1000 | %Y-02-17 | Debtors | 2 time policy | %Y-05-31 | customer_3 | letter | 2 | SI_7 | 60 days last reminder | draft | 1000 | |
|
||||
| 1500 | %Y-04-14 | Debtors | 2 time policy | %Y-05-31 | customer_3 | email | 1 | SI_9 | 30 days end of month | draft | 1500 | |
|
||||
| 840 | %Y-03-31 | Debtors | 3 time policy | %Y-05-31 | customer_4 | email | 2 | SI_11 | 30 days end of month | draft | 840 | USD |
|
||||
| 1500 | %Y-04-14 | Debtors USD | 3 time policy | %Y-05-31 | customer_5_usd | email | 2 | SI_15 | 30 days end of month | draft | 1500 | USD |
|
||||
| 700 | %Y-02-28 | Debtors | 3 time policy | %Y-05-31 | customer_4 | letter | 3 | SI_10 | 10 days last reminder | draft | 700 | |
|
||||
| 450 | %Y-03-15 | Debtors | 3 time policy | %Y-05-31 | customer_4 | letter | 3 | SI_12 | 10 days last reminder | draft | 450 | USD |
|
||||
| 1050 | %Y-04-30 | Debtors | 3 time policy | %Y-05-31 | customer_4 | email | 1 | SI_12 | 10 days net | draft | 1050 | USD |
|
||||
| 1200 | %Y-03-17 | Debtors USD | 3 time policy | %Y-05-31 | customer_5_usd | letter | 3 | SI_14 | 10 days last reminder | draft | 1200 | USD |
|
||||
| 500 | %Y-04-14 | Debtors | 3 time policy | %Y-05-31 | Scrooge McDuck | email | 2 | SI_17 | 30 days end of month | draft | 1500 | |
|
||||
| 1050 | %Y-04-30 | Debtors | 3 time policy | %Y-05-31 | Donald Duck | email | 1 | SI_18 | 10 days net | draft | 1050 | |
|
||||
| 150 | %Y-03-15 | Debtors | 3 time policy | %Y-05-31 | Gus Goose | letter | 3 | SI_19 | 10 days last reminder | draft | 450 | |
|
||||
| 1050 | %Y-04-30 | Debtors | 3 time policy | %Y-05-31 | Gus Goose | email | 1 | SI_19 | 10 days net | draft | 1050 | |
|
||||
| balance | date due | account | policy | date | partner | channel | level | move line | policy level | state | amount due | currency |
|
||||
| 1500 | 2013-04-30 | Debtors | 2 time policy | 2013-05-31 | customer_2 | email | 1 | SI_6 | 30 days end of month | draft | 1500 | USD |
|
||||
| 1000 | 2013-02-28 | Debtors | 2 time policy | 2013-05-31 | customer_2 | letter | 2 | SI_4 | 60 days last reminder | draft | 1000 | |
|
||||
| 1000 | 2013-02-17 | Debtors | 2 time policy | 2013-05-31 | customer_3 | letter | 2 | SI_7 | 60 days last reminder | draft | 1000 | |
|
||||
| 1500 | 2013-04-14 | Debtors | 2 time policy | 2013-05-31 | customer_3 | email | 1 | SI_9 | 30 days end of month | draft | 1500 | |
|
||||
| 840 | 2013-03-31 | Debtors | 3 time policy | 2013-05-31 | customer_4 | email | 2 | SI_11 | 30 days end of month | draft | 840 | USD |
|
||||
| 1500 | 2013-04-14 | Debtors USD | 3 time policy | 2013-05-31 | customer_5_usd | email | 2 | SI_15 | 30 days end of month | draft | 1500 | USD |
|
||||
| 700 | 2013-02-28 | Debtors | 3 time policy | 2013-05-31 | customer_4 | letter | 3 | SI_10 | 10 days last reminder | draft | 700 | |
|
||||
| 449.99 | 2013-03-15 | Debtors | 3 time policy | 2013-05-31 | customer_4 | letter | 3 | SI_12 | 10 days last reminder | draft | 449.99 | USD |
|
||||
| 1050.01 | 2013-04-30 | Debtors | 3 time policy | 2013-05-31 | customer_4 | email | 1 | SI_12 | 10 days net | draft | 1050.01 | USD |
|
||||
| 1200 | 2013-03-17 | Debtors USD | 3 time policy | 2013-05-31 | customer_5_usd | letter | 3 | SI_14 | 10 days last reminder | draft | 1200 | USD |
|
||||
| 500 | 2013-04-14 | Debtors | 3 time policy | 2013-05-31 | Scrooge McDuck | email | 2 | SI_17 | 30 days end of month | draft | 1500 | |
|
||||
| 1050 | 2013-04-30 | Debtors | 3 time policy | 2013-05-31 | Donald Duck | email | 1 | SI_18 | 10 days net | draft | 1050 | |
|
||||
| 150 | 2013-03-15 | Debtors | 3 time policy | 2013-05-31 | Gus Goose | letter | 3 | SI_19 | 10 days last reminder | draft | 450 | |
|
||||
| 1050 | 2013-04-30 | Debtors | 3 time policy | 2013-05-31 | Gus Goose | email | 1 | SI_19 | 10 days net | draft | 1050 | |
|
||||
|
||||
@@ -23,16 +23,16 @@ Feature: Ensure that email credit line generation first pass is correct
|
||||
Given I need a "credit.control.run" with oid: credit_control.run6
|
||||
And having:
|
||||
| name | value |
|
||||
| date | %Y-06-30 |
|
||||
| date | 2013-06-30 |
|
||||
When I launch the credit run
|
||||
Then my credit run should be in state "done"
|
||||
And the generated credit lines should have the following values:
|
||||
| balance | date due | account | policy | date | partner | channel | level | move line | policy level | state | amount due | currency |
|
||||
| 1200 | %Y-03-31 | Debtors | 2 time policy | %Y-06-30 | customer_2 | letter | 2 | SI_5 | 60 days last reminder | draft | 1200 | USD |
|
||||
| 1200 | %Y-03-17 | Debtors | 2 time policy | %Y-06-30 | customer_3 | letter | 2 | SI_8 | 60 days last reminder | draft | 1200 | USD |
|
||||
| 1050 | %Y-04-30 | Debtors | 3 time policy | %Y-06-30 | customer_4 | email | 2 | SI_12 | 30 days end of month | draft | 1050 | USD |
|
||||
| 840 | %Y-03-31 | Debtors | 3 time policy | %Y-06-30 | customer_4 | letter | 3 | SI_11 | 10 days last reminder | draft | 840 | USD |
|
||||
| 1500 | %Y-04-14 | Debtors USD | 3 time policy | %Y-06-30 | customer_5_usd | letter | 3 | SI_15 | 10 days last reminder | draft | 1500 | USD |
|
||||
| 500 | %Y-04-14 | Debtors | 3 time policy | %Y-06-30 | Scrooge McDuck | letter | 3 | SI_17 | 10 days last reminder | draft | 1500 | |
|
||||
| 1050 | %Y-04-30 | Debtors | 3 time policy | %Y-06-30 | Donald Duck | email | 2 | SI_18 | 30 days end of month | draft | 1050 | |
|
||||
| 1050 | %Y-04-30 | Debtors | 3 time policy | %Y-06-30 | Gus Goose | email | 2 | SI_19 | 30 days end of month | draft | 1050 | |
|
||||
| balance | date due | account | policy | date | partner | channel | level | move line | policy level | state | amount due | currency |
|
||||
| 1200 | 2013-03-31 | Debtors | 2 time policy | 2013-06-30 | customer_2 | letter | 2 | SI_5 | 60 days last reminder | draft | 1200 | USD |
|
||||
| 1200 | 2013-03-17 | Debtors | 2 time policy | 2013-06-30 | customer_3 | letter | 2 | SI_8 | 60 days last reminder | draft | 1200 | USD |
|
||||
| 1050.01 | 2013-04-30 | Debtors | 3 time policy | 2013-06-30 | customer_4 | email | 2 | SI_12 | 30 days end of month | draft | 1050.01 | USD |
|
||||
| 840 | 2013-03-31 | Debtors | 3 time policy | 2013-06-30 | customer_4 | letter | 3 | SI_11 | 10 days last reminder | draft | 840 | USD |
|
||||
| 1500 | 2013-04-14 | Debtors USD | 3 time policy | 2013-06-30 | customer_5_usd | letter | 3 | SI_15 | 10 days last reminder | draft | 1500 | USD |
|
||||
| 500 | 2013-04-14 | Debtors | 3 time policy | 2013-06-30 | Scrooge McDuck | letter | 3 | SI_17 | 10 days last reminder | draft | 1500 | |
|
||||
| 1050 | 2013-04-30 | Debtors | 3 time policy | 2013-06-30 | Donald Duck | email | 2 | SI_18 | 30 days end of month | draft | 1050 | |
|
||||
| 1050 | 2013-04-30 | Debtors | 3 time policy | 2013-06-30 | Gus Goose | email | 2 | SI_19 | 30 days end of month | draft | 1050 | |
|
||||
|
||||
@@ -13,23 +13,23 @@
|
||||
Feature: Ensure that email credit line generation first pass is correct
|
||||
|
||||
@account_credit_control_mark
|
||||
Scenario: mark lines
|
||||
Given there is "draft" credit lines
|
||||
And I mark all draft email to state "to_be_sent"
|
||||
Then the draft line should be in state "to_be_sent"
|
||||
Scenario: mark lines
|
||||
Given there is "draft" credit lines
|
||||
And I mark all draft email to state "to_be_sent"
|
||||
Then the draft line should be in state "to_be_sent"
|
||||
|
||||
@account_credit_control_run_month
|
||||
Scenario: Create run
|
||||
Given I need a "credit.control.run" with oid: credit_control.run7
|
||||
And having:
|
||||
| name | value |
|
||||
| date | %Y-07-31 |
|
||||
| date | 2013-07-31 |
|
||||
When I launch the credit run
|
||||
Then my credit run should be in state "done"
|
||||
And the generated credit lines should have the following values:
|
||||
| balance | date due | account | policy | date | partner | channel | level | move line | policy level | state | amount due | currency |
|
||||
| 1500 | %Y-04-30 | Debtors | 2 time policy | %Y-07-31 | customer_2 | letter | 2 | SI_6 | 60 days last reminder | draft | 1500 | USD |
|
||||
| 1500 | %Y-04-14 | Debtors | 2 time policy | %Y-07-31 | customer_3 | letter | 2 | SI_9 | 60 days last reminder | draft | 1500 | USD |
|
||||
| 1050 | %Y-04-30 | Debtors | 3 time policy | %Y-07-31 | customer_4 | letter | 3 | SI_12 | 10 days last reminder | draft | 1050 | USD |
|
||||
| 1050 | %Y-04-30 | Debtors | 3 time policy | %Y-07-31 | Donald Duck | letter | 3 | SI_18 | 10 days last reminder | draft | 1050 | |
|
||||
| 1050 | %Y-04-30 | Debtors | 3 time policy | %Y-07-31 | Gus Goose | letter | 3 | SI_19 | 10 days last reminder | draft | 1050 | |
|
||||
| balance | date due | account | policy | date | partner | channel | level | move line | policy level | state | amount due | currency |
|
||||
| 1500 | 2013-04-30 | Debtors | 2 time policy | 2013-07-31 | customer_2 | letter | 2 | SI_6 | 60 days last reminder | draft | 1500 | USD |
|
||||
| 1500 | 2013-04-14 | Debtors | 2 time policy | 2013-07-31 | customer_3 | letter | 2 | SI_9 | 60 days last reminder | draft | 1500 | USD |
|
||||
| 1050.01 | 2013-04-30 | Debtors | 3 time policy | 2013-07-31 | customer_4 | letter | 3 | SI_12 | 10 days last reminder | draft | 1050.01 | USD |
|
||||
| 1050 | 2013-04-30 | Debtors | 3 time policy | 2013-07-31 | Donald Duck | letter | 3 | SI_18 | 10 days last reminder | draft | 1050 | |
|
||||
| 1050 | 2013-04-30 | Debtors | 3 time policy | 2013-07-31 | Gus Goose | letter | 3 | SI_19 | 10 days last reminder | draft | 1050 | |
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
###############################################################################
|
||||
#
|
||||
# OERPScenario, OpenERP Functional Tests
|
||||
# Copyright 2012 Camptocamp SA
|
||||
# Author Nicolas Bessi
|
||||
##############################################################################
|
||||
|
||||
# Features Generic tags (none for all)
|
||||
##############################################################################
|
||||
|
||||
@account_credit_control @account_credit_control_run @account_credit_control_run_aug
|
||||
|
||||
Feature: Ensure that ignore feature works as expected
|
||||
|
||||
@account_credit_control_mark_as_ignore
|
||||
Scenario: mark last line as ignore
|
||||
Given I ignore the "Gus Goose" credit line at level "3" for move line "SI_19" with amount "1050.0"
|
||||
|
||||
@account_credit_control_run_month_aug
|
||||
Scenario: Create run
|
||||
Given I need a "credit.control.run" with oid: credit_control.runignored
|
||||
And having:
|
||||
| name | value |
|
||||
| date | 2013-08-30 |
|
||||
When I launch the credit run
|
||||
Then my credit run should be in state "done"
|
||||
|
||||
@check_ignored_line
|
||||
Scenario: Check ignored lines
|
||||
Given I have for "Gus Goose" "2" credit lines at level "3" for move line "SI_19" with amount "1050.0" respectively in state "draft" and "ignored"
|
||||
@@ -0,0 +1,42 @@
|
||||
###############################################################################
|
||||
#
|
||||
# OERPScenario, OpenERP Functional Tests
|
||||
# Copyright 2012 Camptocamp SA
|
||||
# Author Nicolas Bessi
|
||||
##############################################################################
|
||||
|
||||
# Features Generic tags (none for all)
|
||||
##############################################################################
|
||||
|
||||
@account_credit_control @account_credit_control_run @account_credit_control_run_change_level
|
||||
|
||||
Feature: Ensure that manually changing an invoice level feature works as expected
|
||||
|
||||
@account_credit_control_change_level
|
||||
Scenario: Change level
|
||||
Given I change level for invoice "SAJ/2014/0004" to "10 days net" of policy "3 time policy"
|
||||
Then wizard selected move lines should be:
|
||||
| name |
|
||||
| SI_4 |
|
||||
When I confirm the level change
|
||||
And I should have "3" credit control lines overridden
|
||||
And one new credit control line of level "10 days net" related to invoice "SAJ/2014/0004"
|
||||
Then I force date of generated credit line to "2013-09-15"
|
||||
|
||||
@account_credit_control_run_month_sept
|
||||
Scenario: Create run
|
||||
Given there is "draft" credit lines
|
||||
And I mark all draft email to state "to_be_sent"
|
||||
Then the draft line should be in state "to_be_sent"
|
||||
Given I need a "credit.control.run" with oid: credit_control.manual_change
|
||||
And having:
|
||||
| name | value |
|
||||
| date | 2013-09-30 |
|
||||
When I launch the credit run
|
||||
Then my credit run should be in state "done"
|
||||
|
||||
@account_credit_control_manual_next_step
|
||||
Scenario: Check manually managed line on run
|
||||
Given the invoice "SAJ/2014/0004" with manual changes
|
||||
And the invoice has "1" line of level "1" for policy "3 time policy"
|
||||
And the invoice has "1" line of level "2" for policy "3 time policy"
|
||||
@@ -118,3 +118,28 @@ def impl(ctx, state):
|
||||
lines = model('credit.control.line').search([('state', '!=', state),
|
||||
('id', 'in', ctx.lines)])
|
||||
assert not lines
|
||||
|
||||
@given(u'I ignore the "{partner}" credit line at level "{level:d}" for move line "{move_line_name}" with amount "{amount:f}"')
|
||||
def impl(ctx, partner, level, move_line_name, amount):
|
||||
print ctx, partner, level, move_line_name, amount
|
||||
to_ignore = model('credit.control.line').search([('partner_id.name', '=', partner),
|
||||
('level', '=', level),
|
||||
('amount_due', '=', amount),
|
||||
('move_line_id.name', '=', move_line_name)])
|
||||
assert to_ignore
|
||||
wiz = model('credit.control.marker').create({'name': 'ignored'})
|
||||
ctx.lines = to_ignore
|
||||
wiz.write({'line_ids': to_ignore})
|
||||
wiz.mark_lines()
|
||||
assert model('credit.control.line').get(to_ignore[0]).state == 'ignored'
|
||||
|
||||
@given(u'I have for "{partner}" "{number:d}" credit lines at level "{level:d}" for move line "{move_line_name}" with amount "{amount:f}" respectively in state "draft" and "ignored"')
|
||||
def impl(ctx, partner, number, level, move_line_name, amount):
|
||||
to_check = model('credit.control.line').search([('partner_id.name', '=', partner),
|
||||
('level', '=', level),
|
||||
('amount_due', '=', amount),
|
||||
('move_line_id.name', '=', move_line_name),
|
||||
('state', 'in', ('draft', 'ignored'))])
|
||||
assert_equal(len(to_check), int(number), msg="More than %s found" % number)
|
||||
lines = model('credit.control.line').browse(to_check)
|
||||
assert set(['ignored', 'draft']) == set(lines.state)
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
@given(u'I change level for invoice "{invoice_name}" to "{level_name}" of policy "{policy_name}"')
|
||||
def impl(ctx, invoice_name, level_name, policy_name):
|
||||
invoice = model('account.invoice').get([('number', '=', invoice_name)])
|
||||
assert_true(invoice, msg='No invoices found')
|
||||
level = model('credit.control.policy.level').get([('name', '=', level_name)])
|
||||
assert_true(level, 'level not found')
|
||||
policy = model('credit.control.policy').get([('name', '=', policy_name)])
|
||||
assert_true(policy, 'Policy not found')
|
||||
assert_equal(policy.id, level.policy_id.id)
|
||||
context = {'active_ids': [invoice.id]}
|
||||
data = {'new_policy_id': policy.id,
|
||||
'new_policy_level_id': level.id}
|
||||
wizard = model('credit.control.policy.changer').create(data, context=context)
|
||||
ctx.wizard = wizard
|
||||
|
||||
@then(u'wizard selected move lines should be')
|
||||
def impl(ctx):
|
||||
assert_true(ctx.wizard)
|
||||
names = [x.name for x in ctx.wizard.move_line_ids]
|
||||
for line in ctx.table:
|
||||
assert_in(line['name'], names)
|
||||
|
||||
@when(u'I confirm the level change')
|
||||
def impl(ctx):
|
||||
assert_true(ctx.wizard)
|
||||
ctx.wizard.set_new_policy()
|
||||
|
||||
@when(u'I should have "{line_number:d}" credit control lines overridden')
|
||||
def impl(ctx, line_number):
|
||||
assert_true(ctx.wizard)
|
||||
move_ids = [x.id for x in ctx.wizard.move_line_ids]
|
||||
overridden = model('credit.control.line').search([('move_line_id', 'in', move_ids),
|
||||
('manually_overridden', '=', True)])
|
||||
# assert len(overridden) == line_number
|
||||
|
||||
@when(u'one new credit control line of level "{level_name}" related to invoice "{invoice_name}"')
|
||||
def impl(ctx, level_name, invoice_name):
|
||||
invoice = model('account.invoice').get([('number', '=', invoice_name)])
|
||||
assert_true(invoice, msg='No invoices found')
|
||||
level = model('credit.control.policy.level').get([('name', '=', level_name)])
|
||||
assert_true(level, 'level not found')
|
||||
assert_true(ctx.wizard)
|
||||
move_ids = [x.id for x in ctx.wizard.move_line_ids]
|
||||
created_id = model('credit.control.line').search([('move_line_id', 'in', move_ids),
|
||||
('manually_overridden', '=', False)])
|
||||
|
||||
assert len(created_id) == 1
|
||||
created = model('credit.control.line').get(created_id[0])
|
||||
ctx.created = created
|
||||
assert_equal(created.policy_level_id.id, level.id)
|
||||
assert_equal(created.invoice_id.id, invoice.id)
|
||||
assert_equal(created.invoice_id.credit_policy_id.id, level.policy_id.id)
|
||||
|
||||
@then(u'I force date of generated credit line to "{date}"')
|
||||
def impl(ctx, date):
|
||||
assert_true(ctx.created)
|
||||
ctx.created.write({'date': date})
|
||||
|
||||
@given(u'the invoice "{invoice_name}" with manual changes')
|
||||
def impl(ctx, invoice_name):
|
||||
invoice = model('account.invoice').get([('number', '=', invoice_name)])
|
||||
assert_true(invoice, msg='No invoices found')
|
||||
man_lines = (x for x in invoice.credit_control_line_ids if x.manually_overridden)
|
||||
assert_true(next(man_lines, None), 'No manual change on the invoice')
|
||||
ctx.invoice = invoice
|
||||
|
||||
@given(u'the invoice has "{line_number:d}" line of level "{level:d}" for policy "{policy_name}"')
|
||||
def impl(ctx, line_number, level, policy_name):
|
||||
assert_true(ctx.invoice)
|
||||
policy = model('credit.control.policy').get([('name', '=', policy_name)])
|
||||
assert_true(policy)
|
||||
lines = model('credit.control.line').search([('invoice_id', '=', ctx.invoice.id),
|
||||
('level', '=', level),
|
||||
('policy_id', '=', policy.id)])
|
||||
assert_equal(len(lines), line_number)
|
||||
@@ -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
|
||||
|
||||
@@ -80,14 +80,18 @@ class CreditCommunication(TransientModel):
|
||||
return cr_l_ids
|
||||
|
||||
def _generate_comm_from_credit_line_ids(self, cr, uid, line_ids, context=None):
|
||||
"""Aggregate credit control line by partner, level, and currency
|
||||
It also generate a communication object per aggregation.
|
||||
"""
|
||||
if not line_ids:
|
||||
return []
|
||||
comms = []
|
||||
sql = ("SELECT distinct partner_id, policy_level_id, credit_control_policy_level.level"
|
||||
sql = ("SELECT distinct partner_id, policy_level_id, "
|
||||
" credit_control_line.currency_id, credit_control_policy_level.level"
|
||||
" FROM credit_control_line JOIN credit_control_policy_level "
|
||||
" ON (credit_control_line.policy_level_id = credit_control_policy_level.id)"
|
||||
" WHERE credit_control_line.id in %s"
|
||||
" ORDER by credit_control_policy_level.level")
|
||||
" ORDER by credit_control_policy_level.level, credit_control_line.currency_id")
|
||||
|
||||
cr.execute(sql, (tuple(line_ids),))
|
||||
res = cr.dictfetchall()
|
||||
@@ -101,8 +105,6 @@ class CreditCommunication(TransientModel):
|
||||
data['partner_id'] = level_assoc['partner_id']
|
||||
data['current_policy_level'] = level_assoc['policy_level_id']
|
||||
comm_id = self.create(cr, uid, data, context=context)
|
||||
|
||||
|
||||
comms.append(self.browse(cr, uid, comm_id, context=context))
|
||||
return comms
|
||||
|
||||
|
||||
@@ -4,17 +4,27 @@
|
||||
<record id="credit_line_emailer_form" model="ir.ui.view">
|
||||
<field name="name">credit.line.emailer.form</field>
|
||||
<field name="model">credit.control.emailer</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Mailer">
|
||||
<form string="Mailer" version="7.0">
|
||||
<separator string="Send emails for the selected lines" colspan="4"/>
|
||||
<newline/>
|
||||
<field name="line_ids" colspan="4" nolabel="1" />
|
||||
<notebook>
|
||||
<page string="Lines">
|
||||
<field name="line_ids" colspan="4" nolabel="1" />
|
||||
</page>
|
||||
</notebook>
|
||||
<newline/>
|
||||
<group colspan="4">
|
||||
<button special="cancel" string="Cancel" icon='gtk-cancel'/>
|
||||
<button name="email_lines" string="Send the emails" type="object" icon="gtk-execute"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button class="oe_highlight"
|
||||
name="email_lines"
|
||||
string="Send the emails"
|
||||
type="object"/>
|
||||
or
|
||||
<button
|
||||
class="oe_link"
|
||||
special="cancel"
|
||||
string="Cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -4,19 +4,34 @@
|
||||
<record id="credit_line_marker_form" model="ir.ui.view">
|
||||
<field name="name">credit.line.marker.form</field>
|
||||
<field name="model">credit.control.marker</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Lines marker">
|
||||
<separator string="Change the state of the selected lines." colspan="4"/>
|
||||
<form string="Lines marker" version="7.0">
|
||||
<separator string="Change the state of the selected lines" colspan="4"/>
|
||||
<newline/>
|
||||
<label string="Warning: you will maybe not be able to revert this operation." colspan="4"></label>
|
||||
<newline/>
|
||||
<field name="name" colspan="4"/>
|
||||
<field name="line_ids" colspan="4" nolabel="1"/>
|
||||
<newline/>
|
||||
<group colspan="4">
|
||||
<button special="cancel" string="Cancel" icon='gtk-cancel'/>
|
||||
<button name="mark_lines" string="Change Lines' State" type="object" icon="gtk-execute"/>
|
||||
<group>
|
||||
<group><field name="name"/></group>
|
||||
<group></group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Lines">
|
||||
<field name="line_ids" colspan="4" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
<newline/>
|
||||
<footer>
|
||||
<button
|
||||
class="oe_highlight"
|
||||
name="mark_lines"
|
||||
string="Change Lines' State"
|
||||
type="object"/>
|
||||
or
|
||||
<button
|
||||
class="oe_link"
|
||||
special="cancel"
|
||||
string="Cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
178
account_credit_control/wizard/credit_control_policy_changer.py
Normal file
178
account_credit_control/wizard/credit_control_policy_changer.py
Normal file
@@ -0,0 +1,178 @@
|
||||
# -*- 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
import logging
|
||||
from openerp.tools.translate import _
|
||||
from openerp.osv import orm, fields
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
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),
|
||||
# Only used to provide dynamic filtering on form
|
||||
'do_nothing': fields.boolean('No follow policy'),
|
||||
'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):
|
||||
"""Get default lines for fields move_line_ids
|
||||
of wizard. Only take lines that are on the same account
|
||||
and move of the invoice and not reconciled
|
||||
|
||||
:return: list of compliant move line ids
|
||||
|
||||
"""
|
||||
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):
|
||||
if invoice.type in ('in_invoice', 'in_refund', 'out_refund'):
|
||||
raise orm.except_orm(_('User error'),
|
||||
_('Please use wizard on cutomer invoices'))
|
||||
|
||||
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 onchange_policy_id(self, cr, uid, ids, new_policy_id, context=None):
|
||||
if not new_policy_id:
|
||||
return {}
|
||||
policy = self.pool['credit.control.policy'].browse(cr, uid,
|
||||
new_policy_id,
|
||||
context=context)
|
||||
return {'value': {'do_nothing': policy.do_nothing}}
|
||||
|
||||
def _mark_as_overridden(self, cr, uid, move_lines, context=None):
|
||||
"""Mark `move_lines` related credit control line as overridden
|
||||
This is done by setting manually_overridden fields to True
|
||||
|
||||
:param move_lines: move line to mark as overridden
|
||||
|
||||
:retun: list of credit line ids that where marked as overridden
|
||||
|
||||
"""
|
||||
credit_model = self.pool['credit.control.line']
|
||||
domain = [('move_line_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_overridden': True},
|
||||
context)
|
||||
return credits_ids
|
||||
|
||||
def _set_invoice_policy(self, cr, uid, move_line_ids, policy,
|
||||
context=None):
|
||||
"""Force policy on invoice"""
|
||||
invoice_model = self.pool['account.invoice']
|
||||
invoice_ids = set([x.invoice.id for x in move_line_ids if x.invoice])
|
||||
invoice_model.write(cr, uid, list(invoice_ids),
|
||||
{'credit_policy_id': policy.id},
|
||||
context=context)
|
||||
|
||||
def _check_accounts_policies(self, cr, uid, lines, policy, context=None):
|
||||
policy_obj = self.pool['credit.control.policy']
|
||||
for line in lines:
|
||||
policy_obj.check_policy_against_account(
|
||||
cr, uid,
|
||||
line.account_id.id,
|
||||
policy.id,
|
||||
context=context
|
||||
)
|
||||
return True
|
||||
|
||||
def set_new_policy(self, cr, uid, wizard_id, context=None):
|
||||
"""Set new policy on an invoice.
|
||||
|
||||
This is done by creating a new credit control line
|
||||
related to the move line and the policy setted in
|
||||
the wizard form
|
||||
|
||||
:return: ir.actions.act_windows dict
|
||||
|
||||
"""
|
||||
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._check_accounts_policies(
|
||||
cr,
|
||||
uid,
|
||||
wizard.move_line_ids,
|
||||
wizard.new_policy_id)
|
||||
self._mark_as_overridden(cr,
|
||||
uid,
|
||||
wizard.move_line_ids,
|
||||
context=context)
|
||||
# As disscused with business expert
|
||||
# draft lines 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 = None
|
||||
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
|
||||
)
|
||||
self._set_invoice_policy(cr, uid,
|
||||
wizard.move_line_ids,
|
||||
wizard.new_policy_id,
|
||||
context=context)
|
||||
if not generated_ids:
|
||||
return {}
|
||||
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
|
||||
@@ -0,0 +1,65 @@
|
||||
<?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"
|
||||
on_change="onchange_policy_id(new_policy_id)"/>
|
||||
<field name="do_nothing"
|
||||
invisible="1"/>
|
||||
<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>
|
||||
@@ -23,6 +23,7 @@ import base64
|
||||
from openerp.osv import orm, fields
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class CreditControlPrinter(orm.TransientModel):
|
||||
"""Print lines"""
|
||||
|
||||
@@ -34,15 +35,16 @@ class CreditControlPrinter(orm.TransientModel):
|
||||
if context is None:
|
||||
context = {}
|
||||
res = False
|
||||
if (context.get('active_model') == 'credit.control.line' and
|
||||
context.get('active_ids')):
|
||||
res = context['active_ids']
|
||||
if context.get('active_model') != 'credit.control.line':
|
||||
return res
|
||||
res = context.get('active_ids', False)
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'mark_as_sent': fields.boolean('Mark letter lines as sent',
|
||||
help="Only letter lines will be marked."),
|
||||
'report_file': fields.binary('Generated Report', readonly=True),
|
||||
'report_name': fields.char('Report name'),
|
||||
'state': fields.char('state', size=32),
|
||||
'line_ids': fields.many2many(
|
||||
'credit.control.line',
|
||||
@@ -62,6 +64,12 @@ class CreditControlPrinter(orm.TransientModel):
|
||||
('channel', '=', 'letter')]
|
||||
return line_obj.search(cr, uid, domain, context=context)
|
||||
|
||||
def _credit_line_predicate(self, cr, uid, line_record, context=None):
|
||||
return True
|
||||
|
||||
def _get_line_ids(self, cr, uid, lines, predicate, context=None):
|
||||
return [l.id for l in lines if predicate(cr, uid, l, context)]
|
||||
|
||||
def print_lines(self, cr, uid, wiz_id, context=None):
|
||||
assert not (isinstance(wiz_id, list) and len(wiz_id) > 1), \
|
||||
"wiz_id: only one id expected"
|
||||
@@ -71,14 +79,22 @@ class CreditControlPrinter(orm.TransientModel):
|
||||
form = self.browse(cr, uid, wiz_id, context)
|
||||
|
||||
if not form.line_ids and not form.print_all:
|
||||
raise orm.except_orm(_('Error'), _('No credit control lines selected.'))
|
||||
raise orm.except_orm(_('Error'),
|
||||
_('No credit control lines selected.'))
|
||||
|
||||
line_ids = self._get_line_ids(cr,
|
||||
uid,
|
||||
form.line_ids,
|
||||
self._credit_line_predicate,
|
||||
context=context)
|
||||
|
||||
line_ids = [l.id for l in form.line_ids]
|
||||
comms = comm_obj._generate_comm_from_credit_line_ids(cr, uid, line_ids,
|
||||
context=context)
|
||||
report_file = comm_obj._generate_report(cr, uid, comms, context=context)
|
||||
|
||||
form.write({'report_file': base64.b64encode(report_file), 'state': 'done'})
|
||||
form.write({'report_file': base64.b64encode(report_file),
|
||||
'report_name': 'credit_control_esr_bvr_%s.pdf' % fields.datetime.now(),
|
||||
'state': 'done'})
|
||||
|
||||
if form.mark_as_sent:
|
||||
comm_obj._mark_credit_line_as_sent(cr, uid, comms, context=context)
|
||||
|
||||
@@ -6,21 +6,34 @@
|
||||
<field name="model">credit.control.printer</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Lines report">
|
||||
<separator colspan="4" string="Print the selected lines"/>
|
||||
<form string="Lines report" version="7.0">
|
||||
<separator string="Print the selected lines" colspan="4"/>
|
||||
<newline/>
|
||||
<field name="mark_as_sent" colspan="4" attrs="{'invisible': [('state', '=', 'done')]}"/>
|
||||
<group>
|
||||
<field name="mark_as_sent"
|
||||
colspan="4"
|
||||
attrs="{'invisible': [('state', '=', 'done')]}"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<notebook>
|
||||
<page string="Lines" attrs="{'invisible': [('state', '=', 'done')]}">
|
||||
<field name="line_ids" colspan="4" nolabel="1"
|
||||
attrs="{'invisible': [('state', '=', 'done')]}" />
|
||||
<field name="report_file" colspan="4" attrs="{'invisible': [('state', '!=', 'done')]}"/>
|
||||
</page>
|
||||
</notebook>
|
||||
<field name="report_name"
|
||||
invisible="1"/>
|
||||
<field name="report_file"
|
||||
colspan="4"
|
||||
filename="report_name"
|
||||
attrs="{'invisible': [('state', '!=', 'done')]}"/>
|
||||
<field name="state" invisible="1" />
|
||||
<newline/>
|
||||
<group colspan="4">
|
||||
<button special="cancel" string="Cancel" icon='gtk-cancel' attrs="{'invisible': [('state', '==', 'done')]}"/>
|
||||
<button name="print_lines" string="Print" type="object" icon="gtk-execute" attrs="{'invisible': [('state', '==', 'done')]}"/>
|
||||
<footer>
|
||||
<button class="oe_highlight" name="print_lines" string="Print" type="object" attrs="{'invisible': [('state', '=', 'done')]}"/>
|
||||
<button special="cancel" string="Cancel" icon='gtk-cancel' attrs="{'invisible': [('state', '=', 'done')]}"/>
|
||||
<button special="cancel" string="Close" icon='gtk-close' attrs="{'invisible': [('state', '!=', 'done')]}"/>
|
||||
</group>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
Reference in New Issue
Block a user